From 304008b5d58940889d4e6e992e587e85b66d7d8e Mon Sep 17 00:00:00 2001 From: Manav Padhariya <52840038+manavluhar@users.noreply.github.com> Date: Mon, 7 Jun 2021 22:01:04 +0530 Subject: [PATCH 001/776] Update README.md Added devdocs Slack Channel link and Magento Community Engineering Slack group link. Changed Twitter Page Link text from Follow @MagentoDevDocs to Twitter @MagentoDevDocs As the functionality of this link is not for follow the @MagentoDevDocs page, the functionality of this link is to open @MagentoDevDocs Twitter page. --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 074a27c7f31..5a2d2b045f1 100644 --- a/README.md +++ b/README.md @@ -167,5 +167,6 @@ Find guidelines for building the site locally in the checked out README. If you have questions, open an issue and ask us. We're looking forward to hearing from you! +- [Slack](https://magentocommeng.slack.com/archives/CAN932A3H) ([Join us](https://opensource.magento.com/slack)) - [Visit our wiki](https://github.com/magento/devdocs/wiki) -- Follow @MagentoDevDocs +- Twitter @MagentoDevDocs From 72832a7932b7996d8069b0b17e685e1e49d4ff6d Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy Date: Mon, 31 Jan 2022 21:13:08 -0600 Subject: [PATCH 002/776] - Add documentation about dynamic message broker for queues; --- .../prod/config-reference-envphp.md | 49 ++- .../async-message-queue-config-files.md | 71 +++- .../message-queues/config-mq.md | 64 +-- .../message-queues/implement-bulk.md | 365 +++++++++++++++++- 4 files changed, 497 insertions(+), 52 deletions(-) mode change 120000 => 100644 src/guides/v2.4/extension-dev-guide/message-queues/async-message-queue-config-files.md mode change 120000 => 100644 src/guides/v2.4/extension-dev-guide/message-queues/implement-bulk.md diff --git a/src/guides/v2.4/config-guide/prod/config-reference-envphp.md b/src/guides/v2.4/config-guide/prod/config-reference-envphp.md index 7608e82cf9f..b8eb99ede34 100644 --- a/src/guides/v2.4/config-guide/prod/config-reference-envphp.md +++ b/src/guides/v2.4/config-guide/prod/config-reference-envphp.md @@ -9,25 +9,26 @@ functional_areas: The `env.php` file contains the following sections: -| Name | Description | -|-------------------------------|-----------------------------------------------------------------| -| `backend` | Settings for the Admin area | -| `cache` | Configure redis page and default cache | -| `cache_types` | Cache storage settings | +| Name | Description | +|-----------------------------|----------------------------------------------------------------| +| `backend` | Settings for the Admin area | +| `cache` | Configure redis page and default cache | +| `cache_types` | Cache storage settings | | `consumers_wait_for_messages` | Configure how consumers process messages from the message queue | -| `cron` | Enable or disable the cron jobs | -| `crypt` | The encryption key for cryptographic functions | -| `db` | Database connection settings | -| `directories` | Magento directories mapping settings | -| `downloadable_domains` | List of downloadable domains | -| `install` | The installation date | -| `lock` | Lock provider settings | -| `MAGE_MODE` | The [Magento mode][magento-mode] | -| `queue` | [Message queues][message-queues] settings | -| `resource` | Mapping of resource name to a connection | -| `session` | Session storage data | -| `system` | Disables the field for editing in the admin | -| `x-frame-options` | Setting for [x-frame-options][x-frame-options] | +| `cron` | Enable or disable the cron jobs | +| `crypt` | The encryption key for cryptographic functions | +| `db` | Database connection settings | +| `default_connection` | Message queues default connection | +| `directories` | Magento directories mapping settings | +| `downloadable_domains` | List of downloadable domains | +| `install` | The installation date | +| `lock` | Lock provider settings | +| `MAGE_MODE` | The [Magento mode][magento-mode] | +| `queue` | [Message queues][message-queues] settings | +| `resource` | Mapping of resource name to a connection | +| `session` | Session storage data | +| `system` | Disables the field for editing in the admin | +| `x-frame-options` | Setting for [x-frame-options][x-frame-options] | ## backend @@ -164,6 +165,18 @@ All database configurations are available in this node. ] ``` +## default_connection +Specify message queues default connection. Can be `db`, `amqp` or any custom value like `redissmq` (but `redissmq` should be configured to be able to use it). The default value is `db`. + +```conf +'queue' => [ + 'default_connection' => 'amqp' +] +``` + +If `queue/default_connection` is specified in `env.php`, this connection is used for all message queues through the system, unless specific connection is defined in `queue_topology.xml`, `queue_publisher.xml` or `queue_consumer.xml` file. +For example, if `queue/default_connection` is `amqp` in `env.php` but `db` connection is specified in queue configuration related xml files of a module, this module will use MySQL as a message broker. + ## directories Optional directory mapping options that need to be set when the web server is configured to serve Magento app from the `/pub` directory for [improved security][change-docroot-to-pub]. diff --git a/src/guides/v2.4/extension-dev-guide/message-queues/async-message-queue-config-files.md b/src/guides/v2.4/extension-dev-guide/message-queues/async-message-queue-config-files.md deleted file mode 120000 index 37aa7258984..00000000000 --- a/src/guides/v2.4/extension-dev-guide/message-queues/async-message-queue-config-files.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/extension-dev-guide/message-queues/async-message-queue-config-files.md \ No newline at end of file diff --git a/src/guides/v2.4/extension-dev-guide/message-queues/async-message-queue-config-files.md b/src/guides/v2.4/extension-dev-guide/message-queues/async-message-queue-config-files.md new file mode 100644 index 00000000000..f2b2880f44d --- /dev/null +++ b/src/guides/v2.4/extension-dev-guide/message-queues/async-message-queue-config-files.md @@ -0,0 +1,70 @@ +--- +group: php-developer-guide +title: Asynchronous Message Queue configuration files +contributor_name: comwrap GmbH +contributor_link: https://www.comwrap.com +functional_areas: + - Services +--- + +When using the Magento message queue, four configuration files in your module must be updated: + +* communication.xml +* queue_consumer.xml +* queue_topology.xml +* queue_publisher.xml + +More information can be found in [Configure message queues]({{ page.baseurl }}/extension-dev-guide/message-queues/config-mq.html). + +Asynchronous and Bulk APIs are built on top of the usual REST API and use the Magento Message Queue Framework for processing messages. To ease development efforts, the Asynchronous API pre-generates the following configuration files: + +* communication.xml +* queue_publisher.xml + +and provides the `queue_topology.xml` and `queue_consumer.xml` files within the `Magento/WebapiAsync` module. + +### communication.xml + +Information about the auto-generation of `communication.xml` can be found in [Topics in Asynchronous API]({{ page.baseurl }}/extension-dev-guide/message-queues/async-topics.html) + +### queue_publisher.xml + +The `queue_publisher.xml` file is generated by the `\Magento\WebapiAsync\Code\Generator\Config\RemoteServiceReader\Publisher` class, which implements `\Magento\Framework\Config\ReaderInterface` and is injected into the `\Magento\Framework\MessageQueue\Publisher\Config\CompositeReader` constructor argument in the main `di.xml` file. + +```xml + + + + Magento\WebapiAsync\Code\Generator\Config\RemoteServiceReader\Publisher + ... + + + +``` + +The sort order is set to 0 and allows developers to change some aspects of the generated configuration in configuration readers such as `queue_publisher.xml` and `env.php`. + +`\Magento\WebapiAsync\Code\Generator\Config\RemoteServiceReader\Publisher::read()` calls `\Magento\AsynchronousOperations\Model\ConfigInterface::getServices()` to get an array of all REST API routes which can be executed asynchronously. Then it defines the connection name as `amqp` and the exchange as `magento` for each generated topic name. + +### queue_consumer.xml + +The asynchronous/bulk API has one defined consumer which processes all asynchronous/bulk APIs messages. + +```xml + +``` + +### queue_topology.xml + +The message queue topology configuration links all auto-generated topic names with prefix `async.` to the `magento` exchange and defines the queue named `async.operations.all` as the destination for all messages. + +```xml + + + +``` + +{:.bs-callout-info} +Message queues connection is defined dynamically based on deployment configuration in `env.php`. If AMQP is configured in deployment configuration of the queue, AMQP connection is used. Otherwise, db connection is used. +As a result, if AMQP is configured in deployment configuration of the queue, connection declaration can be omitted in [message queue configuration files]({{page.baseurl}}/extension-dev-guide/message-queues/config-mq.html): `queue_customer.xml`, `queue_publisher.xml`, `queue_topology.xml`. diff --git a/src/guides/v2.4/extension-dev-guide/message-queues/config-mq.md b/src/guides/v2.4/extension-dev-guide/message-queues/config-mq.md index 542bb57833f..ab078ac7024 100644 --- a/src/guides/v2.4/extension-dev-guide/message-queues/config-mq.md +++ b/src/guides/v2.4/extension-dev-guide/message-queues/config-mq.md @@ -91,17 +91,17 @@ The `queue_consumer.xml` file contains one or more `consumer` elements: #### `consumer` element {:.no_toc} -| Attribute | Description | -| ----------------------------- | ----------- | -| name (required) | The name of the consumer. | -| queue (required) | Defines the queue name to send the message to. | -| handler | Specifies the class and method that processes the message. The value must be specified in the format `\Module\::`.| -| consumerInstance | The Magento class name that consumes the message | -| connection | For AMQP connections, the connection name must match the `connection` attribute in the `queue_topology.xml` file. Otherwise, the connection name must be `db`. | -| maxMessages | Specifies the maximum number of messages to consume.| -| maxIdleTime | Defines the maximum waiting time in seconds for a new message from the queue. If no message was handled within this period of time, the consumer exits. Default value: `null`| -| sleep | Specifies time in seconds to sleep before checking if a new message is available in the queue. Default value is `null` which equals to 1 second.| -| onlySpawnWhenMessageAvailable | Boolean value (`1` or `0` only) that identifies whether a consumer should be spawned only if there is available message in the related queue. Default value: `null`| +| Attribute | Description | +| ----------------------------- |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| name (required) | The name of the consumer. | +| queue (required) | Defines the queue name to send the message to. | +| handler | Specifies the class and method that processes the message. The value must be specified in the format `\Module\::`. | +| consumerInstance | The Magento class name that consumes the message. Default value: `Magento\Framework\MessageQueue\Consumer`. | +| connection | Connection is defined dynamically based on deployment configuration of message queue in `env.php`. If AMQP is configured in deployment configuration, AMQP connection is used. Otherwise, db connection is used. If you still want to specify connection type for consumer, keep in mind that for AMQP connections, the connection name must match the `connection` attribute in the `queue_topology.xml` file. Otherwise, the connection name must be `db`. | +| maxMessages | Specifies the maximum number of messages to consume. | +| maxIdleTime | Defines the maximum waiting time in seconds for a new message from the queue. If no message was handled within this period of time, the consumer exits. Default value: `null` | +| sleep | Specifies time in seconds to sleep before checking if a new message is available in the queue. Default value is `null` which equals to 1 second. | +| onlySpawnWhenMessageAvailable | Boolean value (`1` or `0` only) that identifies whether a consumer should be spawned only if there is available message in the related queue. Default value: `null` | {:.bs-callout-info} The `maxIdleTime` and `sleep` attributes will be handled only by consumers that were fired with a defined `maxMessages` parameter. The `onlySpawnWhenMessageAvailable` attribute is only checked and validated by the `\Magento\MessageQueue\Model\Cron\ConsumersRunner` class that runs consumer processes with cron. @@ -154,8 +154,8 @@ The `queue_topology.xml` file defines the message routing rules and declares que ```xml - - + + value @@ -179,25 +179,25 @@ The `queue_topology.xml` file defines the message routing rules and declares que | Attribute | Description | | -------------- | ----------- | - name (required) | A unique ID for the exchange. - type (required) | Specifies the type of exchange. Must be `topic`. - connection (required) | For AMQP connections, a string that identifies the connection. For MySQL connections, the connection name must be `db`. - durable | Boolean value indicating whether the exchange is persistent. Non-durable exchanges are purged when the server restarts. The default is `true`. - autoDelete | Boolean value indicating whether the exchange is deleted when all queues have finished using it. The default is `false`. - internal | Boolean value. If set to true, the exchange may not be used directly by publishers, but only when bound to other exchanges. The default is `false`. +name (required) | A unique ID for the exchange. +type | Specifies the type of exchange. The default value is `topic` because only `topic` type is supported. +connection | Connection is defined dynamically based on deployment configuration of message queue in `env.php`. If AMQP is configured in deployment configuration, AMQP connection is used. Otherwise, db connection is used. If you still want to specify connection, the connection name must be `amqp` for AMQP. For MySQL connections, the connection name must be `db`. +durable | Boolean value indicating whether the exchange is persistent. Non-durable exchanges are purged when the server restarts. The default is `true`. +autoDelete | Boolean value indicating whether the exchange is deleted when all queues have finished using it. The default is `false`. +internal | Boolean value. If set to true, the exchange may not be used directly by publishers, but only when bound to other exchanges. The default is `false`. #### `binding` element {:.no_toc} The `binding` element is a subnode of the `exchange` element. -| Attribute | Description | -| -------------- | ----------- | -| id (required) | A unique ID for this binding. | -| topic (required) | The name of a topic. You can specify an asterisk (*) or pound sign (#) as wildcards. These are described below the table.| -| destinationType (required) | Must be `queue`. | -| destination (required) | Identifies the name of a queue. | -| disabled | Determines whether this binding is disabled. The default value is `false`. | +| Attribute | Description | +| -------------- |---------------------------------------------------------------------------------------------------------------------------| +| id (required) | A unique ID for this binding. | +| topic (required) | The name of a topic. You can specify an asterisk (*) or pound sign (#) as wildcards. These are described below the table. | +| destinationType | The default value is `queue`. | +| destination (required) | Identifies the name of a queue. | +| disabled | Determines whether this binding is disabled. The default value is `false`. | Example topic names that include wildcards: @@ -261,13 +261,13 @@ The `queue_publisher.xml` file defines which connection and exchange to use to p #### `connection` element {:.no_toc} -The `connection` element is a subnode of the `publisher` element. There must not be more than one enabled active connection to a publisher defined at a time. If you omit the `connection` element, the default connection of `amqp` and exchange `magento` will be used. +The `connection` element is a subnode of the `publisher` element. There must not be more than one enabled active connection to a publisher defined at a time. If you omit the `connection` element, connection will be defined dynamically based on deployment configuration of message queue in `env.php` and exchange `magento` will be used. If AMQP is configured in deployment configuration, AMQP connection is used. Otherwise, db connection is used. -| Attribute | Description | -| -------------------- | ----------- | -| name (required) | For AMQP connections, the connection name must match the `connection` attribute in the `queue_topology.xml` file. Otherwise, the connection name must be `db`. | -| exchange | The name of the exchange to publish to. The default system exchange name is `magento`. | -| disabled | Determines whether this queue is disabled. The default value is `false`. | +| Attribute | Description | +| --------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| name | Connection name is defined dynamically based on deployment configuration of message queue in `env.php`. If you still want to specify connection type for publisher, keep in mind that for AMQP connections, the connection name must match the `connection` attribute in the `queue_topology.xml` file. Otherwise, the connection name must be `db`. | +| exchange | The name of the exchange to publish to. The default system exchange name is `magento`. | +| disabled | Determines whether this queue is disabled. The default value is `false`. | {:.bs-callout-warning} You cannot enable more than one `publisher` for each `topic`. diff --git a/src/guides/v2.4/extension-dev-guide/message-queues/implement-bulk.md b/src/guides/v2.4/extension-dev-guide/message-queues/implement-bulk.md deleted file mode 120000 index 83d2a5e9aa1..00000000000 --- a/src/guides/v2.4/extension-dev-guide/message-queues/implement-bulk.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/extension-dev-guide/message-queues/implement-bulk.md \ No newline at end of file diff --git a/src/guides/v2.4/extension-dev-guide/message-queues/implement-bulk.md b/src/guides/v2.4/extension-dev-guide/message-queues/implement-bulk.md new file mode 100644 index 00000000000..363d96c9551 --- /dev/null +++ b/src/guides/v2.4/extension-dev-guide/message-queues/implement-bulk.md @@ -0,0 +1,364 @@ +--- +group: php-developer-guide +title: Example bulk operations implementation +functional_areas: + - Services +--- + +This document describes how bulk operations can be implemented. There are three primary tasks to accomplish this: + +* Create a [publisher](https://glossary.magento.com/publisher-subscriber-pattern) that sends messages to the message queue +* Create a consumer that receives and processes messages +* Configure the message queues + +### Create a publisher {#createpublisher} + +A publisher's duties include scheduling a bulk operation. It must generate a `bulkUuid` for each operation, send each operation to the message queue, and report on the status of each operations. + +The following code sample shows how these duties can be completed. + +{% collapsible Code sample: %} + +```php +userContext = $userContextInterface; + $this->bulkManagement = $bulkManagement; + $this->operationFactory = $operationFactory; + $this->identityService = $identityService; + $this->urlBuilder = $urlBuilder; + $this->jsonHelper = $jsonHelper; + + } + + /** + * Schedule new bulk operation + * + * @param array $operationData + * @throws LocalizedException + * @return void + */ + public function execute($operationData) + { + $operationCount = count($operationData); + if ($operationCount > 0) { + $bulkUuid = $this->identityService->generateId(); + $bulkDescription = 'Specify here your bulk description'; + + $operations = []; + foreach ($operationData as $operation) { + + $serializedData = [ + //this data will be displayed in Failed item grid in ID column + 'entity_id' => $operation['entity_id'], + //add here logic to add url for your entity(this link will be displayed in the Failed item grid) + 'entity_link' => $this->urlBuilder->getUrl('your_url'), + //this data will be displayed in Failed item grid in the column "Meta Info" + 'meta_information' => 'Specify here meta information for your entity',//this data will be displayed in Failed item grid in the column "Meta Info" + ]; + $data = [ + 'data' => [ + 'bulk_uuid' => $bulkUuid, + //topic name must be equal to data specified in the queue configuration files + 'topic_name' => '%your_topic name%', + 'serialized_data' => $this->jsonHelper->jsonEncode($serializedData), + 'status' => OperationInterface::STATUS_TYPE_OPEN, + ] + ]; + + /** @var OperationInterface $operation */ + $operation = $this->operationFactory->create($data); + $operations[] = $operation; + + } + $userId = $this->userContext->getUserId(); + $result = $this->bulkManagement->scheduleBulk($bulkUuid, $operations, $bulkDescription, $userId); + if (!$result) { + throw new LocalizedException( + __('Something went wrong while processing the request.') + ); + } + } + } +} +``` + +{% endcollapsible %} + +### Create a consumer {#createconsumer} + +A consumer class receives messages from the message queue and changes the status after it is processed. The following example defines a consumer that handles price update bulk operations. + +{% collapsible Code sample: %} + +```php +logger = $logger; + $this->jsonHelper = $jsonHelper; + $this->operationManagement = $operationManagement; + } + + /** + * Processing operation for update price + * + * @param OperationInterface $operation + * @return void + */ + public function processOperation(OperationInterface $operation) + { + $status = OperationInterface::STATUS_TYPE_COMPLETE; + $errorCode = null; + $message = null; + $serializedData = $operation->getSerializedData(); + $unserializedData = $this->jsonHelper->jsonDecode($serializedData); + try { + //add here your own logic for async operations + } catch (\Zend_Db_Adapter_Exception $e) { + //here sample how to process exceptions if they occurred + $this->logger->critical($e->getMessage()); + //you can add here your own type of exception when operation can be retried + if ( + $e instanceof LockWaitException + || $e instanceof DeadlockException + || $e instanceof ConnectionException + ) { + $status = OperationInterface::STATUS_TYPE_RETRIABLY_FAILED; + $errorCode = $e->getCode(); + $message = __($e->getMessage()); + } else { + $status = OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED; + $errorCode = $e->getCode(); + $message = __('Sorry, something went wrong during product prices update. Please see log for details.'); + } + + } catch (NoSuchEntityException $e) { + $this->logger->critical($e->getMessage()); + $status = ($e instanceof TemporaryStateExceptionInterface) ? OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED : OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED; + $errorCode = $e->getCode(); + + $message = $e->getMessage(); + unset($unserializedData['entity_link']); + $serializedData = $this->jsonHelper->jsonEncode($unserializedData); + } catch (LocalizedException $e) { + $this->logger->critical($e->getMessage()); + $status = OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED; + $errorCode = $e->getCode(); + $message = $e->getMessage(); + } catch (\Exception $e) { + $this->logger->critical($e->getMessage()); + $status = OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED; + $errorCode = $e->getCode(); + $message = __('Sorry, something went wrong during product prices update. Please see log for details.'); + } + + //update operation status based on result performing operation(it was successfully executed or exception occurs + $this->operationManagement->changeOperationStatus( + $operation->getId(), + $status, + $errorCode, + $message, + $serializedData + ); + } +} +``` + +{% endcollapsible %} + +### Configure message queues {#configmq} + +The message queue topology must be configured to implement bulk operations. Create or edit the following files in the module's `app/code///etc` directory. + +* `communication.xml` +* `di.xml` +* `queue_consumer.xml` +* `queue_publisher.xml` +* `queue_topology.xml` + +For more information about the `di.xml` file, see [Dependency Injection]({{page.baseurl}}/extension-dev-guide/depend-inj.html). For information the other files, see [Configure message queues]({{page.baseurl}}/extension-dev-guide/message-queues/config-mq.html). + +#### Create `communication.xml` + +The `communication.xml` file defines aspects of the message queue system that apply to all topics for the [module](https://glossary.magento.com/module). Create this file with the following contents: + +```xml + + + + + +``` + +#### Create `di.xml` + +Add the following type to the module's `di.xml` file. + +```xml + + + + + + + +``` + +#### Create `queue_consumer.xml` + +The `queue_consumer.xml` file defines the relationship between a queue and its consumer. Create this file with the following contents: + +```xml + + + +``` + +#### Create `queue_publisher.xml` + +The `queue_publisher.xml` file defines the exchange where a topic is published. Create this file with the following contents: + +```xml + + + + + +``` + +#### Create `queue_topology.xml` + +The `queue_topology.xml` file defines the message routing rules and declares queues and exchanges. Create this file with the following contents: + +```xml + + + + + +``` + +{:.bs-callout-info} +Message queues connection is defined dynamically based on deployment configuration in `env.php`. If AMQP is configured in deployment configuration of the queue, AMQP connection is used. Otherwise, db connection is used. +As a result, if AMQP is configured in deployment configuration of the queue, connection declaration can be omitted in [message queue configuration files]({{page.baseurl}}/extension-dev-guide/message-queues/config-mq.html): `queue_customer.xml`, `queue_publisher.xml`, `queue_topology.xml`. + +#### Related Topics + +* [Message Queues Overview]({{page.baseurl}}/config-guide/mq/rabbitmq-overview.html) +* [Bulk Operations]({{page.baseurl}}/extension-dev-guide/message-queues/bulk-operations.html) +* [Configure message queues]({{page.baseurl}}/extension-dev-guide/message-queues/config-mq.html) From 1f26f6dc9ab1846d035a218d30c960e7b18c9ee0 Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy Date: Tue, 1 Feb 2022 15:20:20 -0600 Subject: [PATCH 003/776] Update documentation related to queue/default_connection config setting --- src/guides/v2.4/config-guide/prod/config-reference-envphp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/config-guide/prod/config-reference-envphp.md b/src/guides/v2.4/config-guide/prod/config-reference-envphp.md index b8eb99ede34..7c3f09d7604 100644 --- a/src/guides/v2.4/config-guide/prod/config-reference-envphp.md +++ b/src/guides/v2.4/config-guide/prod/config-reference-envphp.md @@ -166,7 +166,7 @@ All database configurations are available in this node. ``` ## default_connection -Specify message queues default connection. Can be `db`, `amqp` or any custom value like `redissmq` (but `redissmq` should be configured to be able to use it). The default value is `db`. +Specify message queues default connection. Can be `db`, `amqp` or any custom value like `redismq` (but `redismq` should be configured to be able to use it). The default value is `db`. ```conf 'queue' => [ From 657d71672f31fd7c11d658a2df03af63cf829c91 Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy Date: Thu, 3 Feb 2022 16:02:22 -0600 Subject: [PATCH 004/776] Update documentation related to queue/default_connection config setting --- src/guides/v2.4/config-guide/prod/config-reference-envphp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/config-guide/prod/config-reference-envphp.md b/src/guides/v2.4/config-guide/prod/config-reference-envphp.md index 7c3f09d7604..b3b35cfed7c 100644 --- a/src/guides/v2.4/config-guide/prod/config-reference-envphp.md +++ b/src/guides/v2.4/config-guide/prod/config-reference-envphp.md @@ -166,7 +166,7 @@ All database configurations are available in this node. ``` ## default_connection -Specify message queues default connection. Can be `db`, `amqp` or any custom value like `redismq` (but `redismq` should be configured to be able to use it). The default value is `db`. +Specify message queues default connection. Can be `db`, `amqp` or any custom message queue broker like `redismq`. But `redismq` or `amqp` should be configured first to be able to use it, otherwise messages won't be processed correctly. The default value is `db`. ```conf 'queue' => [ From b30a15ffaf19e3f19e07bd9277b70d8b2f7bb167 Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy Date: Mon, 14 Feb 2022 14:22:31 -0600 Subject: [PATCH 005/776] Update description for queue/default_connection option in env.php --- src/guides/v2.4/config-guide/prod/config-reference-envphp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/config-guide/prod/config-reference-envphp.md b/src/guides/v2.4/config-guide/prod/config-reference-envphp.md index b3b35cfed7c..984b03abf21 100644 --- a/src/guides/v2.4/config-guide/prod/config-reference-envphp.md +++ b/src/guides/v2.4/config-guide/prod/config-reference-envphp.md @@ -166,7 +166,7 @@ All database configurations are available in this node. ``` ## default_connection -Specify message queues default connection. Can be `db`, `amqp` or any custom message queue broker like `redismq`. But `redismq` or `amqp` should be configured first to be able to use it, otherwise messages won't be processed correctly. The default value is `db`. +Specify message queues default connection. Can be `db`, `amqp` or a custom queue system like `redismq`. But `amqp` or `redismq` should be installed and configured first to be able to use it, otherwise messages won't be processed correctly. ```conf 'queue' => [ From 7c7d2538b4fb857482b5a8fa1a6c9b4c253d1bd5 Mon Sep 17 00:00:00 2001 From: Buba Suma Date: Fri, 4 Mar 2022 07:37:42 -0600 Subject: [PATCH 006/776] ACP2E-552: [Documentation] Document the new GraphQL field ConfigurableWishlistItem. configured_variant --- src/guides/v2.4/graphql/interfaces/wishlist-item-interface.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/guides/v2.4/graphql/interfaces/wishlist-item-interface.md b/src/guides/v2.4/graphql/interfaces/wishlist-item-interface.md index 6fad1cad690..9e913b4d98d 100644 --- a/src/guides/v2.4/graphql/interfaces/wishlist-item-interface.md +++ b/src/guides/v2.4/graphql/interfaces/wishlist-item-interface.md @@ -33,8 +33,9 @@ The `ConfigurableWishlistItem` object defines the following attributes that are Attribute | Data type | Description --- | --- | --- -`child_sku` | String! | The SKU of the simple product corresponding to a set of selected configurable options +`child_sku` | String! | Deprecated. Use `configured_variant` instead. The SKU of the simple product corresponding to a set of selected configurable options `configurable_options` | [SelectedConfigurableOption!] | An array of selected configurable options +`configured_variant` | [ProductInterface]({{page.baseurl}}/graphql/interfaces/product-interface.html) | Returns details about the selected variant. The value is null if some options are not configured ### DownloadableWishlistItem attributes {#DownloadableWishlistItem} From 91ab77cfdcbfc27cc641a8fd43181d87661d331b Mon Sep 17 00:00:00 2001 From: Kevin Harper Date: Tue, 8 Mar 2022 20:42:01 -0600 Subject: [PATCH 007/776] Grammar/style updates --- .../v2.4/config-guide/prod/config-reference-envphp.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/guides/v2.4/config-guide/prod/config-reference-envphp.md b/src/guides/v2.4/config-guide/prod/config-reference-envphp.md index 984b03abf21..46dc9d9e266 100644 --- a/src/guides/v2.4/config-guide/prod/config-reference-envphp.md +++ b/src/guides/v2.4/config-guide/prod/config-reference-envphp.md @@ -166,7 +166,8 @@ All database configurations are available in this node. ``` ## default_connection -Specify message queues default connection. Can be `db`, `amqp` or a custom queue system like `redismq`. But `amqp` or `redismq` should be installed and configured first to be able to use it, otherwise messages won't be processed correctly. + +Defines the default connection for message queues. The value can be `db`, `amqp`, or a custom queue system like `redismq`. If you specify any value other than `db`, the message queue software must be installed and configured first. Otherwise, messages will not be processed correctly. ```conf 'queue' => [ @@ -174,8 +175,8 @@ Specify message queues default connection. Can be `db`, `amqp` or a custom queue ] ``` -If `queue/default_connection` is specified in `env.php`, this connection is used for all message queues through the system, unless specific connection is defined in `queue_topology.xml`, `queue_publisher.xml` or `queue_consumer.xml` file. -For example, if `queue/default_connection` is `amqp` in `env.php` but `db` connection is specified in queue configuration related xml files of a module, this module will use MySQL as a message broker. +If `queue/default_connection` is specified in `env.php`, this connection is used for all message queues through the system, unless a specific connection is defined in a `queue_topology.xml`, `queue_publisher.xml` or `queue_consumer.xml` file. +For example, if `queue/default_connection` is `amqp` in `env.php` but a `db` connection is specified in the queue configuration XML files of a module, the module will use MySQL as a message broker. ## directories From 05d9c74c2ee5828b9d6a1ee5ed83110d0f24543c Mon Sep 17 00:00:00 2001 From: flowers Date: Wed, 9 Mar 2022 15:06:44 -0600 Subject: [PATCH 008/776] ACP2E-512: [Documentation] Update documentation for graphql cart requests with new errors field for ACP2E-42 --- .../graphql/interfaces/cart-item-interface.md | 22 ++++++++++++++----- src/guides/v2.4/graphql/queries/cart.md | 4 ++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/guides/v2.4/graphql/interfaces/cart-item-interface.md b/src/guides/v2.4/graphql/interfaces/cart-item-interface.md index f48deaa9dd5..41d5d988e83 100644 --- a/src/guides/v2.4/graphql/interfaces/cart-item-interface.md +++ b/src/guides/v2.4/graphql/interfaces/cart-item-interface.md @@ -16,13 +16,14 @@ The `CartItemInterface` has the following implementations: The `CartItemInterface` and all of its implementations can contain the following attributes. -Attribute | Data Type | Description ---- | --- | --- -`id` | String | Deprecated. Use `uid` instead. The ID of the item -`prices` | [CartItemPrices](#CartItemPrices) | Includes the price of an item, any applied discounts, and calculated totals +Attribute | Data Type | Description +--- |----------------------------------------------------------------------------------| --- +`errors` | [CartItemError](#CartItemErrorObject) | An array of errors encountered while loading the cart item +`id` | String | Deprecated. Use `uid` instead. The ID of the item +`prices` | [CartItemPrices](#CartItemPrices) | Includes the price of an item, any applied discounts, and calculated totals `product` | [ProductInterface]({{ page.baseurl }}/graphql/interfaces/product-interface.html) | Contains attributes that are common to all types of products -`quantity` | Float | The number of items in the cart -`uid` | ID! | The unique ID for the `CartItemInterface` object +`quantity` | Float | The number of items in the cart +`uid` | ID! | The unique ID for the `CartItemInterface` object ### CartItemPrices object {#CartItemPrices} @@ -37,6 +38,15 @@ Attribute | Data Type | Description `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 +### CartItemError object {#CartItemErrorObject} + +The `CartItemError` object can contain the following attributes. + +Attribute | Data Type | Description +--- | --- | --- +`code`| [CartItemErrorType] | An error code that describes the error encountered. CartItemErrorType is an enumeration that can have the value of UNDEFINED, ITEM_QTY, or ITEM_INCREMENTS +`message`| [String] | A localized error message + ### SelectedCustomizableOption attributes {#SelectedCustomizableOption} Several product types support customization. Use the following attributes to identify a customized product that have been placed in a cart. diff --git a/src/guides/v2.4/graphql/queries/cart.md b/src/guides/v2.4/graphql/queries/cart.md index e574c96b197..265240ca374 100644 --- a/src/guides/v2.4/graphql/queries/cart.md +++ b/src/guides/v2.4/graphql/queries/cart.md @@ -95,6 +95,10 @@ The following query shows the status of a cart that is ready to be converted int sku } quantity + errors { + code + message + } } available_payment_methods { code From 60eddd78dfdaf97845452cc2f1a9e5e79a04b033 Mon Sep 17 00:00:00 2001 From: Kevin Harper Date: Wed, 9 Mar 2022 15:08:33 -0600 Subject: [PATCH 009/776] Updates to the note at the end of the topic --- .../v2.4/extension-dev-guide/message-queues/implement-bulk.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/guides/v2.4/extension-dev-guide/message-queues/implement-bulk.md b/src/guides/v2.4/extension-dev-guide/message-queues/implement-bulk.md index 363d96c9551..57097aa54ea 100644 --- a/src/guides/v2.4/extension-dev-guide/message-queues/implement-bulk.md +++ b/src/guides/v2.4/extension-dev-guide/message-queues/implement-bulk.md @@ -354,8 +354,8 @@ The `queue_topology.xml` file defines the message routing rules and declares que ``` {:.bs-callout-info} -Message queues connection is defined dynamically based on deployment configuration in `env.php`. If AMQP is configured in deployment configuration of the queue, AMQP connection is used. Otherwise, db connection is used. -As a result, if AMQP is configured in deployment configuration of the queue, connection declaration can be omitted in [message queue configuration files]({{page.baseurl}}/extension-dev-guide/message-queues/config-mq.html): `queue_customer.xml`, `queue_publisher.xml`, `queue_topology.xml`. +Message queue connections are defined dynamically, based on the deployment configuration in the `env.php` file. If AMQP is configured in the deployment configuration of the queue, AMQP connections are used. Otherwise, database connections are used. +As a result, if AMQP is configured in the deployment configuration of the queue, you can omit connection declarations in the `queue_customer.xml`, `queue_publisher.xml`, and `queue_topology.xml` [message queue configuration files]({{page.baseurl}}/extension-dev-guide/message-queues/config-mq.html). #### Related Topics From e2e9ddd8a530e0346d676d24c8033aca245abf8e Mon Sep 17 00:00:00 2001 From: Kevin Harper Date: Thu, 10 Mar 2022 13:16:50 -0600 Subject: [PATCH 010/776] Update config-reference-envphp.md --- src/guides/v2.4/config-guide/prod/config-reference-envphp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/config-guide/prod/config-reference-envphp.md b/src/guides/v2.4/config-guide/prod/config-reference-envphp.md index 46dc9d9e266..6f2ff60c344 100644 --- a/src/guides/v2.4/config-guide/prod/config-reference-envphp.md +++ b/src/guides/v2.4/config-guide/prod/config-reference-envphp.md @@ -175,7 +175,7 @@ Defines the default connection for message queues. The value can be `db`, `amqp` ] ``` -If `queue/default_connection` is specified in `env.php`, this connection is used for all message queues through the system, unless a specific connection is defined in a `queue_topology.xml`, `queue_publisher.xml` or `queue_consumer.xml` file. +If `queue/default_connection` is specified in the system `env.php` file, this connection is used for all message queues through the system, unless a specific connection is defined in a `queue_topology.xml`, `queue_publisher.xml` or `queue_consumer.xml` file. For example, if `queue/default_connection` is `amqp` in `env.php` but a `db` connection is specified in the queue configuration XML files of a module, the module will use MySQL as a message broker. ## directories From e1405c8947d64db5cccf5d603f59bdee5e75dedd Mon Sep 17 00:00:00 2001 From: jfrontain Date: Wed, 13 Apr 2022 11:26:35 -0500 Subject: [PATCH 011/776] added skeleton files for 2.4.5, 2.4.4-p1, 2.4.3-p3, 2.3.7-p4 release notes --- src/_data/toc/release-notes.yml | 14 ++ .../release-notes/engcomm-2-4-5-issues.md | 0 .../release-notes/engcomm-2-4-5-partner.md | 0 src/guides/v2.3/release-notes/2-3-7-p4.md | 31 +++ .../v2.3/release-notes/bk-release-notes.md | 2 + src/guides/v2.4/release-notes/2-4-3-p3.md | 28 +++ src/guides/v2.4/release-notes/2-4-4-p1.md | 28 +++ .../v2.4/release-notes/bk-release-notes.md | 5 + .../v2.4/release-notes/commerce-2-4-5.md | 234 ++++++++++++++++++ .../v2.4/release-notes/open-source-2-4-5.md | 206 +++++++++++++++ 10 files changed, 548 insertions(+) create mode 100644 src/_includes/release-notes/engcomm-2-4-5-issues.md create mode 100644 src/_includes/release-notes/engcomm-2-4-5-partner.md create mode 100644 src/guides/v2.3/release-notes/2-3-7-p4.md create mode 100644 src/guides/v2.4/release-notes/2-4-3-p3.md create mode 100644 src/guides/v2.4/release-notes/2-4-4-p1.md create mode 100644 src/guides/v2.4/release-notes/commerce-2-4-5.md create mode 100644 src/guides/v2.4/release-notes/open-source-2-4-5.md diff --git a/src/_data/toc/release-notes.yml b/src/_data/toc/release-notes.yml index d53ef84c3a9..003e5213816 100644 --- a/src/_data/toc/release-notes.yml +++ b/src/_data/toc/release-notes.yml @@ -7,6 +7,14 @@ pages: include_versions: ["2.4"] children: + - label: Magento Open Source 2.4.5 Release Notes + url: /release-notes/open-source-2-4-5.html + + - label: Adobe Commerce 2.4.5 Release Notes + url: /release-notes/commerce-2-4-5.html + + - label: Adobe Commerce 2.4.4-p1 Release Notes + url: /release-notes/2-4-4-p1.html - label: Magento Open Source 2.4.4 Release Notes url: /release-notes/open-source-2-4-4.html @@ -14,6 +22,9 @@ pages: - label: Adobe Commerce 2.4.4 Release Notes url: /release-notes/commerce-2-4-4.html + - label: Adobe Commerce 2.4.3-p3 Release Notes + url: /release-notes/2-4-3-p3.html + - label: Adobe Commerce 2.4.3-p2 Release Notes url: /release-notes/2-4-3-p2.html @@ -58,6 +69,9 @@ pages: - label: Component Status url: /release-notes/component-status.html + - label: Adobe Commerce 2.3.7-p4 Release Notes + url: /release-notes/2-3-7-p4.html + - label: Adobe Commerce 2.3.7-p3 Release Notes url: /release-notes/2-3-7-p3.html diff --git a/src/_includes/release-notes/engcomm-2-4-5-issues.md b/src/_includes/release-notes/engcomm-2-4-5-issues.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/_includes/release-notes/engcomm-2-4-5-partner.md b/src/_includes/release-notes/engcomm-2-4-5-partner.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/guides/v2.3/release-notes/2-3-7-p4.md b/src/guides/v2.3/release-notes/2-3-7-p4.md new file mode 100644 index 00000000000..bff3c56ba11 --- /dev/null +++ b/src/guides/v2.3/release-notes/2-3-7-p4.md @@ -0,0 +1,31 @@ +--- +group: release-notes +title: Adobe Commerce 2.3.7-p4 Release Notes +--- + +{{ site.data.var.ee }} 2.3.7-p4 is a security release that provides security fixes that enhance your {{ site.data.var.ee }} 2.3.7 or {{ site.data.var.ce }} 2.3.7 deployment. It provides fixes for vulnerabilities that have been identified in the previous release ({{ site.data.var.ee }} 2.3.7-p3). + +{:.bs-callout-info} +PHP 7.3 reached end of support in December 2021, and {{ site.data.var.ee }} 2.3.x and {{ site.data.var.ce }} 2.3.x will reach end of support in September 2022. **We strongly recommend planning your upgrade now to {{ site.data.var.ee }} 2.4.x or {{ site.data.var.ce }} 2.4.x deployment to help maintain PCI compliance**. + +{:.bs-callout-info} +Releases may contain backward-incompatible changes (BIC). To review minor backward-incompatible changes, see [BIC reference]({{page.baseurl}}/release-notes/backward-incompatible-changes/reference.html). (Major backward-incompatible issues are described in [BIC highlights]({{page.baseurl}}/release-notes/backward-incompatible-changes/index.html). Not all releases introduce major BICs.) + +## What's in this release? + +This security patch includes: + +* Security enhancements +* security bug fixes. See Adobe Security Bulletin for the latest discussion of these fixed issues. + +### Security highlights + +Security improvements for this release improve compliance with the latest security best practices, including: + +## Installation and upgrade instructions + +For instructions on downloading and applying security patches (including patch 2.3.7-p4), see [Quick start install]({{site.baseurl}}/guides/v2.4/install-gde/composer.html). + +## More information? + +For general information about security patches, see [Introducing the New Security Patch Release](https://community.magento.com/t5/Magento-DevBlog/Introducing-the-New-Security-Patch-Release/ba-p/141287). diff --git a/src/guides/v2.3/release-notes/bk-release-notes.md b/src/guides/v2.3/release-notes/bk-release-notes.md index 5eaea28ca5d..cd89915b6a7 100644 --- a/src/guides/v2.3/release-notes/bk-release-notes.md +++ b/src/guides/v2.3/release-notes/bk-release-notes.md @@ -5,6 +5,8 @@ title: 2.3 Release Information ## Magento 2.3.x Release Notes +* [{{site.data.var.ee}} 2.3.7-p4 Release Notes]({{page.baseurl}}/release-notes/2-3-7-p4.html) + * [{{site.data.var.ee}} 2.3.7-p3 Release Notes]({{page.baseurl}}/release-notes/2-3-7-p3.html) * [{{site.data.var.ee}} 2.3.7-p2 Release Notes]({{page.baseurl}}/release-notes/2-3-7-p2.html) diff --git a/src/guides/v2.4/release-notes/2-4-3-p3.md b/src/guides/v2.4/release-notes/2-4-3-p3.md new file mode 100644 index 00000000000..087169a5d6e --- /dev/null +++ b/src/guides/v2.4/release-notes/2-4-3-p3.md @@ -0,0 +1,28 @@ +--- +group: release-notes +title: Adobe Commerce 2.4.3-p3 Release Notes +--- + +{{ site.data.var.ee }} 2.4.3-p3 is a security release that provides two security fixes that enhance your {{ site.data.var.ee }} 2.4.3 or {{ site.data.var.ce }} 2.4.3 deployment. It provides fixes for vulnerabilities that have been identified in the previous release ({{ site.data.var.ee }} 2.4.3 and {{ site.data.var.ce }} 2.4.3). + +{:.bs-callout-info} +Releases may contain backward-incompatible changes (BIC). To review minor backward-incompatible changes, see [BIC reference]({{page.baseurl}}/release-notes/backward-incompatible-changes/reference.html). (Major backward-incompatible issues are described in [BIC highlights]({{page.baseurl}}/release-notes/backward-incompatible-changes/index.html). Not all releases introduce major BICs.) + +## What's in this release? + +This security patch includes: + +* Security enhancements +* security bug fixes. See Adobe Security Bulletin for the latest discussion of these fixed issues. + +### Security highlights + +Security improvements for this release improve compliance with the latest security best practices, including: + +## Installation and upgrade instructions + +For instructions on downloading and applying security patches (including patch 2.4.3-p3), see [Quick start install]({{site.baseurl}}/guides/v2.4/install-gde/composer.html). + +## More information? + +For general information about security patches, see [Introducing the New Security Patch Release](https://community.magento.com/t5/Magento-DevBlog/Introducing-the-New-Security-Patch-Release/ba-p/141287). diff --git a/src/guides/v2.4/release-notes/2-4-4-p1.md b/src/guides/v2.4/release-notes/2-4-4-p1.md new file mode 100644 index 00000000000..f8d08fe54b9 --- /dev/null +++ b/src/guides/v2.4/release-notes/2-4-4-p1.md @@ -0,0 +1,28 @@ +--- +group: release-notes +title: Adobe Commerce 2.4.4-p1 Release Notes +--- + +{{ site.data.var.ee }} 2.4.4-p1 is a security release that provides two security fixes that enhance your {{ site.data.var.ee }} 2.4.4 or {{ site.data.var.ce }} 2.4.4 deployment. It provides fixes for vulnerabilities that have been identified in the previous release ({{ site.data.var.ee }} 2.4.4 and {{ site.data.var.ce }} 2.4.4). + +{:.bs-callout-info} +Releases may contain backward-incompatible changes (BIC). To review minor backward-incompatible changes, see [BIC reference]({{page.baseurl}}/release-notes/backward-incompatible-changes/reference.html). (Major backward-incompatible issues are described in [BIC highlights]({{page.baseurl}}/release-notes/backward-incompatible-changes/index.html). Not all releases introduce major BICs.) + +## What's in this release? + +This security patch includes: + +* Security enhancements +* security bug fixes. See Adobe Security Bulletin for the latest discussion of these fixed issues. + +### Security highlights + +Security improvements for this release improve compliance with the latest security best practices, including: + +## Installation and upgrade instructions + +For instructions on downloading and applying security patches (including patch 2.4.4-p1), see [Quick start install]({{site.baseurl}}/guides/v2.4/install-gde/composer.html). + +## More information? + +For general information about security patches, see [Introducing the New Security Patch Release](https://community.magento.com/t5/Magento-DevBlog/Introducing-the-New-Security-Patch-Release/ba-p/141287). diff --git a/src/guides/v2.4/release-notes/bk-release-notes.md b/src/guides/v2.4/release-notes/bk-release-notes.md index 433a22bca35..9c189ecdfe8 100644 --- a/src/guides/v2.4/release-notes/bk-release-notes.md +++ b/src/guides/v2.4/release-notes/bk-release-notes.md @@ -6,9 +6,14 @@ redirect_from: magento-release-information.html ## {{site.data.var.ee}} and {{site.data.var.ce}} 2.4.x release notes +* [{{site.data.var.ce}} 2.4.5 Release Notes]({{page.baseurl}}/release-notes/open-source-2-4-5.html) +* [{{site.data.var.ee}} 2.4.5 Release Notes]({{page.baseurl}}/release-notes/commerce-2-4-5.html) + +* [{{site.data.var.ee}} 2.4.4-p1 Release Notes]({{page.baseurl}}/release-notes/2-4-4-p1.html) * [{{site.data.var.ce}} 2.4.4 Release Notes]({{page.baseurl}}/release-notes/open-source-2-4-4.html) * [{{site.data.var.ee}} 2.4.4 Release Notes]({{page.baseurl}}/release-notes/commerce-2-4-4.html) +* [{{site.data.var.ee}} 2.4.3-p3 Release Notes]({{page.baseurl}}/release-notes/2-4-3-p3.html) * [{{site.data.var.ee}} 2.4.3-p2 Release Notes]({{page.baseurl}}/release-notes/2-4-3-p2.html) * [{{site.data.var.ee}} 2.4.3-p1 Release Notes]({{page.baseurl}}/release-notes/2-4-3-p1.html) * [{{site.data.var.ce}} 2.4.3 Release Notes]({{page.baseurl}}/release-notes/open-source-2-4-3.html) diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md new file mode 100644 index 00000000000..6a9ed291dea --- /dev/null +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -0,0 +1,234 @@ +--- +group: release-notes +title: Adobe Commerce 2.4.5 Release Notes +--- + +{{ site.data.var.ee }} 2.4.5 introduces support for + +This release includes almost quality fixes and enhancements. + +{:.bs-callout-info} +Releases may contain backward-incompatible changes (BIC). {{ site.data.var.ee }} 2.4.5 contains backward-incompatible changes. To review these backward-incompatible changes, see [BIC reference]({{page.baseurl}}/release-notes/backward-incompatible-changes/reference.html). (Major backward-incompatible issues are described in [BIC highlights]({{page.baseurl}}/release-notes/backward-incompatible-changes/index.html). Not all releases introduce major BICs.) + +## Other release information + +Although code for these features is bundled with quarterly releases of the {{ site.data.var.ee }} core code, several of these projects (for example, B2B, Page Builder, and Progressive Web Applications (PWA) Studio) are also released independently. Bug fixes for these projects are documented in the separate, project-specific release information that is available in the documentation for each project. + +### Hotfixes included in this release + +{{ site.data.var.ee }} 2.4.5 includes resolution of all issues that were addressed by the following hotfixes, which were provided for {{ site.data.var.ee }} and {{ site.data.var.ce }} 2.4.4, 2.4.3-p2, and 2.3.7-p3: + + +## {{ site.data.var.ee }} 2.4.5 highlights + +Look for the following highlights in this release. + +### Security enhancements + +This release includes security fix and platform security improvements. This security fix has been backported to {{ site.data.var.ee }} 2.4.3-p3 and {{ site.data.var.ee }} 2.3.7-p4. + +No confirmed attacks related to these issues have occurred to date. However, certain vulnerabilities can potentially be exploited to access customer information or take over administrator sessions. Most of these issues require that an attacker first obtains access to the Admin. As a result, we remind you to take all necessary steps to protect your Admin, including but not limited to these efforts: + +* IP allowlisting +* [two-factor authentication]({{page.baseurl}}/security/two-factor-authentication.html) +* use of a VPN +* use of a unique location rather than `/admin` +* good password hygiene + +See Adobe Security Bulletin for the latest discussion of these fixed issues. + +#### Additional security enhancements + +Security improvements for this release improve compliance with the latest security best practices, including: + +### Platform enhancements + +{{ site.data.var.ee }} 2.4.5 now supports + +### Performance and scalability enhancements + +{{ site.data.var.ee }} performance enhancements + +Performance enhancements in this release: + +### GraphQL + +This release includes these GraphQL enhancements: + +#### New mutations + +* **Performance improvements**: + +See the [GraphQL Developer Guide]({{page.baseurl}}/graphql/) for details on these enhancements. + +### B2B + +This release includes multiple bug fixes. See [B2B Release Notes]({{page.baseurl}}/release-notes/b2b-release-notes.html) + +### PWA Studio + +PWA Studio v.12.x.x is compatible with {{ site.data.var.ee }} 2.4.5. It includes support for . For information about enhancements and bug fixes, see [PWA Studio releases](https://github.com/magento/pwa-studio/releases). See [Version compatibility](https://developer.adobe.com/commerce/pwa-studio/integrations/adobe-commerce/version-compatibility/) for a list of PWA Studio versions and their compatible {{ site.data.var.ee }} core versions. + +### PayPal Payment enhancements + +### Live Search + +### Accessibility updates + +This release brings increased conformance to standard accessibility guidelines. + +### Page Builder + +## Fixed issues + + + +We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. + +### Installation, upgrade, deployment + +### Accessibility + +### AdminGWS + +### Backend + +### Bundle products + +### Cache + +### Cart and checkout + +### Catalog + +### Catalog rule + +### Configurable products + +### Customer + +### Customer segment + +### Email + +### Frameworks + +### General fixes + +### Gift cards + +### GraphQL + +### Image + +### Import/export + +### Index + +### Infrastructure + +#### Library removals and deprecations + +#### Library upgrades + +### Invoice + +### Logging + +### {{ site.data.var.ee }} coding standard + +### Media Gallery + +### MFTF + +#### New action groups + +#### Action groups + +Repetitive actions have been replaced with action groups in these tests: + +#### New tests + +#### Refactored tests + +### Order + +### Payment methods + +#### PayPal + +### Performance + +### Pricing + +### ProductAlert + +### Product video + +### Return Merchandise Authorizations (RMA) + +### Reviews + +### Sales + +### Sales Rule + +### Search + +### Shipping + +### Staging + +### Store + +### Tax + +### Test + +#### Unit tests + +### Theme + +### Translations and locales + +### UI + +### URL rewrites + +### Web API framework + +### Wish list + +## Known issues + +## Community contributions + +We are grateful to the wider Magento community and would like to acknowledge their contributions to this release. + +The Magento Community Engineering team [Magento Contributors](https://magento.com/magento-contributors) maintains a list of top contributing individuals and partners by month, quarter, and year. From that Contributors page, you can follow links to their merged PRs on GitHub. + +### Partner contributions + +The following table highlights contributions made by Partners. This table lists the Partner who contributed the pull request, the external pull request number, and the GitHub issue number associated with it (if available). + +{% include release-notes/engcomm-2-4-5-partner.md %} + +### Individual contributor contributions + +The following table identifies contributions from our community members. This table lists the community member who contributed the pull request, the external pull request number, and the GitHub issue number associated with it (if available). + +{% include release-notes/engcomm-2-4-5-issues.md %} + +### System requirements + +Our technology stack is built on PHP and MySQL. For more information, see [System Requirements]({{site.baseurl}}/system-requirements.html). + +### Installation and upgrade instructions + +You can install {{site.data.var.ee}} 2.4.5 using [Composer]({{ page.baseurl }}/install-gde/composer.html). + +## Migration tool kits + +The Data Migration Tool helps transfer existing Magento 1.x store data to Magento 2.x. This command-line interface includes verification, progress tracking, logging, and testing functions. For installation instructions, see [Install the Data Migration Tool]({{page.baseurl}}/migration/migration-tool-install.html). Consider exploring or contributing to the [Magento Data Migration repository](https://github.com/magento/data-migration-tool). + +The [Code Migration Toolkit](https://github.com/magento-commerce/code-migration) helps transfer existing Magento 1.x store extensions and customizations to Magento 2.x. The command-line interface includes scripts for converting Magento 1.x modules and layouts. \ No newline at end of file diff --git a/src/guides/v2.4/release-notes/open-source-2-4-5.md b/src/guides/v2.4/release-notes/open-source-2-4-5.md new file mode 100644 index 00000000000..fdf93914334 --- /dev/null +++ b/src/guides/v2.4/release-notes/open-source-2-4-5.md @@ -0,0 +1,206 @@ +--- +group: release-notes +title: Magento Open Source 2.4.5 Release Notes +--- + +{{ site.data.var.ce }} 2.4.5 introduces + +This release includes almost quality fixes and enhancements. + + +{:.bs-callout-info} +Releases may contain backward-incompatible changes (BIC). {{ site.data.var.ce }} 2.4.5 contains backward-incompatible changes. To review these backward-incompatible changes, see [BIC reference]({{page.baseurl}}/release-notes/backward-incompatible-changes/reference.html). (Major backward-incompatible issues are described in [BIC highlights]({{page.baseurl}}/release-notes/backward-incompatible-changes/index.html). Not all releases introduce major BICs.) + +## Other release information + +Although code for these features is bundled with quarterly releases of the {{ site.data.var.ce }} core code, several of these projects are also released independently. Bug fixes for these projects are documented in the separate, project-specific release information that is available in the documentation for each project. + +### Hotfixes included in this release + +{{ site.data.var.ce }} 2.4.4 includes resolution of all issues that were addressed by the following hotfixes, which were provided for {{ site.data.var.ee }} and {{ site.data.var.ce }} 2.4.4, 2.4.3-p2, and 2.3.7-p3: + +## {{ site.data.var.ce }} 2.4.5 highlights + +Look for the following highlights in this release. + +### Security enhancements + +This release includes security fix and platform security improvements. This security fix has been backported to {{ site.data.var.ce }} 2.4.4-p1 and {{ site.data.var.ce }} 2.3.7-p4. + +No confirmed attacks related to these issues have occurred to date. However, certain vulnerabilities can potentially be exploited to access customer information or take over administrator sessions. Most of these issues require that an attacker first obtains access to the Admin. As a result, we remind you to take all necessary steps to protect your Admin, including but not limited to these efforts: + +* IP allowlisting +* [two-factor authentication]({{page.baseurl}}/security/two-factor-authentication.html) +* use of a VPN +* use of a unique location rather than `/admin` +* good password hygiene + +See Adobe Security Bulletin for the latest discussion of these fixed issues. + +#### Additional security enhancements + +Security improvements for this release improve compliance with the latest security best practices, including: + +### Platform enhancements + +{{ site.data.var.ce }} 2.4.5 now supports + +### GraphQL + +This release includes these GraphQL enhancements: + +* **Performance improvements**: + +See the [GraphQL Developer Guide]({{page.baseurl}}/graphql/) for details on these enhancements. + +### PayPal Payment enhancements + +### Accessibility updates + +This release brings enhanced conformance to standard accessibility guidelines. + +### Page Builder + +## Fixed issues + + + +We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. + +### Installation, upgrade, deployment + +### Accessibility + +### Backend + +### Bundle products + +### Cache + +### Cart and checkout + +### Catalog + +### Catalog rule + +### Configurable products + +### Customer + +### Email + +### Frameworks + +### General fixes + +### GraphQL + +### Image + +### Import/export + +### Index + +### Infrastructure + +#### Library removals and deprecations + +#### Library upgrades + +### Invoice + +### Logging + +### {{ site.data.var.ee }} coding standard + +### Media Gallery + +### MFTF + +#### New action groups + +#### Action groups + +Repetitive actions have been replaced with action groups in these tests: + +#### New tests + +#### Refactored tests + +### Order + +### Payment methods + +#### PayPal + +### Performance + +### Pricing + +### ProductAlert + +### Product video + +### Reviews + +### Sales + +### Sales Rule + +### Search + +### Shipping + +### Store + +### Tax + +### Test + +#### Unit tests + +### Theme + +### Translations and locales + +### UI + +### URL rewrites + +### Web API framework + +### Wish list + +## Known Issues + +## Community contributions + +We are grateful to the wider Magento community and would like to acknowledge their contributions to this release. + +The Magento Community Engineering team [Magento Contributors](https://magento.com/magento-contributors) maintains a list of top contributing individuals and partners by month, quarter, and year. From that Contributors page, you can follow links to their merged PRs on GitHub. + +### Partner contributions + +The following table highlights contributions made by Partners. This table lists the Partner who contributed the pull request, the external pull request number, and the GitHub issue number associated with it (if available). + +{% include release-notes/engcomm-2-4-5-partner.md %} + +### Individual contributor contributions + +The following table identifies contributions from our community members. This table lists the community member who contributed the pull request, the external pull request number, and the GitHub issue number associated with it (if available). + +{% include release-notes/engcomm-2-4-5-issues.md %} + +### System requirements + +Our technology stack is built on PHP and MySQL. For more information, see [System Requirements]({{site.baseurl}}/system-requirements.html). + +### Installation and upgrade instructions + +You can install {{site.data.var.ce}} 2.4.5 using [Composer]({{ page.baseurl }}/install-gde/composer.html). + +## Migration tool kits + +The Data Migration Tool helps transfer existing Magento 1.x store data to Magento 2.x. This command-line interface includes verification, progress tracking, logging, and testing functions. For installation instructions, see [Install the Data Migration Tool]({{page.baseurl}}/migration/migration-tool-install.html). Consider exploring or contributing to the [Magento Data Migration repository](https://github.com/magento/data-migration-tool). + +The [Code Migration Toolkit](https://github.com/magento-commerce/code-migration) helps transfer existing Magento 1.x store extensions and customizations to Magento 2.x. The command-line interface includes scripts for converting Magento 1.x modules and layouts. From bf154ed285ea804dc4308d838c085ffe03719320 Mon Sep 17 00:00:00 2001 From: Aakash Kumar Date: Tue, 19 Apr 2022 18:04:53 -0500 Subject: [PATCH 012/776] Update config-cli-subcommands-index.md --- .../v2.3/config-guide/cli/config-cli-subcommands-index.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/guides/v2.3/config-guide/cli/config-cli-subcommands-index.md b/src/guides/v2.3/config-guide/cli/config-cli-subcommands-index.md index f322234f4d7..4cc99ef67ac 100644 --- a/src/guides/v2.3/config-guide/cli/config-cli-subcommands-index.md +++ b/src/guides/v2.3/config-guide/cli/config-cli-subcommands-index.md @@ -136,6 +136,7 @@ You can run the following indexes in parallel mode: - `Catalog Search Fulltext` can be paralleled by store views. - `Category Product` can be paralleled by store views. - `Catalog Price` can be paralleled by website and customer groups. +- `Catalog Permissions` can be paralleed by customer groups. If you want to use parallelization, you must set one of the available modes of dimensions for the product price indexer: @@ -149,6 +150,10 @@ For example, to set the mode per website: ```bash bin/magento indexer:set-dimensions-mode catalog_product_price website ``` +If you want to use parallelization for Catalog permissions, you must set one of the available modes of dimensions for the indexer: + +- `none` (default) +- `customer_group` Or to check the current mode: From 1d2eb0332841f03165408ab613bb322196f53a27 Mon Sep 17 00:00:00 2001 From: Aakash Kumar Date: Tue, 19 Apr 2022 21:28:57 -0500 Subject: [PATCH 013/776] Update config-cli-subcommands-index.md --- .../v2.3/config-guide/cli/config-cli-subcommands-index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/guides/v2.3/config-guide/cli/config-cli-subcommands-index.md b/src/guides/v2.3/config-guide/cli/config-cli-subcommands-index.md index 4cc99ef67ac..99be59e515a 100644 --- a/src/guides/v2.3/config-guide/cli/config-cli-subcommands-index.md +++ b/src/guides/v2.3/config-guide/cli/config-cli-subcommands-index.md @@ -136,7 +136,7 @@ You can run the following indexes in parallel mode: - `Catalog Search Fulltext` can be paralleled by store views. - `Category Product` can be paralleled by store views. - `Catalog Price` can be paralleled by website and customer groups. -- `Catalog Permissions` can be paralleed by customer groups. +- `Catalog Permissions` can be paralleled by customer groups. If you want to use parallelization, you must set one of the available modes of dimensions for the product price indexer: @@ -150,7 +150,7 @@ For example, to set the mode per website: ```bash bin/magento indexer:set-dimensions-mode catalog_product_price website ``` -If you want to use parallelization for Catalog permissions, you must set one of the available modes of dimensions for the indexer: +If you want to use parallelization for Catalog permissions, you must set one of the available modes of dimensions for the Catalog Permissions indexer: - `none` (default) - `customer_group` From 89f3643bb168db2016e9522c0a1de7dcb07d821c Mon Sep 17 00:00:00 2001 From: Donald Booth Date: Wed, 27 Apr 2022 11:30:29 -0400 Subject: [PATCH 014/776] Editorial change --- .../v2.3/config-guide/cli/config-cli-subcommands-index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/guides/v2.3/config-guide/cli/config-cli-subcommands-index.md b/src/guides/v2.3/config-guide/cli/config-cli-subcommands-index.md index 99be59e515a..da02deac4cf 100644 --- a/src/guides/v2.3/config-guide/cli/config-cli-subcommands-index.md +++ b/src/guides/v2.3/config-guide/cli/config-cli-subcommands-index.md @@ -138,7 +138,7 @@ You can run the following indexes in parallel mode: - `Catalog Price` can be paralleled by website and customer groups. - `Catalog Permissions` can be paralleled by customer groups. -If you want to use parallelization, you must set one of the available modes of dimensions for the product price indexer: +To use parallelization, set one of the available dimensions modes for the product price indexer: - `none` (default) - `website` @@ -150,7 +150,7 @@ For example, to set the mode per website: ```bash bin/magento indexer:set-dimensions-mode catalog_product_price website ``` -If you want to use parallelization for Catalog permissions, you must set one of the available modes of dimensions for the Catalog Permissions indexer: +To use parallelization for Catalog permissions, set one of the available dimensions modes for the Catalog Permissions indexer: - `none` (default) - `customer_group` From eb408df6b6b0cd3371d64893818aa37f0fd27e14 Mon Sep 17 00:00:00 2001 From: Andrew Kester Date: Fri, 29 Apr 2022 11:34:55 -0500 Subject: [PATCH 015/776] Add message that grid snapshots are not automated. --- src/cloud/project/project-webint-snap.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cloud/project/project-webint-snap.md b/src/cloud/project/project-webint-snap.md index 3843d9b31d3..3705a0acb39 100644 --- a/src/cloud/project/project-webint-snap.md +++ b/src/cloud/project/project-webint-snap.md @@ -9,6 +9,9 @@ You can back up and restore specific environments at any time using a snapshot. The Pro Staging and Production environments receive regular backups for disaster recovery purposes by default, see [Pro Backup & Disaster Recovery]({{ site.baseurl }}/cloud/architecture/pro-architecture.html#backup-and-disaster-recovery). However, these backups are not publicly accessible because they are stored in a separate system. You can open a ticket to request a backup with a specific date, time, and timezone. Then we can extract it from the external system and provide it to you. +{:.bs-callout-warning} +Snapshots for Starter and Pro Integration environments are not taken automatically. It is the your responsibility to take manual snapshots or setup a con job to automatically take snapshots for these environments. + A _snapshot_ is a complete backup of an environment that includes all persistent data from all running services (for example, your MySQL database, Redis, and so on) and any files stored on the mounted volumes. Because an environment deploys as a read-only file system, restoring a snapshot is very fast. {:.bs-callout-warning} From 6f3a6ea7276caebe6d5f691c3f73479cb0457701 Mon Sep 17 00:00:00 2001 From: Andrew Kester Date: Sun, 1 May 2022 21:04:07 -0500 Subject: [PATCH 016/776] Update snapshot wording. Co-authored-by: hguthrie --- src/cloud/project/project-webint-snap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cloud/project/project-webint-snap.md b/src/cloud/project/project-webint-snap.md index 3705a0acb39..27f8de578bf 100644 --- a/src/cloud/project/project-webint-snap.md +++ b/src/cloud/project/project-webint-snap.md @@ -10,7 +10,7 @@ You can back up and restore specific environments at any time using a snapshot. The Pro Staging and Production environments receive regular backups for disaster recovery purposes by default, see [Pro Backup & Disaster Recovery]({{ site.baseurl }}/cloud/architecture/pro-architecture.html#backup-and-disaster-recovery). However, these backups are not publicly accessible because they are stored in a separate system. You can open a ticket to request a backup with a specific date, time, and timezone. Then we can extract it from the external system and provide it to you. {:.bs-callout-warning} -Snapshots for Starter and Pro Integration environments are not taken automatically. It is the your responsibility to take manual snapshots or setup a con job to automatically take snapshots for these environments. +Snapshots for Starter and Pro Integration environments are different from Pro backup and disaster recovery backups. Snapshots are **not** automatic. It is _your_ responsibility to manually create a snapshot or set up a con job to periodically take snapshots of your Starter or Pro Integration environments. A _snapshot_ is a complete backup of an environment that includes all persistent data from all running services (for example, your MySQL database, Redis, and so on) and any files stored on the mounted volumes. Because an environment deploys as a read-only file system, restoring a snapshot is very fast. From ad0e479802b17a8226178617590de5d730ec899f Mon Sep 17 00:00:00 2001 From: Andrew Kester Date: Sun, 1 May 2022 21:04:23 -0500 Subject: [PATCH 017/776] Update snapshot callout. Co-authored-by: hguthrie --- src/cloud/project/project-webint-snap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cloud/project/project-webint-snap.md b/src/cloud/project/project-webint-snap.md index 27f8de578bf..f278ee14f06 100644 --- a/src/cloud/project/project-webint-snap.md +++ b/src/cloud/project/project-webint-snap.md @@ -9,7 +9,7 @@ You can back up and restore specific environments at any time using a snapshot. The Pro Staging and Production environments receive regular backups for disaster recovery purposes by default, see [Pro Backup & Disaster Recovery]({{ site.baseurl }}/cloud/architecture/pro-architecture.html#backup-and-disaster-recovery). However, these backups are not publicly accessible because they are stored in a separate system. You can open a ticket to request a backup with a specific date, time, and timezone. Then we can extract it from the external system and provide it to you. -{:.bs-callout-warning} +{:.bs-callout-tip} Snapshots for Starter and Pro Integration environments are different from Pro backup and disaster recovery backups. Snapshots are **not** automatic. It is _your_ responsibility to manually create a snapshot or set up a con job to periodically take snapshots of your Starter or Pro Integration environments. A _snapshot_ is a complete backup of an environment that includes all persistent data from all running services (for example, your MySQL database, Redis, and so on) and any files stored on the mounted volumes. Because an environment deploys as a read-only file system, restoring a snapshot is very fast. From 8fd282a085fb16ca93eb802f6fcb524219b21599 Mon Sep 17 00:00:00 2001 From: Tu Van Date: Mon, 2 May 2022 21:10:47 +0700 Subject: [PATCH 018/776] Add missing mode value --- src/guides/v2.3/config-guide/cli/config-cli-subcommands-mode.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.3/config-guide/cli/config-cli-subcommands-mode.md b/src/guides/v2.3/config-guide/cli/config-cli-subcommands-mode.md index b8d4ecbd4d0..ddd180176b2 100644 --- a/src/guides/v2.3/config-guide/cli/config-cli-subcommands-mode.md +++ b/src/guides/v2.3/config-guide/cli/config-cli-subcommands-mode.md @@ -68,7 +68,7 @@ bin/magento deploy:mode:set {mode} [-s|--skip-compilation] where: -- **`{mode}`** is required; it can be either `developer` or `production` +- **`{mode}`** is required; it can be either `default`, `developer` or `production` - **`--skip-compilation`** is an optional parameter you can use to skip [code compilation]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-compiler.html) when you change to production mode. From fed2dfb586891b5f29eb4aae34139f9ad8223d91 Mon Sep 17 00:00:00 2001 From: Vladyslav Sikailo Date: Thu, 5 May 2022 18:39:21 +0300 Subject: [PATCH 019/776] Update info about system.xml's fields validation --- src/guides/v2.4/config-guide/prod/config-reference-systemxml.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/config-guide/prod/config-reference-systemxml.md b/src/guides/v2.4/config-guide/prod/config-reference-systemxml.md index cc3e94c88cb..70806337f1d 100644 --- a/src/guides/v2.4/config-guide/prod/config-reference-systemxml.md +++ b/src/guides/v2.4/config-guide/prod/config-reference-systemxml.md @@ -281,7 +281,7 @@ A ``-Tag can have the following children: | `backend_model` | Specifies a different backend model to modify the configured values. | `typeModel` | | `source_model` | Specifies a different source model that provides a specific set of values. | `typeModel` | | `config_path` | Can be used to overwrite the generic config path of a field. | `typeConfigPath` | -| `validate` | Define different validation rules (comma separated). Full reference list of available validation rules is listed below. | `string` | +| `validate` | Define different validation rules (space separated). Full reference list of available validation rules is listed below. | `string` | | `can_be_empty` | Used when `type` is `multiselect` to specify that a field can be empty. | `int` | | `if_module_enabled` | Used to display a field only when a given module is enabled. | `typeModule` | | `base_url` | Used in combination with `upload_dir` for file uploads. | `typeUrl` | From 5958ef9d74bcaec4ff53262da14bc98dce1bf6c8 Mon Sep 17 00:00:00 2001 From: MontrealStacy <105082094+MontrealStacy@users.noreply.github.com> Date: Fri, 6 May 2022 13:49:17 -0700 Subject: [PATCH 020/776] Tweaked an awkward sentence --- src/guides/v2.3/get-started/bk-get-started-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.3/get-started/bk-get-started-api.md b/src/guides/v2.3/get-started/bk-get-started-api.md index a632e23b2e2..38c62fb6d07 100644 --- a/src/guides/v2.3/get-started/bk-get-started-api.md +++ b/src/guides/v2.3/get-started/bk-get-started-api.md @@ -39,7 +39,7 @@ The APIs can be used to perform a wide array of tasks. For example: * Integrate with CRM (Customer Relationship Management) or ERP (Enterprise Resource Planning) backend systems, such as Salesforce or Xero. -* Integrate with a [CMS](https://glossary.magento.com/cms) (Content Management System). At present, content tagging is not supported. +* Integrate with a [CMS](https://glossary.magento.com/cms) (Content Management System). Content tagging is not currently supported. * Create [JavaScript](https://glossary.magento.com/javascript) widgets in the Magento [storefront](https://glossary.magento.com/storefront) or on the [Admin](https://glossary.magento.com/admin) panel. The [widget](https://glossary.magento.com/widget) makes AJAX calls to access services. From 5bb23c9bac034bea87f0a991961d45f4d4be5141 Mon Sep 17 00:00:00 2001 From: magedocs Date: Mon, 9 May 2022 14:38:44 +0000 Subject: [PATCH 021/776] Update News data --- src/_data/whats-new.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/_data/whats-new.yml b/src/_data/whats-new.yml index 4be295744a3..ac96832ea0e 100644 --- a/src/_data/whats-new.yml +++ b/src/_data/whats-new.yml @@ -4,8 +4,22 @@ description: This page contains recent changes that we think you'd like to know We exclude from this list proofreading, spelling checks, and all minor updates. link: "/whats-new.html" thread: "/whatsnew-feed.xml" -updated: Thu May 5 22:19:39 2022 +updated: Mon May 9 14:38:42 2022 entries: +- description: Added a tutorial on [creating a bundled product](https://devdocs.magento.com/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.html) + with the API. + versions: 2.3.x, 2.4.x + type: New Topic + date: May 8, 2022 + link: https://github.com/magento/devdocs/pull/9407 + merge_commit: 3e39778e0e70a4ee907a075bf41d29cdb0db6384 + contributor: goivvy + membership: false + labels: + - 2.3.x + - New Topic + - 2.4.x + - 'Progress: done' - description: Published [release notes](https://devdocs.magento.com/quality-patches/release-notes.html) for the 1.1.13 Quality Patches Tool package release. versions: 2.3.x, 2.4.x From f3aa8fa01cf43b5a8b17f25004b65eb2224f7919 Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Mon, 9 May 2022 10:48:25 -0500 Subject: [PATCH 022/776] Fixes magento/devdocs#9408 Tip about cloud variables --- src/guides/v2.3/config-guide/prod/config-reference-var-name.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/guides/v2.3/config-guide/prod/config-reference-var-name.md b/src/guides/v2.3/config-guide/prod/config-reference-var-name.md index 58a6e4c560f..9465cc0932c 100644 --- a/src/guides/v2.3/config-guide/prod/config-reference-var-name.md +++ b/src/guides/v2.3/config-guide/prod/config-reference-var-name.md @@ -11,6 +11,9 @@ This topic discusses how to derive an environment variable name knowing a config You can override the value of _any_ configuration setting using environment variables; however, we recommend you maintain consistent settings using the shared configuration file, `config.php`, and the system-specific configuration file, `env.php`, as discussed in [Deployment general overview]({{ page.baseurl }}/config-guide/deployment/pipeline/). +{:.bs-callout-tip} +Check out the [Configure environments]({{ page.baseurl }}/cloud/env/variables-intro.html) topic in the _Cloud_ guide for details on working with variables in {{site.data.var.ece}}. + A environment variable name consists of its scope followed by its configuration path in a particular format. The following sections discuss how to determine a variable name in more detail. You can use variables for any of the following: From d5e56c022b999a8bb21b4bc557a628e8cef59edb Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Mon, 9 May 2022 10:50:50 -0500 Subject: [PATCH 023/776] Fixes magento/devdocs#8857 AWS regions Update AWS regions --- src/cloud/env/environments-start.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cloud/env/environments-start.md b/src/cloud/env/environments-start.md index 01e9371b08a..193f593e97a 100644 --- a/src/cloud/env/environments-start.md +++ b/src/cloud/env/environments-start.md @@ -147,8 +147,8 @@ If you have a corporate firewall that blocks outgoing SSH connections, you can a

50.112.160.58

-

`54.213.195.223`

-

`35.163.170.185`

+

54.213.195.223

+

35.163.170.185

52.209.44.44

From 204a48c47ecc2dce64d67c0bb8283bca6fe0ffe6 Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Mon, 9 May 2022 10:51:40 -0500 Subject: [PATCH 024/776] Remove poor graphic --- src/cloud/project/project-webint-basic.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cloud/project/project-webint-basic.md b/src/cloud/project/project-webint-basic.md index f7450bb6eea..85595c8fc9d 100644 --- a/src/cloud/project/project-webint-basic.md +++ b/src/cloud/project/project-webint-basic.md @@ -6,14 +6,14 @@ functional_areas: - Configuration --- -The {{site.data.var.ece}} [Project Web Interface](https://account.magento.com/customer/account/login/) enables you to do the following for all Starter and Pro environments: +For all {{site.data.var.ece}} projects, you can use the [Project Web Interface](https://account.magento.com/customer/account/login/) to perform the following tasks: - [Access projects](#project-access) - [Configure environment settings](#configure-environment-settings) - [Add users and manage access]({{ site.baseurl }}/cloud/project/user-admin.html) - [Manage Git branches]({{ site.baseurl }}/cloud/project/project-webint-branch.html) -As you make changes to these settings, the branch redeploys to the environment. You can make these setting changes for all Starter and Pro environments. +Changes that you make to environment configuration trigger a redeployment of that environment. ## Access your project and environments {#project-access} @@ -26,9 +26,9 @@ The Project Web Interface provides several ways to access your project and envir To access projects and environments through the Project Web Interface: 1. [Log in to your project](https://account.magento.com/customer/account/login/). -1. Click **Access Site** for a list of URLs for web access and the command for SSH access. +1. The left pane shows your list of environments. +1. Click **Access Site** for a list of storefront URLs for web access and the command for SSH access. - ![Access your project by URL or SSH]({{ site.baseurl }}/common/images/cloud/cloud_project-access.png){:width="600px"} For more information about using SSH, see [SSH to an environment]({{ site.baseurl }}/cloud/env/environments-ssh.html#magento-cli). To clone the project using either the {{site.data.var.ece}} CLI or Git, use the links in the field under the branch name. From 3aa32b09f923778e1fa09b715457280041982148 Mon Sep 17 00:00:00 2001 From: Vladyslav Sikailo Date: Tue, 10 May 2022 13:44:37 +0300 Subject: [PATCH 025/776] fix for 2.3 --- src/guides/v2.3/config-guide/prod/config-reference-systemxml.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.3/config-guide/prod/config-reference-systemxml.md b/src/guides/v2.3/config-guide/prod/config-reference-systemxml.md index d4158510cf8..bd078c4af22 100644 --- a/src/guides/v2.3/config-guide/prod/config-reference-systemxml.md +++ b/src/guides/v2.3/config-guide/prod/config-reference-systemxml.md @@ -281,7 +281,7 @@ A ``-Tag can have the following children: | `backend_model` | Specifies a different backend model to modify the configured values. | `typeModel` | | `source_model` | Specifies a different source model that provides a specific set of values. | `typeModel` | | `config_path` | Can be used to overwrite the generic config path of a field. | `typeConfigPath` | -| `validate` | Define different validation rules (comma separated). Full reference list of available validation rules is listed below. | `string` | +| `validate` | Define different validation rules (space separated). Full reference list of available validation rules is listed below. | `string` | | `can_be_empty` | Used when `type` is `multiselect` to specify that a field can be empty. | `int` | | `if_module_enabled` | Used to display a field only when a given module is enabled. | `typeModule` | | `base_url` | Used in combination with `upload_dir` for file uploads. | `typeUrl` | From d90bd5b45cfee4de3d39639bef04b8947767adab Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Tue, 10 May 2022 09:33:06 -0500 Subject: [PATCH 026/776] Update project-webint-basic.md --- src/cloud/project/project-webint-basic.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cloud/project/project-webint-basic.md b/src/cloud/project/project-webint-basic.md index 85595c8fc9d..b6b5e453d59 100644 --- a/src/cloud/project/project-webint-basic.md +++ b/src/cloud/project/project-webint-basic.md @@ -29,7 +29,6 @@ To access projects and environments through the Project Web Interface: 1. The left pane shows your list of environments. 1. Click **Access Site** for a list of storefront URLs for web access and the command for SSH access. - For more information about using SSH, see [SSH to an environment]({{ site.baseurl }}/cloud/env/environments-ssh.html#magento-cli). To clone the project using either the {{site.data.var.ece}} CLI or Git, use the links in the field under the branch name. The following figure shows an example. From 4234e74fdef8865fcef02bd96ec182a1d434d77d Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Tue, 10 May 2022 12:57:55 -0500 Subject: [PATCH 027/776] Update project-webint-snap.md --- src/cloud/project/project-webint-snap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cloud/project/project-webint-snap.md b/src/cloud/project/project-webint-snap.md index f278ee14f06..2fa65c34635 100644 --- a/src/cloud/project/project-webint-snap.md +++ b/src/cloud/project/project-webint-snap.md @@ -10,7 +10,7 @@ You can back up and restore specific environments at any time using a snapshot. The Pro Staging and Production environments receive regular backups for disaster recovery purposes by default, see [Pro Backup & Disaster Recovery]({{ site.baseurl }}/cloud/architecture/pro-architecture.html#backup-and-disaster-recovery). However, these backups are not publicly accessible because they are stored in a separate system. You can open a ticket to request a backup with a specific date, time, and timezone. Then we can extract it from the external system and provide it to you. {:.bs-callout-tip} -Snapshots for Starter and Pro Integration environments are different from Pro backup and disaster recovery backups. Snapshots are **not** automatic. It is _your_ responsibility to manually create a snapshot or set up a con job to periodically take snapshots of your Starter or Pro Integration environments. +Snapshots for Starter and Pro Integration environments are different from Pro backup and disaster recovery backups. Snapshots are **not** automatic. It is _your_ responsibility to manually create a snapshot or set up a cron job to periodically take snapshots of your Starter or Pro Integration environments. A _snapshot_ is a complete backup of an environment that includes all persistent data from all running services (for example, your MySQL database, Redis, and so on) and any files stored on the mounted volumes. Because an environment deploys as a read-only file system, restoring a snapshot is very fast. From 1661383fb8ce89e79d9c0b67563e8bef0c0289ef Mon Sep 17 00:00:00 2001 From: Donald Booth Date: Wed, 11 May 2022 11:39:44 -0400 Subject: [PATCH 028/776] Small tweak --- src/guides/v2.3/get-started/bk-get-started-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.3/get-started/bk-get-started-api.md b/src/guides/v2.3/get-started/bk-get-started-api.md index 38c62fb6d07..9ab01d035d4 100644 --- a/src/guides/v2.3/get-started/bk-get-started-api.md +++ b/src/guides/v2.3/get-started/bk-get-started-api.md @@ -39,7 +39,7 @@ The APIs can be used to perform a wide array of tasks. For example: * Integrate with CRM (Customer Relationship Management) or ERP (Enterprise Resource Planning) backend systems, such as Salesforce or Xero. -* Integrate with a [CMS](https://glossary.magento.com/cms) (Content Management System). Content tagging is not currently supported. +* Integrate with a [CMS](https://glossary.magento.com/cms) (Content Management System). Currently. content tagging is not supported. * Create [JavaScript](https://glossary.magento.com/javascript) widgets in the Magento [storefront](https://glossary.magento.com/storefront) or on the [Admin](https://glossary.magento.com/admin) panel. The [widget](https://glossary.magento.com/widget) makes AJAX calls to access services. From a09ef58e9464eaf78648e30e01a046d37d410b33 Mon Sep 17 00:00:00 2001 From: Andrii Poltoratskyi Date: Wed, 11 May 2022 09:32:19 -0700 Subject: [PATCH 029/776] updated version updated version for MDVA-4385,MDVA-44147 and MDVA-43451 --- src/quality-patches/release-notes.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/quality-patches/release-notes.md b/src/quality-patches/release-notes.md index 32611fdb1c5..9d1a0d3c1ca 100644 --- a/src/quality-patches/release-notes.md +++ b/src/quality-patches/release-notes.md @@ -28,8 +28,8 @@ For information about quality patches created by the Community for {{site.data.v - **MDVA-43605** _(for Adobe Commerce and Magento Open Source `>=2.3.1 <2.4.5`)_-Fixes the issue where order data returns negative values for row totals when using Rest API. - **MDVA-43102** _(for Adobe Commerce and Magento Open Source `>=2.3.1 <2.4.5`)_-Fixes the issue where the salable quantity is not updated correctly when a refund was done via REST API. - **MDVA-43178** _(for Adobe Commerce and Magento Open Source `>=2.4.3-p2 <2.4.5`)_-Fixes the issue where a customer token for a custom store cannot be retrieved in GraphQL. -- **MDVA-43859** _(for Adobe Commerce and Magento Open Source `>=1.3.0 <1.3.4`)_-Fixes the issue where the error \"No such entity with customerId =\" is logged when a deleted customer tries to log in. -- **MDVA-44147** _(for Adobe Commerce and Magento Open Source `>=1.3.1 <1.3.4`)_-Fixes the issue where a GraphQL request doesn't return Requisition Lists. +- **MDVA-43859** _(for Adobe Commerce and Magento Open Source `>=2.4.1 <2.4.5`)_-Fixes the issue where the error \"No such entity with customerId =\" is logged when a deleted customer tries to log in. +- **MDVA-44147** _(for Adobe Commerce and Magento Open Source `>=2.4.2 <2.4.5`)_-Fixes the issue where a GraphQL request doesn't return Requisition Lists. - **MDVA-44505** _(for Adobe Commerce and Magento Open Source `>=2.4.1 <2.4.3`)_-Fixes the issues where GraphQL Applying Reward Points does not update Grand Total and where store credit is applied multiple times during the order placement. - Updated patches: MDVA-29148, MDVA-36464-V5, MDVA-42584, MDVA-39993-V2. @@ -39,7 +39,7 @@ For information about quality patches created by the Community for {{site.data.v - **MDVA-39605** _(for Adobe Commerce and Magento Open Source `>=2.3.4 <2.4.5`)_-Fixes the issue where Redis cache TTL (expiration date) has a wrong value. - **MDVA-43862** _(for Adobe Commerce and Magento Open Source `>=2.3.3 <2.4.5`)_-Fixes the issue where the customer can’t update cart items because of a GraphQL UpdateCartItems mutation error. - **MDVA-43824** _(for Adobe Commerce and Magento Open Source `>=2.3.6 <=2.3.7-p3 || >=2.4.1 <2.4.5`)_-Fixes the issue where an error appears on canceling orders with a discount. -- **MDVA-43451** _(for Adobe Commerce and Magento Open Source `>=1.3.2 <1.3.4`)_-Fixes the issue where the error “The store that was requested wasn’t found. Verify the store and try again.” appears while configuring a shared catalog for a specific website. +- **MDVA-43451** _(for Adobe Commerce and Magento Open Source `>=2.4.3 <2.4.5`)_-Fixes the issue where the error “The store that was requested wasn’t found. Verify the store and try again.” appears while configuring a shared catalog for a specific website. - **MDVA-43491** _(for Adobe Commerce and Magento Open Source `>=2.3.5 <2.4.5`)_-Fixes the issue where the base image label doesn’t update when importing products for a multi-store website. - **MDVA-43601** _(for Adobe Commerce and Magento Open Source `>=2.3.0 <2.4.5`)_-Fixes the issue with missing triggers after full reindex. - **MDVA-42046** _(for Adobe Commerce and Magento Open Source `>=2.3.4 <=2.3.5-p2 || >=2.4.0 <2.4.5`)_-Fixes the issue where an incorrect value is assigned to a product attribute with a date input field while updating a product. From 2a0e80044b9d7266ce56c687f9e75aa5f5ec0b4d Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Wed, 11 May 2022 13:36:59 -0500 Subject: [PATCH 030/776] fix url --- src/guides/v2.3/config-guide/prod/config-reference-var-name.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.3/config-guide/prod/config-reference-var-name.md b/src/guides/v2.3/config-guide/prod/config-reference-var-name.md index 9465cc0932c..4f550db6c36 100644 --- a/src/guides/v2.3/config-guide/prod/config-reference-var-name.md +++ b/src/guides/v2.3/config-guide/prod/config-reference-var-name.md @@ -12,7 +12,7 @@ This topic discusses how to derive an environment variable name knowing a config You can override the value of _any_ configuration setting using environment variables; however, we recommend you maintain consistent settings using the shared configuration file, `config.php`, and the system-specific configuration file, `env.php`, as discussed in [Deployment general overview]({{ page.baseurl }}/config-guide/deployment/pipeline/). {:.bs-callout-tip} -Check out the [Configure environments]({{ page.baseurl }}/cloud/env/variables-intro.html) topic in the _Cloud_ guide for details on working with variables in {{site.data.var.ece}}. +Check out the [Configure environments]({{ site.baseurl }}/cloud/env/variables-intro.html) topic in the _Cloud_ guide for details on working with variables in {{site.data.var.ece}}. A environment variable name consists of its scope followed by its configuration path in a particular format. The following sections discuss how to determine a variable name in more detail. From 507387b0bbc72589bff641e22b2be0129dbca189 Mon Sep 17 00:00:00 2001 From: gregory-marshall Date: Wed, 11 May 2022 12:51:28 -0700 Subject: [PATCH 031/776] Added link to create a support ticket --- src/cloud/configure/setup-cron-jobs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cloud/configure/setup-cron-jobs.md b/src/cloud/configure/setup-cron-jobs.md index 04eddf28a40..50ffd748522 100644 --- a/src/cloud/configure/setup-cron-jobs.md +++ b/src/cloud/configure/setup-cron-jobs.md @@ -53,7 +53,7 @@ To review cron configuration on Pro plan environments: ``` {:.bs-callout-info} - If the `crontab -l` command returns a `Command not found` error, contact your Customer Technical Advisor (CTA) or Customer Success Manager (CSM) about enabling the auto-crons self-service configuration option on your {{site.data.var.ece}} project. + If the `crontab -l` command returns a `Command not found` error, you must submit a [Support ticket] (https://support.magento.com/hc/en-us/articles/360000913794#submit-ticket) to enable the auto-crons self-service configuration option on your {{site.data.var.ece}} project. The following example shows the crontab output for an environment that has only the default crons configuration: From 530bb68154d7c2707d50eb861f05bdfe703d04de Mon Sep 17 00:00:00 2001 From: gregory-marshall Date: Wed, 11 May 2022 14:47:53 -0700 Subject: [PATCH 032/776] Removed redundant wording --- src/cloud/architecture/pro-develop-deploy-workflow.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cloud/architecture/pro-develop-deploy-workflow.md b/src/cloud/architecture/pro-develop-deploy-workflow.md index 66699d6ffa0..ec9ae8ac46f 100644 --- a/src/cloud/architecture/pro-develop-deploy-workflow.md +++ b/src/cloud/architecture/pro-develop-deploy-workflow.md @@ -17,7 +17,7 @@ The following graphic demonstrates the Pro develop and deploy workflow, which us ## Development workflow {#develop} -The Integration environment provides a single, base integration branch containing your {{site.data.var.ece}} code. You can create one additional, environment branch. This allows for up to two active branches deployed to Platform-as-a-Service (PaaS) containers.(PaaS) containers. +The Integration environment provides a single, base integration branch containing your {{site.data.var.ece}} code. You can create one additional, environment branch. This allows for up to two active branches deployed to Platform-as-a-Service (PaaS) containers. {% include cloud/note-enhanced-integration-envs-kb.md%} From 0c67a578d3154952861ae09ee4127cca9d62d6de Mon Sep 17 00:00:00 2001 From: Daniel Del Carmen Date: Thu, 12 May 2022 17:10:35 +0200 Subject: [PATCH 033/776] Fixed composer version for latest commerce versions --- src/_data/codebase/v2_4/system-requirements.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_data/codebase/v2_4/system-requirements.yml b/src/_data/codebase/v2_4/system-requirements.yml index 8d0e0bec317..1a903583872 100644 --- a/src/_data/codebase/v2_4/system-requirements.yml +++ b/src/_data/codebase/v2_4/system-requirements.yml @@ -1,6 +1,6 @@ --- 2.4.5: - Composer: '2' + Composer: '2.1' Elasticsearch: '7.17' OpenSearch: '1.2' MariaDB: '10.4' @@ -12,7 +12,7 @@ Apache: '2.4' nginx: '1.8' 2.4.4: - Composer: '2' + Composer: '2.1' Elasticsearch: '7.16' OpenSearch: '1.2' MariaDB: '10.4' From 47f40799606121f3b6afe361df57e436196dee84 Mon Sep 17 00:00:00 2001 From: Donald Booth Date: Thu, 12 May 2022 12:41:13 -0400 Subject: [PATCH 034/776] Typo --- src/guides/v2.3/get-started/bk-get-started-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.3/get-started/bk-get-started-api.md b/src/guides/v2.3/get-started/bk-get-started-api.md index 9ab01d035d4..b0e7a1c3e28 100644 --- a/src/guides/v2.3/get-started/bk-get-started-api.md +++ b/src/guides/v2.3/get-started/bk-get-started-api.md @@ -39,7 +39,7 @@ The APIs can be used to perform a wide array of tasks. For example: * Integrate with CRM (Customer Relationship Management) or ERP (Enterprise Resource Planning) backend systems, such as Salesforce or Xero. -* Integrate with a [CMS](https://glossary.magento.com/cms) (Content Management System). Currently. content tagging is not supported. +* Integrate with a [CMS](https://glossary.magento.com/cms) (Content Management System). Currently, content tagging is not supported. * Create [JavaScript](https://glossary.magento.com/javascript) widgets in the Magento [storefront](https://glossary.magento.com/storefront) or on the [Admin](https://glossary.magento.com/admin) panel. The [widget](https://glossary.magento.com/widget) makes AJAX calls to access services. From 49f44f79d206c19a52ec3a0c3ca69fc1904c84d1 Mon Sep 17 00:00:00 2001 From: Donald Booth Date: Thu, 12 May 2022 13:13:11 -0400 Subject: [PATCH 035/776] Update src/guides/v2.3/config-guide/cli/config-cli-subcommands-mode.md Co-authored-by: hguthrie --- src/guides/v2.3/config-guide/cli/config-cli-subcommands-mode.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.3/config-guide/cli/config-cli-subcommands-mode.md b/src/guides/v2.3/config-guide/cli/config-cli-subcommands-mode.md index ddd180176b2..63ffab54472 100644 --- a/src/guides/v2.3/config-guide/cli/config-cli-subcommands-mode.md +++ b/src/guides/v2.3/config-guide/cli/config-cli-subcommands-mode.md @@ -68,7 +68,7 @@ bin/magento deploy:mode:set {mode} [-s|--skip-compilation] where: -- **`{mode}`** is required; it can be either `default`, `developer` or `production` +- **`{mode}`** is required; it can be either `default`, `developer`, or `production` - **`--skip-compilation`** is an optional parameter you can use to skip [code compilation]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-compiler.html) when you change to production mode. From f6af62d5bd31a3fce70e144bfa594bf9414bfe9c Mon Sep 17 00:00:00 2001 From: Dmytro Shevtsov Date: Thu, 12 May 2022 14:58:04 -0500 Subject: [PATCH 036/776] Update the released versions data file Add 2.4.4, 2.4.3-p2, 2.3.7-p3 Update the EOS date for 2.4.0-2.4.3 --- src/_data/core-releases.json | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/_data/core-releases.json b/src/_data/core-releases.json index d188cf40f19..3227681fb18 100644 --- a/src/_data/core-releases.json +++ b/src/_data/core-releases.json @@ -1,10 +1,26 @@ { "2.4.4-2.4.6": { - "releases": [], + "releases": [ + { + "publishedAt": "2022-04-12T14:09:01Z", + "tagName": "2.4.4", + "releaseNotes" : { + "commerce": "https://devdocs.magento.com/guides/v2.4/release-notes/commerce-2-4-4.html", + "opensource": "https://devdocs.magento.com/guides/v2.4/release-notes/open-source-2-4-4.html" + } + } + ], "end-of-support": "2024-11-??" }, "2.4.0-2.4.3": { "releases": [ + { + "publishedAt": "2022-04-12T14:08:56Z", + "tagName": "2.4.3-p2", + "releaseNotes" : { + "common": "https://devdocs.magento.com/guides/v2.4/release-notes/2-4-3-p2.html" + } + }, { "publishedAt": "2021-10-12T14:41:27Z", "tagName": "2.4.3-p1", @@ -64,14 +80,20 @@ } } ], - "end-of-support": "2022-11-??" + "end-of-support": "2022-11-28" }, "2.3": { "releases": [ + { + "publishedAt": "2022-04-12T14:08:47Z", + "tagName": "2.3.7-p3", + "releaseNotes": { + "common": "https://devdocs.magento.com/guides/v2.3/release-notes/2-3-7-p3.html" + } + }, { "publishedAt": "2021-10-12T14:41:22Z", "tagName": "2.3.7-p2", - "commerce": "", "releaseNotes" : { "common": "https://devdocs.magento.com/guides/v2.3/release-notes/2-3-7-p2.html" } From 877e2e1ecb3a3116c3ca3b2679c8740787664279 Mon Sep 17 00:00:00 2001 From: Oleksandra Marchenko Date: Thu, 12 May 2022 15:47:31 -0500 Subject: [PATCH 037/776] Update project-patch.md --- src/cloud/project/project-patch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cloud/project/project-patch.md b/src/cloud/project/project-patch.md index a91be66d3e3..feb48846137 100644 --- a/src/cloud/project/project-patch.md +++ b/src/cloud/project/project-patch.md @@ -18,7 +18,7 @@ Both packages improve the integration of all {{site.data.var.ee}} versions with {:.bs-callout-tip} You can use the [Quality Patches Tool]({{ site.baseurl }}/quality-patches/usage.html) and [{{ site.data.var.mcp-prod }}](#standalone) packages as stand-alone packages for {{ site.data.var.ce }} and {{ site.data.var.ee }} projects. We recommend using the Quality Patches Tool for non-Cloud projects. -When you deploy changes to the remote environment, `{{site.data.var.ct}}` uses {{ site.data.var.mcp-package }} and `magento/quality-patches` to check for pending patches and applies them automatically in the following order: +When you deploy changes to the remote environment, `{{site.data.var.ct}}` uses `{{ site.data.var.mcp-package }}` and `magento/quality-patches` to check for pending patches and applies them automatically in the following order: 1. Apply all required Magento patches included in the {{ site.data.var.mcp-prod }} package. 1. Apply selected optional Magento patches included in the Quality Patches Tool. From ee6f62b1b12c4daf638deaa1a934b49576a1f04d Mon Sep 17 00:00:00 2001 From: Barny Shergold Date: Mon, 16 May 2022 11:01:23 +0100 Subject: [PATCH 038/776] Corrected blog link on release index --- src/release/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/release/index.md b/src/release/index.md index 6847af4905d..395f84ea78a 100644 --- a/src/release/index.md +++ b/src/release/index.md @@ -27,7 +27,7 @@ The following table provides the dates for scheduled releases (dates are subject Patch and Security Patch Releases are opportunities to upgrade the core codebase to keep your platform secure, reliable, and performant. Feature Releases occur every other month. Feature Releases are independent of the core codebase and are available through external module or extension. Any updates to existing independent features will also be released during Feature Release periods and will happen automatically if the feature is already implemented. {:.bs-callout-info} -We have introduced a [new policy](https://www.adobe.com/content/dam/cc/en/legal/terms/enterprise/pdfs/Adobe-Commerce-Software-Lifecycle-Policy.pdf) that applies to our supported release lines. To learn more about the new strategy behind our 2022 release calendar and lifecycle policy, visit our [blog](https://magento.com/blog/accelerating-innovation-through-simplified-release-strategy). +We have introduced a [new policy](https://www.adobe.com/content/dam/cc/en/legal/terms/enterprise/pdfs/Adobe-Commerce-Software-Lifecycle-Policy.pdf) that applies to our supported release lines. To learn more about the new strategy behind our 2022 release calendar and lifecycle policy, visit our [blog](https://business.adobe.com/blog/how-to/accelerating-innovation-through-simplified-release-strategy). ## Early access From bce0d6713d16a0654bf069c9d29ebffbe3945c2c Mon Sep 17 00:00:00 2001 From: magedocs Date: Mon, 16 May 2022 14:38:46 +0000 Subject: [PATCH 039/776] Update News data --- src/_data/whats-new.yml | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/_data/whats-new.yml b/src/_data/whats-new.yml index ac96832ea0e..ac3d642c9ff 100644 --- a/src/_data/whats-new.yml +++ b/src/_data/whats-new.yml @@ -4,8 +4,35 @@ description: This page contains recent changes that we think you'd like to know We exclude from this list proofreading, spelling checks, and all minor updates. link: "/whats-new.html" thread: "/whatsnew-feed.xml" -updated: Mon May 9 14:38:42 2022 +updated: Mon May 16 14:38:43 2022 entries: +- description: Update the [Released versions](https://devdocs.magento.com/release/released-versions.html) + topic:
- Add 2.4.4, 2.4.3-p2, 2.3.7-p3
- Update the end of support date + for 2.4.0-2.4.3 + versions: 2.3.x, 2.4.x + type: Technical + date: May 12, 2022 + link: https://github.com/magento-commerce/devdocs/pull/2958 + merge_commit: 7231798ae6bd3bfc1ad8b524e97d4b3b318fb1dd + contributor: dshevtsov + membership: true + labels: + - 2.3.x + - Technical + - 2.4.x +- description: Published [release notes](https://devdocs.magento.com/quality-patches/release-notes.html) + for the 1.1.14 Quality Patches Tool (QPT) package release. + versions: 2.3.x, 2.4.x + type: Major Update + date: May 10, 2022 + link: https://github.com/magento-commerce/devdocs/pull/2952 + merge_commit: 9e683d39d04237019f5f0ebb581b83b5c59a416b + contributor: apoltoratskyi + membership: true + labels: + - Major Update + - 2.3.x + - 2.4.x - description: Added a tutorial on [creating a bundled product](https://devdocs.magento.com/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.html) with the API. versions: 2.3.x, 2.4.x From a5ac453fc742d868e33f1923a25daba6c4769e6e Mon Sep 17 00:00:00 2001 From: Shrie Spangler Date: Tue, 17 May 2022 10:15:26 -0500 Subject: [PATCH 040/776] Add Pay Services info to Availability topic --- src/release/availability.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/release/availability.md b/src/release/availability.md index 56e9a02785d..6c69fdf2cde 100644 --- a/src/release/availability.md +++ b/src/release/availability.md @@ -10,6 +10,7 @@ The following table describes the status of Adobe Commerce software availability | **{{site.data.var.ee}} 2.4.4** | Available now | [Composer]({{ site.baseurl }}{{ site.gdeurl }}/install-gde/composer.html) | | **{{site.data.var.ece}} Tools (aka ECE-Tools)** | Available now | [Composer]({{ site.baseurl }}/cloud/project/ece-tools-update.html) | | **Live Search** | Available now | [Commerce Marketplace](https://marketplace.magento.com/magento-live-search.html) \| [Developer Documentation]({{ site.baseurl }}/live-search/overview.html) \| [Release Notes](https://docs.magento.com/user-guide/live-search/release-notes.html) \| [User Guide](https://docs.magento.com/user-guide/live-search/overview.html) | +| **Payment Services** | Available now | [Commerce Marketplace](https://marketplace.magento.com/magento-payment-services.html) \| [Release Notes](https://experienceleague.adobe.com/docs/commerce-merchant-services/payment-services/release-notes.html) \| [User Guide](https://experienceleague.adobe.com/docs/commerce-merchant-services/payment-services/guide-overview.html) | | **Product Recommendations** | Available now | [Commerce Marketplace](https://marketplace.magento.com/magento-product-recommendations.html) \| [Developer Documentation]({{ site.baseurl }}/recommendations/product-recs.html) \| [Release Notes]({{ site.baseurl }}/recommendations/release-notes.html) \| [User Guide](https://docs.magento.com/m2/ee/user_guide/marketing/product-recommendations.html) | | **PWA Studio** | Available now | [Documentation](http://pwastudio.io) and [GitHub](https://github.com/magento-research/pwa-studio) | | **Amazon Sales Channel 4.4.1** | Available now for {{site.data.var.ee}} versions 2.4.x and 2.3.x (US, Canada, Mexico, and UK) | [Commerce Marketplace](https://marketplace.magento.com/magento-module-amazon.html) \| [Release Notes]({{ site.baseurl }}/extensions/amazon-sales/release-notes) \| [User Guide]({{ site.user_guide_url }}/sales-channels/asc/amazon-sales-channel.html) | From 3a9c22fb739fa2cb9ca23125db574bbd97958858 Mon Sep 17 00:00:00 2001 From: Shrie Spangler Date: Tue, 17 May 2022 10:51:35 -0500 Subject: [PATCH 041/776] Add Pay Services versioning to mde.yml --- src/_data/mde.yml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/_data/mde.yml b/src/_data/mde.yml index 886d003aff2..0b238a3c58c 100644 --- a/src/_data/mde.yml +++ b/src/_data/mde.yml @@ -876,6 +876,41 @@ extensions: 2.3.2: not supported 2.3.1: supported 2.3.0: compatible + - + name: Payment Services + versions: + - + name: 1.1.0 + support: + 2.4.4: supported + 2.4.3: supported + 2.4.2: supported + 2.4.1: supported + 2.4.0: supported + 2.3.7: not supported + 2.3.6: not supported + 2.3.5-p1: not supported + 2.3.4: not supported + 2.3.3: not supported + 2.3.2: supported + 2.3.1: not supported + 2.3.0: not supported + - + name: 1.0.0 + support: + 2.4.4: supported + 2.4.3: supported + 2.4.2: supported + 2.4.1: supported + 2.4.0: supported + 2.3.7: not supported + 2.3.6: not supported + 2.3.5-p1: not supported + 2.3.4: not supported + 2.3.3: not supported + 2.3.2: not supported + 2.3.1: not supported + 2.3.0: not supported - name: Product Recommendations versions: From db1122c31b7765e7ed6a95a53efc0f83402fe642 Mon Sep 17 00:00:00 2001 From: gregory-marshall Date: Tue, 17 May 2022 09:19:17 -0700 Subject: [PATCH 042/776] Fixed broken link to support --- src/cloud/configure/setup-cron-jobs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cloud/configure/setup-cron-jobs.md b/src/cloud/configure/setup-cron-jobs.md index 50ffd748522..747d2923b89 100644 --- a/src/cloud/configure/setup-cron-jobs.md +++ b/src/cloud/configure/setup-cron-jobs.md @@ -53,7 +53,7 @@ To review cron configuration on Pro plan environments: ``` {:.bs-callout-info} - If the `crontab -l` command returns a `Command not found` error, you must submit a [Support ticket] (https://support.magento.com/hc/en-us/articles/360000913794#submit-ticket) to enable the auto-crons self-service configuration option on your {{site.data.var.ece}} project. + If the `crontab -l` command returns a `Command not found` error, you must submit a [Support ticket](https://support.magento.com/hc/en-us/articles/360000913794#submit-ticket) to enable the auto-crons self-service configuration option on your {{site.data.var.ece}} project. The following example shows the crontab output for an environment that has only the default crons configuration: @@ -120,7 +120,7 @@ The default cron interval for all environments provisioned in the US-3, EU-3, an ### Prerequisite -On {{ site.data.var.ee }} Pro projects, the [auto-crons feature](#verify-cron-configuration-on-pro-projects) must be enabled on your {{site.data.var.ece}} project before you can add custom cron jobs to Staging and Production environments using `.magento.app.yaml`. If this feature is not enabled, contact your Customer Technical Advisor (CTA). +On {{ site.data.var.ee }} Pro projects, the [auto-crons feature](#verify-cron-configuration-on-pro-projects) must be enabled on your {{site.data.var.ece}} project before you can add custom cron jobs to Staging and Production environments using `.magento.app.yaml`. If this feature is not enabled, submit a [Support ticket](https://support.magento.com/hc/en-us/articles/360000913794#submit-ticket) to enable auto-crons. {:.procedure} To add custom crons: From 3443d50003cca8489dadb9f188db00797981e522 Mon Sep 17 00:00:00 2001 From: Shrie Spangler Date: Tue, 17 May 2022 12:05:52 -0500 Subject: [PATCH 043/776] Fix availability calendar error --- src/_data/mde.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_data/mde.yml b/src/_data/mde.yml index 0b238a3c58c..7cafda503c5 100644 --- a/src/_data/mde.yml +++ b/src/_data/mde.yml @@ -892,7 +892,7 @@ extensions: 2.3.5-p1: not supported 2.3.4: not supported 2.3.3: not supported - 2.3.2: supported + 2.3.2: not supported 2.3.1: not supported 2.3.0: not supported - From 57708ce8a45e3b3102a6afd43be8340df3650ebf Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 17 May 2022 14:58:59 -0500 Subject: [PATCH 044/776] Replaced symlinks for 2.4 --- .../archi_perspectives/ABasics_intro.md | 24 ++- .../archi_perspectives/ALayers_intro.md | 37 +++- .../archi_perspectives/arch_diagrams.md | 22 ++- .../components/AComponents.md | 21 ++- .../components/modules/mod_depend.md | 173 +++++++++++++++++- .../components/modules/mod_relationships.md | 53 +++++- .../archi_perspectives/domain_layer.md | 46 ++++- .../archi_perspectives/framework.md | 85 ++++++++- .../archi_perspectives/persist_layer.md | 39 +++- .../archi_perspectives/present_layer.md | 85 ++++++++- .../archi_perspectives/service_layer.md | 81 +++++++- .../archi_perspectives/tech-vision.md | 16 +- .../archi_perspectives/third-party-libs.md | 12 +- .../archi_perspectives/webapi-vision.md | 117 +++++++++++- .../v2.4/architecture/bk-architecture.md | 14 +- src/guides/v2.4/architecture/extensibility.md | 117 +++++++++++- .../global_extensibility_features.md | 95 +++++++++- .../v2.4/architecture/security_intro.md | 49 ++++- .../architecture/storefront_customization.md | 42 ++++- 19 files changed, 1109 insertions(+), 19 deletions(-) mode change 120000 => 100644 src/guides/v2.4/architecture/archi_perspectives/ABasics_intro.md mode change 120000 => 100644 src/guides/v2.4/architecture/archi_perspectives/ALayers_intro.md mode change 120000 => 100644 src/guides/v2.4/architecture/archi_perspectives/arch_diagrams.md mode change 120000 => 100644 src/guides/v2.4/architecture/archi_perspectives/components/AComponents.md mode change 120000 => 100644 src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_depend.md mode change 120000 => 100644 src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_relationships.md mode change 120000 => 100644 src/guides/v2.4/architecture/archi_perspectives/domain_layer.md mode change 120000 => 100644 src/guides/v2.4/architecture/archi_perspectives/framework.md mode change 120000 => 100644 src/guides/v2.4/architecture/archi_perspectives/persist_layer.md mode change 120000 => 100644 src/guides/v2.4/architecture/archi_perspectives/present_layer.md mode change 120000 => 100644 src/guides/v2.4/architecture/archi_perspectives/service_layer.md mode change 120000 => 100644 src/guides/v2.4/architecture/archi_perspectives/tech-vision.md mode change 120000 => 100644 src/guides/v2.4/architecture/archi_perspectives/third-party-libs.md mode change 120000 => 100644 src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md mode change 120000 => 100644 src/guides/v2.4/architecture/bk-architecture.md mode change 120000 => 100644 src/guides/v2.4/architecture/extensibility.md mode change 120000 => 100644 src/guides/v2.4/architecture/global_extensibility_features.md mode change 120000 => 100644 src/guides/v2.4/architecture/security_intro.md mode change 120000 => 100644 src/guides/v2.4/architecture/storefront_customization.md diff --git a/src/guides/v2.4/architecture/archi_perspectives/ABasics_intro.md b/src/guides/v2.4/architecture/archi_perspectives/ABasics_intro.md deleted file mode 120000 index 61e90476769..00000000000 --- a/src/guides/v2.4/architecture/archi_perspectives/ABasics_intro.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/architecture/archi_perspectives/ABasics_intro.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/archi_perspectives/ABasics_intro.md b/src/guides/v2.4/architecture/archi_perspectives/ABasics_intro.md new file mode 100644 index 00000000000..5da43782d09 --- /dev/null +++ b/src/guides/v2.4/architecture/archi_perspectives/ABasics_intro.md @@ -0,0 +1,23 @@ +--- +group: architecture-guide +title: Architectural basics overview +menu_title: Architectural basics +--- + +Magento incorporates the core architectural principles of object-oriented, PHP-based applications. Comprehensive discussions of these general principles exist both on-line and in printed form. + +The following discussion focuses on how these topics apply directly to Magento: + +* [Magento technology stack]({{page.baseurl}}/install-gde/system-requirements.html) +* [Magento View Model]({{page.baseurl}}/extension-dev-guide/view-models.html) +* [Extensibility]({{page.baseurl}}/architecture/extensibility.html) +* [Modularity]({{page.baseurl}}/architecture/extensibility.html#modularity) +* [Event-driven architecture]({{page.baseurl}}/extension-dev-guide/events-and-observers.html) +* [Security]({{page.baseurl}}/architecture/security_intro.html) + +{:.ref-header} +Related topics + +[Architectural diagrams]({{page.baseurl}}/architecture/archi_perspectives/arch_diagrams.html) + +[Versioning]({{page.baseurl}}/extension-dev-guide/versioning/) diff --git a/src/guides/v2.4/architecture/archi_perspectives/ALayers_intro.md b/src/guides/v2.4/architecture/archi_perspectives/ALayers_intro.md deleted file mode 120000 index a049ac06cdf..00000000000 --- a/src/guides/v2.4/architecture/archi_perspectives/ALayers_intro.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/architecture/archi_perspectives/ALayers_intro.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/archi_perspectives/ALayers_intro.md b/src/guides/v2.4/architecture/archi_perspectives/ALayers_intro.md new file mode 100644 index 00000000000..895b8d769da --- /dev/null +++ b/src/guides/v2.4/architecture/archi_perspectives/ALayers_intro.md @@ -0,0 +1,36 @@ +--- +group: architecture-guide +title: Architectural layers overview +menu_title: Architectural layers +--- + +## Magento as layered software + +At its highest level, Magento's product architecture consists of the core product code plus optional *modules*. These optional modules enhance or replace the basic product code. + +If you are substantially customizing the basic Magento product, [module](https://glossary.magento.com/module) development will be your central focus. Modules organize code that supports a particular task or feature. A module can include code to change the look-and-feel of your [storefront](https://glossary.magento.com/storefront) as well as its fundamental behavior. + +Your modules function with the core Magento product code, which is organized into layers. Understanding layered software pattern is essential for understanding basic Magento product organization. + +Layered software is a popular, widely discussed principle in software development. Many resources exist for this topic, but consider consulting Pattern-Oriented Software Architecture for a general discussion. + +## Advantages of layered application design + +Layered application design offers many advantages, but users of Magento will appreciate: + +* Stringent separation of business logic from presentation logic simplifies the customization process. For example, you can alter your storefront appearance without affecting any of the [backend](https://glossary.magento.com/backend) business logic. + +* Clear organization of code predictably points [extension](https://glossary.magento.com/extension) developers to code location. + +{:.ref-header} +Related topics + +[Architectural diagrams]({{page.baseurl}}/architecture/archi_perspectives/arch_diagrams.html) + +[Presentation layer]({{page.baseurl}}/architecture/archi_perspectives/present_layer.html) + +[Service layer]({{page.baseurl}}/architecture/archi_perspectives/service_layer.html) + +[Domain layer]({{page.baseurl}}/architecture/archi_perspectives/domain_layer.html) + +[Persistence layer]({{page.baseurl}}/architecture/archi_perspectives/persist_layer.html) diff --git a/src/guides/v2.4/architecture/archi_perspectives/arch_diagrams.md b/src/guides/v2.4/architecture/archi_perspectives/arch_diagrams.md deleted file mode 120000 index ea447a28b0a..00000000000 --- a/src/guides/v2.4/architecture/archi_perspectives/arch_diagrams.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/architecture/archi_perspectives/arch_diagrams.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/archi_perspectives/arch_diagrams.md b/src/guides/v2.4/architecture/archi_perspectives/arch_diagrams.md new file mode 100644 index 00000000000..05644e6e750 --- /dev/null +++ b/src/guides/v2.4/architecture/archi_perspectives/arch_diagrams.md @@ -0,0 +1,21 @@ +--- +group: architecture-guide +title: Architectural diagrams +menu_title: Architectural diagrams +--- + +## Magento architecture from different perspectives {#m2arch-whatis-overview} + +Depending upon your role and purpose for learning more about Magento, there are several different ways to view the Magento architecture. For example, a developer who wants to create new modules or perhaps customize an existing [module](https://glossary.magento.com/module) will want to understand the architecture of a module itself, and how it fits into the larger view, with the Magento framework and other components. However, a merchant who wants to quickly build an online storefront wants to view the collection of components from a higher level, and understand the components that impact the look, feel, and user interaction components. + +## Architecture layers diagram {#archi-layers} + +The following diagram illustrates the components and shows the "layers" or tiers in Magento. + +![Architectural Diagram]({{site.baseurl}}/common/images/archi_diagram_desired-state.png) + +{:.ref-header} +Related topics + +- [Architecture layers overview]({{page.baseurl}}/architecture/archi_perspectives/ALayers_intro.html) +- [Service Isolation](https://github.com/magento/architecture/blob/master/design-documents/service-isolation.md) diff --git a/src/guides/v2.4/architecture/archi_perspectives/components/AComponents.md b/src/guides/v2.4/architecture/archi_perspectives/components/AComponents.md deleted file mode 120000 index 5078c40bb8d..00000000000 --- a/src/guides/v2.4/architecture/archi_perspectives/components/AComponents.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/architecture/archi_perspectives/components/AComponents.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/archi_perspectives/components/AComponents.md b/src/guides/v2.4/architecture/archi_perspectives/components/AComponents.md new file mode 100644 index 00000000000..cd2e976ed2d --- /dev/null +++ b/src/guides/v2.4/architecture/archi_perspectives/components/AComponents.md @@ -0,0 +1,20 @@ +--- +group: architecture-guide +title: Magento Components +menu_title: Components +--- + +## Magento components + +Magento has several core components that are used to build custom websites, applications, and integrated systems. When you change the appearance or behavior of your Magento store, you are inevitably changing one or more of these **core Magento components**, which include **modules**, **themes**, and **language packages**. Together, these core components determine much of server-side and [storefront](https://glossary.magento.com/storefront) (frontend) appearance and behavior. + +{:.bs-callout-tip} +Throughout the Magento documentation set, we also use the term *component* in its generic sense to mean element or part. However, the term **Magento component** explicitly refers to either a module, theme, or [language package](https://glossary.magento.com/language-package). + +For more information about individual Magento components, see: + +* [Modules]({{page.baseurl}}/architecture/archi_perspectives/components/modules/mod_intro.html) + +* [Themes]({{page.baseurl}}/frontend-dev-guide/themes/theme-overview.html) + +* [Language packages]({{page.baseurl}}/frontend-dev-guide/translations/xlate.html#m2devgde-xlate-languagepack) diff --git a/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_depend.md b/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_depend.md deleted file mode 120000 index cd6e0b10fa5..00000000000 --- a/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_depend.md +++ /dev/null @@ -1 +0,0 @@ -../../../../../v2.3/architecture/archi_perspectives/components/modules/mod_depend.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_depend.md b/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_depend.md new file mode 100644 index 00000000000..bb3c5872c02 --- /dev/null +++ b/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_depend.md @@ -0,0 +1,172 @@ +--- +group: architecture-guide +title: Module dependencies +menu_title: Module dependencies +--- + +## Overview {#m2devgde-moddep-intro} + +A *software dependency* identifies one software component's reliance on another for proper functioning. A core principle of Magento architecture is the **minimization of software dependencies**. Instead of being closely interrelated with other modules, modules are optimally designed to be *loosely coupled*. Loosely coupled modules require little or no knowledge of other modules to perform their tasks. + +Each Magento [module](https://glossary.magento.com/module) is responsible for a unique feature. In practice, this means that: + +* Several modules cannot be responsible for one feature. + +* One module cannot be responsible for several features. + +* Module dependencies on other modules must be declared explicitly. You must also declare any dependency upon other components (for example, a theme, language package, or library). + +* Removing or disabling a module does not result in disabling other modules. + +## Two types of dependencies {#m2devgde-moddep-declare-dep} + +There are two types of Magento [module](https://glossary.magento.com/module) dependencies: hard and soft. + +### Hard dependencies + +A module with a *hard dependency* on another module cannot function without the module it depends on. These modules: + +* Contain code that directly uses logic from another module, such as class constants, static methods, public class properties, interfaces, and traits. +* Contain strings that include class names, method names, class constants, class properties, interfaces, and traits from another module. +* Deserializes an object declared in another module. +* Uses or modifies the database tables used by another module. + +The `require` section of `app/code///composer.json` file contains hard dependency definitions for the module. For example: + +```json + ... + "require": { + "magento/module-catalog": "103.0.*", + "magento/module-email": "101.0.*", + "magento/module-media-storage": "100.3.*", + "magento/module-store": "101.0.*", + "magento/module-theme": "101.0.*", + "magento/module-ui": "101.1.*", + "magento/module-variable": "100.3.*", + "magento/module-widget": "101.1.*", + "magento/module-authorization": "100.3.*" + } + ... +``` + +### Soft dependencies + +A module with a *soft dependency* on another module can function properly without the other module, even if it has a dependency on the other module. These modules: + +* Directly check another module's availability. +* Extend another module's configuration. +* Extend another module's [layout](https://glossary.magento.com/layout). + +The `suggest` section of `app/code///composer.json` file contains soft dependency definitions for the module. For example: + +```json + ... + "suggest": { + "magento/module-graph-ql": "*", + "magento/module-graph-ql-cache": "*", + "magento/module-store-graph-ql": "*" + } + ... +``` + +The `` node of `app/code///etc/module.xml` file also contains soft dependency definitions for the module. For example: + +```xml + + + + + + + +``` + +{:.bs-callout-tip} +If a module uses code from another module, it should declare the dependency explicitly. + +## Module install order + +Magento installs modules in the following order: + +1. The module serving as a dependency for another module +1. The module dependent on it + +## Appropriate dependencies + +Although Magento architecture favors loosely coupled software components, modules can contain dependencies upon these software components: + +* other modules + +* [PHP](https://glossary.magento.com/php) extensions + +* libraries (either Magento Framework [library](https://glossary.magento.com/library) or third party libraries) + +{:.bs-callout-tip} +Note: You can lose the historical information contained in a module if the module is removed or disabled. We recommend alternative storage of module information before you remove or disable a module. + +## Inappropriate dependencies {#m2devgde-moddep-inapp-dep} + +Avoid creating these dependencies: + +* Circular (both direct and indirect) +* Undeclared +* Incorrect + +## Dependencies between modules in different presentation layers {#m2devgde-moddep-diff-layer} + +You can build dependencies between the modules belonging to different layers. + +## Dependencies in the Framework layer {#m2devgde-moddep-frmwk-layer} + +A module belonging to the Magento Framework can be used in the application layer by an explicit dependency. + +{:.bs-callout-tip} +In this case, using interfaces is preferable to using classes. You can build dependencies between classes in the Magento Framework even if they belong to different modules. + +## Dependencies in the application layer {#m2devgde-moddep-app-layer} + +A module belonging to the application layer cannot be used in the Magento Framework. + +You can build dependencies between classes in the application layer, but these classes must belong to the same module. Dependencies between the modules of the application layer should be built only by the [service contract](https://glossary.magento.com/service-contract) or the service provider interface (SPI). + +## Managing module dependencies + +At a high level, there are three main steps for managing module dependencies: + +1. Name and declare the module in the `module.xml` file. + +1. Declare any dependencies that the module has (whether on other modules or on a different component) in the module's `composer.json` file. + +1. (*Optional*) Define the desired load order of config files and `.css` files in the `module.xml` file. + +Example: Module A declares a dependency upon Module B. Thus, in Module A's `module.xml` file, Module B is listed in the `` list, so that B's files are loaded before A's. Additionally, you must declare a dependency upon Module B in A's `composer.json` file. Furthermore, in the [deployment configuration]({{page.baseurl}}/config-guide/config/config-php.html), Modules A and B must both be defined as enabled. + +`etc/module.xml` + +```xml + + + + + + + +``` + +After installing the module and opening `app/etc/config.php`, you are able to see that the Module_B was loaded before Module_A: + +```php +return [ + 'modules' => [ + ... + 'Module_B' => 1, + 'Module_A' => 1, + ... + ] +]; +``` + +{:.ref-header} +Related topics + +[Module overview]({{page.baseurl}}/architecture/archi_perspectives/components/modules/mod_intro.html) diff --git a/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_relationships.md b/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_relationships.md deleted file mode 120000 index fce4636fa1b..00000000000 --- a/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_relationships.md +++ /dev/null @@ -1 +0,0 @@ -../../../../../v2.3/architecture/archi_perspectives/components/modules/mod_relationships.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_relationships.md b/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_relationships.md new file mode 100644 index 00000000000..42d3d12491d --- /dev/null +++ b/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_relationships.md @@ -0,0 +1,52 @@ +--- +group: architecture-guide +title: Module relationships +menu_title: Module relationships +--- + +## Overview {#m2arch-module-relationships-overview} + +Understanding how one [module](https://glossary.magento.com/module) relates to another helps determine how it reacts to changes in that module. + +A single module can have the following types of relationships with another module: + +* **uses**: module A uses module B if it invokes behavior of module B + +* **reacts to**: module A reacts to module B if its behavior is triggered by an [event](https://glossary.magento.com/event) in module B without module B knowing about module A + +* **customizes**: module A customizes module B if it modifies the behavior of module B + +* **implements**: module A implements module B if it implements some, not necessarily all, behavior that is defined in module B + +* **replaces**: module A replaces module B if it provides its own version of the [API](https://glossary.magento.com/api) exposed and implemented by module B + +## Relationship types and scenarios + +### A uses B, C customizes B + +In a scenario where module A uses module B and module C customizes module B, the customizations in module C must not break the API of module B so that module A still functions properly in the face of these customizations. + +![Module relationship scenarios: A uses B, C customizes B]({{site.baseurl}}/common/images/archi_first_relate.png) + +### A reacts to B, C customizes B + +Similarly, in a case where module A reacts to module B and module C customizes module B, the customizations in module C must not interfere with the events in module B that module A depends on. + +![Module relationship scenarios: A reacts to B, C customizes B]({{site.baseurl}}/common/images/archi_second_relate.png) + +### A and C customize B + +If both module A and C customize module B, be careful about how these customizations are implemented so that you avoid conflicts (see below). + +![Module relationship scenarios: A and C customize B]({{site.baseurl}}/common/images/archi_third_relate.png) + +### A replaces B + +If module A replaces module B, it needs to be able to do so in such a way that other modules are not affected. That will mean not having direct hard dependencies on module B, but rather dependencies on a third module, module C, that both module A and B implement. + +![Module relationship scenarios: A replaces B]({{site.baseurl}}/common/images/archi_fourth_relate.png) + +{:.ref-header} +Related topics + +[Module overview]({{page.baseurl}}/architecture/archi_perspectives/components/modules/mod_intro.html) \ No newline at end of file diff --git a/src/guides/v2.4/architecture/archi_perspectives/domain_layer.md b/src/guides/v2.4/architecture/archi_perspectives/domain_layer.md deleted file mode 120000 index f1079abe29f..00000000000 --- a/src/guides/v2.4/architecture/archi_perspectives/domain_layer.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/architecture/archi_perspectives/domain_layer.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/archi_perspectives/domain_layer.md b/src/guides/v2.4/architecture/archi_perspectives/domain_layer.md new file mode 100644 index 00000000000..9f0aead80d0 --- /dev/null +++ b/src/guides/v2.4/architecture/archi_perspectives/domain_layer.md @@ -0,0 +1,45 @@ +--- +group: architecture-guide +title: Domain layer +menu_title: Domain layer +--- + +## The Magento Domain layer + +The domain layer holds the business logic layer of a Magento [module](https://glossary.magento.com/module). It typically does not contain resource-specific or database-specific information. Its primary functions include: + +* Defining the generic Magento data objects, or models, that contain business logic. This logic defines which operations can be performed on particular types of data, such as a Customer object. These models contain generic information only. Applications can also use SOAP or RESTful endpoints to request data from models. + +* (Optionally) Including the implementation of service contracts, although not their definition. + +{:.bs-callout-tip} +**Best practice:** Use service contracts to communicate with the domain layer by passing data types through strongly typed objects. This helps you avoid the need to replace presentation layer code when replacing business layer logic. + +## Models + +Each domain-layer model contains a reference to a resource model, which it uses to retrieve data from the database with MySql calls. This resource model contains logic for connecting to the underlying database, typically MySQL. A model requires a resource model only if the model data must persist. + +## Accessing the domain layer + +There are three primary ways of accessing a module's domain-layer code: + +* Service contracts are the recommended way for one module to access another module's domain-level code. This loosely coupled solution is the optimal way for most modules to access another module. + +* A module can directly call into another module. This tightly coupled solution is not recommended for most situations, but is sometimes unavoidable. + +* Domain layer code in one module can also plug itself into another module by: + + * event hooks + + * plugins + + * `di.xml` files (with an SPI contract) + +Your strategy for calling another module's domain-layer code is highly dependent upon the unique configuration and needs of your system. + +{:.ref-header} +Related topics + +[Architectural diagrams]({{page.baseurl}}/architecture/archi_perspectives/arch_diagrams.html) + +[Architectural layers overview]({{page.baseurl}}/architecture/archi_perspectives/ALayers_intro.html) diff --git a/src/guides/v2.4/architecture/archi_perspectives/framework.md b/src/guides/v2.4/architecture/archi_perspectives/framework.md deleted file mode 120000 index baddb037c3d..00000000000 --- a/src/guides/v2.4/architecture/archi_perspectives/framework.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/architecture/archi_perspectives/framework.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/archi_perspectives/framework.md b/src/guides/v2.4/architecture/archi_perspectives/framework.md new file mode 100644 index 00000000000..4aa1bd994a1 --- /dev/null +++ b/src/guides/v2.4/architecture/archi_perspectives/framework.md @@ -0,0 +1,84 @@ +--- +group: architecture-guide +title: Commerce and Magento Framework +--- + +## Overview + +The Magento Framework controls how application components interact, including request flow, routing, indexing, caching, and [exception](https://glossary.magento.com/exception) handling. It provides services that reduce the effort of creating modules that contain business logic, contributing to the goal of both making Magento code more modular as well as decreasing dependencies. + +This primarily [PHP](https://glossary.magento.com/php) software component is organized into logical groups called *libraries*, which all modules can call. Most of the framework code sits under the domain layer or encloses the presentation, service, and domain layers. The framework contains no business logic. +(Although the Magento Framework does not contain resource models, it does contain a [library](https://glossary.magento.com/library) of code to help implement a resource model.) + +{:.bs-callout-tip} +Don't confuse the Magento Framework with the Zend web application framework that ships with Magento. + +You should never modify Framework files, although if you are extending Magento, you must know how to call Framework libraries. Modules you create will typically inherit from classes and interfaces defined in the Framework directories. + +## Responsibilities + +The Magento Framework provides libraries that help reduce the effort of creating modules that contain business logic. + +The Framework is responsible for operations that are useful for potentially all modules, including: + +* handling HTTP protocols + +* interacting with the database and filesystem + +* rendering content + +## Organization + +Here is the Magento Framework folder structure: + +```tree +vendor/ + ../magento + ../framework +lib/ + ../internal + ../LinLibertineFont + ../web +``` + +* `/vendor/magento/framework` contains only PHP code. These are libraries of code plus the application entry point that routes requests to modules (that in turn call the Framework libraries). For example, libraries in the Framework help implement a resource model (base classes and interfaces to inherit from) but not the resource models themselves. Certain libraries also support [CSS](https://glossary.magento.com/css) rendering. + +* `/lib/internal` contains some non-PHP as well as PHP components. Non-PHP framework libraries includes [JavaScript](https://glossary.magento.com/javascript) and LESS/CSS. + +* `/lib/web` contains JavaScript and CSS/LESS files. These files reside under `web` and not `internal` because they are accessible from a web browser, while the PHP code under `internal` is not. (Any code that a web browser must access should be under `web`, while everything else under `internal`.) + +{:.bs-callout-tip} +The `vendor/magento/framework` directory maps to the `Magento\Framework` [namespace](https://glossary.magento.com/namespace). + +## Highlights of Magento Framework + +The Magento Framework (`lib/internal/Magento/Framework/`) provides a robust range of functionality. If you are an [extension](https://glossary.magento.com/extension) developer, you may be interested in this subset of Framework namespaces. + +|Namespace|Purpose| +|--- |--- | +|`Magento\Framework\DataObject`|Provides standard functionality for storing and retrieving data through magic methods. This is the base class for many Magento classes.| +|`Magento\Framework\Model`|Contains base Model classes that almost all Magento Model classes extend from.| +|`Magento\Framework\Model\AbstractModel`|| +|`Magento\Framework\Model\ResourceModel\AbstractResource`|| +|`Magento\Framework\Controller`|Contains classes to help return different types of results (for example, JSON and redirects).| +|`Magento\Framework\View`|Contains code to render pages and layouts.| +|`Magento\Framework\Data`|Contains additional classes that handle forms.| +|`Magento\Framework\Url`|Contains code to look up other pages in Magento.| +{:style="table-layout:auto"} + +Other namespaces under `Magento\Framework` that will interest extension developers: + +|Namespace|Purpose| +|--- |--- | +|`Magento\Framework\ObjectManager`|Used to provide dependency injection.| +|`Magento\Framework\App`|Contains framework code that has knowledge about the Magento application. This code bootstraps the application and reads in the initial configuration. It also contains the entry point to the command line tools, the web application, and the cron job. And finally, it routes requests while providing the deployment context (such as reading in the configuration for the database configuration, languages, and caching systems).| +|`Magento\Framework\Api`|Contains base classes for advanced functionality of extendable objects through the system (that is, objects that can be extended to add new data through Commerce Marketplace extensions).| +|`Magento\Framework\Config`|Contains the generic configuration reader. Each config file has its own specialized reader extending these classes.| +|`Magento\Framework\Filesystem`|Contains classes that handle reading from and writing to the file system.| +|`Magento\Framework\HTTP\PhpEnvironment`|| +|`Magento\Framework\Session`|| +|`Magento\Framework\Stdlib\Cookie`|Code to handle the HTTP request/responses as well as session/cookies is found here.| +|`Magento\Framework\Exception`|Contains the basic exceptions that are thrown throughout the Magento codebase.| +|`Magento\Framework\Event`|Contains the code that publishes synchronous events and that handles observers for any Magento event is handled here.| +|`Magento\Framework\Validator`|Contains the code that validates data (currencies, not empty) and that handles observers for any Magento event.| +{:style="table-layout:auto"} diff --git a/src/guides/v2.4/architecture/archi_perspectives/persist_layer.md b/src/guides/v2.4/architecture/archi_perspectives/persist_layer.md deleted file mode 120000 index 947d0da76b7..00000000000 --- a/src/guides/v2.4/architecture/archi_perspectives/persist_layer.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/architecture/archi_perspectives/persist_layer.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/archi_perspectives/persist_layer.md b/src/guides/v2.4/architecture/archi_perspectives/persist_layer.md new file mode 100644 index 00000000000..b8d04c610cc --- /dev/null +++ b/src/guides/v2.4/architecture/archi_perspectives/persist_layer.md @@ -0,0 +1,38 @@ +--- +group: architecture-guide +title: Persistence layer +--- + +Magento uses an active record pattern strategy for persistence. In this system, the model object contains a *resource model* that maps an object to one or more database rows. A resource model is responsible for performing functions such as: + +* Executing all CRUD (create, read, update, delete) requests. The resource model contains the SQL code for completing these requests. + +* Performing additional business logic. For example, a resource model could perform data validation, start processes before or after data is saved, or perform other database operations. + +If you expect to return multiple items from a database query, then you would implement a special type of resource model known as a *collection*. A collection is a class that loads multiple models into an array-like structure based on a set of rules. This is similar to a SQL `WHERE` clause. + +A simple resource model defines and interacts with a single table. + +However, some objects have a vast number of attributes, or they could have a set related objects that have varying numbers of attributes. In these cases, the objects are constructed using **Entity-Attribute-Value (EAV)** models. + +Any model that uses an EAV resource has its attributes spread out over a number of MySQL tables. + +The `Customer`, `Catalog` and `Order` resource models use EAV attributes. + +## XML Declarative schema + +With Magento 2.3, we introduced Declarative XML Schemas. +These are XML files that are used to specify the final state of the database. +These files replace PHP update scripts that were required when upgrading a module. +These files allow you to skip the progressive upgrade scripts and jump right to the final state of the database. + +Read more about writing [declarative XML schemas][]. + +{:.ref-header} +Related topics + +[Architectural diagrams]({{page.baseurl}}/architecture/archi_perspectives/arch_diagrams.html) +[Architectural layers overview]({{page.baseurl}}/architecture/archi_perspectives/ALayers_intro.html) + + +[declarative XML schemas]: {{ page.baseurl }}/extension-dev-guide/declarative-schema/db-schema.html diff --git a/src/guides/v2.4/architecture/archi_perspectives/present_layer.md b/src/guides/v2.4/architecture/archi_perspectives/present_layer.md deleted file mode 120000 index cba0f2be7a3..00000000000 --- a/src/guides/v2.4/architecture/archi_perspectives/present_layer.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/architecture/archi_perspectives/present_layer.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/archi_perspectives/present_layer.md b/src/guides/v2.4/architecture/archi_perspectives/present_layer.md new file mode 100644 index 00000000000..d41a6fac09a --- /dev/null +++ b/src/guides/v2.4/architecture/archi_perspectives/present_layer.md @@ -0,0 +1,84 @@ +--- +group: architecture-guide +title: Presentation Layer +--- + +## What is the Magento Presentation layer? + +When you interact with the Magento web interface, you are interacting with *presentation layer* code. The presentation layer is the top layer of the four layers (presentation, service, domain, and persistence layers) described by the Magento architecture. + +The presentation layer contains both view elements **(layouts, blocks, templates)** and **controllers**, which process commands to and from the user interface. Presentation code controls web user interaction with the product and its appearance. You can extensively customize the user interface by using HTML, CSS, and [PHTML](https://glossary.magento.com/phtml) files to modify elements of the presentation layer. Basically, the presentation layer represents the customization of HTML, CSS, JavaScript, Magento UI, PHTML files, and block files. + +## Who uses the Presentation layer? + +Magento uses *areas* to efficiently make web service calls, loading only the dependent code that is required for the particular type of user. Three types of Magento users interact with presentation layer code: + +* **Web users** interact with the storefront, where they can see the View model of data displayed by Magento and interact with product UI elements to request data for view and manipulation. These users work within the `frontend` area. + +* **System administrators** customizing a [storefront](https://glossary.magento.com/storefront) can indirectly manipulate the presentation layer by, for example, adding themes or widgets to the frontend. + +* **Web [API](https://glossary.magento.com/api) calls** can be made through HTTP just like browser requests, and can be made via AJAX calls from the user interface. + +## Presentation layer components + +One helpful way of understanding the Magento presentation layer components is by examining Magento *themes*. +Magento themes organize both the visual aspect of your storefront and certain aspects of product behavior. + +Each [theme](https://glossary.magento.com/theme) resides in a unique directory and contains custom page layouts, templates, skins, and language files that work together to create a distinct user experience. + +For an extensive introduction to theme elements and an overview of how to extend and override the default Magento themes, see the [Frontend Developer Guide][]. + +## GraphQL + +GraphQL is a data query language developed internally by Facebook in 2012 before being publicly released in 2015. Magento implements GraphQL to provide an alternative to REST and SOAP web APIs for frontend development. + +GraphQL allows you to define the structure of the data that you need, and the server returns only the data you request. Each GraphQL-capable module contains a declarative schema that defines the syntax for queries that the module supports, as well as the attributes that can be returned. If you run a REST call such as GET /V1/products/:sku on a simple product, the system might fetch more than 100 lines of data. If all you need is the current price, the call has returned significantly more information than you need. With GraphQL, a query against the same SKU could return just the price. + +More information can be found in the [GraphQL Developer Guide][]. + +## Progressive Web Apps + +The Magento Progressive Web App (PWA) Studio project is a set of developer tools that allow you to develop, deploy, and maintain a PWA storefront on top of Magento 2. +PWA is a way to present a Magento storefront via a set of React JavaScript components. +Using Magento as a headless backend, you can use PWA components to create mobile friendly frontend. + +You can read more about how PWA works with Magento in the [PWA Studio docs][]. + +## View model + +Magento generates the [HTML](https://glossary.magento.com/html) for a page to display to a user from a tree of view elements. + +View elements fall into two main categories: blocks and containers. + +* **Blocks** can generate [dynamic content](https://glossary.magento.com/dynamic-content) and can contain named child view elements that are similar to arguments being passed in. (The `as` attribute holds the child view element names for the parent block to reference them) + +* **Containers** collect an ordered group of children view elements. + +The browser forms a product web page by asking the view element tree to render itself into HTML. +Containers and blocks emit HTML that encloses their children appropriately. +Blocks can generate their content using static HTML, Knockout JS scripts, and PHTML. + +## How Presentation code calls other layers + +Presentation code typically calls service contracts, particularly for a storefront. +However, presentation code is occasionally dependent on a specific implementation that requires the presentation code to directly call the domain layer. +For example, the [Admin](https://glossary.magento.com/admin) UI screens are often tightly linked to a specific implementation and are not generic across implementations. + +The View layer calls code from the Model to get information about the state of the application (for example, the price of a product). Typically, the way it accesses the Model is through service contracts. + +## Presentation layer flow + +Web users interact with components of the presentation layer to select actions that initiate calls to the underlying layers. +Presentation layer components make calls to the service layer, which in turn sends requests to the [domain](https://glossary.magento.com/domain) layer. + +{:.ref-header} +Related topics + +[Architectural diagrams]({{page.baseurl}}/architecture/archi_perspectives/arch_diagrams.html) + +[Architectural layers overview]({{page.baseurl}}/architecture/archi_perspectives/ALayers_intro.html) + + +[Frontend Developer Guide]: {{page.baseurl}}/frontend-dev-guide/bk-frontend-dev-guide.html +[GraphQL Developer Guide]: {{ page.baseurl }}/graphql/ +[PWA Studio docs]: http://pwastudio.io \ No newline at end of file diff --git a/src/guides/v2.4/architecture/archi_perspectives/service_layer.md b/src/guides/v2.4/architecture/archi_perspectives/service_layer.md deleted file mode 120000 index 74092f85a4e..00000000000 --- a/src/guides/v2.4/architecture/archi_perspectives/service_layer.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/architecture/archi_perspectives/service_layer.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/archi_perspectives/service_layer.md b/src/guides/v2.4/architecture/archi_perspectives/service_layer.md new file mode 100644 index 00000000000..c4d567a11d9 --- /dev/null +++ b/src/guides/v2.4/architecture/archi_perspectives/service_layer.md @@ -0,0 +1,80 @@ +--- +group: architecture-guide +title: Service layer +menu_title: Service layer +--- + +## What is a Service layer? + +The service layer provides a bridge between the presentation layer and the domain layer and resource-specific data. +This is implemented using *service contracts*, which are defined using [PHP](https://glossary.magento.com/php) interfaces. + +In general, the service layer: + +* Resides below the presentation layer and above the domain layer. + +* Contains service contracts, which define how the implementation will behave. + +* Provides an easy way to access the REST/SOAP [API](https://glossary.magento.com/api) framework code (which also resides above the service contracts). You can bind service contracts to web service APIs in configuration files --- no coding required. + +* Provides a stable API for other modules to call into. + +## Who accesses the service layer? + +All calls from web service interfaces, or users working with your [storefront](https://glossary.magento.com/storefront) (that is, controller-initiated requests), are typically routed through the service layer. +We strongly encourage the use of service contracts to call business logic. + +External applications can make requests for business logic with simple SOAP and REST calls. +With some simple [XML](https://glossary.magento.com/xml) or JSON, you can expose the service layer's PHP API and make it accessible to REST or SOAP web services. +Once implemented, a web service can make a single API call and return an information-rich data structure. + +[Service contract](https://glossary.magento.com/service-contract) clients include: + +* Controllers (initiated by actions of users of the storefront) + +* Web services (SOAP and REST API calls) + +* Other Magento modules through service contracts + +## Service contract anatomy + +The service contract of a [module](https://glossary.magento.com/module) is defined by the set of interfaces in the module's `/Api` directory. + +This directory contains: + +* Service interfaces in the `/Api` [namespace](https://glossary.magento.com/namespace) of the module ([Catalog API][catalog-api]). + +* Data (or *entity*) interfaces in the `Api/Data` directory ([Catalog API/Data][catalog-api-data]). + Data entities* are data structures passed to and returned from service interfaces. + + Files in the data directory contain `get()` and `set()` methods for entries in the entity table and extension attributes. + +Typically, service contracts provide three distinct types of interfaces: + +* Repository interfaces + +* Management interfaces + +* [Metadata](https://glossary.magento.com/metadata) interfaces + +However, there is no requirement that service contracts conform to all three patterns. + +## Advantages of service contracts + +Service contracts allow you to add a new customer [extension](https://glossary.magento.com/extension) that adds or changes business logic-level resource models without breaking the system. + +This is done using the *<preference>* element in a custom module's [dependency injection](https://glossary.magento.com/dependency-injection) configuration file (`di.xml`) file. + +The `di.xml` file specifies which PHP class to use for the interface `Magento\Customer\Api\CustomerRepositoryInterface`. + +Another module can change this interface file by specifying a different class name. +However, if the client code uses the interface definition only, no class change is necessary. + +{:.ref-header} +Related topics + +* [Architectural diagrams]({{page.baseurl}}/architecture/archi_perspectives/arch_diagrams.html) +* [Architectural layers overview]({{page.baseurl}}/architecture/archi_perspectives/ALayers_intro.html) + +[catalog-api]: {{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Catalog/Api +[catalog-api-data]: {{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Catalog/Api/Data diff --git a/src/guides/v2.4/architecture/archi_perspectives/tech-vision.md b/src/guides/v2.4/architecture/archi_perspectives/tech-vision.md deleted file mode 120000 index fa8e268adb5..00000000000 --- a/src/guides/v2.4/architecture/archi_perspectives/tech-vision.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/architecture/archi_perspectives/tech-vision.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/archi_perspectives/tech-vision.md b/src/guides/v2.4/architecture/archi_perspectives/tech-vision.md new file mode 100644 index 00000000000..f437a525776 --- /dev/null +++ b/src/guides/v2.4/architecture/archi_perspectives/tech-vision.md @@ -0,0 +1,15 @@ +--- +group: architecture-guide +title: Magento technical vision +--- + +The Magento technical vision is a collection of documents that describe the desired state of the Magento platform. + +Each individual technical vision document relates to a set of modules that are logically grouped together. Individual documents typically describe a component's place in the system, its architecture, extension scenarios and a list of invariants that must be preserved at all times during component refactoring or extension to ensure consistency. + +Learn more about the [Magento web API][]. +See the [Magento Coding Standards][] for information about writing clean, readable code. + + +[Magento web API]: {{page.baseurl}}/get-started/bk-get-started-api.html +[Magento Coding Standards]: {{page.baseurl}}/coding-standards/bk-coding-standards.html diff --git a/src/guides/v2.4/architecture/archi_perspectives/third-party-libs.md b/src/guides/v2.4/architecture/archi_perspectives/third-party-libs.md deleted file mode 120000 index f854128a54f..00000000000 --- a/src/guides/v2.4/architecture/archi_perspectives/third-party-libs.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/architecture/archi_perspectives/third-party-libs.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/archi_perspectives/third-party-libs.md b/src/guides/v2.4/architecture/archi_perspectives/third-party-libs.md new file mode 100644 index 00000000000..707e98374bf --- /dev/null +++ b/src/guides/v2.4/architecture/archi_perspectives/third-party-libs.md @@ -0,0 +1,11 @@ +--- +group: architecture-guide +title: Third-party libraries +menu_title: Third-party libraries +--- + +Magento depends on a set of external libraries. You can use [Composer](https://glossary.magento.com/composer) to manage these dependencies. Composer downloads all of the external libraries that are included in its main configuration file and installs them under its default installation directory (`vendor/`). Third-party libraries include the Zend framework files and the Symfony libraries. + +There are some required libraries that Composer does not load. These reside in `lib/` and include [JavaScript](https://glossary.magento.com/javascript) libraries (none of which are loaded by Composer) and a few [PHP](https://glossary.magento.com/php) libraries. (You can also use Composer to manage dependencies between various components within Magento.) + +If you are extending your Magento [storefront](https://glossary.magento.com/storefront) to interact with third-party applications, you might need to include additional external libraries. These external libraries can be as simple as a wrapper for an [API](https://glossary.magento.com/api) of a third-party product you are integrating with your Magento storefront, or an entire framework. diff --git a/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md b/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md deleted file mode 120000 index 46493f2a1c3..00000000000 --- a/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/architecture/archi_perspectives/webapi-vision.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md b/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md new file mode 100644 index 00000000000..880783f56c6 --- /dev/null +++ b/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md @@ -0,0 +1,116 @@ +--- +group: architecture-guide +--- + +# Technical vision - Web API + +Web API is crucial for Magento because of the need to integrate with order management, customer management, and other enterprise management software systems. + +There are many headless Magento installations in which a merchant partially uses Magento functionality, while the other pieces of an eCommerce website are provided by other systems. + +See [more details](https://en.wikipedia.org/wiki/Web_API) about the importance of web APIs in modern web applications. + +## Components Dependencies + +The following diagram shows Web API component dependencies. + +![Web API components dependencies]({{ site.baseurl }}/common/images/coding-standards/webapi-components-dependencies.png) + +## High-level Architecture + +The following image provides an overview of how Web API requests are processed. + +![Web API request processing overview]({{ site.baseurl }}/common/images/coding-standards/webapi-request-processing-high-level-overview.png) + +## Extension Scenarios + +### Declare a new REST and SOAP endpoint + +Any [service contract]({{ page.baseurl }}/extension-dev-guide/service-contracts/service-contracts.html) can be [exposed as REST and SOAP]({{ page.baseurl }}/extension-dev-guide/service-contracts/service-to-web-service.html) endpoints via configuration in a module's `webapi.xml` file. + +### Declare a new GraphQL query/mutation + +1. Create custom resolvers. +1. Declare a custom query/mutation and all necessary types in `schema.graphqls`. + +If the target module is called `MyModule`, then create the resolvers and configuration files in a new module called `MyModuleGraphQl`. + +See the [GraphQL documentation]({{ page.baseurl }}/graphql/index.html) for more information. + +### Add a custom authentication mechanism + +1. Provide a custom implementation of `\Magento\Authorization\Model\UserContextInterface` that verifies a user's identity using a custom authentication mechanism. +1. Declare custom user context in the composite user context for the target area(s) (`webapi_rest`, `webapi_soap`, `webapi_graphql`) : + +```xml + + + + + Vendor\Module\Model\Authentication\CustomUserContext + 100 + + + + +``` + +### Modify the schema of an existing SOAP and REST endpoint + +The recommended approach for modifying an interface is to define a new endpoint. If you simply modify the schema, you might break existing integrations or extensions. + +To extend an interface, use [extension attributes]({{ page.baseurl }}/extension-dev-guide/attributes.html). + +### Modify the schema of an existing GraphQL query + +1. Add a `schema.graphqls` file to the `GraphQl` module. Magento merges this file with configurations from other modules using the same merge rules as other types of configuration. + +1. Write any necessary plugins for existing resolvers related to the query, or create a custom resolver and enable it via override in `schema.graphqls` + +## Model Consistency Constraints + +Any new design related to Web API must satisfy the following constraints to keep the model consistency. + +### General + +1. REST and SOAP must be designed for Admin Panel integrations and be equal in terms of coverage. GraphQL should be designed for storefront scenarios. +1. Any identifier exposed in guest APIs (for example, cart ID) must be masked to prevent the possibility of unauthorized access to the data of other guest users. +1. Authentication must be done via `\Magento\Authorization\Model\UserContextInterface`. +1. Customer-specific identifiers (such as customer ID or cart ID) must be deducted from the record of the successfully authenticated customer. They must not be accepted via request parameters. +1. All new web API endpoints must be covered with web API functional tests. + * For REST and SOAP, by default, the same test will be executed in the scope of different continuous integration jobs. The base class for REST and SOAP tests is `\Magento\TestFramework\TestCase\WebapiAbstract` + * The base class for GraphQL tests is: `\Magento\TestFramework\TestCase\GraphQlAbstract` +1. Web API requests must be processed by custom front controllers with optimized routing to prevent the admin and storefront areas from executing routers. +1. Web API schema should be strictly typed. (All complex types should eventually be resolved to scalar types.) +1. Authentication parameters must be passed via headers. +1. Throttling must be configured by the system integrator. It is not supported by Magento +1. Internal server errors must be masked and never shown to the user in production mode. In developer mode, original exceptions must never be masked and should be displayed along with the related stacktrace. +1. Pagination must be supported by all list operations. + +### GraphQL + +1. Unlimited nesting should be supported during requests for related entities. (For example, get Order => Order Items => Products => Related Products) +1. Field filtration must be performed with SQL queries. Do not filter on the application layer after you've fetched all possible fields. +1. Third-party customizations must be done separately for Service Contracts and for GraphQL +1. For modularity purposes, GraphQL configuration must be declared in a separate module. For example, to expose GraphQL for the module `MyModule`, you must create the `schema.graphqls` file in the `MyModuleGraphQl` module. +1. GraphQL is primarily designed for store-front, one-page apps and mobile applications. It supports token and cookie authentication, as well as guest access to public queries +1. All queries must return the 200 HTTP status code. If an error occurs, return the error in the response body. A 500 status code is allowed when an exception occurs when generating a schema, but not during requests. +1. The Store code should be passed via headers. + +### REST + +1. The resource URL should be versioned (for example: V1). The version must be specified in the following format: `V\d.+` +1. Resource names in a URL should be in plural form (for example: products, carts) +1. ID parameters for operations on entities should be part of the resource URL (for example: /V1/products/**:sku** ) +1. POST should be used to create an entity. + PUT should be used to update an entity. + PATCH should be used to patch (update only selected fields) an update to an entity or entities. +1. REST is designed for system integrations, mobile app integrations, as well as for one-page apps. It supports tokens, cookies, and OAuth 1.0 with token exchange. It also supports guest access to public resources. +1. Responses must return responses with standard [HTTP status codes](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes). +1. The store code must be passed with a URL. For example `GET /rest/frenchStoreView/V1/products`. Persistence operations that should be performed for all stores at once should have 'all' store code in the URL. + +### SOAP + +1. SOAP is designed for systems integration. It supports token authentication for customers and admins, as well as no authentication for anonymous service methods. Cookie authentication and OAuth 1.0 are not supported. +1. The schema is available in the form of a WSDL for all exposed services. +1. All requests must return the 200 HTTP status code. If an error occurs, return the error in the response. diff --git a/src/guides/v2.4/architecture/bk-architecture.md b/src/guides/v2.4/architecture/bk-architecture.md deleted file mode 120000 index 98958620ab6..00000000000 --- a/src/guides/v2.4/architecture/bk-architecture.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/architecture/bk-architecture.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/bk-architecture.md b/src/guides/v2.4/architecture/bk-architecture.md new file mode 100644 index 00000000000..ebe4eb09bbd --- /dev/null +++ b/src/guides/v2.4/architecture/bk-architecture.md @@ -0,0 +1,13 @@ +--- +group: architecture-guide +title: Architecture Guide +landing-page: Architecture +menu_title: Get Started +menu_node: parent +--- + +The Architecture Guide provides a high-level introduction and view of the Magento product. + +The Magento platform and components are explained from the perspective of several audiences: merchants, web store developers (frontend developers), [extension](https://glossary.magento.com/extension) developers, system admins, installers, and integrators. + +More detailed information about building online stores, using the Magento APIs, installing, configuring, and extending the platform is included in other books in our [Magento library]({{site.baseurl}}/index.html). \ No newline at end of file diff --git a/src/guides/v2.4/architecture/extensibility.md b/src/guides/v2.4/architecture/extensibility.md deleted file mode 120000 index bc859dbdb87..00000000000 --- a/src/guides/v2.4/architecture/extensibility.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/architecture/extensibility.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/extensibility.md b/src/guides/v2.4/architecture/extensibility.md new file mode 100644 index 00000000000..9d0f95ec09f --- /dev/null +++ b/src/guides/v2.4/architecture/extensibility.md @@ -0,0 +1,116 @@ +--- +group: architecture-guide +title: Extensibility and modularity +menu_title: Extensibility and modularity +--- + +## Overview + +Product *extensibility* describes how easy it is to expand a product's feature set. An extensible product has been designed from its earliest stages for customization and enhancement. Extensible products are designed for ease in expanding your installation's feature set, enriching current features, and integrating with third-party software. + +Maximizing extensibility has been our goal through all aspects of Magento development. Core tasks such as shipping are packaged as discrete modules, and you expand your features by installing modules that you either buy from third-party vendors or create yourself. While logic specific to each [shipping carrier](https://glossary.magento.com/shipping-carrier) is packaged in a discrete module, you can easily add or delete shipping providers by simply adding or deleting modules. The Magento Framework provides common logic to control routing and other core application functions. + +## What makes a product extensible? + +*Magento extensibility* describes the product's built-in ability for developers and merchants to routinely extend their storefront's capabilities as their business grows. + +The following factors significantly affect extensibility. + +### Architectural principles that guide product structure + +Central to the Magento model of software development is the practice of replacing or extending core code rather than editing it. This strategy supports your efforts to maintain the integrity of the tested code we provide while still extensively customizing your [storefront](https://glossary.magento.com/storefront). + +### Reliance on popular design patterns + +Reliance on known architectural and programming structures helps [PHP](https://glossary.magento.com/php) developers orient themselves to the specific development issues that affect coding in a particular product ecosystem. This can reduce the learning curve for new Magento developers. + +Design patterns are time-tested, widely recognized software architecture constructs. Magento product architecture incorporates many well known patterns, but Model-View-Controller (MVC) holds particular interest for extension developers. + +### Modularity + +The concept of the *module* is the heart of Magento [extension](https://glossary.magento.com/extension) development, and modular design of software components (in particular, modules, themes, and language packages) is a core architectural principle of the product. Self-contained modules of discrete code are organized by feature, thereby reducing each module's external dependencies. + +If a [module](https://glossary.magento.com/module) is self-contained, then you can modify or replace it without affecting other areas of the code. This *loose coupling* of software components reduces the ripple effects throughout your code base of changing code. + + See the [PHP Developer Guide][] for detailed instructions on how to create modules. + +### Rich product ecosystem + +The wider Magento ecosystem provides an extensive community and rich third-party marketplace for extensions. Visit [Commerce Marketplace][] for an overview of the many modules and themes available for download and to buy modules and [theme](https://glossary.magento.com/theme) packages, which offer more possibilities for extending your [storefront](https://glossary.magento.com/storefront). + +### Open-source software to create and manage extensions + +Magento is built on open-source technologies, created for the development community. For example, it uses [Composer](https://glossary.magento.com/composer) to manage dependencies. See [Technology Stack]({{page.baseurl}}/install-gde/system-requirements.html) for a complete list of technologies used. + +### Coding standards + +Adherence to standard best practices for [PHP](https://glossary.magento.com/php) and [JavaScript](https://glossary.magento.com/javascript) code ensures that the code base is sound. Magento has adopted most of the PSR2 Coding Standards for PHP. See [Coding Standards]({{page.baseurl}}/coding-standards/bk-coding-standards.html) for more information. + +### Upgrade and versioning strategies + +Magento has well-defined upgrade and versioning strategies that can help you avoid any problems with software component dependencies. Add modules after confirming that the [module](https://glossary.magento.com/module) version is compatible with the Magento Framework version. + +### Web APIs + +Magento or third-party services can be configured as a web [API](https://glossary.magento.com/api) (REST or SOAP) with some simple [XML](https://glossary.magento.com/xml). You can use these services to integrate your Magento installation into third-party applications, such as CRM (Customer Relationship Management), ERP (Enterprise Resource Planning) back office systems, and [CMS](https://glossary.magento.com/cms) (Content Management Systems). + +See [Getting Started with Magento Web APIs][] for more information. + +### Flexible attribute types + +You can enhance your storefront by adding unique attributes to the default product attributes. For example, you might need to add a new attribute to describe a product, such as texture or an industry-specific rating. You can add these attributes from the Admin, and the storefront displays them. + +|Attribute type|Displayed by storefront?| +|--- |--- | +|EAV|no| +|Custom|yes| +|Extension|no| +{:style="table-layout:auto"} + +Attribute types fall into three general categories: + +* **EAV (Entity-Attribute-Value) attributes** are site-specific attributes that you can define for a local site using the [Admin](https://glossary.magento.com/magento-admin). + +* **Custom attributes** are a subset of EAV attributes. Objects that use EAV attributes typically store values in several MySQL tables. The Customer and [Catalog](https://glossary.magento.com/catalog) modules use EAV attributes. + +* **Extension attributes** often use more [complex data](https://glossary.magento.com/complex-data) types than custom attributes. These attributes do not appear in the storefront. Extension attributes are introduced by modules. + +See [PHP Developer Guide][] for information about using attributes. + +### Service contracts, dependency injection, and dependency inversion + +*Service contracts* provide a new way to access public API endpoints. These PHP interfaces offer robust, stable extension points to which clients can connect. Service contracts define the endpoints that function as a module's public API. Defining these endpoints is an essential part of adding a module. + +Service contracts are discussed throughout the Magento documentation set. See [Service layer][] for a high-level introduction. See [PHP Developer Guide][] for a more detailed discussion of service contracts and dependency injection. + +Magento implements *dependency injection* along with service contracts. Dependency injection provides a mechanism for changing a module's behavior without altering the client or understanding nitty-gritty details of implementation. Both dependency injection and its related concept *dependency inversion* support Magento's fundamental architectural principles of modularity and ease-of-extensibility. They strongly encourage basic coding practices that support the loose coupling of software modules. + +See [PHP Developer Guide][] for information on both dependency injection and service contracts. + +### Plug-ins + +Plug-ins, like modules, are a mechanism for adding features to the core Magento product. Plug-ins enable you to make changes to the behavior of any public method in a Magento class. You can consider it a form of extension that uses the `Plugin` class. + +Plug-ins are also called *interceptors*. Applications use the [plug-in](https://glossary.magento.com/plug-in) pattern to change method behavior without modifying the actual class. Plug-ins can typically intercept method processing before or after the method runs, or only when the method throws an [exception](https://glossary.magento.com/exception). + +See [Plug-ins][] in [PHP Developer Guide][] for information on declaring and prioritizing plug-ins. + +{:.ref-header} +Related topics + +[Architectural basics]({{page.baseurl}}/architecture/archi_perspectives/ABasics_intro.html) + +[Global features that support extensibility]({{page.baseurl}}/architecture/global_extensibility_features.html) + +[Ease of frontend customization]({{page.baseurl}}/architecture/frontend_custom_strategies.html) + +[Extensibility and modularity]({{page.baseurl}}/architecture/extensibility.html) + + +[PHP Developer Guide]: {{page.baseurl}}/extension-dev-guide/bk-extension-dev-guide.html +[Commerce Marketplace]: https://marketplace.magento.com/ +[Technology Stack]: {{page.baseurl}}/install-gde/system-requirements.html +[Plug-ins]: {{page.baseurl}}/extension-dev-guide/plugins.html +[Service layer]: {{page.baseurl}}/architecture/archi_perspectives/service_layer.html +[Getting Started with Magento Web APIs]: {{page.baseurl}}/get-started/bk-get-started-api.html +[Coding Standards]: {{page.baseurl}}/coding-standards/bk-coding-standards.html \ No newline at end of file diff --git a/src/guides/v2.4/architecture/global_extensibility_features.md b/src/guides/v2.4/architecture/global_extensibility_features.md deleted file mode 120000 index 8eb835ce7b1..00000000000 --- a/src/guides/v2.4/architecture/global_extensibility_features.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/architecture/global_extensibility_features.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/global_extensibility_features.md b/src/guides/v2.4/architecture/global_extensibility_features.md new file mode 100644 index 00000000000..2b3aa3757f2 --- /dev/null +++ b/src/guides/v2.4/architecture/global_extensibility_features.md @@ -0,0 +1,94 @@ +--- +group: architecture-guide +title: Global features that support extensibility +--- + +## Overview + +Essential qualities foster extensibility throughout the entire set of Magento components. This discussion focuses on: + +* Modularity +* Reliance on popular design patterns +* Coding standards +* Flexible attribute types +* Web APIs +* Service contracts and [dependency injection](https://glossary.magento.com/dependency-injection) +* Plug-ins +* Declarative schema + +### Modularity + +The concept of the *module* is the heart of Magento [extension](https://glossary.magento.com/extension) development, and modular design of software components (in particular, modules, themes, and language packages) is a core architectural principle of the product. Self-contained modules of discrete code are organized by feature, thereby reducing each module's external dependencies. + +If a [module](https://glossary.magento.com/module) is self-contained, then you can modify or replace it without affecting other areas of the code. This *loose coupling* of software components reduces the ripple effects throughout your code base of changing code. + + See the [PHP Developer Guide]({{ page.baseurl }}/extension-dev-guide/bk-extension-dev-guide.html) for detailed instructions on how to create modules. + +### Reliance on popular design patterns + +Reliance on known architectural and programming structures helps [PHP](https://glossary.magento.com/php) developers orient themselves to the specific development issues that affect coding in a particular product ecosystem. This can reduce the learning curve for new Magento developers. + +Design patterns are time-tested, widely recognized software architecture constructs. Magento product architecture incorporates many well known patterns, but Model-View-Controller (MVC) holds particular interest for extension developers. + +### Coding standards + +Magento developers should familiarize themselves with our coding standards, best practices, and conventions, especially standards for PHP file formatting, coding style, and file naming conventions. Magento standards are based on PSR2 Coding Standards. + +See [Coding Standards]({{page.baseurl}}/coding-standards/bk-coding-standards.html) for guidelines and requirements. + +### Rich product ecosystem + +The wider Magento ecosystem provides an extensive community and rich third-party marketplace for extensions. Visit [Commerce Marketplace](https://marketplace.magento.com/) for an overview of the many modules and themes available for download and to buy modules and [theme](https://glossary.magento.com/theme) packages, which offer more possibilities for extending your [storefront](https://glossary.magento.com/storefront). + +### Flexible attribute types + +You can enhance your storefront by adding unique attributes to the default product attributes. For example, you might need to add a new attribute to describe a product, such as texture or an industry-specific rating. You can add these attributes from the Admin, and the storefront displays them. + +Attribute type | Displayed by storefront? +--- | --- +EAV | No +Custom | Yes +Extension | No + +Attribute types fall into three general categories: + +* **EAV (Entity-Attribute-Value) attributes** are site-specific attributes that you can define for a local site using the [Admin](https://glossary.magento.com/magento-admin). + +* **Custom attributes** are a subset of EAV attributes. Objects that use EAV attributes typically store values in several MySQL tables. The Customer and [Catalog](https://glossary.magento.com/catalog) modules use EAV attributes. + +* **Extension attributes** often use more [complex data](https://glossary.magento.com/complex-data) types than custom attributes. These attributes do not appear in the storefront. Extension attributes are introduced by modules. + +See [PHP Developer Guide]({{page.baseurl}}/extension-dev-guide/bk-extension-dev-guide.html) for information about using attributes. + +### Web APIs + +Magento or third-party services can be configured as a web [API](https://glossary.magento.com/api) (REST or SOAP) with some simple [XML](https://glossary.magento.com/xml). You can use these services to integrate your Magento installation into third-party applications, such as CRM (Customer Relationship Management), ERP (Enterprise Resource Planning) back office systems, and [CMS](https://glossary.magento.com/cms) (Content Management Systems). + +See [Getting Started with Magento Web APIs]({{page.baseurl}}/get-started/bk-get-started-api.html) for more information. + +### Service contracts, dependency injection, and dependency inversion + +*Service contracts* provide a new way to access public API endpoints. These PHP interfaces offer robust, stable extension points to which clients can connect. Service contracts define the endpoints that function as a module's public API. Defining these endpoints is an essential part of adding a module. + +Service contracts are discussed throughout the Magento documentation set. See [Service layer]({{page.baseurl}}/architecture/archi_perspectives/service_layer.html) for a high-level introduction. See [PHP Developer Guide]({{page.baseurl}}/extension-dev-guide/bk-extension-dev-guide.html) for a more detailed discussion of service contracts and dependency injection. + +Magento implements *dependency injection* along with service contracts. Dependency injection provides a mechanism for changing a module's behavior without altering the client or understanding nitty-gritty details of implementation. Both dependency injection and its related concept *dependency inversion* support Magento's fundamental architectural principles of modularity and ease-of-extensibility. They strongly encourage basic coding practices that support the loose coupling of software modules. + +See [PHP Developer Guide]({{page.baseurl}}/extension-dev-guide/bk-extension-dev-guide.html) for information on both dependency injection and service contracts. + +### Plug-ins + +Plug-ins, like modules, are a mechanism for adding features to the core Magento product. Plug-ins enable you to make changes to the behavior of any public method in a Magento class. You can consider it a form of extension that uses the `Plugin` class. + +Plug-ins are also called *interceptors*. Applications use the [plug-in](https://glossary.magento.com/plug-in) pattern to change method behavior without modifying the actual class. Plug-ins can typically intercept method processing before or after the method runs, or only when the method throws an [exception](https://glossary.magento.com/exception). + +See [Plug-ins]({{page.baseurl}}/extension-dev-guide/plugins.html) in [PHP Developer Guide]({{page.baseurl}}/extension-dev-guide/bk-extension-dev-guide.html) for information on declaring and prioritizing plug-ins. + +### Declarative schema + +[Declarative schema]({{page.baseurl}}/extension-dev-guide/declarative-schema/index.html) allows developers to declare the final desired state of the database as it pertains to their modules. The system adjusts to database changes automatically without performing redundant operations. Developers are no longer forced to write installation and upgrade scripts for each new version. In addition, declarative schema allows data be deleted when a module is uninstalled. + +{:.ref-header} +Related topic + +[Extensibility and modularity]({{page.baseurl}}/architecture/extensibility.html) diff --git a/src/guides/v2.4/architecture/security_intro.md b/src/guides/v2.4/architecture/security_intro.md deleted file mode 120000 index df56a02f61d..00000000000 --- a/src/guides/v2.4/architecture/security_intro.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/architecture/security_intro.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/security_intro.md b/src/guides/v2.4/architecture/security_intro.md new file mode 100644 index 00000000000..0d669b65de1 --- /dev/null +++ b/src/guides/v2.4/architecture/security_intro.md @@ -0,0 +1,48 @@ +--- +group: architecture-guide +subgroup: Architectural Basics +title: Security overview +menu_title: Security +menu_order: +--- + +The security of your data and digital experiences is our priority. To better protect {{site.data.var.ee}} and {{site.data.var.ce}} installations from the physical layer up, we have implemented hundreds of processes and controls to help us comply with [industry-accepted standards][1], regulations, and certifications. To help protect installations from the software layer down, we build in security measures that are based on the [Adobe Secure Product Lifecyle][2]. + +Although there is no single way to eliminate all security risks, there are many steps you can take to harden your installations and make them a less attractive target for bad actors. The [Security Best Practices Guide][3] offers insight and practical guidelines to help protect all installations from security incidents. + +## Examples of built-in security measures + +### Enhanced password management + +Magento has strengthened the hashing algorithms (SHA-256) used in password management. Magento now supports Argon2ID13 through the PHP sodium extension, which requires the libsodium library version 1.0.13 or higher. + +### Improved prevention of cross-site scripting (XSS) attacks by making escaped data the default + +The Magento Framework has adopted conventions that regulate the escaping of data in output. These conventions include the ability to escape output for [HTML](https://glossary.magento.com/html) pages (HTML, JSON, and JavaScript) and email. Where possible, escaping is transparent to client code. See [Security measures against XSS attacks]({{page.baseurl}}/extension-dev-guide/xss-protection.html) in the [Frontend](https://glossary.magento.com/frontend) Developer Guide. + +### More flexible file system ownership and permissions + +Starting in version 2.0.6, Magento no longer explicitly sets file system permissions. Instead, we recommend that certain files and directories be writable in a development environment and read-only in a production environment. + +To provide you with a simple way to restrict access to the file system in production, we provide the flexibility for you to further restrict those permissions using a [umask](http://www.cyberciti.biz/tips/understanding-linux-unix-umask-value-usage.html). + +For an overview, see [Overview of ownership and permissions]({{page.baseurl}}/install-gde/prereq/file-sys-perms-over.html). + +For details about ownership and permissions in development and production, see [Magento ownership and permissions in development and production]({{page.baseurl}}/config-guide/prod/prod_file-sys-perms.html). + +### Improved prevention of clickjacking exploits + +Magento safeguards your store from clickjacking attacks by using an X-Frame-Options HTTP request header. For more information, see [X-Frame-Options header]({{page.baseurl}}/config-guide/secy/secy-xframe.html). + +### Use of non-default Admin URL + +A simple [Admin](https://glossary.magento.com/magento-admin) [URL](https://glossary.magento.com/url) (like `admin` or `backend`) makes it easy to target attacks on specific locations using automated password guessing. To prevent against this type of attack, Magento by default creates a random Admin URI when you install the product. The CLI command `php bin/magento info:adminuri` is provided so that you can see the URI if you forget it. You can also use the CLI to change this URI. Although the use of a non-default admin URL will not secure the site, its use will help prevent large-scale automated attacks. See [Display or change the Admin URI]({{page.baseurl}}/install-gde/install/cli/install-cli-adminurl.html) in Configuration Guide for more information. + +{:.ref-header} +Related topics + +[Configuration Guide]({{page.baseurl}}/config-guide/bk-config-guide.html) + +[1]: https://docs.magento.com/m2/ee/user_guide/stores/compliance-industry.html +[2]: https://www.adobe.com/security/engineering.html +[3]: https://www.adobe.com/content/dam/acom/en/security/pdfs/Adobe-Magento-Commerce-Best-Practices-Guide.pdf diff --git a/src/guides/v2.4/architecture/storefront_customization.md b/src/guides/v2.4/architecture/storefront_customization.md deleted file mode 120000 index 5a3f5a5b56d..00000000000 --- a/src/guides/v2.4/architecture/storefront_customization.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/architecture/storefront_customization.md \ No newline at end of file diff --git a/src/guides/v2.4/architecture/storefront_customization.md b/src/guides/v2.4/architecture/storefront_customization.md new file mode 100644 index 00000000000..8eaac330dea --- /dev/null +++ b/src/guides/v2.4/architecture/storefront_customization.md @@ -0,0 +1,41 @@ +--- +group: architecture-guide +title: Storefront customization strategies +menu_title: Storefront customization strategies +--- + +## Overview + +We can generalize about the range of [storefront](https://glossary.magento.com/storefront) customizations that the Magento supports. This range spans the simplest customizations, which involve only small additions to the default Magento storefront settings, to a complete replacement of Magento-provided [HTML](https://glossary.magento.com/html) and [CSS](https://glossary.magento.com/css). + +## Storefront customization levels + +These four levels of potential storefront customization are listed in order to increase complexity. + +### Extend Magento-Provided CSS + +Magento supplies a default [theme](https://glossary.magento.com/theme) and a Less-based CSS. You can substantially change a storefront using CSS only. This uncomplicated strategy might suit projects with a limited budget, or might interest developers who create different skins for a site. A small business enter this process of storefront customization by buying a third-party developed theme from Commerce Marketplace to extend the default values. + +### Replace PHTML template files + +In addition to extending the default CSS, you can generate different HTML [markup](https://glossary.magento.com/markup). For example, you might need to add a missing CSS class name, or add an extra `
` tag to achieve some visual effect. You might also need to tweak some [JavaScript](https://glossary.magento.com/javascript) to cope with different HTML markup. This change is more demanding than simply extending Magento CSS, but is still within the grasp of smaller projects and leaner teams. + +### Replace Magento-Provided CSS + +Rather than edit the default CSS provided by Magento, you might decide to replace all the default storefront CSS code with your own. This strategy avoids tying a project to the Magento-provided CSS, but puts a greater burden on project development and integration. It also allows the use of different CSS tools or technologies not provided with Magento. Partners who build their own set of CSS libraries could reuse these libraries on different customer projects. (These unique CSS libraries may help differentiate a partner from others in the market.) + +In addition to replacing CSS files, you might need to replace small amounts of HTML and JavaScript. + +### Replace Magento-Provided CSS, HTML, and JavaScript + +Delivering a sharply different shopping experience than the default Magento installation provides is a more substantial task. However, the tradeoff might be a more complicated experience integrating additional extensions into your installation in the future. + +{:.bs-callout-tip} + Any customization of your storefront will work optimally, and provide the easiest path for later upgrades, if you follow the best practice of consistently compartmentalizing code by type. For example, keep all HTML in [PHTML](https://glossary.magento.com/phtml) files; keep all JavaScript in JavaScript files. + +{:.ref-header} +Related topics + +[Frontend Developer Guide]({{page.baseurl}}/frontend-dev-guide/bk-frontend-dev-guide.html) + +[JavaScript Developer Guide]({{page.baseurl}}/javascript-dev-guide/bk-javascript-dev-guide.html) From f05f2a02db2943f2b77faa28955de82a1f461be6 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 17 May 2022 16:24:29 -0500 Subject: [PATCH 045/776] Added migration metadata --- src/guides/v2.3/architecture/frontend_custom_strategies.md | 2 ++ .../v2.4/architecture/archi_perspectives/ABasics_intro.md | 2 ++ .../v2.4/architecture/archi_perspectives/ALayers_intro.md | 2 ++ .../v2.4/architecture/archi_perspectives/arch_diagrams.md | 2 ++ .../architecture/archi_perspectives/components/AComponents.md | 2 ++ .../archi_perspectives/components/modules/mod_and_areas.md | 2 ++ .../archi_perspectives/components/modules/mod_depend.md | 2 ++ .../archi_perspectives/components/modules/mod_intro.md | 2 ++ .../archi_perspectives/components/modules/mod_relationships.md | 2 ++ src/guides/v2.4/architecture/archi_perspectives/domain_layer.md | 2 ++ src/guides/v2.4/architecture/archi_perspectives/framework.md | 2 ++ .../v2.4/architecture/archi_perspectives/persist_layer.md | 2 ++ .../v2.4/architecture/archi_perspectives/present_layer.md | 2 ++ .../v2.4/architecture/archi_perspectives/service_layer.md | 2 ++ src/guides/v2.4/architecture/archi_perspectives/tech-vision.md | 2 ++ .../v2.4/architecture/archi_perspectives/third-party-libs.md | 2 ++ .../v2.4/architecture/archi_perspectives/webapi-vision.md | 2 ++ src/guides/v2.4/architecture/bk-architecture.md | 2 ++ src/guides/v2.4/architecture/extensibility.md | 2 ++ src/guides/v2.4/architecture/global_extensibility_features.md | 2 ++ src/guides/v2.4/architecture/security_intro.md | 2 ++ src/guides/v2.4/architecture/storefront_customization.md | 2 ++ 22 files changed, 44 insertions(+) diff --git a/src/guides/v2.3/architecture/frontend_custom_strategies.md b/src/guides/v2.3/architecture/frontend_custom_strategies.md index 91a80385409..e6777b91a94 100644 --- a/src/guides/v2.3/architecture/frontend_custom_strategies.md +++ b/src/guides/v2.3/architecture/frontend_custom_strategies.md @@ -1,6 +1,8 @@ --- group: architecture-guide title: Ease of frontend customization +migrated_to: https://developer.adobe.com/commerce/php/architecture/basics/frontend-customization/ +layout: migrated --- ## Overview {#m2arch-whatis-overview} diff --git a/src/guides/v2.4/architecture/archi_perspectives/ABasics_intro.md b/src/guides/v2.4/architecture/archi_perspectives/ABasics_intro.md index 5da43782d09..55b150e6383 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/ABasics_intro.md +++ b/src/guides/v2.4/architecture/archi_perspectives/ABasics_intro.md @@ -2,6 +2,8 @@ group: architecture-guide title: Architectural basics overview menu_title: Architectural basics +migrated_to: https://developer.adobe.com/commerce/php/architecture/basics/ +layout: migrated --- Magento incorporates the core architectural principles of object-oriented, PHP-based applications. Comprehensive discussions of these general principles exist both on-line and in printed form. diff --git a/src/guides/v2.4/architecture/archi_perspectives/ALayers_intro.md b/src/guides/v2.4/architecture/archi_perspectives/ALayers_intro.md index 895b8d769da..7970024b6ac 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/ALayers_intro.md +++ b/src/guides/v2.4/architecture/archi_perspectives/ALayers_intro.md @@ -2,6 +2,8 @@ group: architecture-guide title: Architectural layers overview menu_title: Architectural layers +migrated_to: https://developer.adobe.com/commerce/php/architecture/layers/ +layout: migrated --- ## Magento as layered software diff --git a/src/guides/v2.4/architecture/archi_perspectives/arch_diagrams.md b/src/guides/v2.4/architecture/archi_perspectives/arch_diagrams.md index 05644e6e750..bd234ab073a 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/arch_diagrams.md +++ b/src/guides/v2.4/architecture/archi_perspectives/arch_diagrams.md @@ -2,6 +2,8 @@ group: architecture-guide title: Architectural diagrams menu_title: Architectural diagrams +migrated_to: https://developer.adobe.com/commerce/php/architecture/basics/diagrams/ +layout: migrated --- ## Magento architecture from different perspectives {#m2arch-whatis-overview} diff --git a/src/guides/v2.4/architecture/archi_perspectives/components/AComponents.md b/src/guides/v2.4/architecture/archi_perspectives/components/AComponents.md index cd2e976ed2d..4bbda0975f8 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/components/AComponents.md +++ b/src/guides/v2.4/architecture/archi_perspectives/components/AComponents.md @@ -2,6 +2,8 @@ group: architecture-guide title: Magento Components menu_title: Components +migrated_to: https://developer.adobe.com/commerce/php/architecture/modules/ +layout: migrated --- ## Magento components diff --git a/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_and_areas.md b/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_and_areas.md index 98320d3185e..54143545735 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_and_areas.md +++ b/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_and_areas.md @@ -2,6 +2,8 @@ group: architecture-guide title: Modules and areas menu_title: Modules and areas +migrated_to: https://developer.adobe.com/commerce/php/architecture/modules/areas/ +layout: migrated --- ## Overview {#m2arch-module-areas-overview} diff --git a/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_depend.md b/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_depend.md index bb3c5872c02..7a3085c1c8a 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_depend.md +++ b/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_depend.md @@ -2,6 +2,8 @@ group: architecture-guide title: Module dependencies menu_title: Module dependencies +migrated_to: https://developer.adobe.com/commerce/php/architecture/modules/dependencies/ +layout: migrated --- ## Overview {#m2devgde-moddep-intro} diff --git a/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_intro.md b/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_intro.md index 0d75d62c1f5..8409fca2ba9 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_intro.md +++ b/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_intro.md @@ -3,6 +3,8 @@ group: architecture-guide title: Module overview menu_title: Module overview redirect_from: guides/v2.4/install-gde/basics/basics_module.html +migrated_to: https://developer.adobe.com/commerce/php/architecture/modules/overview/ +layout: migrated --- ## What is a Magento module? {#arch-modules-overview} diff --git a/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_relationships.md b/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_relationships.md index 42d3d12491d..0e5d5d04285 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_relationships.md +++ b/src/guides/v2.4/architecture/archi_perspectives/components/modules/mod_relationships.md @@ -2,6 +2,8 @@ group: architecture-guide title: Module relationships menu_title: Module relationships +migrated_to: https://developer.adobe.com/commerce/php/architecture/modules/relationships/ +layout: migrated --- ## Overview {#m2arch-module-relationships-overview} diff --git a/src/guides/v2.4/architecture/archi_perspectives/domain_layer.md b/src/guides/v2.4/architecture/archi_perspectives/domain_layer.md index 9f0aead80d0..a68d18df6df 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/domain_layer.md +++ b/src/guides/v2.4/architecture/archi_perspectives/domain_layer.md @@ -2,6 +2,8 @@ group: architecture-guide title: Domain layer menu_title: Domain layer +migrated_to: https://developer.adobe.com/commerce/php/architecture/layers/domain/ +layout: migrated --- ## The Magento Domain layer diff --git a/src/guides/v2.4/architecture/archi_perspectives/framework.md b/src/guides/v2.4/architecture/archi_perspectives/framework.md index 4aa1bd994a1..01ac01d87c1 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/framework.md +++ b/src/guides/v2.4/architecture/archi_perspectives/framework.md @@ -1,6 +1,8 @@ --- group: architecture-guide title: Commerce and Magento Framework +migrated_to: https://developer.adobe.com/commerce/php/architecture/framework/ +layout: migrated --- ## Overview diff --git a/src/guides/v2.4/architecture/archi_perspectives/persist_layer.md b/src/guides/v2.4/architecture/archi_perspectives/persist_layer.md index b8d04c610cc..286390865ee 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/persist_layer.md +++ b/src/guides/v2.4/architecture/archi_perspectives/persist_layer.md @@ -1,6 +1,8 @@ --- group: architecture-guide title: Persistence layer +migrated_to: https://developer.adobe.com/commerce/php/architecture/layers/persistence/ +layout: migrated --- Magento uses an active record pattern strategy for persistence. In this system, the model object contains a *resource model* that maps an object to one or more database rows. A resource model is responsible for performing functions such as: diff --git a/src/guides/v2.4/architecture/archi_perspectives/present_layer.md b/src/guides/v2.4/architecture/archi_perspectives/present_layer.md index d41a6fac09a..40252f46f2b 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/present_layer.md +++ b/src/guides/v2.4/architecture/archi_perspectives/present_layer.md @@ -1,6 +1,8 @@ --- group: architecture-guide title: Presentation Layer +migrated_to: https://developer.adobe.com/commerce/php/architecture/layers/presentation/ +layout: migrated --- ## What is the Magento Presentation layer? diff --git a/src/guides/v2.4/architecture/archi_perspectives/service_layer.md b/src/guides/v2.4/architecture/archi_perspectives/service_layer.md index c4d567a11d9..56ffc6bc1e3 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/service_layer.md +++ b/src/guides/v2.4/architecture/archi_perspectives/service_layer.md @@ -2,6 +2,8 @@ group: architecture-guide title: Service layer menu_title: Service layer +migrated_to: https://developer.adobe.com/commerce/php/architecture/layers/service/ +layout: migrated --- ## What is a Service layer? diff --git a/src/guides/v2.4/architecture/archi_perspectives/tech-vision.md b/src/guides/v2.4/architecture/archi_perspectives/tech-vision.md index f437a525776..665fba6bdf0 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/tech-vision.md +++ b/src/guides/v2.4/architecture/archi_perspectives/tech-vision.md @@ -1,6 +1,8 @@ --- group: architecture-guide title: Magento technical vision +migrated_to: https://developer.adobe.com/commerce/php/architecture/technical-vision/ +layout: migrated --- The Magento technical vision is a collection of documents that describe the desired state of the Magento platform. diff --git a/src/guides/v2.4/architecture/archi_perspectives/third-party-libs.md b/src/guides/v2.4/architecture/archi_perspectives/third-party-libs.md index 707e98374bf..876ca7d9170 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/third-party-libs.md +++ b/src/guides/v2.4/architecture/archi_perspectives/third-party-libs.md @@ -2,6 +2,8 @@ group: architecture-guide title: Third-party libraries menu_title: Third-party libraries +migrated_to: https://developer.adobe.com/commerce/php/architecture/modules/libraries/ +layout: migrated --- Magento depends on a set of external libraries. You can use [Composer](https://glossary.magento.com/composer) to manage these dependencies. Composer downloads all of the external libraries that are included in its main configuration file and installs them under its default installation directory (`vendor/`). Third-party libraries include the Zend framework files and the Symfony libraries. diff --git a/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md b/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md index 880783f56c6..8ce39d434cc 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md +++ b/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md @@ -1,5 +1,7 @@ --- group: architecture-guide +migrated_to: https://developer.adobe.com/commerce/php/architecture/technical-vision/web-api/ +layout: migrated --- # Technical vision - Web API diff --git a/src/guides/v2.4/architecture/bk-architecture.md b/src/guides/v2.4/architecture/bk-architecture.md index ebe4eb09bbd..998121be972 100644 --- a/src/guides/v2.4/architecture/bk-architecture.md +++ b/src/guides/v2.4/architecture/bk-architecture.md @@ -4,6 +4,8 @@ title: Architecture Guide landing-page: Architecture menu_title: Get Started menu_node: parent +migrated_to: https://developer.adobe.com/commerce/php/architecture/ +layout: migrated --- The Architecture Guide provides a high-level introduction and view of the Magento product. diff --git a/src/guides/v2.4/architecture/extensibility.md b/src/guides/v2.4/architecture/extensibility.md index 9d0f95ec09f..c3eaed558a4 100644 --- a/src/guides/v2.4/architecture/extensibility.md +++ b/src/guides/v2.4/architecture/extensibility.md @@ -2,6 +2,8 @@ group: architecture-guide title: Extensibility and modularity menu_title: Extensibility and modularity +migrated_to: https://developer.adobe.com/commerce/php/architecture/modules/ +layout: migrated --- ## Overview diff --git a/src/guides/v2.4/architecture/global_extensibility_features.md b/src/guides/v2.4/architecture/global_extensibility_features.md index 2b3aa3757f2..13193818ba7 100644 --- a/src/guides/v2.4/architecture/global_extensibility_features.md +++ b/src/guides/v2.4/architecture/global_extensibility_features.md @@ -1,6 +1,8 @@ --- group: architecture-guide title: Global features that support extensibility +migrated_to: https://developer.adobe.com/commerce/php/architecture/modules/ +layout: migrated --- ## Overview diff --git a/src/guides/v2.4/architecture/security_intro.md b/src/guides/v2.4/architecture/security_intro.md index 0d669b65de1..4ac4dee9760 100644 --- a/src/guides/v2.4/architecture/security_intro.md +++ b/src/guides/v2.4/architecture/security_intro.md @@ -4,6 +4,8 @@ subgroup: Architectural Basics title: Security overview menu_title: Security menu_order: +migrated_to: https://developer.adobe.com/commerce/php/architecture/basics/security/ +layout: migrated --- The security of your data and digital experiences is our priority. To better protect {{site.data.var.ee}} and {{site.data.var.ce}} installations from the physical layer up, we have implemented hundreds of processes and controls to help us comply with [industry-accepted standards][1], regulations, and certifications. To help protect installations from the software layer down, we build in security measures that are based on the [Adobe Secure Product Lifecyle][2]. diff --git a/src/guides/v2.4/architecture/storefront_customization.md b/src/guides/v2.4/architecture/storefront_customization.md index 8eaac330dea..eef679c8f2e 100644 --- a/src/guides/v2.4/architecture/storefront_customization.md +++ b/src/guides/v2.4/architecture/storefront_customization.md @@ -2,6 +2,8 @@ group: architecture-guide title: Storefront customization strategies menu_title: Storefront customization strategies +migrated_to: https://developer.adobe.com/commerce/php/architecture/basics/frontend-customization/ +layout: migrated --- ## Overview From 3fe6babd9a977e225308e7ff2912631e8ea07d5d Mon Sep 17 00:00:00 2001 From: outis Date: Tue, 17 May 2022 14:25:09 -0700 Subject: [PATCH 046/776] Encode "<" as "<" Fix for #9439. --- .../v2.3/coding-standards/docblock-standard-javascript.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/guides/v2.3/coding-standards/docblock-standard-javascript.md b/src/guides/v2.3/coding-standards/docblock-standard-javascript.md index d3af74620f3..78968907825 100644 --- a/src/guides/v2.3/coding-standards/docblock-standard-javascript.md +++ b/src/guides/v2.3/coding-standards/docblock-standard-javascript.md @@ -388,7 +388,7 @@ new Date() An array of numbers - Array.> + Array.<Array.<string>>
[['one', 'two', 'three'], ['foo', 'bar']]
Array of arrays of strings @@ -404,7 +404,7 @@ new Date() An object. In the object, the values are strings. - Object. + Object.<number, string>
var obj = {};
 obj[1] = 'bar';
An object. In the object, the keys are numbers and the values are strings. @@ -725,4 +725,4 @@ new project.MyClass() - \ No newline at end of file + From 1d4c7e22aeff6c0c54b024044b1fb04fe80de538 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 17 May 2022 17:02:17 -0500 Subject: [PATCH 047/776] Fix migration generator --- src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md b/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md index 8ce39d434cc..59780537b1e 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md +++ b/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md @@ -1,5 +1,6 @@ --- group: architecture-guide +title: Technical vision - Web API migrated_to: https://developer.adobe.com/commerce/php/architecture/technical-vision/web-api/ layout: migrated --- From d86e9e5f1247b73b3c262deb8daa7eccd576e86c Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 17 May 2022 17:06:26 -0500 Subject: [PATCH 048/776] Fixed linter --- .../v2.4/architecture/archi_perspectives/webapi-vision.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md b/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md index 59780537b1e..893b91d7a9c 100644 --- a/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md +++ b/src/guides/v2.4/architecture/archi_perspectives/webapi-vision.md @@ -5,8 +5,6 @@ migrated_to: https://developer.adobe.com/commerce/php/architecture/technical-vis layout: migrated --- -# Technical vision - Web API - Web API is crucial for Magento because of the need to integrate with order management, customer management, and other enterprise management software systems. There are many headless Magento installations in which a merchant partially uses Magento functionality, while the other pieces of an eCommerce website are provided by other systems. From 197f80f735ad5bc64e8a0fd8e2ba231568ef861a Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 17 May 2022 17:56:36 -0500 Subject: [PATCH 049/776] Fixed TOC --- src/_data/toc/architecture-guide.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_data/toc/architecture-guide.yml b/src/_data/toc/architecture-guide.yml index 85354b17ccf..293bcbd8b44 100644 --- a/src/_data/toc/architecture-guide.yml +++ b/src/_data/toc/architecture-guide.yml @@ -59,4 +59,4 @@ pages: children: - label: Web Api - url: /get-started/bk-get-started-api.html + url: /architecture/archi_perspectives/webapi-vision.html From 4a92f1240fb37baa3e7f861f605b4cb9c4e7fa0f Mon Sep 17 00:00:00 2001 From: Marc Ginesta Date: Wed, 18 May 2022 17:51:05 +0200 Subject: [PATCH 050/776] Reference Magento plugin installation in Magento PHPStorm plugin --- src/_data/toc/extension-best-practices.yml | 3 ++ .../phpstorm/download-from-jetbrains.png | Bin 0 -> 747447 bytes .../phpstorm/enable-magento-integration.png | Bin 0 -> 308556 bytes .../phpstorm/install-through-phpstorm.png | Bin 0 -> 349503 bytes .../phpstorm/installation.md | 30 ++++++++++++++++++ .../phpstorm/installation.md | 1 + 6 files changed, 34 insertions(+) create mode 100644 src/common/images/phpstorm/download-from-jetbrains.png create mode 100644 src/common/images/phpstorm/enable-magento-integration.png create mode 100644 src/common/images/phpstorm/install-through-phpstorm.png create mode 100644 src/guides/v2.3/ext-best-practices/phpstorm/installation.md create mode 120000 src/guides/v2.4/ext-best-practices/phpstorm/installation.md diff --git a/src/_data/toc/extension-best-practices.yml b/src/_data/toc/extension-best-practices.yml index 763f626d6db..fc05e581759 100644 --- a/src/_data/toc/extension-best-practices.yml +++ b/src/_data/toc/extension-best-practices.yml @@ -37,6 +37,9 @@ pages: url: /ext-best-practices/phpstorm/introduction.html children: + - label: Installation + url: /ext-best-practices/phpstorm/installation.html + - label: Code generation url: /ext-best-practices/phpstorm/code-generation.html diff --git a/src/common/images/phpstorm/download-from-jetbrains.png b/src/common/images/phpstorm/download-from-jetbrains.png new file mode 100644 index 0000000000000000000000000000000000000000..ab55055e758e1383563b7726cf247f3eb30062b7 GIT binary patch literal 747447 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%0Ado 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

9@nqiT8n9?D|LuUf{|stH4EO38 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

S%d0S{e}%V(LUvUsbvKR){1t0p)+U_ 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%0DM3pbV3 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

xY=Y!M~VL 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⪙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%0D)4Q^bTAF$LY1`7Tu)l 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

d0>gG_a%lB*V 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

uBnu>AlO4TJ1B#L_w{ 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 z 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 D!hC5!^YJXDjt&u;v|Owqb*ie6Ab~`- zQI8Y*6hb(sa3~dx7ph+;bA1KGmP2YgE`j`q17)N=F|qtL-9qL}UeedHNJCQn38+0x zHC__lkQZNNQf=g@wj?S~oruHrQ|~DBeNh6Gfb6lqPT4`OBH>D!@)PdS>B>Cf;xUp* zo!WSbuYn!&YLVzHTOiFdW_k^m#j&VHHdR7>oB7_wy1()lu8XN{kysAAhwRkVZ}?+F z`Q?2W3Im_9q86(U6*etT&ErHtK45wE zzExu&cQ-kxu~zC;5WMY@=ot;}J=Pnhym+&;+PrR6!L(IO17X;t)B+5_UQ$!rHUK=u zk>Sr%A{V(;nClx(*tyy}nR`~JEm!MO?f`NH-0}A(GCwMsnWRPSy&KLw+-sB(0xe7|D{PP(4uyGL>s3=}ZKb6vWRJ`LP}$39bK zhSTkQhKhi%<#PL{Vr>1dACEXpod(tAt*VsPVsZY6^M}`u5brjt^YJ;)_OSUupvm(I z;VMB9dBp4XOQ1N%P~-@HaV$sQqIccoXNl>0@5zdwgSIByDupOHtIcUJNLZe)R($5! zN*{7P=ed!D>SLQbEx5a&u9ps<0h1KsoIyM&BlNsg0DPxVha#o_yO|n75%dHclsr@% z1;FQyzj-Izjf7dItx3xyqAo9vFU@ytD5^~F%L05XQv0$`q07=3t`wJ6uX@qp8eIcPFfBe^ggBv*I1RS8u2_C)#N zUOx(z!k#QSHA@6iHc+z0gfkl-57v;9O!08ZqKophJL8Oe>?!DXj~y;|ITxP=Jl1RhFP2NFgG9y@y5{*~-dSeU*$)@;ly*w{eBE^VpL5fu&o_UnrULSL{ozu4 z(|0DCYtMzJb{4LXE)X6@jrEhkqRa~^5ybE+*NyM9ALs)YP~>vp2v)himHIlbM6De{ zxbMOcb7n@!vk)Z_Qp0u15Mx1sULrglx{Nmy#S0bzds(H##_q!D1_yBsmo0i9J6ywV z3rz+}2PqLAU+1X_6^`5*yw7sVIy45s~Eu8Dm&60{btXM_7YfvV`Dzdk=D#}`eP|sRzO4oj0A^rKHob8(LQ6K!(+1U`r^9GN5-P18r881_I!bV9W#734z^&Ue zk!D;WAuQxY>rDF?;XJ*2aCo1uP8k5GcoSdVOuFuj>gLR% z3F;B4;XdknXie=;kM=ZDFUf@{pw7sB6^vw*WRIWG7Det^)bAsUC3_UrPWcAyE&I-xHwh+wsrT-K=Lv$;W1BxI)9<&}iHKTdnA#1LgqOBQFgb{py{VMTZp%t>@5y)Grjpl16v

  • _OCMeh(*X#jAGa(SGQFT#dgiT$ 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%0Deh{^2zu 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

    dvIqoT%vvnXT>mUvf3XN?Z# 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

    hD4S56fx{$FO)9Q0iO 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

    +

    ...

    +

    ...

    +
    +Scroll to text +``` + +**Unacceptable:** + +```html +
    +

    ...

    +

    ...

    +
    +
    +

    ...

    +

    ...

    +
    +Scroll to text +``` + +### Semantic representation may rely on ID attribute + +- Forces engineers to think about reusable page components instead of unique singleton components. +- Reduces long-term maintenance efforts. + +**Acceptable [PHTML](https://glossary.magento.com/phtml) template:** + +The following acceptable example is terse and uses an Accessible Rich Internet Applications (ARIA) approach. + +```html +
      +
    • button 1
    • +
    • button 2
    • +
    • button 3
    • +
    +
    + + +
    +Scroll to text +``` + +**Unacceptable combination of PHTML, JavaScript, and CSS files:** + +The following unacceptable example replaces a single PHTML file with a combination of a PHTML, JavaScript, and CSS files. + +**PHTML file:** + +```php +
      +
    • button 1
    • +
    • button 2
    • +
    • button 3
    • +
    +``` + +**JavaScript file:** + +```js +$('#my-special-menu').on('click','li[id^="button"]', function() { ... }) +``` + +**CSS file:** + +```css +#my-special-menu { ... } +#my-special-menu > li { ... } +``` + +### You must follow the separation of presentation and content methodology + +The following list will help you make a distinction between the actual meaning of a document, and how this meaning is presented to its readers: + +**Content (Semantics)** includes: + +- logic +- information +- data +- model +- outline +- message + +**Presentation** includes: + +- aesthetic +- graphics +- design +- style +- visualization +- view + +### You must use semantic HTML markup only, and must not use presentation markup + +**Acceptable:** + +```html +

    HTML has been created to semantically represent documents.

    +

    Warning: Following the procedure described below may irreparably damage your equipment.

    +``` + +**Unacceptable:** + +```html +

    HTML has been created to semantically represent documents.

    +

    Warning: Following the procedure described below may irreparably damage your equipment.

    +``` + +## Code demarcation + +### Visual representation must rely only on HTML `class` attributes, CSS pseudo-classes and pseudo-elements, HTML tags, and form element's type attribute and form elements state attributes (example: `disabled`, `checked`). + +As the first option, you are required to use [HTML](https://glossary.magento.com/html) class attributes. In case this option is not applicable then it is recommended to use HTML tags and form element's type attribute. + +- Enforces clean, strict separation between visual and business logic layers. +- Allows [frontend](https://glossary.magento.com/frontend) and [backend](https://glossary.magento.com/backend) teams to work independently. +- Allows changing look and feel without affecting business functionality, and vice versa. +- Enables frontend teams to clean up old styles quickly and easily when refactoring. + +**Acceptable CSS selectors:** + +```css +.notices-wrapper { ... } +.page-header:after { ... } +.payment-list:first-child { ... } +.caution { ... } +.caution.link { ... } +form input[type="password"] { ... } +.control-text:focus { ... } +a:hover { ... } +nav li._active { ... } +``` + +**Unacceptable CSS selectors:** + +```css +#header { ... } +[data-action="delete"] { ... } +form input[name="password"] { ... } +section[role="main"] { ... } +[role="menu] [role="menuitem"] { ... } +[role="menu] [role="menuitem"].active { ... } +``` + +### You must not hard-code CSS styles in JavaScript files + +{% +include note.html +type='info' +content='Exception: CSS attributes where values must be calculated beyond the css-topics/LESS code. + +- Simplifies change of the default look and feel by adding CSS classes to and removing them from elements. +- Improves style extensibility. +- Reduces long-term maintenance efforts by containing CSS styles in a single place.' + +%} + +**Acceptable [JavaScript](https://glossary.magento.com/javascript) [widget](https://glossary.magento.com/widget) file:** + +```js +... + options: { + hOffset: 0, + myCustomElement: '[data-container="my-custom-element"]', + hiddenClass: '_hidden' + } +... + this.element.toggleClass(this.options.hiddenClass); +... + this.options.hOffset = /* calculation based on dimensions of some DOM elements within a widget */ + this.element.find(this.options.myCustomElement).css({'margin-top', this.options.hOffset + 'px'}); +... +``` + +**Unacceptable JavaScript file:** + +```js +this.element.on('click', function() { + if ($(this).is(':visible')) { + $(this).css({ visibility: 'hidden' }); + } else { + $(this).css({ visibility: 'visible' }); + } +}); +``` + +### You must not use inline CSS styles inside HTML tags + +- Improves style extensibility allowing engineers to overload styles easier by toggling classes. +- Enforces clean, strict separation between visual presentation and markup. +- Enables frontend teams quickly and easily clean up old styles. + +**Acceptable PHTML template:** + +```php +
    ...
    +``` + +**Unacceptable PHTML template:** + +```php +
    ...
    +``` + +## Business logic and JavaScript + +### Business logic must rely on only the form, form element name attributes, or data attributes + +- Enforces clean, strict separation between visual and business logic layers. +- Allows frontend and backend teams to work independently. +- Allows changing business logic without affecting styling and vice versa. + +**Acceptable PHTML template:** + +```php +
    +
    More details
    +``` + +**Acceptable JavaScript file:** + +```js +options { + deleteAction: '[data-action="delete"]', + tooltip: '[data-role="tooltip"]' +} +... +this.element.find(this.options.deleteAction).on( ... ); +this.element.on('click', this.options.deleteAction , function() { ... }); +... +// Globally initialized widgets +$( this.options.tooltip).tooltip(); // Globally for ALL tooltip elements +... +``` + +**Unacceptable PHTML file:** + +```html +
    +``` + +**Unacceptable JavaScript file:** + +```js +$('#my-widget').doSomething(); +$('.parent').on('click', '.button', function() { ... }); +$('form').validate(); +$('[role="menu"]').navigation(); +``` + +### You must assign HTML helper classes in JavaScript to modify presentation layer + +HTML helper class names added in JavaScript REQUIRE underscore symbol ("_") at the beginning and must be written in lowercase. + +**Acceptable:** + +```html +
    Content
    +
    Content
    +
    Content
    +
    Content
    +``` + +**Unacceptable:** + +```html +
    Content
    +
    Content
    +
    Content
    + +``` + +### You must not select DOM elements based on HTML structure + +- Allows frontend teams to modify markup and themes without affecting business logic. + +**Acceptable JavaScript file:** + +```js +this.element.find('[data-action="edit"]'); +this.elements.closest('[data-container]'); +``` + +**Unacceptable JavaScript file:** + +```js +this.element.children().children().html('hello world'); +this.element.parent().find('[data-action="edit"]').data('entity_id'); +``` + +### You must use jQuery templates to insert recurring markup into DOM structure + +- Reinstates emphasis on jQuery templates. For more information, see JavaScript Coding Best Practices. +- Reduces long-term maintenance efforts by having markup code stored in one place. +- Simplifies frontend debugging efforts. + +## PHTML templates and PHP files + +### You must not hard-code inline CSS styles in PHP classes + +- Reduces long-term maintenance efforts by having styles stored in one place. +- Simplifies debugging and reduces number of files to be modified. +- Makes styles more extensible and easier to override when needed. + +**Acceptable PHP file:** + +```php +... +$fieldset->addField('new_category_parent', 'text', [ + 'label' => __('Parent Category'), + 'title' => __('Parent Category'), + 'required' => true, + 'class' => 'parent category', +]); +... +``` + +**Unacceptable PHP file:** + +```php +... +$fieldset->addField('new_category_parent', 'text', [ + 'label' => __('Parent Category'), + 'title' => __('Parent Category'), + 'required' => true, + 'style' => 'border: 1px solid #ccc;', +]); +... +``` + +### You must not hard-code inline JavaScript in PHP classes + +- Reduces long term maintenance by having frontend business logic stored in one place. +- Reduces the number of files to be modified. + +**Acceptable PHP file:** + +```php +... +public function getSelectorOptions() +{ + return $selectorOptions; +} +... +``` + +**Acceptable PHTML template:** + +```php +... +
    +... +``` + +or + +**Acceptable PHTML template:** + +```php +... +
    + +... +``` + +**Unacceptable PHP file:** + +```php +... +public function getAfterElementHtml() +{ + return << +jQuery('#{$htmlId}-suggest').treeSuggest({$selectorOptions}); + +... +``` + +**Unacceptable PHTML template:** + +```php +getAfterElementHtml(); ?> +``` + +### You must not hard-code HTML markup (used in the `` tag) in PHP classes + +- Reduces long-term maintenance efforts by having markup stored in one place. +- Reduces the number of files to be modified. + +**Acceptable PHP file:** + +```php +... +public function getAttributeName($element) +{ + return ($element->getExtType() === 'multiple') ? $element->getId() . '_checkbox' : NULL; +} + +public function getAttributeId($element) +{ + return $element->getId(); +} +... +``` + +**Acceptable PHTML template:** + +```php + + + + +``` + +**Unacceptable PHP file:** + +```php +... +public function getCheckbox($elementName){ + $elementNameTag = $this->getAttributeName($elementName) ? 'name="' . $this->getAttributeName($elementName) . '"' : NULL; + $tpl = ""; + return $tpl; +} +... +``` + +**Unacceptable PHTML template:** + +```php + + + + +``` diff --git a/src/guides/v2.4/coding-standards/code-standard-html.md b/src/guides/v2.4/coding-standards/code-standard-html.md deleted file mode 120000 index 6aeae57681b..00000000000 --- a/src/guides/v2.4/coding-standards/code-standard-html.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/coding-standards/code-standard-html.md \ No newline at end of file diff --git a/src/guides/v2.4/coding-standards/code-standard-html.md b/src/guides/v2.4/coding-standards/code-standard-html.md new file mode 100644 index 00000000000..b365851d0ee --- /dev/null +++ b/src/guides/v2.4/coding-standards/code-standard-html.md @@ -0,0 +1,145 @@ +--- +group: coding-standards +subgroup: 01_Coding standards +title: HTML style guide +landing-page: Coding standards +menu_title: HTML style guide +menu_order: 9 +functional_areas: + - Standards +migrated_to: https://developer.adobe.com/commerce/php/coding-standards/html-style-guide/ +layout: migrated +--- + +This style guide defines Magento internal requirements for [HTML](https://glossary.magento.com/html) code style for teams that develop Less and [CSS](https://glossary.magento.com/css) code. We recommend that developers who create extensions and customizations also use these standards. + +The guide is based on the [Google HTML/CSS Style Guide](https://google.github.io/styleguide/htmlcssguide.xml) with certain modifications that are described further. + +## Indentations + +Use only spaces for indentation: + +* Tab size: 4 spaces +* Indent size: 4 spaces +* Continuation indent: 4 spaces + +**Recommended:** + +```html +
      +
    • One
    • +
    • Two
    • +
    +``` + +## End of file + +Add a blank line at the end of file. + +## Self-closing tags + +Always close self-closing tags. + +**Inappropriate:** + +```html +
    +image + +``` + +**Recommended:** + +```html +
    +image + +``` + +## Line length + +Avoid code lines longer than 120 characters. When using an editor, it is inconvenient to scroll right and left to read the HTML code. Align tag attributes one under another to increase code readability. + +**Inappropriate:** + +```html + +``` + +**Recommended:** + +```html + +``` + +## Spaces around equals sign ("=") + +Spaces around equals sign ("=") are acceptable, but not recommended. The code without spaces is easier to read. + +**Not recommended:** + +```html + +``` + +**Recommended:** + +```html + +``` + +## Spaces and colon in attributes + +Use no space before the colon and one space after the colon for the sake of readability. + +**Not recommended:** + +```html + + +``` + +**Recommended:** + +```html + +``` + +## Block-level elements + +Use appropriate HTML5 elements for blocks. The following diagram shows how to define which HTML5 element to use for a block: + +![]({{ site.baseurl }}/common/images/h5d-sectioning-flowchart.png) + +## Class names + +Use semantic class names and IDs. Avoid presentational class names. + +**Inappropriate:** + +```html + +``` + +**Recommended:** + +```html + + +``` + +## Accessibility + +All pages should comply with the [Web Content Accessibility Guidelines (WCAG) 2.0](https://www.w3.org/TR/WCAG20/). + +## Microdata + +All crucial pages (like product page) should contain [microdata](https://www.w3.org/TR/microdata/). Please pay attention to this recommendation when adding new functionality. diff --git a/src/guides/v2.4/coding-standards/code-standard-javascript.md b/src/guides/v2.4/coding-standards/code-standard-javascript.md index 7fcad041123..eafb118b658 100644 --- a/src/guides/v2.4/coding-standards/code-standard-javascript.md +++ b/src/guides/v2.4/coding-standards/code-standard-javascript.md @@ -4,6 +4,8 @@ title: JavaScript coding standard landing-page: Coding standards functional_areas: - Standards +migrated_to: https://developer.adobe.com/commerce/php/coding-standards/js/ +layout: migrated --- Use Magento's [ESLint Rules][eslint-rules] to make sure your code adheres to Magento's coding standards. diff --git a/src/guides/v2.4/coding-standards/code-standard-jquery-widgets.md b/src/guides/v2.4/coding-standards/code-standard-jquery-widgets.md deleted file mode 120000 index 9ce02c39eab..00000000000 --- a/src/guides/v2.4/coding-standards/code-standard-jquery-widgets.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/coding-standards/code-standard-jquery-widgets.md \ No newline at end of file diff --git a/src/guides/v2.4/coding-standards/code-standard-jquery-widgets.md b/src/guides/v2.4/coding-standards/code-standard-jquery-widgets.md new file mode 100644 index 00000000000..73c43b42a19 --- /dev/null +++ b/src/guides/v2.4/coding-standards/code-standard-jquery-widgets.md @@ -0,0 +1,357 @@ +--- +group: coding-standards +subgroup: 01_Coding standards +title: jQuery widget coding standard +landing-page: Coding standards +menu_title: jQuery widget coding standard +menu_order: 7 +functional_areas: + - Standards +migrated_to: https://developer.adobe.com/commerce/php/coding-standards/jquery-widgets/ +layout: migrated +--- + +In the Magento system, all jQuery UI widgets and interactions are built on a simple, reusable base---the [jQuery UI Widget Factory][jquery-ui-widget-factory]. + +The factory provides a flexible base for building complex, stateful plug-ins with a consistent [API](https://glossary.magento.com/api). +It is designed not only for plug-ins that are part of [jQuery](https://glossary.magento.com/jquery) UI, but for general usage by developers who want to create object-oriented components without reinventing common infrastructure. + +For more information, see the [jQuery Widget API documentation][jquery-ui-api-doc]. + +This standard is mandatory for Magento core developers and recommended for third-party [extension](https://glossary.magento.com/extension) developers. +Some parts of Magento code might not comply with the standard, but we are working to gradually improve this. + +Use [RFC 2119][rfc2119] to interpret the "must," "must not," "required," "shall," "shall not," "should," "should not," "recommended," "may," and "optional" keywords. + +## Naming conventions + +* [Widget](https://glossary.magento.com/widget) names must consist of one or more non-abbreviated English word and in camelcase format. + + ```javascript + (function($) { + $.widget('mage.accordion', $.ui.accordion, { + // ... My custom code ... + }); + ``` + +* Widget names should be verbose enough to fully describe their purpose and behavior. + + ```javascript + // Declaration of the frontend.advancedEventTrigger widget + (function($) { + "use strict"; + + $.widget('mage.advancedEventTrigger', $.ui.button, { + // ... My custom code ... + }); + }) (jQuery); + ``` + +## Instantiation and resources + +* Additional [JavaScript](https://glossary.magento.com/javascript) files used as a resources must be dynamically loaded using the `$.mage.components()` method and must not be included in the `` block. +* Use the `$.mage.components()` method to load additional JavaScript resource files not included in the `` block. +* You must use `$.mage.extend()` to extend an existing set of widget resources. +* You must instantiate widgets using the `data-mage-init` attribute. + You can use the `.mage()` [plug-in](https://glossary.magento.com/plug-in) to instantiate widgets that use callback methods. + + Benefits: + + * You leverage the benefits of `$.mage.extend()` and `$.mage.components()`. + * Using `data-mage-init` minimizes the inline JavaScript code footprint. + * You can modify widget initialization parameters. + + ```javascript + // Widget initialization using the data-mage-init attribute +
    + + // Widget initialization using the mage plug-in + (function($) { + $('selector').mage('dialog', { + close: function(e) { + $(this).dialog('destroy'); + } + }); + })(jQuery); + ``` + +* You can declare callback methods inline JavaScript but not methods and widgets. + + ```javascript + // Widget initialization and configuration + $('selector').mage('dialog', { + close: function(e) { + $(this).dialog('destroy'); + } + }); + + // Widget initialization and binding event handlers + $('selector').mage('dialog').on('dialogclose', { + $(this).dialog('destroy'); + }); + + // Extension for widget in a JavaScript file + $.widget('mage.dialog', $.ui.dialog, { + close: function() { + this.destroy(); + } + }); + + // Extension of widget resources + (function($) { + $.mage + .extend('dialog', 'dialog', + 'getViewFileUrl('Enterprise_\*Module\*::page/js/dialog.js') ?>') + })(jQuery); + ``` + +### Initializing a component on a selector + +There are two ways to initialize a component on a selector: + +* Initialize the component in the `data-mage-init` attribute: + + ```html +
    + ``` + +* Use a script type `text/x-magento-init` attribute: + + ```html + + ``` + +In these cases the path to the file is: + + `Vendor/Module/view/frontend/web/js/jsfilename.js` + + which contains your code: + + ```javascript + define(['uiComponent'], + function (Component) { + 'use strict'; + return Component.extend({ + initialize: function (config, node) { + // some code + } + }); + }); + ``` + +### Initializing a component on a selector with parameters + +When a component is initialized, it is also important to send parameters to it, which are normally determined dynamically in PHP. + +* `data-mage-init` + + ```html +
    + ``` + +* Using a script type `text/x-magento-init` attribute. For example: + + ```html + + ``` + +## Development standards + +* Widgets should comply with the [single responsibility principle][single-responsibility-principle]. + + Widgets should not have responsibilities not related to the [entity](https://glossary.magento.com/entity) described by the widget. + + ```javascript + // Widget "dialog" that is responsible + // only for opening content in an interactive overlay. + $.widget('mage.dialog', { + // Code logic + }); + + // Widget "validation" that is responsible + // only for validating the form fields. + $.widget('mage.validation', $.ui.sortable, { + // Code logic + }); + + $('selector') + .mage('dialog') + .find('form') + .mage('validation'); + ``` + +* Widget properties that modify the widget's behavior must be located in the widget's options to make them configurable and reusable. + + ```javascript + //Declaration of the backend.dialog widget + $.widget('mage.dialog', { + options: { + modal: false, + autoOpen: true, + // Additional widget options + }, + // Additional widget properties + }); + + // Initializing + $('selector').mage('dialog', { + modal: true, + autoOpen: false + }); + ``` + +* Widget communications must be handled by jQuery events + + ```html + + ... +

    =rE-=eJ|%jVE`>mpky#k27ts{k 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 Zz!wtq+IR1o)_uT_)_whZWop(h{~xcSWkCP{ literal 0 HcmV?d00001 diff --git a/src/common/images/phpstorm/install-through-phpstorm.png b/src/common/images/phpstorm/install-through-phpstorm.png new file mode 100644 index 0000000000000000000000000000000000000000..ac6004ca9b90a658504a44a2b209c9b9aafc0e8d GIT binary patch literal 349503 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%0AYSsmmi4AG`T{K7PIZ&!8y7m_v{m-d-h^1#_ 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 z¨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 Plugins`. + +![]({{site.baseurl}}/common/images/phpstorm/install-through-phpstorm.png) + +In any case, after installing it you will need to enable the integration with Magento through `Preferences -> Frameworks`. + +To do so, you have to check the `Enable Magento Integration` as it indicated [here](https://github.com/magento/magento2-phpstorm-plugin#installation). + +Apart from this, you are also asked for: + +- Magento installation path +- Adobe Commerce version (i.e., `2.4.1`) +- Default license name for new modules (by default, `Proprietary`) + +![]({{site.baseurl}}/common/images/phpstorm/enable-magento-integration.png) + +You can find more information in the following page: + +- [Using the Upgrade Compatibility Tool on PHP Storm](https://experienceleague.adobe.com/docs/commerce-learn/tutorials/upgrade/uct-phpstorm.html?lang=en). diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/installation.md b/src/guides/v2.4/ext-best-practices/phpstorm/installation.md new file mode 120000 index 00000000000..00e4a464c34 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/phpstorm/installation.md @@ -0,0 +1 @@ +../../../v2.3/ext-best-practices/phpstorm/installation.md \ No newline at end of file From 8774f4e99c41bc34626f77efd2f0db7787e008fd Mon Sep 17 00:00:00 2001 From: Marc Ginesta Date: Wed, 18 May 2022 18:15:38 +0200 Subject: [PATCH 051/776] Fix MD030 Spaces after list markers --- .../v2.3/ext-best-practices/phpstorm/installation.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/guides/v2.3/ext-best-practices/phpstorm/installation.md b/src/guides/v2.3/ext-best-practices/phpstorm/installation.md index ed33285432b..689db8ba841 100644 --- a/src/guides/v2.3/ext-best-practices/phpstorm/installation.md +++ b/src/guides/v2.3/ext-best-practices/phpstorm/installation.md @@ -19,12 +19,12 @@ To do so, you have to check the `Enable Magento Integration` as it indicated [he Apart from this, you are also asked for: -- Magento installation path -- Adobe Commerce version (i.e., `2.4.1`) -- Default license name for new modules (by default, `Proprietary`) +* Magento installation path +* Adobe Commerce version (i.e., `2.4.1`) +* Default license name for new modules (by default, `Proprietary`) ![]({{site.baseurl}}/common/images/phpstorm/enable-magento-integration.png) You can find more information in the following page: -- [Using the Upgrade Compatibility Tool on PHP Storm](https://experienceleague.adobe.com/docs/commerce-learn/tutorials/upgrade/uct-phpstorm.html?lang=en). +* [Using the Upgrade Compatibility Tool on PHP Storm](https://experienceleague.adobe.com/docs/commerce-learn/tutorials/upgrade/uct-phpstorm.html?lang=en). From 8880bbf9315f773d7b3e1010ff99e9cdea7efd4b Mon Sep 17 00:00:00 2001 From: jfrontain Date: Wed, 18 May 2022 12:07:36 -0500 Subject: [PATCH 052/776] added note about AC-2260 --- src/guides/v2.4/release-notes/commerce-2-4-4.md | 4 ++++ src/guides/v2.4/release-notes/open-source-2-4-4.md | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/guides/v2.4/release-notes/commerce-2-4-4.md b/src/guides/v2.4/release-notes/commerce-2-4-4.md index 2ba7b6cc277..91d46aa0846 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-4.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-4.md @@ -20,6 +20,10 @@ Although code for these features is bundled with quarterly releases of the {{ si {:.bs-callout-info} All vendor-bundled extensions, with the exception of Braintree, have been removed from {{ site.data.var.ee }} 2.4.4. +{:.bs-callout-info} + +Merchants upgrading to {{ site.data.var.ee }} 2.4.4 or {{ site.data.var.ce }} 2.4.4 after July 2022 will see a warning from Composer about unallowed plugins. Plugins will not be loaded during upgrade unless they have been explicitly allowed. To implement this, Composer is changing the default value of the `allow-plugins` option to `{}`. See the [Composer plugins issues when upgrading to Adobe Commerce 2.4.4](https://support.magento.com/hc/en-us/articles/6215997614093-Composer-plugins-issues-when-upgrading-to-Adobe-Commerce-2-4-4) Knowledge Base article for instructions on explicitly allowing plugin loading. + ### Hotfixes included in this release {{ site.data.var.ee }} 2.4.4 includes resolution of all issues that were addressed by the following hotfixes, which were provided for {{ site.data.var.ee }} and {{ site.data.var.ce }} 2.4.3, 2.4.3-p1, and 2.3.7-p2: diff --git a/src/guides/v2.4/release-notes/open-source-2-4-4.md b/src/guides/v2.4/release-notes/open-source-2-4-4.md index 9ac6654ad6c..b1b00a43404 100644 --- a/src/guides/v2.4/release-notes/open-source-2-4-4.md +++ b/src/guides/v2.4/release-notes/open-source-2-4-4.md @@ -20,6 +20,10 @@ Although code for these features is bundled with quarterly releases of the {{ si {:.bs-callout-info} All vendor-bundled extensions, with the exception of Braintree, have been removed from {{ site.data.var.ce }} 2.4.4. +{:.bs-callout-info} + +Merchants upgrading to {{ site.data.var.ee }} 2.4.4 or {{ site.data.var.ce }} 2.4.4 after July 2022 will see a warning from Composer about unallowed plugins. Plugins will not be loaded during upgrade unless they have been explicitly allowed. To implement this, Composer is changing the default value of the `allow-plugins` option to `{}`. See the [Composer plugins issues when upgrading to Adobe Commerce 2.4.4](https://support.magento.com/hc/en-us/articles/6215997614093-Composer-plugins-issues-when-upgrading-to-Adobe-Commerce-2-4-4) Knowledge Base article for instructions on explicitly allowing plugin loading. + ### Hotfixes included in this release {{ site.data.var.ce }} 2.4.4 includes resolution of all issues that were addressed by the following hotfixes, which were provided for {{ site.data.var.ee }} and {{ site.data.var.ce }} 2.4.3, 2.4.3-p1, and 2.3.7-p2: From b5b1b072b2e99236ed5ab931ec0961d46a9662b0 Mon Sep 17 00:00:00 2001 From: Barbazul Date: Wed, 18 May 2022 15:12:13 -0300 Subject: [PATCH 053/776] Cleared a wrong comment regarding path repository support --- .../v2.3/extension-dev-guide/build/composer-integration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.3/extension-dev-guide/build/composer-integration.md b/src/guides/v2.3/extension-dev-guide/build/composer-integration.md index c45cf90a9c5..f5863490fb7 100644 --- a/src/guides/v2.3/extension-dev-guide/build/composer-integration.md +++ b/src/guides/v2.3/extension-dev-guide/build/composer-integration.md @@ -12,7 +12,7 @@ Composer reads a `composer.json` file in Magento's root directory to download th We recommend you include `composer.json` in your component's root directory even if you do not intend to distribute it to other merchants using Magento. {:.bs-callout-info} -Magento does not support the [`path`][3] repository. +Magento does not support the [`path`][3] repository pointing to a folder outside of Magento root. ## composer.json From 115a47ed6e91ac252c428fe8ffc38ea202e8f310 Mon Sep 17 00:00:00 2001 From: jfrontain Date: Wed, 18 May 2022 13:15:39 -0500 Subject: [PATCH 054/776] added max a's review comments --- src/guides/v2.4/release-notes/commerce-2-4-4.md | 3 +-- src/guides/v2.4/release-notes/open-source-2-4-4.md | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/guides/v2.4/release-notes/commerce-2-4-4.md b/src/guides/v2.4/release-notes/commerce-2-4-4.md index 91d46aa0846..136ffb0bf47 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-4.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-4.md @@ -22,8 +22,7 @@ All vendor-bundled extensions, with the exception of Braintree, have been remove {:.bs-callout-info} -Merchants upgrading to {{ site.data.var.ee }} 2.4.4 or {{ site.data.var.ce }} 2.4.4 after July 2022 will see a warning from Composer about unallowed plugins. Plugins will not be loaded during upgrade unless they have been explicitly allowed. To implement this, Composer is changing the default value of the `allow-plugins` option to `{}`. See the [Composer plugins issues when upgrading to Adobe Commerce 2.4.4](https://support.magento.com/hc/en-us/articles/6215997614093-Composer-plugins-issues-when-upgrading-to-Adobe-Commerce-2-4-4) Knowledge Base article for instructions on explicitly allowing plugin loading. - +Merchants upgrading to {{ site.data.var.ee }} 2.4.4 or {{ site.data.var.ce }} 2.4.4 from 2.3.7 or later and 2.4.3or later after July 2022 will see a warning from Composer about unallowed plugins. Plugins will not be loaded during upgrade unless they have been explicitly allowed. To implement this, Composer 2.2.x is changing the default value of the `allow-plugins` option to `{}`. See the [Composer plugins issues when upgrading to Adobe Commerce 2.4.4](https://support.magento.com/hc/en-us/articles/6215997614093-Composer-plugins-issues-when-upgrading-to-Adobe-Commerce-2-4-4) Knowledge Base article for instructions on explicitly allowing plugin loading. ### Hotfixes included in this release {{ site.data.var.ee }} 2.4.4 includes resolution of all issues that were addressed by the following hotfixes, which were provided for {{ site.data.var.ee }} and {{ site.data.var.ce }} 2.4.3, 2.4.3-p1, and 2.3.7-p2: diff --git a/src/guides/v2.4/release-notes/open-source-2-4-4.md b/src/guides/v2.4/release-notes/open-source-2-4-4.md index b1b00a43404..b98b15747ca 100644 --- a/src/guides/v2.4/release-notes/open-source-2-4-4.md +++ b/src/guides/v2.4/release-notes/open-source-2-4-4.md @@ -22,7 +22,7 @@ All vendor-bundled extensions, with the exception of Braintree, have been remove {:.bs-callout-info} -Merchants upgrading to {{ site.data.var.ee }} 2.4.4 or {{ site.data.var.ce }} 2.4.4 after July 2022 will see a warning from Composer about unallowed plugins. Plugins will not be loaded during upgrade unless they have been explicitly allowed. To implement this, Composer is changing the default value of the `allow-plugins` option to `{}`. See the [Composer plugins issues when upgrading to Adobe Commerce 2.4.4](https://support.magento.com/hc/en-us/articles/6215997614093-Composer-plugins-issues-when-upgrading-to-Adobe-Commerce-2-4-4) Knowledge Base article for instructions on explicitly allowing plugin loading. +Merchants upgrading to {{ site.data.var.ee }} 2.4.4 or {{ site.data.var.ce }} 2.4.4 from 2.3.7 or later and 2.4.3or later after July 2022 will see a warning from Composer about unallowed plugins. Plugins will not be loaded during upgrade unless they have been explicitly allowed. To implement this, Composer 2.2.x is changing the default value of the `allow-plugins` option to `{}`. See the [Composer plugins issues when upgrading to Adobe Commerce 2.4.4](https://support.magento.com/hc/en-us/articles/6215997614093-Composer-plugins-issues-when-upgrading-to-Adobe-Commerce-2-4-4) Knowledge Base article for instructions on explicitly allowing plugin loading. ### Hotfixes included in this release From b9e49a77ec253d31c96f47007d250a55093aab82 Mon Sep 17 00:00:00 2001 From: Marc Ginesta Date: Thu, 19 May 2022 10:27:27 +0200 Subject: [PATCH 055/776] Remove useless blank line Co-authored-by: Daniel Del Carmen --- .../phpstorm/installation.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/guides/v2.3/ext-best-practices/phpstorm/installation.md b/src/guides/v2.3/ext-best-practices/phpstorm/installation.md index 689db8ba841..bd4b5953de5 100644 --- a/src/guides/v2.3/ext-best-practices/phpstorm/installation.md +++ b/src/guides/v2.3/ext-best-practices/phpstorm/installation.md @@ -5,6 +5,31 @@ functional_areas: - Standards --- +To install the Magento PHPStorm plugin: + +* Download the plugin from the [PHPStorm Marketplace](https://plugins.jetbrains.com/plugin/8024-magento-phpstorm). + + ![]({{site.baseurl}}/common/images/phpstorm/download-from-jetbrains.png) + +* In your PHPStorm screen navigate to **Preferences** > **Plugins** and select Magento PHPStorm. + + ![]({{site.baseurl}}/common/images/phpstorm/install-through-phpstorm.png) + +After the installation, it is necessary to enable the integration with Magento: + +1. Go to **Preferences** > **Frameworks**. +1. Select the **Enable Magento Integration** checkbox. See [Install PHPStorm plugin](https://github.com/magento/magento2-phpstorm-plugin#installation) topic for more information. + +You also need to provide: + +* Magento installation path +* Adobe Commerce version (i.e., `2.4.1`) +* Default license name for new modules (by default, `Proprietary`) + +![]({{site.baseurl}}/common/images/phpstorm/enable-magento-integration.png) + +See the video tutorial [Using the Upgrade Compatibility Tool on PHP Storm](https://experienceleague.adobe.com/docs/commerce-learn/tutorials/upgrade/uct-phpstorm.html?lang=en) page for more information about the Magento PHPStorm plugin. + You can download this plugin from the [PHP Storm Marketplace](https://plugins.jetbrains.com/plugin/8024-magento-phpstorm). ![]({{site.baseurl}}/common/images/phpstorm/download-from-jetbrains.png) From e0db29cae72336093eb7c54fcd7ac6c91b236ef4 Mon Sep 17 00:00:00 2001 From: Marc Ginesta Date: Thu, 19 May 2022 10:37:50 +0200 Subject: [PATCH 056/776] Rephrase Co-authored-by: Daniel Del Carmen --- src/guides/v2.3/ext-best-practices/phpstorm/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.3/ext-best-practices/phpstorm/installation.md b/src/guides/v2.3/ext-best-practices/phpstorm/installation.md index bd4b5953de5..4eedd886ac0 100644 --- a/src/guides/v2.3/ext-best-practices/phpstorm/installation.md +++ b/src/guides/v2.3/ext-best-practices/phpstorm/installation.md @@ -11,7 +11,7 @@ To install the Magento PHPStorm plugin: ![]({{site.baseurl}}/common/images/phpstorm/download-from-jetbrains.png) -* In your PHPStorm screen navigate to **Preferences** > **Plugins** and select Magento PHPStorm. +* You can also install it from your PHPStorm screen . Navigate to **Preferences** > **Plugins** and select Magento PHPStorm. ![]({{site.baseurl}}/common/images/phpstorm/install-through-phpstorm.png) From 9cbf1591b62aee0822c1d214500888808d6d2ee9 Mon Sep 17 00:00:00 2001 From: Marc Ginesta Date: Thu, 19 May 2022 10:47:44 +0200 Subject: [PATCH 057/776] Rephrase and clean --- .../phpstorm/installation.md | 26 +------------------ .../phpstorm/introduction.md | 2 ++ 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/src/guides/v2.3/ext-best-practices/phpstorm/installation.md b/src/guides/v2.3/ext-best-practices/phpstorm/installation.md index 4eedd886ac0..75334418f45 100644 --- a/src/guides/v2.3/ext-best-practices/phpstorm/installation.md +++ b/src/guides/v2.3/ext-best-practices/phpstorm/installation.md @@ -11,7 +11,7 @@ To install the Magento PHPStorm plugin: ![]({{site.baseurl}}/common/images/phpstorm/download-from-jetbrains.png) -* You can also install it from your PHPStorm screen . Navigate to **Preferences** > **Plugins** and select Magento PHPStorm. +* Or alternatively, you can install it from your PHPStorm screen. Navigate to **Preferences** > **Plugins** and select Magento PHPStorm. ![]({{site.baseurl}}/common/images/phpstorm/install-through-phpstorm.png) @@ -29,27 +29,3 @@ You also need to provide: ![]({{site.baseurl}}/common/images/phpstorm/enable-magento-integration.png) See the video tutorial [Using the Upgrade Compatibility Tool on PHP Storm](https://experienceleague.adobe.com/docs/commerce-learn/tutorials/upgrade/uct-phpstorm.html?lang=en) page for more information about the Magento PHPStorm plugin. - -You can download this plugin from the [PHP Storm Marketplace](https://plugins.jetbrains.com/plugin/8024-magento-phpstorm). - -![]({{site.baseurl}}/common/images/phpstorm/download-from-jetbrains.png) - -Or alternatively, you can look for it and install it directly on your PHP Storm through `Preferences -> Plugins`. - -![]({{site.baseurl}}/common/images/phpstorm/install-through-phpstorm.png) - -In any case, after installing it you will need to enable the integration with Magento through `Preferences -> Frameworks`. - -To do so, you have to check the `Enable Magento Integration` as it indicated [here](https://github.com/magento/magento2-phpstorm-plugin#installation). - -Apart from this, you are also asked for: - -* Magento installation path -* Adobe Commerce version (i.e., `2.4.1`) -* Default license name for new modules (by default, `Proprietary`) - -![]({{site.baseurl}}/common/images/phpstorm/enable-magento-integration.png) - -You can find more information in the following page: - -* [Using the Upgrade Compatibility Tool on PHP Storm](https://experienceleague.adobe.com/docs/commerce-learn/tutorials/upgrade/uct-phpstorm.html?lang=en). diff --git a/src/guides/v2.3/ext-best-practices/phpstorm/introduction.md b/src/guides/v2.3/ext-best-practices/phpstorm/introduction.md index a84b7c04a32..698d2e3f97c 100644 --- a/src/guides/v2.3/ext-best-practices/phpstorm/introduction.md +++ b/src/guides/v2.3/ext-best-practices/phpstorm/introduction.md @@ -7,6 +7,8 @@ functional_areas: The PHPStorm plugin is a tool created by the community to optimize routine coding operations and improve the {{site.data.var.ee}} development experience. The plugin is compatible with the IntelliJ IDEA Ultimate and PhpStorm IDEs. The functionality includes {{site.data.var.ee}} specific code generation shortcuts, code inspections, autocomplete functionality for configuration files, MFTF tests, and RequireJS. +Check the [Installation]({{site.baseurl}}/guides/v2.3/ext-best-practices/phpstorm/installation.html) topic for detailed steps. + See the [Code generation]({{site.baseurl}}/guides/v2.3/ext-best-practices/phpstorm/code-generation.html) topic for more information. The PHPStorm plugin includes shortcuts for Functional Testing, Require JS mapping, GraphQL, Plugin declaration inspection, code generation, and many more. From 70d1f46743829f1f619a6236c129ad9b90949184 Mon Sep 17 00:00:00 2001 From: Marc Ginesta Date: Thu, 19 May 2022 10:51:17 +0200 Subject: [PATCH 058/776] Fix MD030 --- src/guides/v2.3/ext-best-practices/phpstorm/installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/guides/v2.3/ext-best-practices/phpstorm/installation.md b/src/guides/v2.3/ext-best-practices/phpstorm/installation.md index 75334418f45..895ad2cd56c 100644 --- a/src/guides/v2.3/ext-best-practices/phpstorm/installation.md +++ b/src/guides/v2.3/ext-best-practices/phpstorm/installation.md @@ -17,8 +17,8 @@ To install the Magento PHPStorm plugin: After the installation, it is necessary to enable the integration with Magento: -1. Go to **Preferences** > **Frameworks**. -1. Select the **Enable Magento Integration** checkbox. See [Install PHPStorm plugin](https://github.com/magento/magento2-phpstorm-plugin#installation) topic for more information. +1. Go to **Preferences** > **Frameworks**. +1. Select the **Enable Magento Integration** checkbox. See [Install PHPStorm plugin](https://github.com/magento/magento2-phpstorm-plugin#installation) topic for more information. You also need to provide: From 7c5db53e22df38256e99ce405c41e2fa54eac0ad Mon Sep 17 00:00:00 2001 From: Dmytro Shevtsov Date: Thu, 19 May 2022 10:54:28 -0500 Subject: [PATCH 059/776] Update ruby dependencies --- Gemfile.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 48c4ded247c..1b67dfda3ea 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -54,11 +54,11 @@ GEM filesize (0.2.0) forwardable-extended (2.6.0) fspath (3.1.2) - html-proofer (3.19.3) + html-proofer (3.19.4) addressable (~> 2.3) mercenary (~> 0.3) - nokogiri (~> 1.12) - parallel (~> 1.3) + nokogiri (~> 1.13) + parallel (~> 1.10) rainbow (~> 3.0) typhoeus (~> 1.3) yell (~> 2.0) @@ -72,13 +72,13 @@ GEM image_size (>= 1.5, < 4) in_threads (~> 1.3) progress (~> 3.0, >= 3.0.1) - image_optim_pack (0.8.0.20220131) + image_optim_pack (0.8.0.20220418) fspath (>= 2.1, < 4) image_optim (~> 0.19) - image_optim_pack (0.8.0.20220131-x86_64-darwin) + image_optim_pack (0.8.0.20220418-x86_64-darwin) fspath (>= 2.1, < 4) image_optim (~> 0.19) - image_size (3.0.1) + image_size (3.0.2) in_threads (1.6.0) jekyll (4.2.2) addressable (~> 2.4) @@ -118,8 +118,8 @@ GEM jekyll (>= 3.3, < 5.0) jekyll-watch (2.2.1) listen (~> 3.0) - json (2.6.1) - kramdown (2.3.2) + json (2.6.2) + kramdown (2.4.0) rexml kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) @@ -140,14 +140,14 @@ GEM mixlib-cli (2.1.8) mixlib-config (3.0.9) tomlrb - mixlib-shellout (3.2.6) + mixlib-shellout (3.2.7) chef-utils multipart-post (2.1.1) netrc (0.11.0) - nokogiri (1.13.4) + nokogiri (1.13.6) mini_portile2 (~> 2.8.0) racc (~> 1.4) - nokogiri (1.13.4-x86_64-darwin) + nokogiri (1.13.6-x86_64-darwin) racc (~> 1.4) octokit (4.22.0) faraday (>= 0.9) @@ -157,7 +157,7 @@ GEM forwardable-extended (~> 2.6) progress (3.6.0) progressbar (1.11.0) - public_suffix (4.0.6) + public_suffix (4.0.7) racc (1.6.0) rainbow (3.1.1) rake (13.0.6) From bb66230535309316d1fd6462ecaa6fbe9637bce9 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Thu, 19 May 2022 15:29:47 -0500 Subject: [PATCH 060/776] ACP2E-743: [Documentation] Mention that some Inventory tasks need cron to be set up and run --- src/guides/v2.3/install-gde/install/post-install-config.md | 1 + src/guides/v2.4/install-gde/install/post-install-config.md | 1 + 2 files changed, 2 insertions(+) diff --git a/src/guides/v2.3/install-gde/install/post-install-config.md b/src/guides/v2.3/install-gde/install/post-install-config.md index f9bb0a7b591..144e8cdebeb 100644 --- a/src/guides/v2.3/install-gde/install/post-install-config.md +++ b/src/guides/v2.3/install-gde/install/post-install-config.md @@ -11,6 +11,7 @@ Now that you've finished installing the Magento application, you need to configu ## Set up cron {#post-install-cron} cron---the UNIX task scheduler---is critical to Magento's day-to-day operations. It schedules things like reindexing, newsletters, e-mails, sitemaps, and so on. A *crontab* is a cron configuration. +Magento services must be installed in *crontab*, otherwise, some core functionality as well as some third party extensions will not be functioning properly. {% include config/setup-cron_2.3_how-to.md %} diff --git a/src/guides/v2.4/install-gde/install/post-install-config.md b/src/guides/v2.4/install-gde/install/post-install-config.md index 156a51a6844..51c9abe7236 100644 --- a/src/guides/v2.4/install-gde/install/post-install-config.md +++ b/src/guides/v2.4/install-gde/install/post-install-config.md @@ -11,6 +11,7 @@ Now that you've finished installing the Magento application, you need to configu ## Set up cron {#post-install-cron} cron---the UNIX task scheduler---is critical to Magento's day-to-day operations. It schedules things like reindexing, newsletters, e-mails, sitemaps, and so on. A *crontab* is a cron configuration. +Magento services must be installed in *crontab*, otherwise, some core functionality as well as some third party extensions will not be functioning properly. {% include config/setup-cron_how-to.md %} From d3e3fbcc55ed100d355a65d7f98c3575d16c5dbf Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Thu, 19 May 2022 16:01:17 -0500 Subject: [PATCH 061/776] Added migrated metadata --- .../coding-standards/bk-coding-standards.md | 29 +- .../code-standard-demarcation.md | 486 +++++++- .../coding-standards/code-standard-html.md | 146 ++- .../code-standard-javascript.md | 2 + .../code-standard-jquery-widgets.md | 358 +++++- .../coding-standards/code-standard-less.md | 868 +++++++++++++- .../coding-standards/code-standard-php.md | 69 +- .../v2.4/coding-standards/contributing.md | 2 + .../docblock-standard-general.md | 866 +++++++++++++- .../docblock-standard-javascript.md | 731 +++++++++++- .../coding-standards/technical-guidelines.md | 1007 ++++++++++++++++- 11 files changed, 4555 insertions(+), 9 deletions(-) mode change 120000 => 100644 src/guides/v2.4/coding-standards/bk-coding-standards.md mode change 120000 => 100644 src/guides/v2.4/coding-standards/code-standard-demarcation.md mode change 120000 => 100644 src/guides/v2.4/coding-standards/code-standard-html.md mode change 120000 => 100644 src/guides/v2.4/coding-standards/code-standard-jquery-widgets.md mode change 120000 => 100644 src/guides/v2.4/coding-standards/code-standard-less.md mode change 120000 => 100644 src/guides/v2.4/coding-standards/code-standard-php.md mode change 120000 => 100644 src/guides/v2.4/coding-standards/docblock-standard-general.md mode change 120000 => 100644 src/guides/v2.4/coding-standards/docblock-standard-javascript.md mode change 120000 => 100644 src/guides/v2.4/coding-standards/technical-guidelines.md diff --git a/src/guides/v2.4/coding-standards/bk-coding-standards.md b/src/guides/v2.4/coding-standards/bk-coding-standards.md deleted file mode 120000 index cbb75078c18..00000000000 --- a/src/guides/v2.4/coding-standards/bk-coding-standards.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/coding-standards/bk-coding-standards.md \ No newline at end of file diff --git a/src/guides/v2.4/coding-standards/bk-coding-standards.md b/src/guides/v2.4/coding-standards/bk-coding-standards.md new file mode 100644 index 00000000000..deb6a7c26a4 --- /dev/null +++ b/src/guides/v2.4/coding-standards/bk-coding-standards.md @@ -0,0 +1,28 @@ +--- +group: coding-standards +subgroup: 01_Coding standards +title: Coding Standards +landing-page: Coding Standards +menu_title: Coding Standards +menu_order: 1 +menu_node: parent +functional_areas: + - Standards +migrated_to: https://developer.adobe.com/commerce/php/coding-standards/ +layout: migrated +--- + + + +Like many large projects, Magento has coding standards. + +Use Magento's coding standards when you contribute to Magento's codebase or create extensions. + +- [Code demarcation standard]({{ page.baseurl }}/coding-standards/code-standard-demarcation.html) +- [PHP coding standard]({{ page.baseurl }}/coding-standards/code-standard-php.html) +- [JavaScript coding standard]({{ page.baseurl }}/coding-standards/code-standard-javascript.html) +- [jQuery widget coding standard]({{ page.baseurl }}/coding-standards/code-standard-jquery-widgets.html) +- [DocBlock standard]({{ page.baseurl }}/coding-standards/docblock-standard-general.html) +- [JavaScript DocBlock standard]({{ page.baseurl }}/coding-standards/docblock-standard-javascript.html) +- [LESS coding standard]({{ page.baseurl }}/coding-standards/code-standard-less.html) +- [HTML style guide]({{ page.baseurl }}/coding-standards/code-standard-html.html) diff --git a/src/guides/v2.4/coding-standards/code-standard-demarcation.md b/src/guides/v2.4/coding-standards/code-standard-demarcation.md deleted file mode 120000 index 98266ffa0ab..00000000000 --- a/src/guides/v2.4/coding-standards/code-standard-demarcation.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/coding-standards/code-standard-demarcation.md \ No newline at end of file diff --git a/src/guides/v2.4/coding-standards/code-standard-demarcation.md b/src/guides/v2.4/coding-standards/code-standard-demarcation.md new file mode 100644 index 00000000000..fa4cb26c4b9 --- /dev/null +++ b/src/guides/v2.4/coding-standards/code-standard-demarcation.md @@ -0,0 +1,485 @@ +--- +group: coding-standards +subgroup: 01_Coding standards +landing-page: Coding standards +title: Code demarcation standard +menu_title: Code demarcation standard +menu_order: 1 +functional_areas: + - Standards +migrated_to: https://developer.adobe.com/commerce/php/coding-standards/code-demarcation/ +layout: migrated +--- + +Magento core developers must follow the Magento code demarcation standard. + +This standard is recommended for third-party [extension](https://glossary.magento.com/extension) developers. + +Some parts of Magento code might not comply with the standard, but we are working to gradually improve this. + +The standard was developed in the scope of our efforts to ensure the following: + +- Decouple visual (CSS) layer from the functional (JavaScript) layer. +- Decouple functional (JavaScript) layer from the [markup](https://glossary.magento.com/markup) (HTML). +- Reinstate emphasis on using of [jQuery](https://glossary.magento.com/jquery) templates. +- Reinstate emphasis on decoupling HTML, [CSS](https://glossary.magento.com/css) and JS from [PHP](https://glossary.magento.com/php) classes. + +Use [RFC 2119](http://www.ietf.org/rfc/rfc2119.txt) to interpret the "MUST," "MUST NOT," "REQUIRED," "SHALL," "SHALL NOT," "SHOULD," "SHOULD NOT," "RECOMMENDED," "MAY," and "OPTIONAL" keywords. + +## Semantics + +### For attribute names and values you must use meaningful unabbreviated lowercase words comprised of Latin characters concatenated with a hyphen (`-`) + +- Helps simplify and unify naming conventions that are used to apply visual styles to page elements. + +**Acceptable:** + +```html +

  • diff --git a/src/guides/v2.4/get-started/api-security.md b/src/guides/v2.4/get-started/api-security.md deleted file mode 120000 index e9157c4e3a7..00000000000 --- a/src/guides/v2.4/get-started/api-security.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/get-started/api-security.md \ No newline at end of file diff --git a/src/guides/v2.4/get-started/api-security.md b/src/guides/v2.4/get-started/api-security.md new file mode 100644 index 00000000000..f1536edf037 --- /dev/null +++ b/src/guides/v2.4/get-started/api-security.md @@ -0,0 +1,170 @@ +--- +group: web-api +title: API security +functional_areas: + - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/api-security/ +layout: migrated +--- + +This topic describes best practices for [API security](https://owasp.org/www-project-api-security/). + +## Input limiting + +Imposing restrictions on the size and number of resources that a user can request through an API can help mitigate denial-of-service (DoS) vulnerabilities. By default, the following built-in API rate limiting is available: + +- REST requests containing inputs that represent a list of entities. When enabled, the default maximum is 20 for synchronous requests and 5,000 for asynchronous requests. +- REST and GraphQL queries that allow paginated results can be limited to a maximum number of items per page. When enabled, the default maximum is 300. +- REST queries that allow paginated results can have a default number of items per page imposed. When enabled, the default maximum is 20. + +By default, these input limits are disabled, but you can use the following methods to enable them: + +- Set the values in the [Admin](https://docs.magento.com/user-guide/configuration/services/magento-web-api.html). +- Run the [`bin/magento config:set` command]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-config-mgmt-set.html#config-cli-config-set). +- Add entries to the [`env.php` file]({{ page.baseurl }}/config-guide/prod/config-reference-configphp.html#system). +- Set [environment variables]({{ page.baseurl }}/config-guide/deployment/pipeline/example/environment-variables.html). + +When input limiting has been enabled, the system uses the default value for each limitation listed above. You can also configure custom values. + +Although some simple examples for configuring these values from the CLI are provided below, all of the values can be [configured per website and per store view]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-config-mgmt-set.html#config-cli-config-set) in addition to being configurable globally. In addition, these values can also be configured [via `env.php`]({{ page.baseurl }}/config-guide/prod/config-reference-configphp.html#system) +as well as via [environment variables]({{ page.baseurl }}/config-guide/deployment/pipeline/example/environment-variables.html). + + + +In addition, the Admin provides a configuration setting for limiting session sizes for Admin users and storefront visitors. + +### Enable the input limiting system + +To enable these input limiting features from the Admin, go to **Stores** > Settings > **Configuration** > **Services** > **Web Api Limits** or **GraphQL Input Limits** and set **Enable Input Limits** to **Yes**. + +To enable with the CLI, run one or both of the following commands: + +```bash +bin/magento config:set webapi/validation/input_limit_enabled 1 +``` + +```bash +bin/magento config:set graphql/validation/input_limit_enabled 1 +``` + +### Maximum parameter inputs + +The `EntityArrayValidator` class constructor limits the number of objects that can be given to inputs that represent arrays of objects. For example, the `PUT /V1/guest-carts/{cartId}/collect-totals` endpoint contains the input parameter `additionalData->extension_attributes->gift_messages`, which represents a list of gift message information objects. + +There are four possible input arrays: + +- `additional_data` +- `agreement_ids` +- `gift_messages` +- `custom_attributes` + +```json +{ + "paymentMethod": { + "po_number": "string", + "method": "string", + "additional_data": [ + "string" + ], + "extension_attributes": { + "agreement_ids": [ + "string" + ] + } + }, + "shippingCarrierCode": "string", + "shippingMethodCode": "string", + "additionalData": { + "extension_attributes": { + "gift_messages": [ + { + "gift_message_id": 0, + "customer_id": 0, + "sender": "string", + "recipient": "string", + "message": "string", + "extension_attributes": { + "entity_id": "string", + "entity_type": "string", + "wrapping_id": 0, + "wrapping_allow_gift_receipt": true, + "wrapping_add_printed_card": true + } + } + ] + }, + "custom_attributes": [ + { + "attribute_code": "string", + "value": "string" + } + ] + } +} +``` + +By default, any one of these arrays can include up to 20 items, but you can change this value in the configuration UI via **Stores** > Settings > **Configuration** > **Services** > **Web API Input Limits** > **Input List Limit** or via CLI using the `webapi/validation/complex_array_limit` configuration path. + +### Input limit for REST endpoints + +Some REST endpoints can contain a high number of elements, and developers need a way to set the limit for each endpoint. The limit for a specific REST endpoint can be set in the `webapi.xml` configuration file for synchronous requests and `webapi_async.xml` for asynchronous requests. +To do this, assign a value for the `` attribute within a `` definition. The value for `input-array-size-limit` must be a non-negative integer. + +The following example sets the input limit for the `/V1/some-custom-route` route. +If the route works synchronously, open the `/etc/webapi.xml` configuration file. Otherwise, open `/etc/webapi_async.xml`. +Add the `data` tag with the `input-array-size-limit` attribute to the route configuration. + +```xml + + + + + + + + + + + +``` + +Clear the configuration cache for the changes to take effect. + +```bash +bin/magento cache:clear config +``` + +### Values by default for REST endpoints + +If you need to change the default limits for REST endpoints, then edit the `webapi` section of the `/app/etc/env.php` file as follows: +```conf +[ +//... + 'webapi' => [ + 'sync' => [ + 'default_input_array_size_limit' => , //overrides values for synchronous REST endpoints + ], + 'async' => [ + 'default_input_array_size_limit' => , //overrides values for asynchronous REST endpoints + ], + ] +//... +]; +``` + +### Maximum page size + +The maximum page size setting controls the pagination of various web API responses. By default, the maximum value is `300`. You can change the default in the Admin by selecting **Stores** > Settings > **Configuration** > **Services** > **Web API Input Limits** or **GraphQl Input Limits** > **Maximum Page Size** field. + +[GraphQL security configuration]({{page.baseurl}}/graphql/security-configuration.html) describes how to set the maximum page size in GraphQL. + +### Default page size + +The Default Page Size setting controls the pagination of various web API responses. You can change the default value of `20` in the Admin by selecting **Stores** > Settings > **Configuration** > **Services** > **Web API Input Limits** > **Default Page Size**. To change the value from the CLI, run the following command: + +```shell +bin/magento config:set webapi/validation/default_page_size 30 +``` diff --git a/src/guides/v2.4/get-started/authentication/gs-authentication-oauth.md b/src/guides/v2.4/get-started/authentication/gs-authentication-oauth.md deleted file mode 120000 index eec336fbe5c..00000000000 --- a/src/guides/v2.4/get-started/authentication/gs-authentication-oauth.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/get-started/authentication/gs-authentication-oauth.md \ No newline at end of file diff --git a/src/guides/v2.4/get-started/authentication/gs-authentication-oauth.md b/src/guides/v2.4/get-started/authentication/gs-authentication-oauth.md new file mode 100644 index 00000000000..1ec2a40f8b1 --- /dev/null +++ b/src/guides/v2.4/get-started/authentication/gs-authentication-oauth.md @@ -0,0 +1,469 @@ +--- +group: web-api +title: OAuth-based authentication +functional_areas: + - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-oauth/ +layout: migrated +--- + +Magento OAuth authentication is based on [OAuth 1.0a](https://tools.ietf.org/html/rfc5849), an open standard for secure [API](https://glossary.magento.com/api) authentication. OAuth is a token-passing mechanism that allows a system to control which third-party applications have access to internal data without revealing or storing any user IDs or passwords. + +In Magento, a third-party application that uses OAuth for authentication is called an [_integration_]( {{ page.baseurl }}/get-started/create-integration.html ). An integration defines which resources the application can access. The application can be granted access to all resources or a customized subset of resources. + +As the process of registering the integration proceeds, Magento creates the tokens that the application needs for authentication. It first creates a request token. This token is short-lived and must be exchanged for an access token. Access tokens are long-lived and will not expire unless the merchant revokes access from the application. + +## OAuth overview {#overview} + +The following diagram shows the OAuth authentication process. Each step is described further. +![OAuth flow]({{ page.baseurl }}/get-started/authentication/images/oauthflow.png) + +1. **Create an integration**. The merchant creates an integration from [Admin](https://glossary.magento.com/admin). Magento generates a consumer key and a consumer secret. + +1. **Activate the integration**. The OAuth process begins when the merchant activates the integration. Magento sends the OAuth consumer key and secret, an OAuth verifier, and the store [URL](https://glossary.magento.com/url) to the external application via HTTPS post to the page defined in the **Callback Link** field in Admin. See [Activate an integration](#activate) for more information. + +1. **Process activation information**. The integrator must store the activation information received in step 2. These parameters will be used to ask for tokens. + +1. **Call the application's login page**. Magento calls the page defined in the **Identity Link** field in Admin. + +1. **Merchant logs in to the external application.** If the login is successful, the application returns to the location specified in the call. The login page is dismissed. + +1. **Ask for a request token**. The application uses the `POST /oauth/token/request` REST API to ask for a request token. The `Authorization` header includes the consumer key and other information. See [Get a request token](#pre-auth-token) for details about this token request. + +1. **Send the request token**. Magento returns a request token and request token secret. + +1. **Ask for an access token**. The application uses the `POST /oauth/token/access` REST API to ask for an access token. The `Authorization` header includes the request token and other information. See [Get an access token](#get-access-token) for details about this token request. + +1. **Magento sends the access token**. If this request is successful, Magento returns an access token and access token secret. + +1. **The application can access Magento resources.** All requests sent to Magento must use the full set of request parameters in `Authorization` header. See [Access the web APIs](#web-api-access) for more information. + +## Activate an integration {#activate} + +The integration must be configured from the [Admin](https://glossary.magento.com/magento-admin) (**System > Extensions > Integrations**). The configuration includes a callback URL and an identity link URL. The callback URL specifies where OAuth credentials can be sent when using OAuth for token exchange. The identity link points to the login page of the third-party application that is integrating with Magento. + +A merchant can choose to select **Save and Activate** when the integration is created. Alternatively, the merchant can click on **Activate** against a previously saved integration from the Integration grid. + +When the integration is created, Magento generates a consumer key and a consumer secret. + +Activating the integration submits the credentials to the endpoint specified when creating the Integration. An HTTP POST from Magento to the Integration endpoint will contain these attributes: + +* `store_base_url` For example, `http://my-magento-store.com/`. +* `oauth_verifier` +* `oauth_consumer_key` +* `oauth_consumer_secret` + +Integrations use the `oauth_consumer_key` key to get a request token and the `oauth_verifier` to get an access token. + +## OAuth handshake details {#oauth-handshake} + +The process of completing the OAuth handshake requires that you + +* [Get a request token](#pre-auth-token) +* [Get an access token](#get-access-token) + +This process is known as a 2-legged OAuth handshake. + +### Get a request token {#pre-auth-token} + +A request token is a temporary token that the user exchanges for an access token. Use the following API to get a request token from Magento: + +`POST /oauth/token/request` + +You must include these request parameters in the `Authorization` header in the call: + +Parameter | Description +--- | --- +`oauth_consumer_key` | The consumer key is generated when you create the integration. +`oauth_signature_method` | The name of the signature method used to sign the request. Must be the value `HMAC-SHA1`. +`oauth_signature` | A generated value (signature) +`oauth_nonce` | A random value that is uniquely generated by the application. +`oauth_timestamp` | A positive integer, expressed in the number of seconds since January 1, 1970 00:00:00 GMT. +`oauth_version` | The OAuth version. + +The response contains these fields: + +* `oauth_token`. The token to be used when requesting an access token. +* `oauth_token_secret`. A secret value that establishes ownership of the token. + +A valid response looks like this: + +`oauth_token=4cqw0r7vo0s5goyyqnjb72sqj3vxwr0h&oauth_token_secret=rig3x3j5a9z5j6d4ubjwyf9f1l21itrr` + +### Get an access token {#get-access-token} + +The request token must be exchanged for an access token. Use the following API to get an access token from Magento: + +`POST /oauth/token/access` + +You must include these request parameters in the `Authorization` header in the call: + +Parameter | Description +--- | --- +`oauth_consumer_key` | The consumer key value that you retrieve after you register the integration. +`oauth_nonce` | A random value that is uniquely generated by the application. +`oauth_signature` | A generated value (signature) +`oauth_signature_method` | The name of the signature method used to sign the request. Must be the value `HMAC-SHA1`. +`oauth_timestamp` | A positive integer, expressed in the number of seconds since January 1, 1970 00:00:00 GMT. +`oauth_version` | The OAuth version. +`oauth_token` | The `oauth_token` value, or request token, obtained in [Get a request token](#pre-auth-token). +`oauth_verifier` | The verification code that is tied to the consumer and request token. It is sent as part of the initial POST operation when the integration is activated. + +A valid response looks like this: +`oauth_token=0lnuajnuzeei2o8xcddii5us77xnb6v0&oauth_token_secret=1c6d2hycnir5ygf39fycs6zhtaagx8pd` + +The response contains these fields: + +* `oauth_token`. The access token that provides access to protected resources. +* `oauth_token_secret`. The secret that is associated with the access token. + +## Access the web APIs {#web-api-access} + +After the integration is authorized to make API calls, third-party applications (registered as integrations in Magento) can invoke Magento web APIs by using the access token. + +To use the access token to make [web API](https://glossary.magento.com/web-api) calls: + +`GET /rest/V1/products/1234` + +You must include these request parameters in the `Authorization` request header in the call: + +* `oauth_consumer_key`. The customer key value provided after the registration of the application. +* `oauth_nonce`. A random value, uniquely generated by the application. +* `oauth_signature_method`. The name of the signature method used to sign the request. Valid values are: `HMAC-SHA1`, `RSA-SHA1`, and `PLAINTEXT`. +* `oauth_signature`. A generated value (signature). +* `oauth_timestamp`. A positive integer, expressed in the number of seconds since January 1, 1970 00:00:00 GMT. +* `oauth_token`. The `oauth_token`, or access token, value obtained in [Get an access token](#get-access-token). + +## The OAuth signature {#oauth-signature} + +All OAuth handshake requests and Web Api requests include the signature as part of [Authorization](https://glossary.magento.com/authorization) header. Its generated as follows: + +You concatenate a set of URL-encoded attributes and parameters to construct the signature base string. + +Use the ampersand (`&`) character to concatenate these attributes and parameters: + +1. HTTP method +1. URL +1. `oauth_nonce` +1. `oauth_signature_method` +1. `oauth_timestamp` +1. `oauth_version` +1. `oauth_consumer_key` +1. `oauth_token` + +To generate the signature, you must use the HMAC-SHA1 signature method. The signing key is the concatenated values of the consumer secret and token secret separated by the ampersand (`&`) character (ASCII code 38), even if empty. You must use parameter encoding to encode each value. + +## OAuth token exchange example {#oauth-example} + +The scripts provided in this document simulate the Magento 2 [OAuth 1.0a](https://tools.ietf.org/html/rfc5849) token exchange flow. You can drop these scripts under the document root directory of your Magento application so that they can be exposed as endpoints that your Magento application can interact with to mimic the token exchange. + +The OAuth client is extended from and attributed to [PHPoAuthLib](https://github.com/Lusitanian/PHPoAuthLib), which is the same lib used in the [Magento OAuth client]({{ site.mage2bloburl }}/{{ page.guide_version }}/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/Rest/OauthClient.php). + +To simulate the OAuth 1.0a token exchange flow: + +1. Login to your Admin and navigate to **System > Extensions > Integrations** +1. Click on **Add New Integration**. +1. Complete all details in the Integration Info tab: + * **Name** : SomeUniqueIntegrationName + * **Callback URL** : http://your_app_host/endpoint.php + * **Identity link URL** : http://your_app_host/login.php + * Add permissions as desired on the **API** tab +1. Select the **Save and Activate** option from the drop down menu. +1. A pop-up window displays, confirming API permissions. Click **Allow**. (Make sure your browser allows pop-up windows.) The credentials are posted to `endpoint.php`. You should also see another pop-up for the identity linking step that opens the script from `login.php`. +1. Click **Login**. (There is no actual login check since this is a simulation.). The `checklogin.php` script is called. It uses the posted credentials to complete the token exchange. +1. When the token exchange completes successfully, the user is redirected back to the Integrations grid. The newly-created integration should be in the Active state. +1. Click on the edit icon of the integration and check the Integration Details on the Integration Info tab. It should show all the credentials that can be used to make an authenticated API request using OAuth 1.0. + +### checklogin.php + +{% collapsible Click to expand %} +```php +requestRequestToken(); +$accessToken = $oAuthClient->requestAccessToken( + $requestToken->getRequestToken(), + $oauthVerifier, + $requestToken->getRequestTokenSecret() +); + +header("location: $callback"); +``` +{% endcollapsible %} + +### endpoint.php +{% collapsible Click to expand %} +```php + + +
    + + + + + + + + + + + + + + + + + + + + +
    Integrations Login
    Username:
    Password:
      
    + +
    + + +HTML; +``` +{% endcollapsible %} + +### OauthClient.php + +Change the instances of `http://magento.host` in this example to a valid base URL. + +{% collapsible Click to expand %} + +```php +_parseToken($responseBody); + } + + /** + * Parses the request token response and returns a TokenInterface. + * + * @param string $responseBody + * @return TokenInterface + * @throws TokenResponseException + */ + protected function parseRequestTokenResponse($responseBody) + { + $data = $this->_parseResponseBody($responseBody); + if (isset($data['oauth_verifier'])) { + $this->_oauthVerifier = $data['oauth_verifier']; + } + return $this->_parseToken($responseBody); + } + + /** + * Parse response body and create oAuth token object based on parameters provided. + * + * @param string $responseBody + * @return StdOAuth1Token + * @throws TokenResponseException + */ + protected function _parseToken($responseBody) + { + $data = $this->_parseResponseBody($responseBody); + $token = new StdOAuth1Token(); + $token->setRequestToken($data['oauth_token']); + $token->setRequestTokenSecret($data['oauth_token_secret']); + $token->setAccessToken($data['oauth_token']); + $token->setAccessTokenSecret($data['oauth_token_secret']); + $token->setEndOfLife(StdOAuth1Token::EOL_NEVER_EXPIRES); + unset($data['oauth_token'], $data['oauth_token_secret']); + $token->setExtraParams($data); + return $token; + } + + /** + * Parse response body and return data in array. + * + * @param string $responseBody + * @return array + * @throws \OAuth\Common\Http\Exception\TokenResponseException + */ + protected function _parseResponseBody($responseBody) + { + if (!is_string($responseBody)) { + throw new TokenResponseException("Response body is expected to be a string."); + } + parse_str($responseBody, $data); + if (null === $data || !is_array($data)) { + throw new TokenResponseException('Unable to parse response.'); + } elseif (isset($data['error'])) { + throw new TokenResponseException("Error occurred: '{$data['error']}'"); + } + return $data; + } + + /** + * @override to fix since parent implementation from lib not sending the oauth_verifier when requesting access token + * Builds the authorization header for an authenticated API request + * + * @param string $method + * @param UriInterface $uri the uri the request is headed + * @param \OAuth\OAuth1\Token\TokenInterface $token + * @param $bodyParams array + * @return string + */ + protected function buildAuthorizationHeaderForAPIRequest( + $method, + UriInterface $uri, + TokenInterface $token, + $bodyParams = null + ) { + $this->signature->setTokenSecret($token->getAccessTokenSecret()); + $parameters = $this->getBasicAuthorizationHeaderInfo(); + if (isset($parameters['oauth_callback'])) { + unset($parameters['oauth_callback']); + } + + $parameters = array_merge($parameters, ['oauth_token' => $token->getAccessToken()]); + $parameters = array_merge($parameters, $bodyParams); + $parameters['oauth_signature'] = $this->signature->getSignature($uri, $parameters, $method); + + $authorizationHeader = 'OAuth '; + $delimiter = ''; + + foreach ($parameters as $key => $value) { + $authorizationHeader .= $delimiter . rawurlencode($key) . '="' . rawurlencode($value) . '"'; + $delimiter = ', '; + } + + return $authorizationHeader; + } +} +``` + +{% endcollapsible %} + +{:.ref-header} +Related topics + +[Create an integration]( {{ page.baseurl }}/get-started/create-integration.html ) + +[OAuth error codes]( {{ page.baseurl }}/get-started/authentication/oauth-errors.html ) + +[Construct a request]( {{ page.baseurl }}/get-started/gs-web-api-request.html ) + +[Configure services as web APIs]( {{ page.baseurl }}/extension-dev-guide/service-contracts/service-to-web-service.html ) diff --git a/src/guides/v2.4/get-started/authentication/gs-authentication-session.md b/src/guides/v2.4/get-started/authentication/gs-authentication-session.md deleted file mode 120000 index 94fd5110c8d..00000000000 --- a/src/guides/v2.4/get-started/authentication/gs-authentication-session.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/get-started/authentication/gs-authentication-session.md \ No newline at end of file diff --git a/src/guides/v2.4/get-started/authentication/gs-authentication-session.md b/src/guides/v2.4/get-started/authentication/gs-authentication-session.md new file mode 100644 index 00000000000..16421580c06 --- /dev/null +++ b/src/guides/v2.4/get-started/authentication/gs-authentication-session.md @@ -0,0 +1,36 @@ +--- +group: web-api +subgroup: 40_Authentication +title: Session-based authentication +menu_title: Session-based authentication +menu_order: 4 +functional_areas: + - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-session/ +layout: migrated +--- + +As a customer, you log in to the Magento [storefront](https://glossary.magento.com/storefront) with your customer credentials. As an admin, you log in to the [Admin](https://glossary.magento.com/magento-admin) with your [admin](https://glossary.magento.com/admin) credentials. + +The Magento web [API](https://glossary.magento.com/api) framework uses your logged-in session information to verify your identity and authorize access to the requested resource. + +Customers can access resources that are configured with `anonymous` or `self` permission in the `webapi.xml` configuration file. + +Admins can access resources that are assigned to their Admin profile. + + {:.bs-callout-info} +The Magento [web API](https://glossary.magento.com/web-api) framework enables guest users to access resources that are configured with `anonymous` permission. Any user that the framework cannot authenticate through existing authentication mechanisms is considered a guest user. + +For example, if a customer is logged in to the Magento storefront and the [JavaScript](https://glossary.magento.com/javascript) [widget](https://glossary.magento.com/widget) invokes the `self` API, details for the logged-in customer are fetched: + +`GET /rest/V1/customers/me` + +Similarly, if an admin is logged in to the Admin and the JavaScript widget invokes the `Magento_Customer::group` API, details for the logged-in admin are fetched. The web API framework establishes the identity of the admin user based on logged-in session information and authorizes access to the `Magento_Customer::group` resource. + +{:.bs-callout-warning} +Admin session-based authentication is not currently possible for API endpoints. +The session based authentication functionality is restricted to AJAX calls. Direct browser requests cannot be made due to security vulnerabilities. A developer can create a custom storefront widget that can issue requests without additional authentication steps. + +## Related topic + +[Configure services as web APIs]({{ page.baseurl }}/extension-dev-guide/service-contracts/service-to-web-service.html) diff --git a/src/guides/v2.4/get-started/authentication/gs-authentication-token.md b/src/guides/v2.4/get-started/authentication/gs-authentication-token.md index afa3694fd39..94ceff95c94 100644 --- a/src/guides/v2.4/get-started/authentication/gs-authentication-token.md +++ b/src/guides/v2.4/get-started/authentication/gs-authentication-token.md @@ -3,6 +3,8 @@ group: web-api title: Token-based authentication functional_areas: - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-token/ +layout: migrated --- To make a web [API](https://glossary.magento.com/api) call from a client such as a mobile application, you must supply an *access token* on the call. The token acts like an electronic key that lets you access the API. diff --git a/src/guides/v2.4/get-started/authentication/gs-authentication.md b/src/guides/v2.4/get-started/authentication/gs-authentication.md index 6c8f21ea539..445c36252b2 100644 --- a/src/guides/v2.4/get-started/authentication/gs-authentication.md +++ b/src/guides/v2.4/get-started/authentication/gs-authentication.md @@ -3,6 +3,8 @@ group: web-api title: Authentication functional_areas: - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication/ +layout: migrated --- Magento allows developers to define web [API](https://glossary.magento.com/api) resources and their permissions in the `webapi.xml` configuration file. See [Services as Web APIs]({{ page.baseurl }}/extension-dev-guide/service-contracts/service-to-web-service.html). diff --git a/src/guides/v2.4/get-started/authentication/images/gs_auth_token1.png b/src/guides/v2.4/get-started/authentication/images/gs_auth_token1.png deleted file mode 120000 index 5cecf8f56a5..00000000000 --- a/src/guides/v2.4/get-started/authentication/images/gs_auth_token1.png +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/get-started/authentication/images/gs_auth_token1.png \ No newline at end of file diff --git a/src/guides/v2.4/get-started/authentication/images/gs_auth_token1.png b/src/guides/v2.4/get-started/authentication/images/gs_auth_token1.png new file mode 100644 index 0000000000000000000000000000000000000000..4f338d76d37f3be861ab5185d90dad5bb6ba175d GIT binary patch literal 85897 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\wo(5$MD49p6}zh$Psr=K2oU5z80<`mK!w6S0UR zKO2HY+he27=hU!;?VtN%wdl@ZEedqj@HHO8JZEk9poQWUD^t+L;Wv6J*dhBcybPPn zI%FjeZtOuLu?Y;}jn+d%5#=^S^Y*u9dyQo>wG5e-_lwXoO?ul7CADLJ3$MmcCa&A* zQ4!YTFqMOjPTnOec9V#)V1g912A{#(ucMV8)8vWR&^>E)ae1^obPsQeZ8(%K=+gLV z8-DTd)@$+7iys&qRQDg!iQ!x29w9b0bF^|Nu`$$~4k{GEY|@zzDIGx9%?srn22cfw zFL=Z7!Q%d#xz@aqh;$CrMuJ_Ge7ct^}0os=5gM5qT7`J=Ou#5lkPx%+9 z&)FIeax|s`Cw8P|G!56?WT5H}+m*Uo&Xp~VQ`cgUct-`uveZh&-duSYD#?cC)ZT8Wo|=*Hms_Me@N6}bGp^bN3YE* zOz#>Z1iun6ra|}gFTkD|s`o})Da2J#e63U6V@UBYqS9TXO*41px$^+QBJy2{bXd4v z`+DL|Si`t`P%yMO>&#wE0m&{*;2zS8nd;P;AHu9b5J&Y3o}2r6L5^59HTAUqa#OkL zwUr7a=gR1FQL2Sj++Wjdw5T^==G*3eGFiVqQ?;N2>xaJ~@!y~AboVhMTSu+eJj4wa z6wZVjP}Z9x6#nOs-WrdYl?s&lL9+6+B5T5E(wifG_MGMXWBi^?Uh2}1kD&8d83NHb z6thNDGg3sV9}H{^6C~aYSJ^b(hdMgo>}UOscl>Rznl&QvYa>F54Rz+5Bk9hEIn(2a zK3Fo{aWl&5F|{MZS>4Wp8Wg@c-t zB(*-HXgEvfSif!6k0)_X%qJ&W%--J592)j*%W6_5_qUCQCu8$c5bU!kSRtwd7k7Ea6@!m-!y=vAf!kfW81WDx*F6oF$X{ zyODS!KDN04+p7g~Ecg5k>^roOZ#kwrM3pyU6GWGbkUdhA^N7(3yMWBkAGQvysL^Ep ziYr!>y$51g$B8CxW>b_>R$~{ zfzvP%v_`&2NW^p;>`C1{G#XMoxOeFjZWIKQ{lm^fl}Rv_J4Q&>In?8Zpt*D?9;pPT z50iM(n zcfl|wvGgKY%>YD-z2N@61vNkk^pANP6F@fHE)v5!!~g6LV34AzlEKjD&x(2ew^!UL zA})Ro9EV%iQqt4I@Ry8XA3hLVU`$)&Wp&`?#rOaiB!6effGzmVu3e(1`orQn{tq3NHgT%+e=1CGsWX6eGP=oVyP2D~SqPiCSb!gwxH-9m*f@FFIJq^r z_=Nd{ggJRxI5~wmIi(I-ock+XEJOa`7K*%*=$%9G$#eY^_-@!5z|Fw*{g{zs1jgy;=qr)X>8&@Yg6E6zt SxN7hxm*ixWrQwpsf&T;hIxQ^# literal 0 HcmV?d00001 diff --git a/src/guides/v2.4/get-started/authentication/images/oauthflow.png b/src/guides/v2.4/get-started/authentication/images/oauthflow.png deleted file mode 120000 index 321497b0291..00000000000 --- a/src/guides/v2.4/get-started/authentication/images/oauthflow.png +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/get-started/authentication/images/oauthflow.png \ No newline at end of file diff --git a/src/guides/v2.4/get-started/authentication/images/oauthflow.png b/src/guides/v2.4/get-started/authentication/images/oauthflow.png new file mode 100644 index 0000000000000000000000000000000000000000..600b1646a3df4ddbb45851562b3541e0124f0c1d GIT binary patch literal 23873 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 M)78&qol`;+0M^dh-2eap literal 0 HcmV?d00001 diff --git a/src/guides/v2.4/get-started/authentication/oauth-errors.md b/src/guides/v2.4/get-started/authentication/oauth-errors.md deleted file mode 120000 index 045a2369cbf..00000000000 --- a/src/guides/v2.4/get-started/authentication/oauth-errors.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/get-started/authentication/oauth-errors.md \ No newline at end of file diff --git a/src/guides/v2.4/get-started/authentication/oauth-errors.md b/src/guides/v2.4/get-started/authentication/oauth-errors.md new file mode 100644 index 00000000000..4aaae6a1f80 --- /dev/null +++ b/src/guides/v2.4/get-started/authentication/oauth-errors.md @@ -0,0 +1,34 @@ +--- +group: web-api +title: OAuth error codes +functional_areas: + - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/authentication/oauth-errors/ +layout: migrated +--- + +When the third-party application makes an invalid request to Magento, the following OAuth-related errors can occur: + +HTTP code | Error code | Text representation | Description +--- | --- | --- | --- +400 | 1 | `version_rejected` | The `oauth_version` parameter does not correspond to the "1.0" value. +400 | 2 | `parameter_absent` | A required parameter is missing in the request. The name of the missing parameter is specified additionally in the response. +400 | 3 | `parameter_rejected` | The type of the parameter or its value do not meet the protocol requirements (for example, array is passed instead of the string). +400 | 4 | `timestamp_refused` | The timestamp value in the oauth_timestamp parameter is incorrect. +401 | 5 | `nonce_used` | The nonce-timestamp combination has already been used. +400 | 6 | `signature_method_rejected`| The signature method is not supported. The following methods are supported: HMAC-SHA1. +401 | 7 | `signature_invalid` | The signature is invalid. +401 | 8 | `consumer_key_rejected` | The Consumer Key has incorrect length or does not exist. +401 | 9 | `token_used` | An attempt of authorization of an already authorized token or an attempt to exchange a not temporary token for a permanent one. +401 | 10 | `token_expired` | The temporary token has expired. At the moment, the mechanism of expiration of temporary tokens is not implemented and the current error is not used. +401 | 11 | `token_revoke` | The token is revoked by the user who authorized it. +401 | 12 | `token_rejected` | The token is not valid, or does not exist, or is not valid for using in the current type of request. +401 | 13 | `verifier_invalid` |The confirmation string does not correspond to the token. +403 | 14 | `permission_unknown` |The consumer permission is unknown. +403 | 15 | `permission_denied` |The consumer does not authorized to access the resource. +405 | 16 | `method_not_allowed` |The method is not supported or not allowed. +403 | 17 | `consumer_key_invalid` |The Consumer Key is invalid. + +## Related topic + +[OAuth-based authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-oauth.html) diff --git a/src/guides/v2.4/get-started/bk-get-started-api.md b/src/guides/v2.4/get-started/bk-get-started-api.md deleted file mode 120000 index 8a981c490b2..00000000000 --- a/src/guides/v2.4/get-started/bk-get-started-api.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/get-started/bk-get-started-api.md \ No newline at end of file diff --git a/src/guides/v2.4/get-started/bk-get-started-api.md b/src/guides/v2.4/get-started/bk-get-started-api.md new file mode 100644 index 00000000000..0198aba818c --- /dev/null +++ b/src/guides/v2.4/get-started/bk-get-started-api.md @@ -0,0 +1,56 @@ +--- +group: web-api +subgroup: 01_Introduction +title: Getting Started with our Web APIs +landing-page: Getting Started with our APIs +menu_title: Introduction +menu_order: 1 +menu_node: parent +functional_areas: + - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/bk-get-started-api/ +layout: migrated +--- + +## What are the Magento web APIs? {#whatare} + +The Magento web [API](https://glossary.magento.com/api) framework provides integrators and developers the means to use web services that communicate with the Magento system. Key features include: + +* Support for [GraphQL]({{page.baseurl}}/graphql/index.html), [REST]({{ page.baseurl }}/rest/bk-rest.html) (Representational State Transfer) and [SOAP]({{ page.baseurl }}/soap/bk-soap.html) (Simple Object Access Protocol). In Magento 2, the [web API](https://glossary.magento.com/web-api) coverage is the same for both REST and SOAP. + +* Three types of [authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication.html): + * Third-party applications authenticate with [OAuth 1.0a]({{ page.baseurl }}/get-started/authentication/gs-authentication-oauth.html). + * Mobile applications authenticate using [tokens]({{ page.baseurl }}/get-started/authentication/gs-authentication-token.html). + * Administrators and customers are authenticated with [login credentials]({{ page.baseurl }}/get-started/authentication/gs-authentication-token.html). + +* All accounts and integrations are assigned resources that they have access to. The API framework checks that any call has the [authorization](https://glossary.magento.com/authorization) to perform the request. + +* Any Magento or third-party service can be [configured as a web API]({{ page.baseurl }}/extension-dev-guide/service-contracts/service-to-web-service.html) with a few lines of [xml](https://glossary.magento.com/xml). To configure a web API, you define XML elements and attributes in a `webapi.xml` configuration file. If a service is not defined in a configuration file, it will not be exposed at all. + +* The framework is based on the CRUD (create, read, update, delete) & search model. The system does not currently support webhooks. + +* The framework supports field filtering of web API responses to conserve mobile bandwidth. + +* Integration style web APIs enable a single web API call to run multiple services at once for a more efficient integration. An example of this behavior can be seen in the [Catalog](https://glossary.magento.com/catalog) where one web API call can create a product. If your payload includes the `stock_item` and `media_gallery_entries` objects, then the framework will also create the product’s inventory & media in that one API call. + +## What can I do with the Magento web APIs? {#uses} + +The APIs can be used to perform a wide array of tasks. For example: + +* Create a shopping app. This can be a traditional app that a user downloads on a mobile device. You could also create an app that an employee uses on a showroom floor to help customers make purchases. + +* Integrate with CRM (Customer Relationship Management) or ERP (Enterprise Resource Planning) backend systems, such as Salesforce or Xero. + +* Integrate with a [CMS](https://glossary.magento.com/cms) (Content Management System). Currently, content tagging is not supported. + +* Create [JavaScript](https://glossary.magento.com/javascript) widgets in the Magento [storefront](https://glossary.magento.com/storefront) or on the [Admin](https://glossary.magento.com/admin) panel. The [widget](https://glossary.magento.com/widget) makes AJAX calls to access services. + +## How do I get started? {#procedure} + +You must register a web service on [Admin](https://glossary.magento.com/magento-admin). Use the following general steps to set up Magento to enable web services. + +1. If you are using token-based authentication, create a web services user on Admin by selecting **System** > Permission > **All Users** > Add New User. (If you are using session-based or OAuth authentication, you do not need to create the new user in the Admin.) +1. Create a new integration on Admin. To create an integration, click **System** > Extensions > **Integration** > Add New Integration**. Be sure to restrict which resources the integration can access. +1. Use a REST or SOAP client to configure authentication. + +See the User Guide for more information. diff --git a/src/guides/v2.4/get-started/create-integration.md b/src/guides/v2.4/get-started/create-integration.md deleted file mode 120000 index 16a3c14970d..00000000000 --- a/src/guides/v2.4/get-started/create-integration.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/get-started/create-integration.md \ No newline at end of file diff --git a/src/guides/v2.4/get-started/create-integration.md b/src/guides/v2.4/get-started/create-integration.md new file mode 100644 index 00000000000..89b9dbc2dc8 --- /dev/null +++ b/src/guides/v2.4/get-started/create-integration.md @@ -0,0 +1,343 @@ +--- +group: web-api +subgroup: Web APIs +title: Create an integration +menu_title: Create an integration +menu_order: 1 +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/create-integration/ +layout: migrated +--- + +An **integration** enables third-party services to call the Magento web APIs. The Magento APIs currently supports Accounting, Enterprise Resource Planning (ERP), Customer Relationship Management (CRM), Product Information Management (PIM), and marketing automation systems out of the box. + +Implementing a simple integration requires little knowledge of [PHP](https://glossary.magento.com/php) or Magento internal processes. However, you will need a working knowledge of + +* [Magento REST or SOAP Web APIs]({{ page.baseurl }}/get-started/bk-get-started-api.html) +* [Web API authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication.html) +* [OAuth-based authentication]( {{ page.baseurl }}/get-started/authentication/gs-authentication-oauth.html ) + +Before you begin creating a module, make sure that you have a working installation of Magento 2.0, and the [Magento System Requirements]({{ page.baseurl }}/install-gde/system-requirements.html). + +To create an integration, follow these general steps: + +1. [Create a module with the minimal structure and configuration.](#skeletal) +1. [Add files specific to the integration.](#files) +1. [Install the module.](#install) +1. [Check the integration.](#check) +1. [Integrate with your application.](#integrate) + +## Create a skeletal module {#skeletal} + +To develop a module, you must: + +1. **Create the module file structure.** The module for an integration, like any other of your custom modules, should be placed under `/app/code/app/code//`. E.g. `/app/code/Vendor1/Module1` + + Also create `etc`, `etc/integration`, and `Setup` subdirectories under `/app/code//`, as shown in the following example: + + ```bash + cd + ``` + + ```bash + mkdir -p app/code///etc/integration + ``` + + ```bash + mkdir -p app/code///Setup + ``` + + For more detailed information, see [Create your component file structure]({{ page.baseurl }}/extension-dev-guide/build/module-file-structure.html). + +1. **Define your module configuration file.** The `etc/module.xml` file provides basic information about the module. Change directories to the `etc` directory and create the `module.xml` file. You must specify values for the following attributes: + + + + + + + + + + + + + +
    AttributeDescription
    nameA string that uniquely identifies the [module](https://glossary.magento.com/module).
    setup_versionThe version of Magento the component uses
    + The following example shows an example `etc/module.xml` file. + + ```xml + + + + + + + + + ``` + + Module `Magento_Integration` is added to "sequence" to be loaded first. It helps to avoid the issue, when a module with integration config loaded, that leads to a malfunction. + +1. **Add your module's `composer.json` file.** Composer is a dependency manager for PHP. You must create a `composer.json` file for your module so that Composer can install and update the libraries your module relies on. Place the `composer.json` file in the `module-` directory. + + The following example demonstrates a minimal `composer.json` file. + + ```json + { + "name": "Vendor1_Module1", + "description": "create integration from config", + "require": { + "php": "~7.2.0|~7.3.0", + "magento/framework": "2.0.0", + "magento/module-integration": "2.0.0" + }, + "type": "magento2-module", + "version": "1.0", + "autoload": { + "files": [ "registration.php" ], + "psr-4": { + "Vendor1\\Module1\\": "" + } + } + } + ``` + +For more information, see [Create a component]({{ page.baseurl }}/extension-dev-guide/build/create_component.html). + +1. **Create a `registration.php` file** The `registration.php` registers the module with the Magento system. It must be placed in the module's root directory. + + ```php + integrationManager = $integrationManager; + } + + /** + * {@inheritdoc} + */ + + public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + { + $this->integrationManager->processIntegrationConfig(['TestIntegration']); + } + } + ``` + + In the following line + + `$this->integrationManager->processIntegrationConfig(['testIntegration']);` + + `testIntegration` must refer to your `etc/integration/config.xml` file, and the integration name value must be the same. + + The following example demonstrates a minimal `config.xml` file. + + ```xml + + + someone@example.com + https://example.com + https://example.com/identity_link_url + + + ``` + + Also, be sure to change the path after `namespace` for your vendor and module names. + +## Create integration files {#files} + +Magento provides the Integration module, which simplifies the process of defining your integration. This module automatically performs functions such as: + +* Managing the third-party account that connects to Magento. +* Maintaining OAuth authorizations and user data. +* Managing security tokens and requests. + +To customize your module, you must create multiple [XML](https://glossary.magento.com/xml) files and read through others files to determine what resources existing Magento modules have access to. + +The process for customizing your module includes + +* [Define the required resources](#resources) +* [Pre-configure the integration](#preconfig) + +### Define the required resources {#resources} + +The `etc/integration/api.xml` file defines which [API](https://glossary.magento.com/api) resources the integration has access to. + +To determine which resources an integration needs access to, review the permissions defined in each module's `etc/acl.xml` file. + +In the following example, the test integration requires access to the following resources in the Sales module: + +```xml + + + + + + + + + + + + + + + +``` + +### Pre-configure the integration {#preconfig} + +Your module can optionally provide values in configuration file `config.xml`, so that the integration can be automatically pre-configured with default values. To enable this feature, update the `config.xml` file in the `etc/integration` directory. + + {:.bs-callout-info} +If you pre-configure the integration, the values cannot be edited from the [admin](https://glossary.magento.com/admin) panel. + +The file defines which API resources the integration has access to. + +```xml + + + + + + + +``` + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ElementDescription
    integrationsContains one or more integration definitions.
    integration name=""Defines an integration. The name must be specified.
    emailAn email to associate with this integration.
    endpoint_url

    Optional. The [URL](https://glossary.magento.com/url) where OAuth credentials can be sent when using OAuth for token exchange. We strongly recommend using https://.

    +

    See OAuth-based authentication for details.

    identity_link_urlOptional. The URL that redirects the user to link their 3rd party account with the Magento integration.
    + +## Install your module {#install} + +Use the following steps to install your module: + +1. Run the following command to update the Magento [database schema](https://glossary.magento.com/database-schema) and data. + + ```bash + bin/magento setup:upgrade + ``` + +1. Run the following command to generate the new code. + + {:.bs-callout-info} + In Production mode, you may receive a message to 'Please rerun Magento compile command'. Enter the command below. Magento does not prompt you to run the compile command in Developer mode. + + ```bash + bin/magento setup:di:compile + ``` + +1. Run the following command to clean the cache. + + ```bash + bin/magento cache:clean + ``` + +## Check your integration {#check} + +Log in to Magento and navigate to **System > Extensions > Integrations**. The integration should be displayed in the grid. + +## Integrate with your application {#integrate} + +Before you can activate your integration in Magento, you must create two pages on your application to handle OAuth communications. + +* The location specified in the `identity_link_url` parameter must point to a page that can handle login requests. + +* The location specified in the `endpoint_url` parameter (**Callback URL** in Admin) must be able to process OAuth token exchanges. + +### Login page {#login} + +When a merchant clicks the **Activate** button in Admin, a pop-up login page for the third-party application displays. Magento sends values for `oauth_consumer_key` and `success_call_back` parameters. The application must store the value for `oauth_consumer_key` to tie it to the login ID. Use the `success_call_back` parameter to return control back to Magento. + +### Callback page {#callback} + +The callback page must be able to perform the following tasks: + +* Receive an initial HTTPS POST that Magento sends when the merchant activates integration. This post contains the Magento store URL, an `oauth_verifier`, the OAuth consumer key, and the OAuth consumer secret. The consumer key and secret are generated when the integration is created. + +* Ask for a request token. A request token is a temporary token that the user exchanges for an access token. Use the following API to get a request token from Magento: + + `POST /oauth/token/request` + + See [Get a request token]( {{ page.baseurl }}/get-started/authentication/gs-authentication-oauth.html#pre-auth-token ) for more details about this call. + +* Parse the request token response. The response contains an `oauth_token` and `oauth_token_secret`. + +* Ask for an access token. The request token must be exchanged for an access token. Use the following API to get a request token from Magento: + + `POST /oauth/token/access` + + See [Get an access token]( {{ page.baseurl }}/get-started/authentication/gs-authentication-oauth.html#get-access-token ) for more details about this call. + +* Parse the access token response. The response contains an `oauth_token` and `oauth_token_secret`. These values will be different than those provided in the request token response. + +* Save the access token and other OAuth parameters. The access token and OAuth parameters must be specified in the `Authorization` header in each call to Magento. + +## Related Topics + +* [Web API authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication.html) +* [OAuth-based authentication]( {{ page.baseurl }}/get-started/authentication/gs-authentication-oauth.html ) +* [Magento System Requirements]({{ page.baseurl }}/install-gde/system-requirements.html) +* [Create the module file structure]({{ page.baseurl }}/extension-dev-guide/build/module-file-structure.html) +* [Create a component]({{ page.baseurl }}/extension-dev-guide/build/create_component.html) diff --git a/src/guides/v2.4/get-started/gs-curl.md b/src/guides/v2.4/get-started/gs-curl.md index c3641e08d07..13d534a1fe1 100644 --- a/src/guides/v2.4/get-started/gs-curl.md +++ b/src/guides/v2.4/get-started/gs-curl.md @@ -3,6 +3,8 @@ group: web-api title: Use cURL to run the request functional_areas: - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/gs-curl/ +layout: migrated --- ['cURL'](https://curl.haxx.se/) is a command-line tool that lets you transmit HTTP requests and receive responses from the command line or a shell script. It is available for Linux distributions, Mac OS X, and Windows. diff --git a/src/guides/v2.4/get-started/gs-web-api-request.md b/src/guides/v2.4/get-started/gs-web-api-request.md index 05f30ad911f..e03b32da787 100644 --- a/src/guides/v2.4/get-started/gs-web-api-request.md +++ b/src/guides/v2.4/get-started/gs-web-api-request.md @@ -1,6 +1,8 @@ --- group: web-api title: Construct a request +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/gs-web-api-request/ +layout: migrated --- To configure a web API, developers define some of the elements of each API call in the `/vendor///etc/webapi.xml` file, where `` is your vendor name (for example, `magento`) and `` is your module name (which exactly matches its definition in `composer.json`). For example, the web API for the Customer service is defined in the `/vendor/magento/module-customer/etc/webapi.xml` configuration file. Service data interfaces and builders define the required and optional parameters and the return values for the [API](https://glossary.magento.com/api) calls. diff --git a/src/guides/v2.4/get-started/gs-web-api-response.md b/src/guides/v2.4/get-started/gs-web-api-response.md deleted file mode 120000 index 6352bb65a64..00000000000 --- a/src/guides/v2.4/get-started/gs-web-api-response.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/get-started/gs-web-api-response.md \ No newline at end of file diff --git a/src/guides/v2.4/get-started/gs-web-api-response.md b/src/guides/v2.4/get-started/gs-web-api-response.md new file mode 100644 index 00000000000..8b1f5f71e7f --- /dev/null +++ b/src/guides/v2.4/get-started/gs-web-api-response.md @@ -0,0 +1,90 @@ +--- +group: web-api +subgroup: 20_REST +title: Status codes and responses +menu_title: Status codes and responses +menu_order: 3 +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/gs-web-api-response/ +layout: migrated +--- + +## REST responses {#rest-responses} + +Each web [API](https://glossary.magento.com/api) call returns a HTTP status code and a response payload. When an error occurs, the response body also returns an error message. + +### HTTP status codes {#http-status-codes} + +Each [web API](https://glossary.magento.com/web-api) call returns an HTTP status code that reflects the result of a request: + +HTTP code | Meaning | Description +--- | --- | --- +200 | Success | The framework returns HTTP 200 to the caller upon success. +400 | Bad Request | If service implementation throws either `Magento_Service_Exception` or its derivative, the framework returns a HTTP 400 with a error response including the service-specific error code and message. This error code could indicate a problem such as a missing required parameter or the supplied data didn't pass validation. +401 | Unauthorized | The caller was not authorized to perform the request. For example, the request included an invalid token or a user with customer permissions attempted to access an object that requires administrator permissions. +403 | Forbidden | Access is not allowed for reasons that are not covered by error code 401. +404 | Not found | The specified REST endpoint does not exist. The caller can try again. +405 | Not allowed | A request was made of a resource using a method that is not supported by that resource. For example, using GET on a form which requires data to be presented via POST, or using PUT on a read-only resource. +406 | Not acceptable | The requested resource is only capable of generating content that is not acceptable according to the Accept headers sent in the request. +500 | System Errors | If service implementation throws any other exception like network errors, database communication, framework returns HTTP 500. + +### Response payload {#response-payload} + +POST, PUT, and GET web API calls return a response payload. This payload is a JSON- or XML-formatted response body. The `Accept: application/` header in the request determines the format of the response body, where `FORMAT` is either `json` or `xml`. + +A successful DELETE call returns `true`. An unsuccessful DELETE call returns a payload similar to the other calls. + +The response payload depends on the call. +For example, a `GET /V1/customers/:customerId` call returns the following payload: + +```json +{ + "customers": { + "customer": { + "email": "user@example.com", + "firstname": "John", + "lastname": "Doe" + }, + "addresses": [ + { + "defaultShipping": true, + "defaultBilling": true, + "firstname": "John", + "lastname": "Doe", + "region": { + "regionCode": "CA", + "region": "California", + "regionId": 12 + }, + "postcode": "90001", + "street": ["Zoe Ave"], + "city": "Los Angeles", + "telephone": "555-000-00-00", + "countryId": "US" + } + ] + } +} +``` + +This JSON-formatted response body includes a `customer` object with the customer email, first name, and last name, and customer address information. The information in this response body shows account information for the specified customer. + +### Error format {#error-format} + +When an error occurs, the response body contains an error code, error message, and optional parameters. + +Part | Description +--- | --- | --- +`code` | The status code representing the error. +`message` | The message explaining the error. +`parameters` | Optional. An array of attributes used to generate a different and/or localized error message for the client. + +As an example, Magento returns a `code` of `400` and the following `message` when an invalid `sku` value is specified in the call `PUT V1/products/:sku`. + +```json +{ + "message": "Invalid product data: %1", + "parameters": [ + "Invalid attribute set entity type" + ] +} +``` diff --git a/src/guides/v2.4/get-started/rest_front.md b/src/guides/v2.4/get-started/rest_front.md deleted file mode 120000 index 54a71fc4b2f..00000000000 --- a/src/guides/v2.4/get-started/rest_front.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/get-started/rest_front.md \ No newline at end of file diff --git a/src/guides/v2.4/get-started/rest_front.md b/src/guides/v2.4/get-started/rest_front.md new file mode 100644 index 00000000000..dc485cfbff2 --- /dev/null +++ b/src/guides/v2.4/get-started/rest_front.md @@ -0,0 +1,56 @@ +--- +group: web-api +subgroup: 20_REST +title: Use REST APIs +menu_order: 1 +menu_node: parent +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/rest_front/ +layout: migrated +--- + +The Magento REST [API](https://glossary.magento.com/api) defines a set of functions that a developer can use to perform requests and receive responses. These interactions are performed using the HTTP protocol. + +The caller issues an HTTP request, which contains the following elements: + +* An HTTP header that provides authentication and other instructions +* A verb, which can be one of GET, POST, PUT, or DELETE. +* An endpoint, which is a Uniform Resource Indicator (URI) that identifies the server, the web service, and the resource being acted on. +* The call payload, which is set of input parameters and attributes that you supply with the request. + +Magento returns a response payload as well as an HTTP status code. + +This guide introduces web API, REST, and cURL command concepts. It shows you how to authenticate and construct and run REST [web API](https://glossary.magento.com/web-api) calls. You run REST web API calls through cURL commands or a REST client. + +Read the following sections to get up and running with the Magento web APIs: + + + + diff --git a/src/guides/v2.4/get-started/soap/soap-web-api-calls.md b/src/guides/v2.4/get-started/soap/soap-web-api-calls.md deleted file mode 120000 index 20be4d735ba..00000000000 --- a/src/guides/v2.4/get-started/soap/soap-web-api-calls.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/get-started/soap/soap-web-api-calls.md \ No newline at end of file diff --git a/src/guides/v2.4/get-started/soap/soap-web-api-calls.md b/src/guides/v2.4/get-started/soap/soap-web-api-calls.md new file mode 100644 index 00000000000..2b9d41b96e5 --- /dev/null +++ b/src/guides/v2.4/get-started/soap/soap-web-api-calls.md @@ -0,0 +1,98 @@ +--- +group: web-api +subgroup: 30_SOAP +title: Use SOAP Services +menu_title: Use SOAP Services +menu_order: 1 +menu_node: parent +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/soap/soap-web-api-calls/ +layout: migrated +--- + +## WSDL File {#wsdl} + +A WSDL file is generated only for services that you request. This means that different clients may use different services and therefore use different WSDLs. + +The Magento web [API](https://glossary.magento.com/api) uses WSDL 1.2, which complies with WS-I 2.0 Basic Profile. + +Each Magento service interface that is part of a [service contract](https://glossary.magento.com/service-contract) is represented as a separate service in the WSDL. + +To consume several services, you must specify them in the WSDL endpoint [URL](https://glossary.magento.com/url). + +| Service | WSDL endpoint URL | Available services | +| --------- | ---------- | ------------------------------------------ | +| customer | http://magentohost/soap?wsdl&services=customerCustomerRepositoryV1 | \Magento\Customer\Api\Data\CustomerInterface | +| customer, catalogProduct | http://magentohost/soap/custom_store?wsdl&services=customerCustomerRepositoryV1,catalogProductRepositoryV1 | \Magento\Customer\Api\Data\CustomerInterface, \Magento\Catalog\Api\Data\ProductInterface | + +The WSDL URL follows the following pattern: + +`http:///soap/?wsdl&services=,` + +You must specify each service version in the endpoint URL. + +This way, you can have a strict contract between your application and the service provider. + +If you want an overview to all the available Web Services, use the following URL format to get a list of all SOAP Services: + +`http:///soap/all?wsdl_list=1` + +```xml + + ... + + http:///soap/all?wsdl&services=storeStoreRepositoryV1 + + + http:///soap/all?wsdl&services=storeGroupRepositoryV1 + + + http:///soap/all?wsdl&services=storeWebsiteRepositoryV1 + + ... + +``` + +### Service class-to-service name conversion rules + +Service names use the following conventions: + +* CamelCase is used for service naming. +* The string `Service` is omitted. +* The `Magento` prefix is omitted. +* The `Interface` suffix is omitted. +* If the service name is the same as the [module](https://glossary.magento.com/module) name, the module name is omitted. For example, if there is a customer service interface in the customer module, the word `customer` will be used in the service name only once. + +| Original Service Interface Name | Service Name | +|---------- +| \Magento\Customer\Api\Data\CustomerInterface | customerCustomerRepositoryV1 | +| \Magento\Customer\Api\AccountManagementInterface | customerAccountManagementV1 | +| \Enterprise\Customer\Service\V3\Customer\AddressInterface | enterpriseCustomerAddressV3 | + +## Authentication {#auth} + +Protected SOAP resources can be accessed using bearer tokens (OAuth access tokens) over HTTP. Access tokens are strings representing an access [authorization](https://glossary.magento.com/authorization) issued to the client. For more information, see [OAuth-based authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-oauth.html) + +The following [PHP](https://glossary.magento.com/php) script illustrates how to get an access token: + +```php + [ + 'header' => 'Authorization: Bearer 36849300bca4fbff758d93a3379f1b8e' + ] + ]; +$wsdlUrl = 'http://magento.ll/soap/default?wsdl=1&services=testModule1AllSoapAndRestV1'; +$serviceArgs = ["id" => 1]; + +$context = stream_context_create($opts); +$soapClient = new SoapClient($wsdlUrl, ['version' => SOAP_1_2, 'stream_context' => $context]); + +$soapResponse = $soapClient->testModule1AllSoapAndRestV1Item($serviceArgs); ?> +``` + +{:.ref-header} +Related topics + +* [OAuth-based authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-oauth.html) +* [Service contracts]({{ page.baseurl }}/extension-dev-guide/service-contracts/service-contracts.html) +* [SOAP Reference]({{ page.baseurl }}/soap/bk-soap.html) diff --git a/src/guides/v2.4/get-started/web-api-functional-testing.md b/src/guides/v2.4/get-started/web-api-functional-testing.md deleted file mode 120000 index 463ef1b8ec7..00000000000 --- a/src/guides/v2.4/get-started/web-api-functional-testing.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/get-started/web-api-functional-testing.md \ No newline at end of file diff --git a/src/guides/v2.4/get-started/web-api-functional-testing.md b/src/guides/v2.4/get-started/web-api-functional-testing.md new file mode 100644 index 00000000000..72019acee64 --- /dev/null +++ b/src/guides/v2.4/get-started/web-api-functional-testing.md @@ -0,0 +1,122 @@ +--- +group: web-api +title: Web API functional testing +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/web-api-functional-testing/ +layout: migrated +--- + +The Web [API](https://glossary.magento.com/api) testing framework allows you to test Magento [Web API](https://glossary.magento.com/web-api) from the client application point of view. The tests can be used with either REST or SOAP. The REST or SOAP [adapter](https://glossary.magento.com/adapter) that runs the tests is specified in PHPUnit configuration. See [How to Run the Tests](#howto) for more information. + +To run Web API tests for GraphQl, see [GraphQL functional testing]({{ page.baseurl }}/graphql/functional-testing.html). + +## Implementation Details {#details} + +The Web API functional testing framework depends on the integration testing framework and reuses most of classes implemented there. + +### Custom Annotations for Data Fixtures {#custom} + +In the Web API functional tests only, the custom annotation `@magentoApiDataFixture` is available for declaring fixtures. The difference of this annotation from `@magentoDataFixture` is that the fixture will be committed and accessible during HTTP requests made within the test body. The usage rules of `@magentoApiDataFixture` are the same as `@magentoDataFixture` usage rules. + +{:.bs-callout-tip} +If data was added to the DB using `@magentoApiDataFixture`, it will not be automatically cleared after test execution. The data is cleared when `@magentoDataFixture` is used. + +Do not define fixtures in `dev/tests/api-functional`. Instead, they must be taken from `dev/tests/integration`. The integration framework defines most necessary fixtures, and they should be reused during Web API functional testing. If the existing set of fixtures is insufficient, add new fixtures under `dev/tests/integration`. The fixtures will then be available for both testing frameworks. + +To keep your test environment clean, clear all entities created in fixture files or within tests itself from the DB after test execution. This can be done either directly in tearDown or by a corresponding rollback for the fixture file. This file should be named the same as a fixture, but with `_rollback` suffix. + +## How to Create a New Test {#create} + +All Web API functional tests should inherit from the generic test case `Magento\TestFramework\TestCase\WebapiAbstract`. It defines the `_webApiCall()` method, which should be used to perform Web API calls from tests. Clients of `_webApiCall()` are unaware of which adapter will be used to perform the remote call. + +```php +namespace Magento\Webapi\Routing; + +class CoreRoutingTest extends \Magento\TestFramework\TestCase\WebapiAbstract +{ + public function testBasicRoutingExplicitPath() + { + $itemId = 1; + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/testmodule1/' . $itemId, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + ], + 'soap' => [ + 'service' => 'testModule1AllSoapAndRestV1', + 'operation' => 'testModule1AllSoapAndRestV1Item', + ], + ]; + $requestData = ['itemId' => $itemId]; + $item = $this->_webApiCall($serviceInfo, $requestData); + $this->assertEquals('testProduct1', $item['name'], "Item was retrieved unsuccessfully"); + } +} +``` + +The test above should be able to test SOAP and REST, depending on what adapter is currently used by the testing framework. The format of `$serviceInfo` is defined by the Web API client adapter interface: + +```php +namespace Magento\TestFramework\TestCase\Webapi; + +interface AdapterInterface +{ + /** + * Perform call to the specified service method. + * + * @param array $serviceInfo
    +     * array(
    +     *     'rest' => array(
    +     *         'resourcePath' => $resourcePath, // e.g. /products/:id
    +     *         'httpMethod' => $httpMethod,     // e.g. GET
    +     *         'token' => '21hasbtlaqy8t3mj73kjh71cxxkqj4aq'    // optional : for token based Authentication. Will
    +     *                                                             override default OAuth based authentication provided
    +     *                                                             by test framework
    +     *     ),
    +     *     'soap' => array(
    +     *         'service' => $soapService,    // soap service name with Version suffix e.g. catalogProductV1, customerV2
    +     *         'operation' => $operation     // soap operation name e.g. catalogProductCreate
    +     *     )
    +     * );
    +     * 
    + * @param array $arguments + * @param string|null $storeCode if store code not provided, default store code will be used + * @param \Magento\Integration\Model\Integration|null $integration + * @return array|string|int|float|bool + */ + public function call($serviceInfo, $arguments = [], $storeCode = null, $integration = null); +} +``` + +## How to Run the Tests {#howto} + +### Prerequisites {#prereq} + +1. Install the [PHP](https://glossary.magento.com/php) Soap [extension](https://glossary.magento.com/extension). + + Copy `php_soap.dll` or `php_soap.so` to your PHP extensions directory. Edit your `php.ini` file and enable the PHP Soap extension. Usually this means deleting the leading semi-colon in front of the extension. Then restart Apache. + + `extension=php_soap.dll` + +1. Before running the functional tests you need to clear your [cache](https://glossary.magento.com/cache). Now you are ready to run the tests. + +### Running the Tests {#running} + +1. Copy `dev/tests/api-functional/phpunit_rest.xml.dist` and `phpunit_soap.xml.dist` to `dev/tests/api-functional/phpunit_rest.xml` and `phpunit_soap.xml`. + +1. Define the Magento instance URL as a value of `TESTS_BASE_URL`, Test Webservice User as value of `TESTS_WEBSERVICE_USER` and Test Webservice API key as value of `TESTS_WEBSERVICE_APIKEY` in copied file i.e. `phpunit_rest.xml` or `phpunit_soap.xml`. + +1. Copy `dev/tests/api-functional/config/install-config-mysql.php.dist` to `dev/tests/api-functional/config/install-config-mysql.php`. + +1. Configure your DB connection and install settings in `dev/tests/api-functional/config/install-config-mysql.php`. Specify the Magento database. The base URL to access this Magento instance must be the same specified in the `phpunit_rest.xml` or `phpunit_soap.xml` file. + +1. Run `phpunit` using the `dev/tests/api-functional/phpunit_rest.xml` or `dev/tests/api-functional/phpunit_soap.xml` configuration file:: + + ```bash + vendor/bin/phpunit --configuration + ``` + + or + + ```bash + vendor/bin/phpunit -c + ``` diff --git a/src/guides/v2.4/graphql/mutations/change-customer-password.md b/src/guides/v2.4/graphql/mutations/change-customer-password.md index 38b3da2468b..917fe8888bc 100644 --- a/src/guides/v2.4/graphql/mutations/change-customer-password.md +++ b/src/guides/v2.4/graphql/mutations/change-customer-password.md @@ -5,7 +5,7 @@ title: changeCustomerPassword mutation Use the `changeCustomerPassword` mutation to change the password for the logged-in customer. -To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-session.html). +To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-session.html). ## Syntax diff --git a/src/guides/v2.4/graphql/mutations/create-customer-address.md b/src/guides/v2.4/graphql/mutations/create-customer-address.md index ed906b06ede..3fa21bdb1c0 100644 --- a/src/guides/v2.4/graphql/mutations/create-customer-address.md +++ b/src/guides/v2.4/graphql/mutations/create-customer-address.md @@ -5,7 +5,7 @@ title: createCustomerAddress mutation Use the `createCustomerAddress` mutation to create the customer's address. -To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-session.html). +To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-session.html). ## Syntax diff --git a/src/guides/v2.4/graphql/mutations/create-customer.md b/src/guides/v2.4/graphql/mutations/create-customer.md index b2bc573d14b..cdcd3fd3e8c 100644 --- a/src/guides/v2.4/graphql/mutations/create-customer.md +++ b/src/guides/v2.4/graphql/mutations/create-customer.md @@ -8,7 +8,7 @@ We recommend using the [createCustomerV2 mutation]({{page.baseurl}}/graphql/muta The `createCustomer` mutation creates a new customer. -To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-session.html). +To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-session.html). ## Syntax diff --git a/src/guides/v2.4/graphql/mutations/delete-customer-address.md b/src/guides/v2.4/graphql/mutations/delete-customer-address.md deleted file mode 120000 index a23b0a6c3c3..00000000000 --- a/src/guides/v2.4/graphql/mutations/delete-customer-address.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/graphql/mutations/delete-customer-address.md \ No newline at end of file diff --git a/src/guides/v2.4/graphql/mutations/delete-customer-address.md b/src/guides/v2.4/graphql/mutations/delete-customer-address.md new file mode 100644 index 00000000000..20bb320db83 --- /dev/null +++ b/src/guides/v2.4/graphql/mutations/delete-customer-address.md @@ -0,0 +1,74 @@ +--- +group: graphql +title: deleteCustomerAddress mutation +--- + +Use the `deleteCustomerAddress` mutation to delete the specified customer address. + +To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-session.html). + +## Syntax + +```graphql +mutation { + deleteCustomerAddress( + id: Int! + ) { + Boolean + } +} +``` + +## Example usage + +The following call deletes a customer's address. + +**Request:** + +```graphql +mutation { + deleteCustomerAddress(id: 4) +} +``` + +**Response:** + +```json +{ + "data": { + "deleteCustomerAddress": true + } +} +``` + +## Input attributes + +The `deleteCustomerAddress` mutation requires the following input: + +Attribute | Data Type | Description +--- | --- | --- +`id` | Int! | The ID assigned to the address object + +## Output attributes + +The `deleteCustomerAddress` mutation returns a Boolean value that indicates whether the operation was successful. + +## Errors + +Error | Description +--- | --- +`Address "id" value should be specified` | The `id` argument is zero. +`Could not find a address with ID "XXX"` | The customer address specified in the `id` argument does not exist. +`Customer Address XXX is set as default billing address and cannot be deleted` | You cannot delete a default billing address. +`Customer Address XXX is set as default shipping address and cannot be deleted` | You cannot delete a default shipping address. +`Field "deleteCustomerAddress" argument "id" requires type Int!, found "XXX".` | The specified `id` argument value has the wrong type. +`Syntax Error: Expected Name, found )` | The `id` argument was omitted or does not have a value. +`The current customer isn't authorized.` | The current customer is not currently logged in, or the customer's token does not exist in the `oauth_token` table. + +## Related topics + +* [customer query]({{page.baseurl}}/graphql/queries/customer.html) +* [createCustomer mutation]({{page.baseurl}}/graphql/mutations/create-customer.html) +* [updateCustomer mutation]({{page.baseurl}}/graphql/mutations/update-customer.html) +* [createCustomerAddress mutation]({{page.baseurl}}/graphql/mutations/create-customer-address.html) +* [updateCustomerAddress mutation]({{page.baseurl}}/graphql/mutations/update-customer-address.html) diff --git a/src/guides/v2.4/graphql/mutations/generate-customer-token.md b/src/guides/v2.4/graphql/mutations/generate-customer-token.md index eaaa8abb1d9..2d6c6561d68 100644 --- a/src/guides/v2.4/graphql/mutations/generate-customer-token.md +++ b/src/guides/v2.4/graphql/mutations/generate-customer-token.md @@ -5,7 +5,7 @@ title: generateCustomerToken mutation Use the `generateCustomerToken` mutation to create a new customer token. -To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-session.html). +To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-session.html). ## Syntax diff --git a/src/guides/v2.4/graphql/mutations/revoke-customer-token.md b/src/guides/v2.4/graphql/mutations/revoke-customer-token.md deleted file mode 120000 index b033a1df12f..00000000000 --- a/src/guides/v2.4/graphql/mutations/revoke-customer-token.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/graphql/mutations/revoke-customer-token.md \ No newline at end of file diff --git a/src/guides/v2.4/graphql/mutations/revoke-customer-token.md b/src/guides/v2.4/graphql/mutations/revoke-customer-token.md new file mode 100644 index 00000000000..33cfa0f5447 --- /dev/null +++ b/src/guides/v2.4/graphql/mutations/revoke-customer-token.md @@ -0,0 +1,61 @@ +--- +group: graphql +title: revokeCustomerToken mutation +--- + +Use the `revokeCustomerToken` mutation to revokes the customer's token. + +To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-session.html). + +## Syntax + +```graphql +mutation { + revokeCustomerToken { + RevokeCustomerTokenOutput + } +} +``` + +## Example usage + +The following call revokes the customer's token. + +**Request:** + +```graphql +mutation { + revokeCustomerToken { + result + } +} +``` + +**Response:** + +```json +{ + "data": { + "revokeCustomerToken": { + "result": true + } + } +} +``` + +## Output attributes + +Attribute | Data Type | Description +--- | --- | --- +`result` | Boolean! | Returns `true` if the token was successfully revoked + +## Errors + +Error | Description +--- | --- +`The current customer isn't authorized.` | The current customer is not currently logged in, or the customer's token does not exist in the `oauth_token` table. + +## Related topics + +* [customer query]({{page.baseurl}}/graphql/queries/customer.html) +* [generateCustomerToken mutation]({{page.baseurl}}/graphql/mutations/generate-customer-token.html) diff --git a/src/guides/v2.4/graphql/mutations/update-customer-address.md b/src/guides/v2.4/graphql/mutations/update-customer-address.md index 01b4bc699c7..3403482f5ab 100644 --- a/src/guides/v2.4/graphql/mutations/update-customer-address.md +++ b/src/guides/v2.4/graphql/mutations/update-customer-address.md @@ -5,7 +5,7 @@ title: updateCustomerAddress mutation Use the `updateCustomerAddress` mutation to update the customer's address. -To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-session.html). +To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-session.html). ## Syntax diff --git a/src/guides/v2.4/graphql/mutations/update-customer-email.md b/src/guides/v2.4/graphql/mutations/update-customer-email.md index 09de6eb8971..eab69c23916 100644 --- a/src/guides/v2.4/graphql/mutations/update-customer-email.md +++ b/src/guides/v2.4/graphql/mutations/update-customer-email.md @@ -5,7 +5,7 @@ title: updateCustomerEmail mutation Use the `updateCustomerEmail` mutation to change the email address for the logged-in customer. -To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-session.html). +To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-session.html). ## Syntax diff --git a/src/guides/v2.4/graphql/mutations/update-customer-v2.md b/src/guides/v2.4/graphql/mutations/update-customer-v2.md index 4a2f2c64b40..d27c374ddd2 100644 --- a/src/guides/v2.4/graphql/mutations/update-customer-v2.md +++ b/src/guides/v2.4/graphql/mutations/update-customer-v2.md @@ -7,7 +7,7 @@ The `updateCustomerV2` mutation updates the personal information in an existing The `updateCustomerV2` mutation supersedes the `updateCustomer` mutation as the means to update a customer account. The input objects differ between these two mutations. The `updateCustomer` mutation required the `CustomerInput` object, as did the `createCustomer` mutation. Updating a customer does not require any specific attribute, while several attributes are required when you create a customer. You could not determine this by looking at the schema for those mutations. The `updateCustomerV2` mutation requires the `CustomerUpdateInput` object, which it does not share with the [`createCustomerV2` mutation]({{page.baseurl}}/graphql/mutations/create-customer-v2.html). -To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-session.html). +To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-session.html). ## Syntax diff --git a/src/guides/v2.4/graphql/mutations/update-customer.md b/src/guides/v2.4/graphql/mutations/update-customer.md index b088d69cbf7..83a937c751c 100644 --- a/src/guides/v2.4/graphql/mutations/update-customer.md +++ b/src/guides/v2.4/graphql/mutations/update-customer.md @@ -8,7 +8,7 @@ We recommend using the [updateCustomerV2 mutation]({{page.baseurl}}/graphql/muta The `updateCustomer` mutation updates the customer's personal information. -To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-session.html). +To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-session.html). ## Syntax diff --git a/src/guides/v2.4/graphql/queries/customer-orders.md b/src/guides/v2.4/graphql/queries/customer-orders.md index 79cf639b07b..d717428d3c6 100644 --- a/src/guides/v2.4/graphql/queries/customer-orders.md +++ b/src/guides/v2.4/graphql/queries/customer-orders.md @@ -7,7 +7,7 @@ The `customerOrders` query has been deprecated. Specify the `orders` object in t The Sales module performs a wide variety of functions, including order, invoice, and shipment management. However, most of these functions are performed on the backend, and the customer does not have access to this information. By returning a list of customer orders, the `customerOrders` query allows a customer to retrieve their order histories. -We recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-session.html). +We recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-session.html). ## Syntax diff --git a/src/guides/v2.4/graphql/queries/customer.md b/src/guides/v2.4/graphql/queries/customer.md index 1eb3559822e..2b659eefabe 100644 --- a/src/guides/v2.4/graphql/queries/customer.md +++ b/src/guides/v2.4/graphql/queries/customer.md @@ -5,7 +5,7 @@ title: customer query The `customer` query returns information about the logged-in customer, store credit history and customer's wishlist. -To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-session.html). +To return or modify information about a customer, we recommend you use customer tokens in the header of your GraphQL calls. However, you also can use [session authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-session.html). ## Syntax diff --git a/src/guides/v2.4/rest/generate-local.md b/src/guides/v2.4/rest/generate-local.md index 0deddf1a270..e6446fedaf6 100644 --- a/src/guides/v2.4/rest/generate-local.md +++ b/src/guides/v2.4/rest/generate-local.md @@ -29,7 +29,7 @@ To view the Swagger documentation for a specific store view, use this URL: - The assigned store code - `all`. This value only applies to the [CMS](https://glossary.magento.com/cms) and Product modules. If this value is specified, the API call affects all the merchant's stores. -By default, Magento returns documentation for resources available to anonymous users across all stores. If you specify a valid customer or admin token in the `api_key` text box in the upper right corner, Swagger returns documentation for all the endpoints the user has access to. To generate an API key, call the `POST /V1/integration/customer/token` endpoint or a 2FA endpoint such as `POST /V1/tfa/provider/google/authenticate` with the appropriate payload, as directed in [Token-based authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-token.html). +By default, Magento returns documentation for resources available to anonymous users across all stores. If you specify a valid customer or admin token in the `api_key` text box in the upper right corner, Swagger returns documentation for all the endpoints the user has access to. To generate an API key, call the `POST /V1/integration/customer/token` endpoint or a 2FA endpoint such as `POST /V1/tfa/provider/google/authenticate` with the appropriate payload, as directed in [Token-based authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-token.html). The generated Swagger documentation provides the capability to test REST requests. A user can enter a sample request, then press the **Try it out!** button, and Swagger returns information such as a `curl` command, a request URL, a response body, a response code, and the response header. The **Try it out!** button will not work unless a bearer [authorization](https://glossary.magento.com/authorization) token has been specified. @@ -56,7 +56,7 @@ To return information about all services: `http:///rest//schema` {:.bs-callout-info} -You must specify an authorization token for an [admin](https://glossary.magento.com/admin) user to return information for most endpoints. See [Token-based authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-token.html) for more information. +You must specify an authorization token for an [admin](https://glossary.magento.com/admin) user to return information for most endpoints. See [Token-based authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-token.html) for more information. ## Return the complete JSON schema @@ -85,4 +85,4 @@ You may also use web server rewrite rules to redirect users trying to access the Related topics [Restricting access to anonymous web APIs]({{ page.baseurl }}/rest/anonymous-api-security.html) -[Token-based authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-token.html) +[Token-based authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-token.html) diff --git a/src/guides/v2.4/rest/tutorials/index.md b/src/guides/v2.4/rest/tutorials/index.md deleted file mode 120000 index 8a05582005e..00000000000 --- a/src/guides/v2.4/rest/tutorials/index.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/rest/tutorials/index.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/index.md b/src/guides/v2.4/rest/tutorials/index.md new file mode 100644 index 00000000000..1f0a4ecc97a --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/index.md @@ -0,0 +1,71 @@ +--- +group: rest-api +title: REST tutorials +functional_areas: + - Integration + - Orders + - Sales +--- + +The REST tutorials provide an introduction to Magento web APIs. In general, the tutorials guide you through commonly-performed complex tasks: + +* The [**order processing** tutorial]({{ page.baseurl }}/rest/tutorials/orders/order-intro.html) demonstrates the lifecycle of an order. Major steps include creating a quote, converting it to an order, issuing an invoice, and shipping the order. + +* The [**order processing with Inventory Management**]({{ page.baseurl }}/rest/tutorials/inventory/index.html) tutorial builds upon the original order processing tutorial. It also configures sources and stocks and other Inventory Management features. + +* The [**configurable product** tutorial]({{ page.baseurl }}/rest/tutorials/configurable-product/config-product-intro.html) helps you plan then create a configurable product and its component simple products. + +* The [**bulk API configurable product** tutorial]({{ page.baseurl }}/rest/tutorials/bulk-configurable-product/config-product-intro.html) demonstrates how to create configurable products using bulk APIs. + +* The [**grouped products** tutorial]({{ page.baseurl }}/rest/tutorials/grouped-product/create-and-manage-grouped-products.html) demonstrates how to create and manage grouped products. + +## Complete these prerequisites + +Before you begin any tutorial, make sure you know the basics about {{site.data.var.ce}} + +* Install a Magento 2.3 (or later) instance with sample data. + + The sample data defines a functional store, called Luma, that sells fitness clothing and accessories. The store does not provide any sandbox accounts for testing credit card payments, so transactions will be simulated using an offline [payment method](https://glossary.magento.com/payment-method). + +* Install a REST client. You can use any REST client to send calls to Magento. [Postman](https://www.getpostman.com/) is recommended. + +* Know how to construct a REST call in Magento. See [Construct a request](https://developer.adobe.com/commerce/webapi/get-started/gs-web-api-request.html) for details. + +* Find the Magento REST API documentation. You can view the [static REST API documentation on devdocs]({{site.baseurl}}/redoc/{{page.guide_version}}/) or [generate a local API reference]({{ page.baseurl }}/rest/generate-local.html). + +* Find the Magento Merchant documentation. Refer to [Getting Started with {{site.data.var.ce}}]({{ site.user_guide_url }}/getting-started.html) for information about the Luma store that is created when you install Magento with the sample data. + +## Performing steps + +Although some steps require that you configure Magento in some way, you perform most steps by sending one or more REST calls to Magento. Each step that makes a REST call provides the following information: + +**Endpoint:** + +This section lists the HTTP verb and full path to the endpoint. The basic structure of a REST call in Magento is + +` http:///rest//` + +where: + +Element | Description +--- | --- +`HTTP verb` | One of `GET`, `POST`, `PUT`, or `DELETE` +`host` | The hostname or IP address (and optionally, port) of the Magento installation. +`scope` | Specifies which store the call affects. In this tutorial, this value is `default`. +`endpoint` | The full URI (Uniform Resource Identifier) to the endpoint. These values always start with `/V1`. For example, `/V1/orders/4`. + +**Scope:** + +The **Scope:** section is included when the tutorial requires that you send requests to different stores. + +**HTTP headers:** + +This section indicates which key/value pairs you must specify in the HTTP headers. All calls require one or more HTTP headers. + +**Payload:** + +This section lists the information that is sent to Magento. All payload samples are valid and can be copied and pasted into your calls, but you might need to change the `id` values that Magento returns. + +**Response:** + +This section lists the information that Magento sends to the REST client. These values are often referenced in other steps in the tutorial. The values Magento returns might be different than the values listed in the examples provided in this tutorial. diff --git a/src/guides/v2.4/rest/tutorials/inventory/index.md b/src/guides/v2.4/rest/tutorials/inventory/index.md index f7562733679..33f70691e77 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/index.md +++ b/src/guides/v2.4/rest/tutorials/inventory/index.md @@ -26,7 +26,7 @@ This **14-step tutorial** generally takes **1 hour**. * Install a REST client. You can use any REST client to send calls to Magento. [Postman](https://www.getpostman.com/) is recommended. -* Know how to construct a REST call in Magento. See [Construct a request]({{ page.baseurl }}/get-started/gs-web-api-request.html) for details. +* Know how to construct a REST call in Magento. See [Construct a request](https://developer.adobe.com/commerce/webapi/get-started/gs-web-api-request.html) for details. * Obtain an admin authorization token. Multiple calls in this tutorial require administrator privileges. See [Generate the admin token]({{ page.baseurl }}/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. diff --git a/src/guides/v2.4/rest/tutorials/orders/order-admin-token.md b/src/guides/v2.4/rest/tutorials/orders/order-admin-token.md index e0b8e0f5f13..3302c31bf0b 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-admin-token.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-admin-token.md @@ -52,7 +52,7 @@ Your request must specify the admin user's `username`, `password` and `otp` (one By default, an admin token is valid for 4 hours. To change this value, log in to Admin and go to **Stores** > **Settings** > **Configuration** > **Services** > **OAuth** > **Access Token Expiration** > **Admin Token Lifetime (hours)**. -See [Token-based authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-token.html) for more information about authorization tokens. +See [Token-based authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-token.html) for more information about authorization tokens. **Endpoint:** diff --git a/src/guides/v2.4/rest/tutorials/orders/order-intro.md b/src/guides/v2.4/rest/tutorials/orders/order-intro.md index dcaeb63320e..a9d40b3af87 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-intro.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-intro.md @@ -30,7 +30,7 @@ Complete the following prerequisites: * Set up [two-factor authentication]({{page.baseurl}}/security/two-factor-authentication.html). This tutorial assumes Google Authenticator is your 2FA solution. -* Know how to construct a REST call in Magento. See [Construct a request]({{ page.baseurl }}/get-started/gs-web-api-request.html) for details. +* Know how to construct a REST call in Magento. See [Construct a request](https://developer.adobe.com/commerce/webapi/get-started/gs-web-api-request.html) for details. * Find the Magento REST API documentation. You can view the [static REST API documentation on devdocs]({{ site.baseurl }}/redoc/{{page.guide_version}}/) or [generate a local API reference]({{ page.baseurl }}/rest/generate-local.html). diff --git a/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md b/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md deleted file mode 120000 index ccbff19c1d5..00000000000 --- a/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/orders/order-issue-refund.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md b/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md new file mode 100644 index 00000000000..7903ae264ba --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md @@ -0,0 +1,87 @@ +--- +layout: tutorial +group: rest-api +title: Step 10. Issue a partial refund +subtitle: Order processing tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +menu_order: 10 +level3_subgroup: order-tutorial +redirect_from: + - /guides/v2.3/get-started/order-tutorial/order-issue-refund.html +functional_areas: + - Integration + - Orders + - Sales +--- + +Magento 2.1.3 introduced two endpoints that streamline the process of issuing a refund by creating a creditmemo and updating the order or [invoice](https://glossary.magento.com/invoice) in one call. + +Endpoint | Description +--- | --- +`POST /V1/order//refund` | Issues an offline refund +`POST /V1/invoice//refund` | Issue a refund with an online payment system + +In this example, the customer did not like the fit of the Radiant T-M-Orange shirt and wants a refund. + +Since the customer paid for the order with a bank transfer, we'll call `POST /V1/order//refund`. The `order_item_id` for the Radiant Tee-M-Orange is `3`. + +The `arguments` object allows you to adjust the amount of the credit to be refunded. Since the customer used the `tablerate` shipping method, which applied to the whole order, we'll assume that a refund can't be applied to the shipping costs. Therefore, the shipping_amount is set to `0`. + +If the customer had selected the `flatrate` shipping method ($5 per item), we would set the value of `shipping_amount` to `5`. + +The `return_to_stock_items` array specifies which `order_item_id`s can be returned to stock and be resold. + +**Endpoint:** + +`POST /rest//V1/order/5/refund` + +**Headers:** + +`Content-Type: application/json` + +`Authorization: Bearer ` + +**Payload:** + +```json +{ + "items": [ + { + "order_item_id": 3, + "qty": 1 + } + ], + "notify": true, + "arguments": { + "shipping_amount": 0, + "adjustment_positive": 0, + "adjustment_negative": 0, + "extension_attributes": { + "return_to_stock_items": [ + 3 + ] + } + } +} +``` + +**Response:** + +A [credit memo](https://glossary.magento.com/credit-memo) id, such as `3`. + +### Verify this step {#verify-step} + +Log in to [Admin](https://glossary.magento.com/admin). Click **Sales** > **Credit Memos**. The credit memo is displayed in the grid. + +## Congratulations! You've finished. +{:.no_toc} + +{:.ref-header} +Related topics + +* [Getting Started with Magento Web APIs](https://developer.adobe.com/commerce/webapi/get-started/bk-get-started-api.html) +* [Create a configurable product Tutorial]({{ page.baseurl }}/rest/tutorials/configurable-product/config-product-intro.html) +* [REST API Reference Overview]({{ page.baseurl }}/rest/bk-rest.html) +* [REST API documentation]({{site.baseurl}}/redoc/{{page.guide_version}}/) diff --git a/src/guides/v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md b/src/guides/v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md index c076fdafda7..cf37e7d9e38 100644 --- a/src/guides/v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md +++ b/src/guides/v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md @@ -14,7 +14,7 @@ Your request must specify the admin user's `username`, `password` and `otp` (one By default, an admin token is valid for 4 hours. To change this value, log in to Admin and go to **Stores** > **Settings** > **Configuration** > **Services** > **OAuth** > **Access Token Expiration** > **Admin Token Lifetime (hours)**. -See [Token-based authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication-token.html) for more information about authorization tokens. +See [Token-based authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-token.html) for more information about authorization tokens. **Endpoint:** diff --git a/src/guides/v2.4/test/testing.md b/src/guides/v2.4/test/testing.md index 3e42efc0437..451c5672e73 100644 --- a/src/guides/v2.4/test/testing.md +++ b/src/guides/v2.4/test/testing.md @@ -239,7 +239,7 @@ MFTF tests are kept within its respective Module folder: [Magento definition of done]: {{ site.baseurl }}/contributor-guide/contributing_dod.html [Functional]: {{ site.baseurl }}/mftf/docs/introduction.html -[Web API Functional]: {{ page.baseurl }}/get-started/web-api-functional-testing.html +[Web API Functional]: https://developer.adobe.com/commerce/webapi/get-started/web-api-functional-testing.html [Integration]: {{ page.baseurl }}/test/integration/integration_test_execution.html [performance toolkit]: {{ page.baseurl }}/config-guide/cli/config-cli-subcommands-perf-data.html [JavaScript]: {{ page.baseurl }}/test/js/jasmine.html @@ -248,7 +248,7 @@ MFTF tests are kept within its respective Module folder: [Magento backward compatibility policy]: {{ site.baseurl }}/contributor-guide/backward-compatible-development/ [Functional Testing Framework]: https://github.com/magento/mtf [Magento Functional Testing Framework]: {{ site.baseurl }}/mftf/docs/introduction.html -[Web API functional testing]: {{ page.baseurl }}/get-started/web-api-functional-testing.html +[Web API functional testing]: https://developer.adobe.com/commerce/webapi/get-started/web-api-functional-testing.html [Running Integration Tests]: {{ page.baseurl }}/test/integration/integration_test_execution.html [Extension Developer Guide on JavaScript Tests]: {{ page.baseurl }}/test/js/jasmine.html [`magento dev:tests:run`]: {{ page.baseurl }}/config-guide/cli/config-cli-subcommands-test.html From 26854a9ce6c604ff909529ac76869c9f31b90409 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Fri, 3 Jun 2022 09:35:59 -0500 Subject: [PATCH 113/776] Added AWS versions per PM --- src/_data/codebase/v2_4/system-requirements.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/_data/codebase/v2_4/system-requirements.yml b/src/_data/codebase/v2_4/system-requirements.yml index 695cc2286db..cd1d51915a2 100644 --- a/src/_data/codebase/v2_4/system-requirements.yml +++ b/src/_data/codebase/v2_4/system-requirements.yml @@ -11,6 +11,11 @@ Varnish: '7.0' Apache: '2.4' nginx: '1.8' + AWS Aurora (MySQL): '5.7' + AWS S3: ✔️ + AWS MQ: '3.8.11' + AWS ElastiCache: Redis 6 + AWS ElasticSearch: '7.9' 2.4.4: Composer: '2.1' Elasticsearch: '7.16' @@ -23,6 +28,11 @@ Varnish: '7.0' Apache: '2.4' nginx: '1.8' + AWS Aurora (MySQL): '5.7' + AWS S3: ✔️ + AWS MQ: '3.8.11' + AWS ElastiCache: Redis 6 + AWS ElasticSearch: '7.9' 2.4.3-p2: Composer: '1' Elasticsearch: '7.16' @@ -35,6 +45,11 @@ Varnish: '6.5' Apache: '2.4' nginx: '1.8' + AWS Aurora (MySQL): '5.7' + AWS S3: ✔️ + AWS MQ: '3.8.11' + AWS ElastiCache: Redis 6 + AWS ElasticSearch: '7.9' 2.4.3: Composer: '1' Elasticsearch: '7.10' From 7d78fa6764f1612e0819b8df48f0ceadbd6272a4 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Fri, 3 Jun 2022 09:57:32 -0500 Subject: [PATCH 114/776] Removed obsolete items --- src/_data/roadmap.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/_data/roadmap.yml b/src/_data/roadmap.yml index ecf51101bad..da71aa4f8e0 100644 --- a/src/_data/roadmap.yml +++ b/src/_data/roadmap.yml @@ -15,18 +15,12 @@ roadmap: status: inProgress - name: GraphQL - Caching updates status: inProgress - - name: jQuery 3.6.x support - status: inProgress - - name: OpenSearch 1.x support - status: inProgress - name: Payment services (extension) status: inProgress type: Extension - name: PayPal and Braintree updates status: inProgress type: Extension - - name: PHP 8.1 support - status: inProgress - name: PWA - Global theming/styling status: inProgress - name: PWA - Custom product attributes @@ -42,8 +36,6 @@ roadmap: type: Extension - name: Planned features: - - name: Framework updates (for example, KnockoutJS and RequireJS) - status: Planned - name: GraphQL - Personalization updates status: Planned - name: GraphQL - Page Builder improvements From 4d35917078ec1f67d4085283713f5fcc57432140 Mon Sep 17 00:00:00 2001 From: Jared Hoover <98363870+jhadobe@users.noreply.github.com> Date: Fri, 3 Jun 2022 10:14:29 -0500 Subject: [PATCH 115/776] Update soap-web-api-calls.md --- src/guides/v2.4/get-started/soap/soap-web-api-calls.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/get-started/soap/soap-web-api-calls.md b/src/guides/v2.4/get-started/soap/soap-web-api-calls.md index 2b9d41b96e5..ae82edc7193 100644 --- a/src/guides/v2.4/get-started/soap/soap-web-api-calls.md +++ b/src/guides/v2.4/get-started/soap/soap-web-api-calls.md @@ -5,7 +5,7 @@ title: Use SOAP Services menu_title: Use SOAP Services menu_order: 1 menu_node: parent -migrated_to: https://developer.adobe.com/commerce/webapi/get-started/soap/soap-web-api-calls/ +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/soap-web-api-calls/ layout: migrated --- From ce6341a1abd63fe3808f6ca81e564dc2e1892eaa Mon Sep 17 00:00:00 2001 From: Dmytro Shevtsov Date: Thu, 2 Jun 2022 14:50:44 -0500 Subject: [PATCH 116/776] Update the migrated_log plugin Add more handling for exceptions --- _plugins/generators/migrated_log.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/_plugins/generators/migrated_log.rb b/_plugins/generators/migrated_log.rb index a58abc98477..a10c591f813 100644 --- a/_plugins/generators/migrated_log.rb +++ b/_plugins/generators/migrated_log.rb @@ -17,15 +17,14 @@ def generate(site) migrated_pages = @site.pages.filter { |page| page.data['layout'] == 'migrated' } url_prefix = site.config['url'] + site.config['baseurl'] - migrated_pages_data = [] migrated_pages.each do |page| migrated_page = { path: page.path, - title: page.data['title'], - guide: @site.data['toc'][page.data['group']]['label'], + title: page.data['title'] || abort("Error in '#{page.path}'.\n Check 'title' in the frontmatter.".red), + guide: @site.data.dig('toc', page.data['group'], 'label') || abort("Error in '#{page.path}'.\n Check 'group' in the frontmatter here, or 'label' in the corresponting TOC.".red), migrated_from: url_prefix + page.url, - migrated_to: page.data['migrated_to'], + migrated_to: page.data['migrated_to'] || abort("Error in '#{page.path}'.\n Check 'migrated_to' in the frontmatter.".red), migrated_to_source: if page.data['migrated_to'].start_with?('https://experienceleague.adobe.com') 'Adobe Experience League' elsif page.data['migrated_to'].start_with?('https://developer.adobe.com') From aada063dcb6c78e6252dfe035bf23aa3028d0586 Mon Sep 17 00:00:00 2001 From: Dmitry Shevtsov <12731225+dshevtsov@users.noreply.github.com> Date: Thu, 2 Jun 2022 17:01:32 -0500 Subject: [PATCH 117/776] Update _plugins/generators/migrated_log.rb Co-authored-by: Jeff Matthews --- _plugins/generators/migrated_log.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_plugins/generators/migrated_log.rb b/_plugins/generators/migrated_log.rb index a10c591f813..06b51415c57 100644 --- a/_plugins/generators/migrated_log.rb +++ b/_plugins/generators/migrated_log.rb @@ -21,10 +21,10 @@ def generate(site) migrated_pages.each do |page| migrated_page = { path: page.path, - title: page.data['title'] || abort("Error in '#{page.path}'.\n Check 'title' in the frontmatter.".red), - guide: @site.data.dig('toc', page.data['group'], 'label') || abort("Error in '#{page.path}'.\n Check 'group' in the frontmatter here, or 'label' in the corresponting TOC.".red), + title: page.data['title'] || abort("Error in '#{page.path}'.\n Check 'title' in the file's frontmatter.".red), + guide: @site.data.dig('toc', page.data['group'], 'label') || abort("Error in '#{page.path}'.\n Check 'group' in the file's frontmatter or 'label' in the corresponding TOC.".red), migrated_from: url_prefix + page.url, - migrated_to: page.data['migrated_to'] || abort("Error in '#{page.path}'.\n Check 'migrated_to' in the frontmatter.".red), + migrated_to: page.data['migrated_to'] || abort("Error in '#{page.path}'.\n Check 'migrated_to' in the file's frontmatter.".red), migrated_to_source: if page.data['migrated_to'].start_with?('https://experienceleague.adobe.com') 'Adobe Experience League' elsif page.data['migrated_to'].start_with?('https://developer.adobe.com') From 48d3d42602d2b54eecff02fe1757c44cc84b6299 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Fri, 3 Jun 2022 11:19:45 -0500 Subject: [PATCH 118/776] Updated per Eric Erway --- src/_data/roadmap.yml | 49 +++++++++++++------------------------------ 1 file changed, 15 insertions(+), 34 deletions(-) diff --git a/src/_data/roadmap.yml b/src/_data/roadmap.yml index da71aa4f8e0..7ca5b5bf4ff 100644 --- a/src/_data/roadmap.yml +++ b/src/_data/roadmap.yml @@ -3,54 +3,35 @@ roadmap: features: - name: Accessibility improvements for storefront/admin status: inProgress - - name: Channel manager with Walmart Marketplace (extension) + - name: Composer 2.2 support status: inProgress - type: Extension - - name: Express Checkout for Adobe Commerce (extension) + - name: Elasticsearch 7.17 support status: inProgress - type: Extension - - name: Framework updates (for example, KnockoutJS and RequireJS) + - name: Mobile layout optimization status: inProgress - - name: GraphQL - Admin configuration + - name: Column grid layouts (viewports) status: inProgress - - name: GraphQL - Caching updates - status: inProgress - - name: Payment services (extension) - status: inProgress - type: Extension - - name: PayPal and Braintree updates - status: inProgress - type: Extension - - name: PWA - Global theming/styling - status: inProgress - - name: PWA - Custom product attributes + - name: Security and quality improvements status: inProgress - - name: PWA - Performance optimizations + - name: Performance optimizations (catalog/pricing) status: inProgress - - name: PWA - Shopping and cart improvements + - name: Replace Froogaloop library with player.js status: inProgress - - name: Security and quality improvements + - name: TineyMCE 5.10 support status: inProgress - - name: Vendor Bundled Extensions (VBEs) – Remove (except Braintree) + - name: Latest Vimeo API support status: inProgress - type: Extension - name: Planned features: - - name: GraphQL - Personalization updates + - name: OpenSearch as independent search engine status: Planned - - name: GraphQL - Page Builder improvements + - name: Personalization and inventory improvements status: Planned - - name: GraphQL - Inventory improvements + - name: Remove jquery-migrate status: Planned - - name: Page Builder - Mobile layout optimization - status: Planned - - name: Page Builder - Column grid layouts (viewports) - status: Planned - - name: PWA - Server-side rendering (SSR) - status: Planned - - name: PWA - Extensibility improvements (payment/ship) - status: Planned - - name: PWA - Bundle product type + - name: Remove PHP 7.4 compatibility status: Planned - name: Security and quality improvements status: Planned + - name: Symfony dependency updates + status: Planned From d28c98fdc48452671bd65a6223d92ea86861f28b Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Fri, 3 Jun 2022 11:24:46 -0500 Subject: [PATCH 119/776] Fixed typo --- src/_data/roadmap.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_data/roadmap.yml b/src/_data/roadmap.yml index 7ca5b5bf4ff..d364bcdf355 100644 --- a/src/_data/roadmap.yml +++ b/src/_data/roadmap.yml @@ -17,7 +17,7 @@ roadmap: status: inProgress - name: Replace Froogaloop library with player.js status: inProgress - - name: TineyMCE 5.10 support + - name: TinyMCE 5.10 support status: inProgress - name: Latest Vimeo API support status: inProgress From ebbb1122bf1c75d63e8672bee8df078847072b1f Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Fri, 3 Jun 2022 13:38:41 -0500 Subject: [PATCH 120/776] Added 2.4.5 changes per PM --- src/_data/codebase/v2_4/system-requirements.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_data/codebase/v2_4/system-requirements.yml b/src/_data/codebase/v2_4/system-requirements.yml index cd1d51915a2..e11dd1cdebb 100644 --- a/src/_data/codebase/v2_4/system-requirements.yml +++ b/src/_data/codebase/v2_4/system-requirements.yml @@ -11,9 +11,9 @@ Varnish: '7.0' Apache: '2.4' nginx: '1.8' - AWS Aurora (MySQL): '5.7' + AWS Aurora (MySQL): '8.0.mysql_aurora.3.01.0' AWS S3: ✔️ - AWS MQ: '3.8.11' + AWS MQ: '3.9.13' AWS ElastiCache: Redis 6 AWS ElasticSearch: '7.9' 2.4.4: From 6374a27a6158b60a75ec1b99faf8a115f7aff403 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Fri, 3 Jun 2022 14:40:36 -0500 Subject: [PATCH 121/776] Added AWS OS --- src/_data/codebase/v2_4/system-requirements.yml | 11 ++++++----- .../install/system-requirements-table.html | 17 ++++++++++++++--- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/_data/codebase/v2_4/system-requirements.yml b/src/_data/codebase/v2_4/system-requirements.yml index e11dd1cdebb..806f5adac4e 100644 --- a/src/_data/codebase/v2_4/system-requirements.yml +++ b/src/_data/codebase/v2_4/system-requirements.yml @@ -11,11 +11,12 @@ Varnish: '7.0' Apache: '2.4' nginx: '1.8' - AWS Aurora (MySQL): '8.0.mysql_aurora.3.01.0' + AWS Aurora (MySQL): '8.0' AWS S3: ✔️ AWS MQ: '3.9.13' AWS ElastiCache: Redis 6 - AWS ElasticSearch: '7.9' + AWS Elasticsearch: '7.9' + AWS OpenSearch: '1.2' 2.4.4: Composer: '2.1' Elasticsearch: '7.16' @@ -32,7 +33,7 @@ AWS S3: ✔️ AWS MQ: '3.8.11' AWS ElastiCache: Redis 6 - AWS ElasticSearch: '7.9' + AWS Elasticsearch: '7.9' 2.4.3-p2: Composer: '1' Elasticsearch: '7.16' @@ -49,7 +50,7 @@ AWS S3: ✔️ AWS MQ: '3.8.11' AWS ElastiCache: Redis 6 - AWS ElasticSearch: '7.9' + AWS Elasticsearch: '7.9' 2.4.3: Composer: '1' Elasticsearch: '7.10' @@ -65,7 +66,7 @@ AWS S3: ✔️ AWS MQ: '3.8.11' AWS ElastiCache: Redis 6 - AWS ElasticSearch: '7.9' + AWS Elasticsearch: '7.9' 2.4.2: Composer: '1' Elasticsearch: '7.9' diff --git a/src/_includes/install/system-requirements-table.html b/src/_includes/install/system-requirements-table.html index 2d75e7fb706..adb3166a719 100644 --- a/src/_includes/install/system-requirements-table.html +++ b/src/_includes/install/system-requirements-table.html @@ -178,10 +178,21 @@ {% endfor %} - AWS ElasticSearch + AWS Elasticsearch {% for requirement in requirements %} - {% if requirement[1]['AWS ElasticSearch'] %} - {{requirement[1]['AWS ElasticSearch']}} + {% if requirement[1]['AWS Elasticsearch'] %} + {{requirement[1]['AWS Elasticsearch']}} + {% else %} + -- + {% endif %} + + {% endfor %} + + + AWS OpenSearch + {% for requirement in requirements %} + {% if requirement[1]['AWS OpenSearch'] %} + {{requirement[1]['AWS OpenSearch']}} {% else %} -- {% endif %} From 4239d7d4133cbe8ae0f687f375ed20fd5ff8302e Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Mon, 6 Jun 2022 07:31:46 -0500 Subject: [PATCH 122/776] Added description metadata --- src/release/roadmap.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/release/roadmap.md b/src/release/roadmap.md index fb0951ae58e..49b7bdd0433 100644 --- a/src/release/roadmap.md +++ b/src/release/roadmap.md @@ -1,6 +1,7 @@ --- title: Roadmap group: release +description: See what we have planned for Adobe Commerce and Magento Open Source. --- The following table contains the status of items on the {{ site.data.var.ce }} roadmap (items are subject to change): From 4403acf4511f71c47b6c1f8b05d51fe776e04230 Mon Sep 17 00:00:00 2001 From: magedocs Date: Mon, 6 Jun 2022 14:38:50 +0000 Subject: [PATCH 123/776] Update News data --- src/_data/whats-new.yml | 52 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/src/_data/whats-new.yml b/src/_data/whats-new.yml index 8003466bf10..f082de6a6ea 100644 --- a/src/_data/whats-new.yml +++ b/src/_data/whats-new.yml @@ -4,8 +4,58 @@ description: This page contains recent changes that we think you'd like to know We exclude from this list proofreading, spelling checks, and all minor updates. link: "/whats-new.html" thread: "/whatsnew-feed.xml" -updated: Tue May 31 10:19:27 2022 +updated: Mon Jun 6 14:38:47 2022 entries: +- description: Added missing versions for Amazon Web Services on the [system requirements](https://devdocs.magento.com/guides/v2.4/install-gde/system-requirements.html) + page. + versions: 2.4.x + type: Technical + date: June 3, 2022 + link: https://github.com/magento-commerce/devdocs/pull/2989 + merge_commit: bf13a57daa910a8e3fa6953c4d3f74589726b0d1 + contributor: jeff-matthews + membership: true + labels: + - Technical + - 2.4.x +- description: Added descriptions of B2B [message queue consumers](https://devdocs.magento.com/extensions/b2b/#start-message-consumers). + versions: 2.3.x, 2.4.x + type: Major Update + date: June 3, 2022 + link: https://github.com/magento-commerce/devdocs/pull/2982 + merge_commit: e3b399bd80df81a7e09f73c99427859d2d29ec1f + contributor: jeff-matthews + membership: true + labels: + - Major Update + - 2.3.x + - 2.4.x +- description: Updated the product [roadmap](https://devdocs.magento.com/release/roadmap.html) + with items for the second half of 2022. + versions: 2.4.x + type: Major Update + date: June 3, 2022 + link: https://github.com/magento-commerce/devdocs/pull/2990 + merge_commit: b7431cbb627bbf652969ee644f44dedbc710e821 + contributor: jeff-matthews + membership: true + labels: + - Major Update + - 2.4.x +- description: The [PHP Developer Guide](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/bk-extension-dev-guide.html) + topics moved to the [Adobe Developer documentation](https://developer.adobe.com/commerce/php/development/) + and will be redirected soon. + versions: 2.4.x + type: Major Update + date: June 1, 2022 + link: https://github.com/magento-commerce/devdocs/pull/2984 + merge_commit: 43e38bd962d38b9a1a82f96aa3679583059b24fb + contributor: jeff-matthews + membership: true + labels: + - Major Update + - 2.4.x + - migration - description: Updated the [Xdebug topic](https://devdocs.magento.com/cloud/howtos/debug.html#pro-debug) to clarify that Xdebug is available and enabled in Pro Staging and Production environments. From 304a768f7af370078649fa1f3436926caa8b54e5 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Mon, 6 Jun 2022 10:03:05 -0500 Subject: [PATCH 124/776] Updates from Eric --- src/_data/roadmap.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/_data/roadmap.yml b/src/_data/roadmap.yml index d364bcdf355..97e1c9f2958 100644 --- a/src/_data/roadmap.yml +++ b/src/_data/roadmap.yml @@ -13,11 +13,9 @@ roadmap: status: inProgress - name: Security and quality improvements status: inProgress - - name: Performance optimizations (catalog/pricing) - status: inProgress - name: Replace Froogaloop library with player.js status: inProgress - - name: TinyMCE 5.10 support + - name: TindevdocsyMCE 5.10 support status: inProgress - name: Latest Vimeo API support status: inProgress @@ -31,7 +29,5 @@ roadmap: status: Planned - name: Remove PHP 7.4 compatibility status: Planned - - name: Security and quality improvements - status: Planned - name: Symfony dependency updates status: Planned From b6c8f4d19abaa96310c4a07314c94590054d9585 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Mon, 6 Jun 2022 10:08:09 -0500 Subject: [PATCH 125/776] Fix typo --- src/_data/roadmap.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_data/roadmap.yml b/src/_data/roadmap.yml index 97e1c9f2958..f64c2bf3eed 100644 --- a/src/_data/roadmap.yml +++ b/src/_data/roadmap.yml @@ -15,7 +15,7 @@ roadmap: status: inProgress - name: Replace Froogaloop library with player.js status: inProgress - - name: TindevdocsyMCE 5.10 support + - name: TinyMCE 5.10 support status: inProgress - name: Latest Vimeo API support status: inProgress From 12f79ede4f9aaca595b052e1fded0dcb1b2c143c Mon Sep 17 00:00:00 2001 From: Greg Marshall Date: Mon, 6 Jun 2022 09:30:14 -0700 Subject: [PATCH 126/776] Update src/cloud/env/variables-deploy.md Co-authored-by: hguthrie --- src/cloud/env/variables-deploy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cloud/env/variables-deploy.md b/src/cloud/env/variables-deploy.md index 7ca49c47b0b..894456bbfce 100644 --- a/src/cloud/env/variables-deploy.md +++ b/src/cloud/env/variables-deploy.md @@ -386,7 +386,7 @@ If you specify `\Magento\Framework\Cache\Backend\RemoteSynchronizedCache` as the Do not enable this variable on scaled architecture (split architecture) projects. It causes Redis connection errors. Redis slaves are still active but will not be used for Redis reads. As an alternative, we recommend the following: use {{site.data.var.ee}} 2.3.5 or later on Cloud projects with a scaled architecture, implement a new Redis backend configuration, and implement L2 caching for Redis. {:.bs-callout-tip} -The `REDIS_USE_SLAVE_CONNECTION` variable is supported only on Adobe Commerce on cloud infrastructure Staging and Production Pro cluster environments and is not supported on Starter projects. +The `REDIS_USE_SLAVE_CONNECTION` variable is supported only on {{site.data.var.ece}} Staging and Production Pro cluster environments and is not supported on Starter projects. {{site.data.var.ee}} can read multiple Redis instances asynchronously. Set to `true` to automatically use a _read-only_ connection to a Redis instance to receive read-only traffic on a non-master node. This improves performance through load balancing, because only one node needs to handle read-write traffic. Set to `false` to remove any existing read-only connection array from the `env.php` file. From 80c35b458ae752150e397f66f376179f7ff661c8 Mon Sep 17 00:00:00 2001 From: Greg Marshall Date: Mon, 6 Jun 2022 09:30:20 -0700 Subject: [PATCH 127/776] Update src/cloud/env/variables-deploy.md Co-authored-by: hguthrie --- src/cloud/env/variables-deploy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cloud/env/variables-deploy.md b/src/cloud/env/variables-deploy.md index 894456bbfce..cf3e7175585 100644 --- a/src/cloud/env/variables-deploy.md +++ b/src/cloud/env/variables-deploy.md @@ -301,7 +301,7 @@ See [Configure the lock]({{site.baseurl}}/guides/v2.3/install-gde/install/cli/in - **Version**—{{site.data.var.ee}} 2.1.4 and later {:.bs-callout-tip} -The `MYSQL_USE_SLAVE_CONNECTION` variable is supported only on Adobe Commerce on cloud infrastructure Staging and Production Pro cluster environments and is not supported on Starter projects. +The `MYSQL_USE_SLAVE_CONNECTION` variable is supported only on {{site.data.var.ece}} Staging and Production Pro cluster environments and is not supported on Starter projects. {{site.data.var.ee}} can read multiple databases asynchronously. Set to `true` to automatically use a _read-only_ connection to the database to receive read-only traffic on a non-master node. This improves performance through load balancing, because only one node needs to handle read-write traffic. Set to `false` to remove any existing read-only connection array from the `env.php` file. From d4b9736e0a3816725c66c8d4f2d280e69be1c68c Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Mon, 6 Jun 2022 14:24:45 -0500 Subject: [PATCH 128/776] Replace symlinks --- .../admin/admin-best-practices.md | 16 +- .../admin/ext-best-practices_admin_FAQ.md | 28 +- .../admin/feedback-placement-and-design.md | 27 +- .../admin/placement-and-design.md | 127 ++++- .../bk-ext-best-practices.md | 30 +- .../extension-coding/coding-best-practices.md | 11 +- .../extension-coding/coding-faq.md | 33 +- .../example-module-adminpage.md | 347 ++++++++++++- .../extension-coding/observers-bp.md | 54 +- .../extension-coding/working-with-arch-bp.md | 56 ++- .../phpstorm/adding-code-inspections.md | 222 ++++++++- .../built-in-upgrade-compatibility-tool.md | 86 +++- .../phpstorm/code-generation.md | 43 +- .../phpstorm/code-inspection.md | 29 +- .../phpstorm/installation.md | 32 +- .../phpstorm/introduction.md | 17 +- .../phpstorm/issue-reporting.md | 23 +- .../phpstorm/new-features.md | 29 +- .../phpstorm/uct-run-configuration.md | 57 ++- .../security/writing-secure-code.md | 52 +- .../storefront/storefront-best-practices.md | 37 +- .../tutorials/copy-fieldsets.md | 180 ++++++- .../create-access-control-list-rule.md | 185 ++++++- .../tutorials/create-integration-with-api.md | 170 ++++++- .../tutorials/custom-import-entity.md | 466 ++++++++++++++++- .../tutorials/custom-widget.md | 173 ++++++- .../tutorials/dynamic-row-system-config.md | 258 +++++++++- .../serialized-to-json-data-upgrade.md | 470 +++++++++++++++++- 28 files changed, 3230 insertions(+), 28 deletions(-) mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/admin/admin-best-practices.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/admin/ext-best-practices_admin_FAQ.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/admin/feedback-placement-and-design.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/admin/placement-and-design.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/bk-ext-best-practices.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/extension-coding/coding-best-practices.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/extension-coding/coding-faq.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/extension-coding/example-module-adminpage.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/extension-coding/observers-bp.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/extension-coding/working-with-arch-bp.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/phpstorm/adding-code-inspections.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/phpstorm/built-in-upgrade-compatibility-tool.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/phpstorm/code-generation.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/phpstorm/code-inspection.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/phpstorm/installation.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/phpstorm/introduction.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/phpstorm/issue-reporting.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/phpstorm/new-features.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/phpstorm/uct-run-configuration.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/security/writing-secure-code.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/storefront/storefront-best-practices.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/tutorials/copy-fieldsets.md mode change 120000 => 100755 src/guides/v2.4/ext-best-practices/tutorials/create-access-control-list-rule.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/tutorials/create-integration-with-api.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/tutorials/custom-import-entity.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/tutorials/custom-widget.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/tutorials/dynamic-row-system-config.md mode change 120000 => 100644 src/guides/v2.4/ext-best-practices/tutorials/serialized-to-json-data-upgrade.md diff --git a/src/guides/v2.4/ext-best-practices/admin/admin-best-practices.md b/src/guides/v2.4/ext-best-practices/admin/admin-best-practices.md deleted file mode 120000 index c9576c27d97..00000000000 --- a/src/guides/v2.4/ext-best-practices/admin/admin-best-practices.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/admin/admin-best-practices.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/admin/admin-best-practices.md b/src/guides/v2.4/ext-best-practices/admin/admin-best-practices.md new file mode 100644 index 00000000000..acb6bddc02b --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/admin/admin-best-practices.md @@ -0,0 +1,15 @@ +--- +group: extension-best-practices +title: Admin +functional_areas: + - Standards +--- + +This section of the Best Practices Guide discusses the Admin, the UI panel used by Magento administrators. It is where Magento system and [storefront](https://glossary.magento.com/storefront) parameters can be modified and configured. Third-party extensions installed by the system [admin](https://glossary.magento.com/admin) or merchant are also found in this area, along with any of their configuration settings. + +This is an important section to read, because what [extension](https://glossary.magento.com/extension) developers choose to do (or not do) when coding to integrate their extensions has a big impact on the look and feel of the Admin UI. + +{:.bs-callout-info} + Remember that most merchants have multiple extensions installed, and most of these extensions are exposed through the Admin. In order to prevent a cluttered Admin, please follow the guidelines, and communicate with Magento and the community when you have questions. + +For additional information on design topics for the Admin, read the [Admin Pattern Library]({{ page.baseurl }}/pattern-library/bk-pattern.html) and the [Admin Style Guide]({{ page.baseurl }}/design-styleguide/bk-styleguide.html). diff --git a/src/guides/v2.4/ext-best-practices/admin/ext-best-practices_admin_FAQ.md b/src/guides/v2.4/ext-best-practices/admin/ext-best-practices_admin_FAQ.md deleted file mode 120000 index 99f59eea4be..00000000000 --- a/src/guides/v2.4/ext-best-practices/admin/ext-best-practices_admin_FAQ.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/admin/ext-best-practices_admin_FAQ.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/admin/ext-best-practices_admin_FAQ.md b/src/guides/v2.4/ext-best-practices/admin/ext-best-practices_admin_FAQ.md new file mode 100644 index 00000000000..fe6b6fa3a85 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/admin/ext-best-practices_admin_FAQ.md @@ -0,0 +1,27 @@ +--- +group: extension-best-practices +subgroup: 01_Admin +title: Admin FAQ +menu_title: Admin FAQ +menu_order: 1000 +functional_areas: + - Standards +--- + +This page is a compilation of frequently asked questions by the Magento Community about extensions integrating with the [Admin](https://glossary.magento.com/admin). + +#### Where should my extension appear in the Admin? + +The appropriate place for your [extension](https://glossary.magento.com/extension) to appear in the Admin depends on what it does. For a list of extension types and their proper spot in the Admin, please consult the article: [Admin panel placement and design]({{ page.baseurl }}/ext-best-practices/admin/placement-and-design.html). + +____ + +#### What are the rules about using the left-navigation "slide-out panels" in the Admin? + +The slide-out panel is designed to accommodate several links. There can be several columns in the slide-out panel to accommodate many extension links. See the details and specifications about [slide-out panels]({{ page.baseurl }}/pattern-library/containers/slideouts-modals-overlays/slideouts-modals-overalys.html). + +____ + +#### Are there "rules" about using icons or images that appear beside the name of my extension in the Admin? + +You should avoid using icons or images besides the name of your extension in the Admin. More details about icons and images in the Admin panel can be found in the article about [Admin panel placement and design]({{ page.baseurl }}/ext-best-practices/admin/placement-and-design.html#icons-in-navigation). diff --git a/src/guides/v2.4/ext-best-practices/admin/feedback-placement-and-design.md b/src/guides/v2.4/ext-best-practices/admin/feedback-placement-and-design.md deleted file mode 120000 index 34785652171..00000000000 --- a/src/guides/v2.4/ext-best-practices/admin/feedback-placement-and-design.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/admin/feedback-placement-and-design.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/admin/feedback-placement-and-design.md b/src/guides/v2.4/ext-best-practices/admin/feedback-placement-and-design.md new file mode 100644 index 00000000000..2b014617c47 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/admin/feedback-placement-and-design.md @@ -0,0 +1,26 @@ +--- +menu_title: Feedback for Admin Panel Placement and Design +menu_order: 1 +functional_areas: + - Standards +--- + +Please provide feedback for the article: [Admin Panel Placement and Design]({{ page.baseurl }}/ext-best-practices/admin/placement-and-design.html) on this page via GitHub. + +You can leave high-level feedback for specific sections by clicking the Edit icon above, and adding comments beneath the relevant section name below. + +For more detailed comments, please create a Pull Request on the specific page. + +### Article Sections + +* Overview +* Things to Avoid + * Icons in the Primary Navigation + * Advertising in Navigation +* Placement guidelines for [extension](https://glossary.magento.com/extension) types + * Standard Connector + * Store Feature Connector + * Connector with additional features + * Feature Extensions + * Integrated Extensions + * Codebase Extensions diff --git a/src/guides/v2.4/ext-best-practices/admin/placement-and-design.md b/src/guides/v2.4/ext-best-practices/admin/placement-and-design.md deleted file mode 120000 index 3fc5b64885e..00000000000 --- a/src/guides/v2.4/ext-best-practices/admin/placement-and-design.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/admin/placement-and-design.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/admin/placement-and-design.md b/src/guides/v2.4/ext-best-practices/admin/placement-and-design.md new file mode 100644 index 00000000000..41a87fb25d3 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/admin/placement-and-design.md @@ -0,0 +1,126 @@ +--- +group: extension-best-practices +subgroup: 01_Admin +title: Admin Panel Placement and Design +menu_title: Admin Panel Placement and Design +menu_order: 1 +functional_areas: + - Standards +--- + +## Overview + +Magento’s flexible platform lets you place an [extension](https://glossary.magento.com/extension) anywhere in the [Admin](https://glossary.magento.com/admin) panel. However, it can be difficult finding the right place for your extension and how it should look, so we’ve prepared the following guidelines to help. + +## Things to Avoid + +We discourage practices that diminish the user experience in the Admin. The following design decisions that have been seen in some extensions create a negative user experience and should be avoided. + +### Icons in the Primary Navigation {#icons-in-navigation} + +Icons should not be added to the primary navigation panel in the Admin. If every extension added its own icon to the primary navigation panel, the interface will quickly become cluttered and unusable. + +Icons should not be used in any of the navigation submenu panels to bring attention to your extension. Your navigation listing should conform to the look and feel of its surroundings and not look out of place. + +Your extension's settings and configuration area is an appropriate place to use icons. + +For more information about icon design and Magento's icon library, see the article about [Iconography]({{ page.baseurl }}/design-styleguide/iconography/iconography.html) in the Admin Style Guide book. + +### Advertising in Navigation + +It is not appropriate to use the [Admin](https://glossary.magento.com/magento-admin) navigation for marketing or to [cross-sell](https://glossary.magento.com/cross-sell) extensions after your extensions has been installed in Magento. A [new section](#feature-extensions) is under proposal that will possibly be more suitable for marketing and advertising content. + +Do not use the name of your company or marketing jargon as part of an extension name or the extension name itself in the Admin. You should create a unique feature name that users will understand because people usually search for extensions by feature or function keywords, not by a company or brand name. + +## Placement guidelines for extension types + +From the list of extension types below, determine the type of extension you have and read the guidance for placement and style. + +*The names for the types of extensions listed below are for reference purposes only.* + +### Standard Connector + +These extensions provide additional [API](https://glossary.magento.com/api) over Magento's existing API and is responsible for providing settings between Magento and another system. + +**Placement:** + +All required settings for this connector type should appear in the **Stores** > Settings > **Configuration** section. The actual listings for these extension settings should appear after all of Magento's listed settings. All the setting details and configurations should appear in the section to the right. + +![Connector settings placement]({{ site.baseurl }}/common/images/ext-best-practices/connector-settings-placement.png) + +**Style:** + +* The style of the listing for your settings should match the look of Magento's listed settings. +* Icons or images should not be used in the navigation listing for your settings. + +--- + +### Store Feature Connector + +These extensions are responsible for integrating with different systems and need additional +settings displayed under specific entries in the **Store** > Settings > **Configuration** section. + +**Placement:** + +The settings for these extensions should be displayed under its respective parent section under the **Store** > Settings > **Configuration** section. + +For example, if the extension is for Shipping, then you can place it under **Store** > Settings > **Configuration** > **Sales** > **Shipping Settings**. + +![Store Feature Connector placement]({{ site.baseurl }}/common/images/ext-best-practices/store-feature-connector-placement.png) + +--- + +### Connector with additional features + +These extensions are responsible for integrating with different systems and need additional settings and configurations for synchronizing with these systems. + +**Placement:** + +If all the settings for an extension can be consolidated into one section, then the extension can be added to one of the primary navigation's submenu as links under the appropriate parent item. Avoid placing extension settings in multiple sections, such as the Configuration section and another related section. + +For example, if your extension is related to the "Reports" functionality then its settings should appear as a link under the Report Section in the Primary navigation. + +![Connector with additional features placement]({{ site.baseurl }}/common/images/ext-best-practices/additional-feature-placement.png) + +**Style:** + +* The styles of the links in the admin should follow the same styles of the default Magento Navigation Links. +* Do not introduce custom icons in the navigation submenus. + +--- + +### Feature Extensions + +These are extensions which provide additional functionality to Magento that do not already exist as a feature. These extensions usually demand an additional primary navigation item. + +**Placement:** + +There will be a new, dedicated section designed for such exclusive extensions. When feature-level extensions are installed, those extensions will live under this section. The exact final name of this new section has not been decided (we welcome your feedback), but in the image below it is named Extensions. + +![Feature Placement]({{ site.baseurl }}/common/images/ext-best-practices/feature-placement.png){:height="190px" width="350px"} + +{:.bs-callout-info} + The name and icon for this section is still TBD. + This new section is a future proposal, and we welcome feedback about if and how advertisements should be displayed here. + +Since this section is not yet available, you should place your extension in one of the previously mentioned areas where it would be the most appropriate. + +--- + +### Integrated Extensions + +These are add-ons to existing Magento feature and might appear as a nested feature. + +**Placement:** + +As these are integrated features no direct/indirect accessible links are available from the admin. + +--- + +### Codebase Extensions + +These extensions are created as a code and do not need to have a representation in the admin panel. + +**Placement:** + +As these extensions do not have additional settings no direct/indirect accessible links are available from the admin. diff --git a/src/guides/v2.4/ext-best-practices/bk-ext-best-practices.md b/src/guides/v2.4/ext-best-practices/bk-ext-best-practices.md deleted file mode 120000 index b23982b0427..00000000000 --- a/src/guides/v2.4/ext-best-practices/bk-ext-best-practices.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/ext-best-practices/bk-ext-best-practices.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/bk-ext-best-practices.md b/src/guides/v2.4/ext-best-practices/bk-ext-best-practices.md new file mode 100644 index 00000000000..c163f168be0 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/bk-ext-best-practices.md @@ -0,0 +1,29 @@ +--- +group: extension-best-practices +title: Best Practices for Extension Developers +functional_areas: + - Standards +--- + +{:.bs-callout-info} +This Best Practices guide is a living document, meant to be improved and revised as the software and our recommendations change. This guide combines best practices our community requested with guidelines that our Magento User Experience (UX), Engineering, and Product teams create. +If you have feedback about these recommendations, submit a pull request (PR) to the [Admin Panel Placement and Design topic]({{ page.baseurl }}/ext-best-practices/admin/feedback-placement-and-design.html). Give us your best practices recommendations, tell us about your challenges, and tell us how we can help standardize these guidelines. + +Magento consists of the core product code plus optional components that enhance or replace the core product code. There are over 100 out-of-the-box components in the form of modules, themes, and language packages available for Magento 2. + +Magento's architecture allows for enhancements by letting you develop your own component. Keep in mind that in addition to Magento's own modules, your [extension](https://glossary.magento.com/extension) will be running alongside components from other developers. For this reason, it is important that your component behaves correctly in Magento's modular environment. + +The table below is data from a recent poll that shows the distribution of the amount of extensions installed on a Magento instance for each edition. So for example, 32% of merchants on EE have over 50 different extensions installed! + +| Edition | 1-9 extensions | 10-30 extensions| 31-50 extensions| 50+ extensions| +| --------- | --- | ----- | ----- | --- | +| Community | 10% | 53% | 26% | 11% | +| Enterprise| 9% | 32% | 27% | 32% | + +This guide provides best practices, guidelines, and tips for creating extensions. We encourage you to follow our best practices when developing code for your Magento components. + +### Related Content + +* [Admin Design Pattern Library]({{ page.baseurl }}/pattern-library/bk-pattern.html) - An in depth guide to the design patterns used in the Admin. +* [PHP Developer Guide]({{ page.baseurl }}/extension-dev-guide/bk-extension-dev-guide.html) - An in depth guide to creating Magento components. +* [Frontend Developer Guide]({{ page.baseurl }}/frontend-dev-guide/bk-frontend-dev-guide.html) - An in depth guide to creating a Magento storefront theme. diff --git a/src/guides/v2.4/ext-best-practices/extension-coding/coding-best-practices.md b/src/guides/v2.4/ext-best-practices/extension-coding/coding-best-practices.md deleted file mode 120000 index 09c042b7da0..00000000000 --- a/src/guides/v2.4/ext-best-practices/extension-coding/coding-best-practices.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/extension-coding/coding-best-practices.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/extension-coding/coding-best-practices.md b/src/guides/v2.4/ext-best-practices/extension-coding/coding-best-practices.md new file mode 100644 index 00000000000..51b58037285 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/extension-coding/coding-best-practices.md @@ -0,0 +1,10 @@ +--- +group: extension-best-practices +title: Extension Coding +functional_areas: + - Standards +--- + +The coding best practices presented in this section should be known and understood by you, the developer, when creating or maintaining your extensions. This ensures that the [extension](https://glossary.magento.com/extension) you develop behaves and functions correctly within the Magento application architecture. This guide is not only meant to educate you about coding best practices, but to also highlight some pitfalls we have seen other extension developers fall into so that you may avoid them. + +For in depth content about creating extensions, see the [PHP Developer Guide]({{ page.baseurl }}/extension-dev-guide/bk-extension-dev-guide.html). diff --git a/src/guides/v2.4/ext-best-practices/extension-coding/coding-faq.md b/src/guides/v2.4/ext-best-practices/extension-coding/coding-faq.md deleted file mode 120000 index 808984f4a5d..00000000000 --- a/src/guides/v2.4/ext-best-practices/extension-coding/coding-faq.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/extension-coding/coding-faq.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/extension-coding/coding-faq.md b/src/guides/v2.4/ext-best-practices/extension-coding/coding-faq.md new file mode 100644 index 00000000000..dfe7f1f61b7 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/extension-coding/coding-faq.md @@ -0,0 +1,32 @@ +--- +group: extension-best-practices +subgroup: 02_Extension-Coding +title: Coding FAQ +menu_title: Coding FAQ +menu_order: 1000 +functional_areas: + - Standards +--- + +This page is a compilation of frequently asked coding questions by the Magento Community. + +### What do I need to know to work with the framework? + +* [SOLID principles](https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)) - The essential principles needed to create maintainable and extendable code. +* [PHP](http://php.net/) - This is the programming language used for developing Magento 2 code. +* [HTML](https://en.wikipedia.org/wiki/HTML), [CSS](https://en.wikipedia.org/wiki/Cascading_Style_Sheets), and [JavaScript](https://www.javascript.com/) - Languages used for [frontend development]({{ page.baseurl }}/frontend-dev-guide/bk-frontend-dev-guide.html). +* [Architecture basics overview]({{ page.baseurl }}/architecture/archi_perspectives/ABasics_intro.html) - Developers should be familiar with the architectural concepts used in Magento such as the [Model-View-Controller](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) pattern and the [Command Query Responsibility Segregation](http://martinfowler.com/bliki/CQRS.html) principle. +* [Dependency Injection]({{ page.baseurl }}/extension-dev-guide/depend-inj.html) - An important [design pattern](https://glossary.magento.com/design-pattern) used in Magento to handle dependencies across classes and modules. + +### In Magento 2, how can my extension distinguish between the {{site.data.var.ce}} and the {{site.data.var.ee}}? + +The correct edition can be obtained through `\Magento\Framework\App\ProductMetadataInterface::getEdition`. + +In {{site.data.var.ce}} that interface maps to the concrete implementation `Magento\Framework\AppInterface\ProductMetadata`. +However, in {{site.data.var.ee}}, the Commerce [module](https://glossary.magento.com/module) will override that mapping and the interface will be implemented by `\Magento\Enterprise\Model\ProductMetadata`. + +Just relying on the interface through [dependency injection](https://glossary.magento.com/dependency-injection) will get you the right class, and calling "getEdition" will return the right answer. + +### How do I configure my module so that it appears in a specific place on the Admin? + +Use the `/etc/adminhtml/menu.xml` file to configure from where on the [Admin](https://glossary.magento.com/admin) your [extension](https://glossary.magento.com/extension) is accessible. diff --git a/src/guides/v2.4/ext-best-practices/extension-coding/example-module-adminpage.md b/src/guides/v2.4/ext-best-practices/extension-coding/example-module-adminpage.md deleted file mode 120000 index 5cc8d61d608..00000000000 --- a/src/guides/v2.4/ext-best-practices/extension-coding/example-module-adminpage.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/extension-coding/example-module-adminpage.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/extension-coding/example-module-adminpage.md b/src/guides/v2.4/ext-best-practices/extension-coding/example-module-adminpage.md new file mode 100644 index 00000000000..4753b6738f3 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/extension-coding/example-module-adminpage.md @@ -0,0 +1,346 @@ +--- +group: extension-best-practices +title: Creating an admin page +functional_areas: + - Standards +--- + +## Overview + +This tutorial gives instructions for the creation of a [module](https://glossary.magento.com/module) that displays a simple page in the [Magento admin](https://glossary.magento.com/magento-admin). + +For the purposes of this tutorial 'MyCompany' is the name of the company associated with a module named `ExampleAdminNewPage`. + +## Working directory + +Start by creating the working directory for all the module files. + +In your Magento development environment under the `app/code` directory, run the following command: + +```bash +mkdir -p MyCompany/ExampleAdminNewPage +``` + +This command creates the `MyCompany` company directory and the `ExampleAdminNewPage` module directory. The latter will be the root directory for the module we will create. + +## Initial boilerplate files + +These initial boilerplate files are the bare essential files needed for any Magento module. + +### `composer.json` + +{:.no_toc} +In the module's root directory, create the file `composer.json`. This file gives [composer](https://glossary.magento.com/composer) the ability to install this module and its dependencies. +For more information see: [`composer.json`]({{ page.baseurl }}/extension-dev-guide/build/composer-integration.html). + +{% collapsible File content for composer.json %} + ```json + { + "name": "mycompany/sample-module-minimal", + "description": "A module that creates a page in the Magento admin area", + "type": "magento2-module", + "version": "1.0.0", + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "require": { + "php": "~7.2.0||~7.3.0" + }, + "autoload": { + "files": [ "registration.php" ], + "psr-4": { + "MyCompany\\ExampleAdminNewPage\\": "" + } + } + } + ``` +{% endcollapsible %} + +### `registration.php` + +{:.no_toc} +In the module's root directory, create the file `registration.php`. This file registers the module `MyCompany_ExampleAdminNewPage` with Magento. + +For more information see: [registering your component]({{ page.baseurl }}/extension-dev-guide/build/component-registration.html). + +{% collapsible File content for registration.php %} +```php + + + + + +``` + +{% endcollapsible %} + +If your module does not implement [Declarative Schema]({{ page.baseurl }}/extension-dev-guide/declarative-schema/index.html), define the `setup_version` attribute in the module element. + +```xml + +``` + +If your module has a dependency with other modules, you can change the loading order sequence of the module by using the `sequence` node. +In the example below, `MyCompany_ExampleAdminNewPage` will be loaded after the `Magento_Checkout` module. + +```xml + + + + + +``` + +## Routing and navigation + +Before we can view the module's page, we need a way to navigate to it. These files create a link to the page in the left navigation and tells Magento how to resolve requests for that page. + +For more information on this topic, see: [routing]({{ page.baseurl }}/extension-dev-guide/routing.html). + +### `etc/adminhtml/menu.xml` +{:.no_toc} +Under the created `etc` directory, create a new directory called `adminhtml`. Under that directory, create the file `menu.xml`. This [XML](https://glossary.magento.com/xml) file adds new menu items to the Magento [admin](https://glossary.magento.com/admin). + +The `menu.xml` file provided below adds two items in the Content section of the left navigation: + +1. A new separate section with the title **Greetings** under Content. +1. A link with the label **Hello World** that leads to a page request for `exampleadminnewpage/helloworld/index` underneath that new section. + +![Hello World menu item]({{ site.baseurl }}/common/images/ext-best-practices/hello-world-menu-item.png){:width="322px"} + +The following parts make up the generated page request link to the **Hello World** page: + +* `exampleadminnewpage` - This is the `frontName`. Because its purpose is to help route requests to the correct module, we give it the same name as the module, but this is not required. +* `helloworld` - This specifies the name of the controller to use. +* `index` - In the XML file, since the action for the controller is not specified, Magento uses the default value `index`. + +[//]: # (Stop list rendering before collapsible, see: https://github.com/magento/devdocs/issues/2655) +{% collapsible File content for menu.xml %} + +```xml + + + + + + + +``` + +{% endcollapsible %} + +### `etc/adminhtml/routes.xml` +{:.no_toc} +Under `etc/adminhtml` create the file `routes.xml`. The contents of this XML file tells Magento to route requests that use the `frontName` `exampleadminnewpage` to this module. + +{% collapsible File content for routes.xml %} + +```xml + + + + + + + + +``` + +{% endcollapsible %} + +## Page controller + +Now that we have a link to the **Hello World** page, we need to create the file needed to handle that request. + +### `Controller/Adminhtml/HelloWorld/Index.php` +{:.no_toc} +In the module's root directory, run the following command: + +```bash +mkdir -p Controller/Adminhtml/HelloWorld +``` + +Inside `Controller/Adminhtml/HelloWorld` directory, create the file `Index.php`. This file is the class assigned to the default Index action for the `HelloWorld` controller. Since the admin area serves this page, the file belongs in the `Adminhtml` directory, and the class itself extends [`\Magento\Backend\App\Action`]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Backend/App/Action.php). + +{% collapsible File content for Index.php %} + +```php +resultPageFactory = $resultPageFactory; + } + + /** + * Load the page defined in view/adminhtml/layout/exampleadminnewpage_helloworld_index.xml + * + * @return Page + */ + public function execute() + { + $resultPage = $this->resultPageFactory->create(); + $resultPage->setActiveMenu(static::MENU_ID); + $resultPage->getConfig()->getTitle()->prepend(__('Hello World')); + + return $resultPage; + } +} +``` + +{% endcollapsible %} + +## Page view + +Now that Magento knows how to handle requests for the **Hello World** page, we need view files that define the look of the page. + +Create the necessary directories for the files by running the following commands from the module's root directory: + +```bash +mkdir -p view/adminhtml/layout +mkdir -p view/adminhtml/templates +``` + +These files belong in the `view/adminhtml` directory because the Magento admin area use these files during page generation. + +### `view/adminhtml/layout/exampleadminnewpage_helloworld_index.xml` +{:.no_toc} + +This file defines the [layout](https://glossary.magento.com/layout) and structure of the index page for the HelloWorld controller. It sets the title to "Greetings" and instructs Magento to use the `helloworld.phtml` template as the content in a `Magento\Backend\Block\Template` block class. + +The name of this file uses the following pattern: *routeId*\_*controller*\_*action*.xml + +{% collapsible File content for exampleadminnewpage_helloworld_index.xml %} + +```xml + + + + + Greetings + + + + + + + + +``` + +{% endcollapsible %} + +### `view/adminhtml/templates/helloworld.phtml` +{:.no_toc} + +This template file contains the actual page content for the **Hello World** page. + +```html +

    Hello World!

    +``` + +## Full module directory structure + +The module is now complete. Your module's directory structure under `app/code` should look like the following: + +```tree +MyCompany +|-- ExampleAdminNewPage + | + |-- Controller + | |-- Adminhtml + | |-- HelloWorld + | |-- Index.php + |-- etc + | |-- adminhtml + | | |-- menu.xml + | | |-- routes.xml + | |-- module.xml + |-- view + | |-- adminhtml + | |-- layout + | | |-- exampleadminnewpage_helloworld_index.xml + | |-- templates + | |-- helloworld.phtml + |-- composer.json + |-- registration.php +``` + +## Installing the module + +Now that the module is code-complete, run the following commands to install it: + +1. `bin/magento module:status` - This command shows a list of enabled/disabled modules. +1. `bin/magento module:enable MyCompany_ExampleAdminNewPage` - If necessary, run this to enable the disabled module. +1. `bin/magento setup:upgrade` - This command will properly register the module with Magento. +1. `bin/magento setup:di:compile` - This command compiles classes used in dependency injections. +1. `bin/magento setup:static-content:deploy` - (Production mode only) This command deploys static view files. If you are in developer mode, refer to [Clean static files cache]({{ page.baseurl }}/frontend-dev-guide/cache_for_frontdevs.html#clean_static_cache) to refresh the static view files. +1. `bin/magento cache:clean` - This command cleans the cache. + +Once the module installation has completed, the link to the **Hello World** page should appear in the **Greetings** section under **Content** in the left navigation in the admin area. Clicking this link will take you to a page that looks like the one pictured below. + +![Hello World Page]({{ site.baseurl }}/common/images/ext-best-practices/hello-world-page.png) + +## Related topics + +* [Create an ACL rule]({{ page.baseurl }}/ext-best-practices/tutorials/create-access-control-list-rule.html) diff --git a/src/guides/v2.4/ext-best-practices/extension-coding/observers-bp.md b/src/guides/v2.4/ext-best-practices/extension-coding/observers-bp.md deleted file mode 120000 index 9a213f00ee0..00000000000 --- a/src/guides/v2.4/ext-best-practices/extension-coding/observers-bp.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/extension-coding/observers-bp.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/extension-coding/observers-bp.md b/src/guides/v2.4/ext-best-practices/extension-coding/observers-bp.md new file mode 100644 index 00000000000..7f1b6656958 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/extension-coding/observers-bp.md @@ -0,0 +1,53 @@ +--- +group: extension-best-practices +subgroup: 02_Extension-Coding +title: Observers Best Practices +menu_title: Observers best practices +menu_order: 4 +functional_areas: + - Standards +--- + +### Overview +[Observers]({{ page.baseurl }}/extension-dev-guide/events-and-observers.html) are capable of modifying the behavior of a Magento application because they are dynamically injected into the execution flow. Poorly designed and coded observers can cause issues, instabilities, or otherwise break the application. + +We encourage you to follow these best practices aimed towards reducing problems when your observer is executed. + +### Best practices + +#### Make your observer efficient + +Try to keep your observer small and efficient by avoiding complex computations, if possible. This is especially important when your observer is listening to an [event](https://glossary.magento.com/event) that is frequently dispatched. Having complex computations in your observer can slow down application processes. + +#### Do not include business logic + +Your observer should not contain logic other than what is needed for it to run. Business logic should be encapsulated in other classes that your observer uses. + +#### Declare observer in the appropriate scope + +Make your observer as specific as it needs to be. Declare your observer in the appropriate area: + +| Area | File location | Description | +| --- | --- | --- | +| `global` | `/etc/events.xml` | Observer will be executed in all areas: `adminhtml`, `crontab`, `frontend`, `graphql`, `webapi_rest`, `webapi_soap`. | +| `adminhtml` | `/etc/adminhtml/events.xml` | Observer will be executed in the `adminhtml` area only. | +| `crontab` | `/etc/crontab/events.xml` | Observer will be executed in the `crontab` area only. | +| `frontend` | `/etc/frontend/events.xml` | Observer will be executed in the `frontend` area only. | +| `graphql` | `/etc/graphql/events.xml` | Observer will be executed in the `graphql` area only. | +| `webapi_rest` | `/etc/webapi_rest/events.xml` | Observer will be executed in the `webapi_rest` area only. | +| `webapi_soap` | `/etc/webapi_soap/events.xml` | Observer will be executed in the `webapi_soap` area only. | + +{:.bs-callout-info} +It is `NOT RECOMMENDED` to register everything in the `global` area, as the bootstrapping process will become much heavier. For example, the application must run and process additional checks for your observer. + +#### Avoid cyclical event loops + +Cyclical event loops occur when your observer calls the method of an object that dispatches an event that triggers a chain of events that ends up dispatching that same initial event that executes your observer in a recurring manner. Make sure your observer is not dispatching an event that it immediately listens to or will listen to in the chain of events that follows. + +#### Do not rely on invocation order + +Your observer should not make assumptions about the order in which it will be invoked nor should it rely on the execution of another observer. Observers listening to the same event may be invoked in any order when that event is dispatched. + +### Recommended Reading + +* [Events and Observers]({{ page.baseurl }}/extension-dev-guide/events-and-observers.html) diff --git a/src/guides/v2.4/ext-best-practices/extension-coding/working-with-arch-bp.md b/src/guides/v2.4/ext-best-practices/extension-coding/working-with-arch-bp.md deleted file mode 120000 index 04471c8c147..00000000000 --- a/src/guides/v2.4/ext-best-practices/extension-coding/working-with-arch-bp.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/extension-coding/working-with-arch-bp.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/extension-coding/working-with-arch-bp.md b/src/guides/v2.4/ext-best-practices/extension-coding/working-with-arch-bp.md new file mode 100644 index 00000000000..3bea82d4d49 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/extension-coding/working-with-arch-bp.md @@ -0,0 +1,55 @@ +--- +group: extension-best-practices +subgroup: 02_Extension-Coding +title: Working with the Architecture +menu_title: Working with the Architecture +menu_order: 2 +functional_areas: + - Standards +--- + +In addition to understanding fundamental programming designs/concepts, you are encouraged to learn how the MVC architecture works in our code and how to work with Magento's generated code and factories. + +### Avoid modification of the Magento Core + +The core code is the default Magento code that comes with the application. You should never edit the core code because code changes occur between version upgrades and any changes you make will get overwritten. Try achieving your desired behavior with plugins, overriding interface preferences, and [event](https://glossary.magento.com/event) observers. + +If you feel that Magento can be improved with your core code changes, please consider [contributing via Git]({{ site.baseurl }}/contributor-guide/contributing.html). + +### Learn the architecture + +To create the optimum module, you should get to know the Magento 2 architecture. Start off by familiarizing yourself with the [Admin Pattern Library]({{ page.baseurl }}/pattern-library/bk-pattern.html), the core [Magento Components]({{ page.baseurl }}/extension-dev-guide/bk-extension-dev-guide.html), and our [service contracts]({{ page.baseurl }}/extension-dev-guide/service-contracts/service-contracts.html) and [APIs]({{ page.baseurl }}/get-started/bk-get-started-api.html). + +### Check your extension configurations + +Make sure your [extension](https://glossary.magento.com/extension) is configured correctly in each of your extension's configuration files. Invalid or unexpected values will cause your extension to behave incorrectly within Magento. + +### Know and leverage the Magento 2 framework + +There have been some significant changes from Magento 1. Be sure to study the capabilities and standards of the Magento 2 Framework. + +For example: + +- Instead of creating custom validators from scratch, implement the [`\Magento\Framework\Validator\ValidatorInterface`]({{ site.mage2bloburl }}/{{ page.guide_version }}/lib/internal/Magento/Framework/Validator/ValidatorInterface.php). +- Instantiating a database connection can be expensive and unnecessary. Magento provides resource models for performing SQL commands. (See [Persistence Layer]({{ page.baseurl }}/architecture/archi_perspectives/persist_layer.html)) +- Consider using Magento framework conventions instead of low-level or [PHP](https://glossary.magento.com/php) functionality. +- Use the [`Magento\Framework\Data\Collection`]({{ site.mage2bloburl }}/{{ page.guide_version }}/lib/internal/Magento/Framework/Data/Collection.php) class to retrieve a collection of filtered objects instead of directly querying the database. + +### Use dependency injection + +Direct class instantiation is not recommended because the class can be rewritten. If the class is created directly, any rewrites will not be applied and it breaks Magento's class rewrite capability. We encourage you to become familiar with how we use [dependency injection]({{ page.baseurl }}/extension-dev-guide/depend-inj.html) to get an instance of a class. + +### Follow Model-View-Control (MVC) pattern + +Make sure your extension adheres to the MVC Pattern, and that it does not violate any of its principles. + +Some important things to check in your extensions: + +- Make sure your Business Logic, Configuration, and SQL are implemented in the correct places. +- Make sure that CSS, JavaScript, HTML, and [XML](https://glossary.magento.com/xml) code are all in the appropriate files (i.e. they should not be inline). +- Use appropriate logic in a Block, Helper, Template, Controller, or Model. +- Ensure correct [module](https://glossary.magento.com/module) design. + +### Use the PHP_CodeSniffer tool + +[PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) is a set of PHP scripts that checks your code for violations of a particular coding standard. It can be used in conjunction with the [Magento Coding Standard](https://github.com/magento/magento-coding-standard) to check your code for some of the more common Magento and PHP problems. Using these two tools will ensure that your extension code meets many of [Magento's coding standards]({{ page.baseurl }}/coding-standards/bk-coding-standards.html). It also has the added benefits of keeping your code clean and maintainable. diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/adding-code-inspections.md b/src/guides/v2.4/ext-best-practices/phpstorm/adding-code-inspections.md deleted file mode 120000 index ea5a1afde2a..00000000000 --- a/src/guides/v2.4/ext-best-practices/phpstorm/adding-code-inspections.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/phpstorm/adding-code-inspections.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/adding-code-inspections.md b/src/guides/v2.4/ext-best-practices/phpstorm/adding-code-inspections.md new file mode 100644 index 00000000000..07f96d366ba --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/phpstorm/adding-code-inspections.md @@ -0,0 +1,221 @@ +--- +group: extension-best-practices +title: Adding code inspections +functional_areas: + - Standards +--- + +The IntelliJ Platform provides tools designed for static code analysis called code inspections, which help you maintain and clean up code without actually executing it. +Read more in the [official documentation](https://plugins.jetbrains.com/docs/intellij/code-inspections.html). + +you can find plugin inspections in `Settings | Preferences... | Editor | Inspections`. +Use a filter to find only the plugin inspections: `Magento 2`. + +![Image of the Magento 2 Group Inspections]({{site.baseurl}}/common/images/phpstorm/Intellij-idea-plugin-editor-local-inspections.png) + +See [Inspections topic](https://jetbrains.design/intellij/text/inspections/) in the IntelliJ Platform UI Guidelines +for naming, writing descriptions, and messages for inspections to avoid basic naming convention issues before code review. + +### To add a new inspection +Adding a new code inspection includes: + +1. Declaring an inspection in the plugin configuration file +1. Implementing a local inspection class to inspect code in the IntelliJ Platform-based IDE editor +1. Creating a visitor to traverse the PSI tree of the file being edited and inspecting for problematic syntax +1. Writing an HTML description of the inspection for display in the inspection preferences panel +1. Create a unit test for the inspection +1. Implementing a quick fix class to correct syntax problems by altering the PSI tree as needed +1. Implementing an inspection preferences panel to display information about the inspection + +### Declaring an inspection in the plugin configuration file + +You must declare all plugin inspections in the `` XML node of the plugin configuration file. + +For example, we will implement a local inspection tool for checking preference XML tag attributes (`di.xml` file) +if they are valid classes FQNs. + +```xml + +``` + +The `` tag attributes: + +1. `language` - desired file language (ex.: XML, PHP, CSS, JavaScript, etc.) +1. `groupPath` - the first level group in the inspection preferences panel +1. `shortName` - local inspection identity +1. `bundle` - which bundle to use to display name in the inspection preferences panel, constant value: `magento2.inspection` +1. `key` - which bundle message to use to display name in the inspection preferences panel +1. `groupBundle` - the second level group bundle, constant value: `magento2.inspection` +1. `groupKey` - group bundle message, constant value: `inspection.group.name` +1. `enabledByDefault` - is it should be enabled by default +1. `level` - inspection severity level +1. `ImplementationClass` - inspection implementation class + +Add a new bundle message with key `inspection.displayName.InvalidDiTypeInspection` to the [InspectionBundleMessagesFile]: + +```properties +inspection.displayName.InvalidDiTypeInspection=Invalid type configuration in the `etc/di.xml` file +``` + +### Implementing a local inspection class to inspect code in the IntelliJ Platform-based IDE editor + +The base class for all local inspections is `com.intellij.codeInspection.LocalInspectionTool`. + +**Plugin extension points:** + +| Language | Example Implementation | Extension Point Class | +| ------------------------------ | --------------------------------------------- | --------------------- | +| `PHP` | [PluginInspection] | `com.jetbrains.php.lang.inspections.PhpInspection` | +| `XML` | [ModuleDeclarationInModuleXmlInspection] | `com.intellij.codeInspection.XmlSuppressableInspectionTool` | + +Implement `InvalidDependencyInjectionTypeInspection` inspection that extends `XmlSuppressableInspectionTool`: + +```java +/* + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +package com.magento.idea.magento2plugin.inspections.xml; + +import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.codeInspection.XmlSuppressableInspectionTool; +import com.intellij.psi.PsiElementVisitor; +import org.jetbrains.annotations.NotNull; + +public class InvalidDependencyInjectionTypeInspection extends XmlSuppressableInspectionTool { + + @Override + public @NotNull PsiElementVisitor buildVisitor( + final @NotNull ProblemsHolder holder, + final boolean isOnTheFly + ) { + // TODO: Implement visitor for InvalidDependencyInjectionTypeInspection type. + return super.buildVisitor(holder, isOnTheFly); + } +} +``` + +### Creating a visitor to traverse the PSI tree of the file being edited and inspecting for problematic syntax + +All visitors should extend `com.intellij.psi.PsiElementVisitor`. + +**Visitors implementations for different languages:** + +| Language | Visitor Implementation Class | +| ------------------------------ | --------------------- | +| `PHP` | `com.jetbrains.php.lang.psi.visitors.PhpElementVisitor` | +| `XML` | `com.intellij.psi.XmlElementVisitor` | +| `JSON` | `com.intellij.json.psi.JsonElementVisitor` | +| `JavaScript` | `com.intellij.psi.PsiElementVisitor` | + +Let's implement new `XmlElementVisitor` that overrides `visitXmlTag` method. That visitor will check all XML tags +in all XML files. We should dedicate it to check only expected XML files (`di.xml`) and expected XML tags (``). +Use the following code to check only expected XML files: + +```java +final PsiFile file = xmlTag.getContainingFile(); + +if (!file.getName().equals(ModuleDiXml.FILE_NAME) + || !xmlTag.getName().equals(ModuleDiXml.TYPE_TAG)) { + return; +} +``` + +Now we can access the `` tag's `name` attribute to check its value: + +```java +final XmlAttribute nameAttribute = xmlTag.getAttribute(ModuleDiXml.NAME_ATTR); +``` + +The `XmlTag.getAttribute()` method returns `@Nullable` value. We should check if our attribute is accessible for working with it. +Also, later we will need to use the `XmlTag.getValueElement()` method to register problems using `ProblemsHolder` if they occur. +The `XmlTag.getValueElement()` method also returns `@Nullable` value. Let's use this code to skip checking incorrect XML attributes: + +```java +if (nameAttribute == null || nameAttribute.getValue() == null || nameAttribute.getValueElement() == null) { + return; +} +``` + +Now we can access attribute values. We can check if an attribute value is an existing class by using the [PhpClassExistenceValidator] type instance. +To report problem with the `name` attribute value, you can use the following code: + +```java +problemsHolder.registerProblem( + nameAttribute.getValueElement(), + inspectionBundle.message( + "inspection.error.idAttributeCanNotBeEmpty", + nameAttribute.getName() + ), + ProblemHighlightType.ERROR +); +``` + +You cannot access the tag value of the `PsiElement` type. +You should report problems with the tag element similar to Intellij Idea inspections. For example: `com.intellij.xml.util.CheckEmptyTagInspection`. + +So, there is a full example: [InvalidDependencyInjectionTypeInspection] + +### Writing HTML descriptions + +This section shows you how to display an HTML description of the inspection in the inspection preferences panel. + +You must describe all inspections in the description file. To do this, you can add a new HTML file to the following path: +`./resources/inspectionDescriptions/{shortName}.html`, where `{shortName}` is a `shortName` attribute value in the +local inspection declaration. Or you can just use Intellij Idea automation to do this (preferred). +All inspection implementation classes have highlighted class names if they don't have description files. Here's a quick fix to create it: +![Create Inspection Description File Quick Fix]({{site.baseurl}}/common/images/phpstorm/Intellij-idea-plugin-create-inspection-description-quick-fix.png) + +Use [Inspections topic](https://jetbrains.design/intellij/text/inspections/) to write better descriptions for inspections using naming conventions. + +### Create a unit test for the inspection + +You must deliver each inspection with the unit test for it. The root folder for all inspections unit tests is `./tests/com/magento/idea/magento2plugin/inspections`. As base classes for your tests you should use predefined implementations based on languages. + +**Base classes implementations for different languages:** + +| Language | Abstract Class | +| ------------------------------ | --------------------- | +| `php` | `com.magento.idea.magento2plugin.inspections.php.InspectionPhpFixtureTestCase` | +| `xml` | `com.magento.idea.magento2plugin.inspections.xml.InspectionXmlFixtureTestCase` | +| `graphql` | `com.magento.idea.magento2plugin.inspections.graphqls.InspectionGraphqlsFixtureTestCase` | + +If you cover new language area, please extend the `com.magento.idea.magento2plugin.inspections.BaseInspectionsTestCase` class and add a new abstract class for that area. +All test class names should have the suffix "test" and all testing methods should have the prefix "test" and detailed description in the annotation. +Also, you should enable testing inspection in the `setUp()` method. + +```java +public class TypeConfigurationTagTypesInspectionTest extends InspectionXmlFixtureTestCase { + + @Override + public void setUp() throws Exception { + super.setUp(); + myFixture.enableInspections(InvalidDependencyInjectionTypeInspection.class); + } + + /** + * Test type doesn't exists highlighting: . + */ + public void testNameAttributeValueTypeDoesNotExists() { + // TODO: write a test. + } +} +``` + +The root folder for your test data is: `./testData/inspections`. The internal folder structure is the same as for your test cases, accordingly to the testing file language. +To add data for your new test case use the next rule: create directory inside tested language folder that has the same name as your testing class **without suffix Test** (for the example above it is folder with the name: `TypeConfigurationTagTypesInspection`). +For each testing method create folder in it that has a name the same as method name **without test prefix** in the camel case format (for the example above it is folder with the name: `nameAttributeValueTypeDoesNotExists` inside the `TypeConfigurationTagTypesInspection` folder). + +Magento 2 SandBox that used for the tests is in the `./testData/project/magento2` folder. + +[InspectionBundleMessagesFile]: https://github.com/magento/magento2-phpstorm-plugin/blob/4.0.0-develop/resources/magento2/inspection.properties +[PluginInspection]: https://github.com/magento/magento2-phpstorm-plugin/blob/4.0.0-develop/src/com/magento/idea/magento2plugin/inspections/php/PluginInspection.java +[ModuleDeclarationInModuleXmlInspection]: https://github.com/magento/magento2-phpstorm-plugin/blob/4.0.0-develop/src/com/magento/idea/magento2plugin/inspections/xml/ModuleDeclarationInModuleXmlInspection.java +[PhpClassExistenceValidator]: https://github.com/magento/magento2-phpstorm-plugin/blob/4.0.0-develop/src/com/magento/idea/magento2plugin/inspections/validator/PhpClassExistenceValidator.java +[InvalidDependencyInjectionTypeInspection]: https://github.com/magento/magento2-phpstorm-plugin/blob/4.0.0-develop/src/com/magento/idea/magento2plugin/inspections/xml/InvalidDependencyInjectionTypeInspection.java diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/built-in-upgrade-compatibility-tool.md b/src/guides/v2.4/ext-best-practices/phpstorm/built-in-upgrade-compatibility-tool.md deleted file mode 120000 index 07dee582635..00000000000 --- a/src/guides/v2.4/ext-best-practices/phpstorm/built-in-upgrade-compatibility-tool.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/phpstorm/built-in-upgrade-compatibility-tool.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/built-in-upgrade-compatibility-tool.md b/src/guides/v2.4/ext-best-practices/phpstorm/built-in-upgrade-compatibility-tool.md new file mode 100644 index 00000000000..6b5a8252449 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/phpstorm/built-in-upgrade-compatibility-tool.md @@ -0,0 +1,85 @@ +--- +group: extension-best-practices +title: The built-in Upgrade Compatibility Tool (MVP) +functional_areas: +- Standards +--- + +The built-in Upgrade Compatibility Tool aims to achieve the same issues coverage as original Adobe Commerce [Upgrade Compatibility Tool](https://experienceleague.adobe.com/docs/commerce-operations/upgrade-guide/upgrade-compatibility-tool/overview.html). +There are three types of inspections covered by this MVP version: + +* Deprecation (severity level: WARNING) +* API coverage (severity level: ERROR) +* Existence (severity level: CRITICAL) + +A complete list of inspections that are already available in the original tool, can be found by the [following link](https://experienceleague.adobe.com/docs/commerce-operations/upgrade-guide/upgrade-compatibility-tool/error-messages.html). + +This feature can be used in three different ways, from the user's point of view: + +* Run compatibility inspections in a [run tool window](https://www.jetbrains.com/help/idea/run-tool-window.html), with the familiar output, as in the original Adobe Commerce [Upgrade Compatibility Tool](https://experienceleague.adobe.com/docs/commerce-operations/upgrade-guide/upgrade-compatibility-tool/overview.html) +* Run inspections in real time, on the files that are opened in the editor (default) +* [Run inspections manually](https://www.jetbrains.com/help/idea/running-inspections.html) through the user interface on the selected scope of files (default) + +It was developed with an aim to use IntelliJ IDEA in the most effective way. So, inspections that are running during +the code analysis can alternatively be enabled in the [inspections settings](https://www.jetbrains.com/help/idea/code-inspection.html) +`Preferences -> Editor -> Inspections -> UCT`: + +![]({{site.baseurl}}/common/images/phpstorm/built-in-uct/uct-inspections-settings.png) + +It allows you to see the problematic code just in real time, without running it intentionally during code writing or file viewing. +**The result of the real time inspection is most suitable for use during development, to be always compatible with future versions**: + +![]({{site.baseurl}}/common/images/phpstorm/built-in-uct/uct-inspections-highlighting.png) +![]({{site.baseurl}}/common/images/phpstorm/built-in-uct/uct-inspections-highlighting-2.png) +![]({{site.baseurl}}/common/images/phpstorm/built-in-uct/uct-inspections-highlighting-3.png) +![]({{site.baseurl}}/common/images/phpstorm/built-in-uct/uct-inspections-highlighting-4.png) + +The second IntelliJ IDEA tool that we can use for running UCT inspections is called **Inspect Code**. It is available under menu item +`Code -> Inspect Code`. Also, you can open a context menu under the target directory that allows IntelliJ IDEA to populate the path to analyse for you automatically: + +![]({{site.baseurl}}/common/images/phpstorm/built-in-uct/run-inspect-code-from-context-menu.png) + +By calling the **Inspect Code** action from the context menu, the Inspection Scope will be populated for us automatically. +The last thing to configure here is **Inspection Profile**. +By default, there will be the **Project Default** profile with all inspections that are not connected to our goal. + +![]({{site.baseurl}}/common/images/phpstorm/built-in-uct/uct-intellij-idea-based-analysis-configuration.png) + +You can create a new profile with the only UCT inspections enabled (for further information [read here](https://www.jetbrains.com/help/idea/customizing-profiles.html)): + +![]({{site.baseurl}}/common/images/phpstorm/built-in-uct/uct-inspections-profile.png) + +For this inspection type you do not need to have UCT inspections enabled for your project. +**The result of this inspection is most suitable for code refactoring when eliminating problematic code**: + +![]({{site.baseurl}}/common/images/phpstorm/built-in-uct/uct-analysis-through-intellj-idea-inspect-code-action.png) + +**The most powerful inspection type is the execution of compatibility inspections in a [run tool window](https://www.jetbrains.com/help/idea/run-tool-window.html) with the familiar output as in the original Adobe Commerce [Upgrade Compatibility Tool](https://experienceleague.adobe.com/docs/commerce-operations/upgrade-guide/upgrade-compatibility-tool/overview.html)**. + +**Advantages from using this inspection:** + +* All problems are gathered in one place +* There are links to the problem files, a stored report in json format, links to the web page with detailed descriptions of all the error codes +* This report can be easily used from the merchant, management or agency side +* There is a complexity score that helps measure the upgrade complexity + +Before using it, you should configure the built-in UCT in a same way to the CLI Run Configuration. +All fields, as above, are described in the Upgrade Compatibility Tool Run Configuration section and are more detailed +in the [official documentation](https://experienceleague.adobe.com/docs/commerce-operations/upgrade-guide/upgrade-compatibility-tool/run.html). +Go to the UCT configuration dialog `Tools -> Configure The Upgrade Compatibility Tool` and configure it as required: + +![]({{site.baseurl}}/common/images/phpstorm/built-in-uct/uct-settings.png) + +After this, you can run this tool at any time you require by using `Tools -> Run The Upgrade Compatibility Tool`: + +![]({{site.baseurl}}/common/images/phpstorm/built-in-uct/run-the-built-in-uct-min.gif) + +For this inspection type you do not need to have UCT inspections enabled for your project, but it is easier to see the problems in the file +after navigating to it. + +{:.bs-callout-warning} +**Keep in mind**, that for all inspection types the target Magento version (coming version) is configured +in the built-in UCT configuration dialog `Tools -> Configure The Upgrade Compatibility Tool`. +This is also applicable for the other selected configurations on the screenshot below: + +![]({{site.baseurl}}/common/images/phpstorm/built-in-uct/shared-configurations-for-all-inspection-types.png) diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/code-generation.md b/src/guides/v2.4/ext-best-practices/phpstorm/code-generation.md deleted file mode 120000 index 3805109b8bf..00000000000 --- a/src/guides/v2.4/ext-best-practices/phpstorm/code-generation.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/phpstorm/code-generation.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/code-generation.md b/src/guides/v2.4/ext-best-practices/phpstorm/code-generation.md new file mode 100644 index 00000000000..7749e31f0e6 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/phpstorm/code-generation.md @@ -0,0 +1,42 @@ +--- +group: extension-best-practices +title: Code generation +functional_areas: + - Standards +--- + +The PHPStorm plugin enables features and functionality to help you create custom extensions. + +### XML file header + +The **XML file header** template is located in the PHPStorm plugin menu, under **Preferences** > **Editor** > **File and Code Templates**. + +You can configure the **XML file header** that appears in all generated XML files in the PHPStorm plugin GUI: + +![]({{site.baseurl}}/common/images/phpstorm/xml-file-header.png) + +#### Usage + +All generated XML files will include the **XML file header**: + +![]({{site.baseurl}}/common/images/phpstorm/xml-file-header-in-file.png) + +### Web API declaration generation + +![]({{site.baseurl}}/common/images/phpstorm/web-api-declaration-2-min.gif) + +### Web API interface for service (PHP class) generation + +![]({{site.baseurl}}/common/images/phpstorm/declare-web-api-interface-min.gif) + +### Web API generation for the Magento Entity Creator + +From now on, the Entity Creator feature also includes the Web API generation. + +![]({{site.baseurl}}/common/images/phpstorm/entity-creator-web-api-generation-min.gif) + +There is an example of the output for generated entity when accessing get list REST API endpoint from the Postman application and from the admin panel in browser: + +![]({{site.baseurl}}/common/images/phpstorm/get-list-rest-api-call.png) + +![]({{site.baseurl}}/common/images/phpstorm/get-list-in-browser.png) diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/code-inspection.md b/src/guides/v2.4/ext-best-practices/phpstorm/code-inspection.md deleted file mode 120000 index d8c9ad951ef..00000000000 --- a/src/guides/v2.4/ext-best-practices/phpstorm/code-inspection.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/phpstorm/code-inspection.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/code-inspection.md b/src/guides/v2.4/ext-best-practices/phpstorm/code-inspection.md new file mode 100644 index 00000000000..bfa745a1772 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/phpstorm/code-inspection.md @@ -0,0 +1,28 @@ +--- +group: extension-best-practices +title: Code inspection +functional_areas: + - Standards +--- + +### Web API XML service tag attributes inspections + +![]({{site.baseurl}}/common/images/phpstorm/service-tag-inspections-min.gif) + +### DI XML preference tag attributes inspections + +![]({{site.baseurl}}/common/images/phpstorm/preference-tag-inspections-min.gif) + +### DI XML type tag attributes inspections that related to the PHP/Magento types + +The `Type` tag inspections (in the di.xml files) detect empty values or invalid values where a Type values (class, interface, virtual type) are expected. + +![]({{site.baseurl}}/common/images/phpstorm/type-tag-inspections-1-min.gif) + +It also supports recursive inspection for `xsi:type="array"` arguments. + +![]({{site.baseurl}}/common/images/phpstorm/type-tag-inspections-2-min.gif) + +### DI XML plugin type attribute inspections + +![]({{site.baseurl}}/common/images/phpstorm/plugin-tag-inspections-min.gif) diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/installation.md b/src/guides/v2.4/ext-best-practices/phpstorm/installation.md deleted file mode 120000 index 00e4a464c34..00000000000 --- a/src/guides/v2.4/ext-best-practices/phpstorm/installation.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/phpstorm/installation.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/installation.md b/src/guides/v2.4/ext-best-practices/phpstorm/installation.md new file mode 100644 index 00000000000..895ad2cd56c --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/phpstorm/installation.md @@ -0,0 +1,31 @@ +--- +group: extension-best-practices +title: Installation +functional_areas: + - Standards +--- + +To install the Magento PHPStorm plugin: + +* Download the plugin from the [PHPStorm Marketplace](https://plugins.jetbrains.com/plugin/8024-magento-phpstorm). + + ![]({{site.baseurl}}/common/images/phpstorm/download-from-jetbrains.png) + +* Or alternatively, you can install it from your PHPStorm screen. Navigate to **Preferences** > **Plugins** and select Magento PHPStorm. + + ![]({{site.baseurl}}/common/images/phpstorm/install-through-phpstorm.png) + +After the installation, it is necessary to enable the integration with Magento: + +1. Go to **Preferences** > **Frameworks**. +1. Select the **Enable Magento Integration** checkbox. See [Install PHPStorm plugin](https://github.com/magento/magento2-phpstorm-plugin#installation) topic for more information. + +You also need to provide: + +* Magento installation path +* Adobe Commerce version (i.e., `2.4.1`) +* Default license name for new modules (by default, `Proprietary`) + +![]({{site.baseurl}}/common/images/phpstorm/enable-magento-integration.png) + +See the video tutorial [Using the Upgrade Compatibility Tool on PHP Storm](https://experienceleague.adobe.com/docs/commerce-learn/tutorials/upgrade/uct-phpstorm.html?lang=en) page for more information about the Magento PHPStorm plugin. diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/introduction.md b/src/guides/v2.4/ext-best-practices/phpstorm/introduction.md deleted file mode 120000 index ab9fbea2c6c..00000000000 --- a/src/guides/v2.4/ext-best-practices/phpstorm/introduction.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/phpstorm/introduction.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/introduction.md b/src/guides/v2.4/ext-best-practices/phpstorm/introduction.md new file mode 100644 index 00000000000..698d2e3f97c --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/phpstorm/introduction.md @@ -0,0 +1,16 @@ +--- +group: extension-best-practices +title: PHPStorm plugin +functional_areas: + - Standards +--- + +The PHPStorm plugin is a tool created by the community to optimize routine coding operations and improve the {{site.data.var.ee}} development experience. The plugin is compatible with the IntelliJ IDEA Ultimate and PhpStorm IDEs. The functionality includes {{site.data.var.ee}} specific code generation shortcuts, code inspections, autocomplete functionality for configuration files, MFTF tests, and RequireJS. + +Check the [Installation]({{site.baseurl}}/guides/v2.3/ext-best-practices/phpstorm/installation.html) topic for detailed steps. + +See the [Code generation]({{site.baseurl}}/guides/v2.3/ext-best-practices/phpstorm/code-generation.html) topic for more information. + +The PHPStorm plugin includes shortcuts for Functional Testing, Require JS mapping, GraphQL, Plugin declaration inspection, code generation, and many more. + +See the [Adding Code Inspections]({{site.baseurl}}/guides/v2.3/ext-best-practices/phpstorm/adding-code-inspections.html) topic for more information on static code analysis. diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/issue-reporting.md b/src/guides/v2.4/ext-best-practices/phpstorm/issue-reporting.md deleted file mode 120000 index 6aa53f7085e..00000000000 --- a/src/guides/v2.4/ext-best-practices/phpstorm/issue-reporting.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/phpstorm/issue-reporting.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/issue-reporting.md b/src/guides/v2.4/ext-best-practices/phpstorm/issue-reporting.md new file mode 100644 index 00000000000..2a0482f9368 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/phpstorm/issue-reporting.md @@ -0,0 +1,22 @@ +--- +group: extension-best-practices +title: Issue reporting +functional_areas: + - Standards +--- + +There is now an extension point for the errorHandler to integrate the plugin with the IDE's dialog to report fatal errors. + +* When an issue occurred click on the `See details and submit report` link for reporting an issue. + +* Fill the issue description and click on the `Report Me` button: + +![]({{site.baseurl}}/common/images/phpstorm/report-me.png) + +* Change the auto generated issue title to the proper one: + +![]({{site.baseurl}}/common/images/phpstorm/issue-title.png) + +* Fill the rest with available information about an issue (such as steps to reproduce, expected behaviour etc.) and click on the `Submit new issue` button: + +![]({{site.baseurl}}/common/images/phpstorm/issue-description.png) diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/new-features.md b/src/guides/v2.4/ext-best-practices/phpstorm/new-features.md deleted file mode 120000 index 7665da12170..00000000000 --- a/src/guides/v2.4/ext-best-practices/phpstorm/new-features.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/phpstorm/new-features.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/new-features.md b/src/guides/v2.4/ext-best-practices/phpstorm/new-features.md new file mode 100644 index 00000000000..a53dc4b3e3c --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/phpstorm/new-features.md @@ -0,0 +1,28 @@ +--- +group: extension-best-practices +title: New features +functional_areas: + - Standards +--- + +The following sections describe best practices for using the PHPStorm plugin. + +### JS and CSS support for Copy Magento Path action + +You can now copy the Magento Path for both JS and CSS files + +For JS files: + +![]({{site.baseurl}}/common/images/phpstorm/copy-js-path.png) + +For CSS files: + +![]({{site.baseurl}}/common/images/phpstorm/copy-css-path.png) + +### Changed the content of the generated plugin class + +![]({{site.baseurl}}/common/images/phpstorm/changed-plugin-generation-min.gif) + +### Use of hardcoded entity id value into the constant in all files generated by the Entity Creator + +![]({{site.baseurl}}/common/images/phpstorm/entity-id-used-as-constant.png) diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/uct-run-configuration.md b/src/guides/v2.4/ext-best-practices/phpstorm/uct-run-configuration.md deleted file mode 120000 index bcd2daf6d7c..00000000000 --- a/src/guides/v2.4/ext-best-practices/phpstorm/uct-run-configuration.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/phpstorm/uct-run-configuration.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/phpstorm/uct-run-configuration.md b/src/guides/v2.4/ext-best-practices/phpstorm/uct-run-configuration.md new file mode 100644 index 00000000000..610eba6844a --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/phpstorm/uct-run-configuration.md @@ -0,0 +1,56 @@ +--- +group: extension-best-practices +title: Run the Upgrade Compatibility Tool +functional_areas: + - Standards +--- + +Run Configurations are used to run internal and external processes from within IntelliJ Platform-based products. + +## Setup the Run Configuration + +See the [Run/Debug configurations topic](https://www.jetbrains.com/help/idea/run-debug-configuration.html) in the IntelliJ IDEA to understand the concept of a run configuration. + +The Run Configuration is a Graphical User Interface (GUI) for the {{site.data.var.uct}}. This allows the {{site.data.var.uct}} instance to be configured using Composer. We recommend that you install the {{site.data.var.uct}} in the current project. However, if the {{site.data.var.uct}} is located outside the current project, a message displays providing an optoin to download and install it in the current project. + +{:.bs-callout-warning} +The {{site.data.var.uct}} is an {{site.data.var.ee}} feature. You need your {{site.data.var.ee}} license key to install it. + +![]({{site.baseurl}}/common/images/phpstorm/uct-run-configuration-1-min.gif) + +When you create a new run configuration for a specific tool, create it from one of the dedicated configuration templates. Templates implement the startup logic and define the list of parameters and their default values. + +The {{site.data.var.uct}} Run Configuration template is located in the PHPStorm plugin menu, under **Run/Debug configurations** > **Add New Configuration** > **Upgrade Compatibility Tool**. + +![]({{site.baseurl}}/common/images/phpstorm/uct-run-configuration-template-position.png) + +These are the main components of the {{site.data.var.uct}} Run Configuration template: + +![]({{site.baseurl}}/common/images/phpstorm/uct-run-configuration-template-view.png) + +* *{{site.data.var.uct}} (UCT) executable*: Path where the {{site.data.var.uct}} executable script is located. Determined by the `bin/uct` path from the {{site.data.var.uct}} source root directory. +* *Project root*: Current PHPStorm plugin root directory. +* *Path*: Path to analize. Restricts the search to a specific folder. This is an optional field. +* *Coming version*: The {{site.data.var.ee}} targeted version. +* *Min issue level*: The minimum issue level to show in the report. Default is [WARNING]. This is an optional field. +* *Ignore current version compatibility issues*: use this option when you do not want to include known critical issues, errors and warnings in your {{site.data.var.uct}} report. This is an optional field. +* *Message*: Message that appears if the {{site.data.var.uct}} cannot be located for the current PHPStorm plugin project. +* *Link*: Link to install the {{site.data.var.uct}} for the current PHPStorm plugin project. + +See [Run](https://experienceleague.adobe.com/docs/commerce-operations/upgrade-guide/upgrade-compatibility-tool/run.html) topic for more information on these specific options of the {{site.data.var.uct}}. + +After you correctly configure the template, you can run the {{site.data.var.uct}} with a single click in your Run Configuration GUI. + +## Run the tool + +To run the {{site.data.var.uct}} click `UCT Run`. + +![]({{site.baseurl}}/common/images/phpstorm/uct-run-configuration-3-min.gif) + +The results are displayed in the console, including handy navigation to the compatibility issues in the code. + +The output of the tool is displayed in the PHPStorm console with the ability to click and navigate to the references: + +* Code that has an issue. +* Issue code description in the documentation. +* Report file. diff --git a/src/guides/v2.4/ext-best-practices/security/writing-secure-code.md b/src/guides/v2.4/ext-best-practices/security/writing-secure-code.md deleted file mode 120000 index 22bd18e9d0e..00000000000 --- a/src/guides/v2.4/ext-best-practices/security/writing-secure-code.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/security/writing-secure-code.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/security/writing-secure-code.md b/src/guides/v2.4/ext-best-practices/security/writing-secure-code.md new file mode 100644 index 00000000000..afd336fb36c --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/security/writing-secure-code.md @@ -0,0 +1,51 @@ +--- +group: extension-best-practices +subgroup: Security +title: Writing secure code +menu_title: Writing secure code +menu_order: 2100 +--- + +## Overview + +Using [PHP](https://glossary.magento.com/php) features that are known to be exploitable or non-secure can lead to remote code execution or weak cryptography. +As a developer, you should avoid using features that introduce vulnerabilities in your code. + +## PHP functions to avoid + +The following is a list of PHP functions that are known to be vulnerable and exploitable. +Avoid using these functions in your code. + +* [`eval`][0] - Using `eval` is considered bad practice because of its ability to [execute arbitrary PHP code][1]. +* [`serialize`][2]/[`unserialize`][3] - Attackers can create an exploit for these functions by passing a string with a serialized arbitrary object to the `unserialize` function to [run arbitrary code][4]. +* [`md5`][5] - The algorithm for this function is known to have [cryptographic weaknesses][6]. + You should never use this function for hashing passwords or any other sensitive data. +* [`srand`][7] - Using a predetermined number to seed the random number generator results in a [predictable sequence of numbers][8]. +* [`mt_srand`][9] - This function is a pseudo-random number generator (PRNG) and is [not cryptographically secure][10]. + +## Standard PHP library classes to avoid + +* [`ArrayObject`](http://php.net/manual/en/class.arrayobject.php) - Using `ArrayObject` class is not recommended because it contains `unserialize` method, which attackers can use to create an exploit. + + If you need to use the `ArrayObject` class, override the `serialize`/`unserialize` methods so that they use secure logic. + Convert objects into arrays to serialize them, and reconstruct the objects using arrays during unserialization. + + You can use [Serialize Library][12] in framework for a secure way of serializing/unserializing data. + +## Related Topics + +* [Serialize Library][12] + +[0]:http://php.net/manual/en/function.eval.php +[1]:https://www.owasp.org/index.php/PHP_Security_Cheat_Sheet#Code_Injection +[2]:http://php.net/manual/en/function.serialize.php +[3]:http://php.net/manual/en/function.unserialize.php +[4]:https://www.owasp.org/index.php/PHP_Object_Injection +[5]:http://php.net/manual/en/function.md5.php +[6]:https://www.owasp.org/index.php/Guide_to_Cryptography#Hashes +[7]:http://php.net/manual/en/function.srand.php +[8]:http://programmers.stackexchange.com/questions/76229/predicting-the-output-of-phps-rand +[9]:http://php.net/manual/en/function.mt-rand.php +[10]:http://phpsecurity.readthedocs.io/en/latest/Insufficient-Entropy-For-Random-Values.html +[11]:http://php.net/manual/en/class.arrayobject.php +[12]: {{ page.baseurl }}/extension-dev-guide/framework/serializer.html "Serialize Library" diff --git a/src/guides/v2.4/ext-best-practices/storefront/storefront-best-practices.md b/src/guides/v2.4/ext-best-practices/storefront/storefront-best-practices.md deleted file mode 120000 index db605b33e9a..00000000000 --- a/src/guides/v2.4/ext-best-practices/storefront/storefront-best-practices.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/storefront/storefront-best-practices.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/storefront/storefront-best-practices.md b/src/guides/v2.4/ext-best-practices/storefront/storefront-best-practices.md new file mode 100644 index 00000000000..f42ed96fb37 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/storefront/storefront-best-practices.md @@ -0,0 +1,36 @@ +--- +group: extension-best-practices +title: Storefront UI best practices +functional_areas: + - Frontend + - Theme + - Standards +--- + +The [storefront](https://glossary.magento.com/storefront) theme is the front facing interface for a Magento application that can be customized through a [theme extension]({{ page.baseurl }}/frontend-dev-guide/themes/theme-overview.html). We suggest adopting the following best practices to avoid common problems we have seen other developers make while making a [theme](https://glossary.magento.com/theme) [extension](https://glossary.magento.com/extension). + +### Clear your cache periodically + +Forgetting to clear or disable caching can cause a lot of development headache. Visual spot checks on rendered content are unreliable when the content being displayed is retrieved from the [cache](https://glossary.magento.com/cache). We recommend clearing your cache before doing visual checks for your theme to make sure the content displayed is correct. + +You can manage your cache in the [Admin](https://glossary.magento.com/admin) section under **System** > Tools > **Cache Management**. + +**Recommended Reading:** + +* [Clear directories during development]({{ page.baseurl }}/howdoi/php/php_clear-dirs.html) + +### Consider different resolutions/devices + +When developing your theme extension, you should check how it looks using different resolutions or devices. We recommend you apply [responsive web design(RWD)](https://en.wikipedia.org/wiki/Responsive_web_design) concepts to optimize the look and feel of your theme on different devices and resolutions. To help you with this task, both [Chrome](https://developer.chrome.com/devtools) and [Firefox](https://developer.mozilla.org/en-US/docs/Tools) web browsers have built-in developer tools that allow you to view your theme under different resolutions. + +**Recommended Reading:** + +* [How to make your theme responsive and mobile]({{ page.baseurl }}/frontend-dev-guide/responsive-web-design/rwd_overview.html) + +### Inherit and customize + +There is a lot of work in building a theme extension for Magento from scratch. This is why we recommend you inherit and customize an existing theme. Magento comes with both Blank and Luma themes after initial install. You can leverage the work already done to make those two themes responsive by setting one of them as your theme's parent. + +**Recommended Reading:** + +* [Theme inheritance]({{ page.baseurl }}/frontend-dev-guide/themes/theme-inherit.html) diff --git a/src/guides/v2.4/ext-best-practices/tutorials/copy-fieldsets.md b/src/guides/v2.4/ext-best-practices/tutorials/copy-fieldsets.md deleted file mode 120000 index 9680a32316b..00000000000 --- a/src/guides/v2.4/ext-best-practices/tutorials/copy-fieldsets.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/tutorials/copy-fieldsets.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/tutorials/copy-fieldsets.md b/src/guides/v2.4/ext-best-practices/tutorials/copy-fieldsets.md new file mode 100644 index 00000000000..01dec00f66f --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/tutorials/copy-fieldsets.md @@ -0,0 +1,179 @@ +--- +group: extension-best-practices +subgroup: Tutorials +title: Copying fieldsets +menu_title: Copying fieldsets +menu_order: 1000 +functional_areas: + - Standards +--- + +## Overview + +In this tutorial, you will learn to copy custom data from a [quote](https://glossary.magento.com/quote) object to an order object using the [Magento/Framework/DataObject/Copy][0] class. + +## Step 1: Define your attributes {#step-1} + +The following code defines a simple [extension attribute][1] named `demo` for the Cart and Order objects. + +**etc/extension_attributes.xml:** + +```xml + + + + + + + + +``` + +## Step 2: Configure the fieldset {#step-2} + +The following code adds the `demo` field to the `sales_convert_quote` fieldset with the `to_order` aspect. +The code snippet in the next step uses the name of the fieldset and aspect to specify which fields to copy. + +**etc/fieldset.xml:** + +The following example shows how to copy `sales_convert_quote`.`demo` to `sales_order`.`demo`. + +```xml + + +
    + + + +
    +
    +
    +``` + +Use the `targetField` attribute to specify the destination field. The following example shows how to copy `sales_convert_quote`.`demo` to `sales_order`.`order_demo`. + +```xml + + +
    + + + +
    +
    +
    +``` + +Define a new `aspect` if you need to copy a field of a source table into multiple fields in a destination table. + +The following example shows how to copy `sales_convert_quote`.`demo` into + +- `sales_order`.`demo` +- `sales_order`.`order_demo` + +```xml + + +
    + + + + +
    +
    +
    +``` + +## Step 3: Copy the fieldset {#step-3} + +For copying the fieldset, we'll observe the `sales_model_service_quote_submit_before` event by using the following code in our `etc/events.xml`: + +```xml + + + + + +``` + +The following code snippets highlight the code pieces needed to copy a fieldset using the `\Magento\Framework\DataObject\Copy` class. + +```php +objectCopyService = $objectCopyService; + ... + } + + /** + * @param Observer $observer + */ + public function execute(Observer $observer) + { + /* @var Order $order */ + $order = $observer->getEvent()->getData('order'); + /* @var Quote $quote */ + $quote = $observer->getEvent()->getData('quote'); + + $this->objectCopyService->copyFieldsetToTarget('sales_convert_quote', 'to_order', $quote, $order); + ... + + return $this; + } +} +``` + +In the code, an instance of the `Copy` class is obtained from the constructor using [dependency injection][2]. +The `copyFieldsetToTarget` function call with the `$quote` and `$order` parameters copies the fieldset for the two objects. + +## Step 4: Compile and cache clean + +Compile the code with this command: + +```bash +bin/magento setup:di:compile +``` + +and clean the cache with this command: + +```bash +bin/magento cache:clean +``` + +[0]:{{ site.mage2bloburl }}/{{ page.guide_version }}/lib/internal/Magento/Framework/DataObject/Copy.php +[1]:{{ page.baseurl }}/extension-dev-guide/attributes.html +[2]:{{ page.baseurl }}/extension-dev-guide/depend-inj.html diff --git a/src/guides/v2.4/ext-best-practices/tutorials/create-access-control-list-rule.md b/src/guides/v2.4/ext-best-practices/tutorials/create-access-control-list-rule.md deleted file mode 120000 index 5cc3aadbaf2..00000000000 --- a/src/guides/v2.4/ext-best-practices/tutorials/create-access-control-list-rule.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/tutorials/create-access-control-list-rule.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/tutorials/create-access-control-list-rule.md b/src/guides/v2.4/ext-best-practices/tutorials/create-access-control-list-rule.md new file mode 100755 index 00000000000..d73c26cf1cf --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/tutorials/create-access-control-list-rule.md @@ -0,0 +1,184 @@ +--- +group: extension-best-practices +title: Creating an Access Control List (ACL) rule +contributor_name: Ziffity +contributor_link: https://www.Ziffity.com/ +--- + +Access Control List (ACL) rules allow an admin to limit the permissions of users in Magento. For example, you can use ACL rules to authorize the users to access menus, controllers, API endpoints and conditionally render [layout](https://glossary.magento.com/layout) [blocks](https://glossary.magento.com/block). + +In this tutorial, we are creating four custom resources (Custom Menu, Create, Delete, View), then creating a role that has access to these resources, and taking steps to restrict access by four entities (Admin users, controllers, web APIs and layout block). + +## Step 1. Define the custom resources + +1. Create the `etc/acl.xml` file in your module. This file adds the custom resources in resource tree. + + ```xml + + + + + + + + + + + + + + + + + ``` + + | Attribute | Description | + | --------- | ----------- | + | `id` | Unique string. Should be in the format `Vendor_ModuleName::resourceName` | + | `title` | Title which is displayed in the menu bar | + | `sortOrder` | Position in which menu is displayed | + +1. Clean the cache by clicking **System** > **Cache Management** > **Flush Magento Cache** or by entering the following command: + + ```bash + bin/magento cache:clean + ``` + +1. Navigate to **System** > Permissions > **User Roles**. + +1. After clicking the **Add New Role** button, enter values for **Role Name** and **Your Password**. + +1. Then, click a Role Resources tab and select **Resource Access as Custom**. + + ![Resource access as custom]({{ site.baseurl }}/common/images/ext-best-practices/resource-access-custom-create-acl-rule.png) + +1. Select the **Custom Menu**, **Create**, and **Delete** resources and save the role. + + ![Resource tree]({{ site.baseurl }}/common/images/ext-best-practices/role-resources-create-acl-rule.png) + +## Step 2. Restrict access to Admin users + +### Restrict the admin menu + +In your module, create the `etc/adminhtml/menu.xml` file. This file defines a menu that will be hidden from unauthorized users. The `resource` attributes in the `add` nodes determine which resource each action accesses. + +```xml + + + + + + + + + +``` + +| Attribute | Description | +| --------- | ----------- | +| `id` | Unique string. Should be in the format: `Vendor_ModuleName::resourceName` | +| `title` | Title which is displayed in menu bar| +| `module` | Module which containing the current menu | +| `sortOrder` | Position in which menu to be displayed | +| `parent` | The another menu which is parent of current menu | +| `action` | Url of the page which needs to be displayed after clicking the menu. It should be in following format: `front_name/controller_path/action` | +| `resource` | ACL rule to restrict the access | + +Clean the cache by clicking **System** > **Cache Management** > **Flush Magento Cache** or by entering the following command: + +```bash +bin/magento cache:clean +``` + +The menu displays as follows: + +![custom menu]({{ site.baseurl }}/common/images/ext-best-practices/custom_menu.jpg) + +### Restrict admin controllers + +We can restrict the access to admin controllers by setting the `ADMIN_RESOURCE` constant. + +Add the following to your module's `Controller/Adminhtml/Create/Index.php` file: + +```php +const ADMIN_RESOURCE = 'Vendor_MyModule::create' +``` + +Add the following to your module's `Controller/Adminhtml/Delete/Index.php` file: + +```php +const ADMIN_RESOURCE = 'Vendor_MyModule::delete'; +``` +If the user does not have permission, the action page displays an "Access Denied" message. + +### Content restrictions for admin users + +With the ACL it is also possible to [render layout blocks dynamically]({{ page.baseurl }}/frontend-dev-guide/layouts/xml-manage.html#ref_config_block) on the page. + +It is enough to set the block's value for `aclResource` attribute: + +```xml + + + +``` + +The `view/adminhtml/layout/custommenu_view_index.xml` example file below contains two blocks that display information to the end-user, one of which is accessible only to users with ACL `Vendor_MyModule::view_additional` permissions. + +```xml + + + + + View + + + + + + + Page Content + + + + + - additional + + + + + +``` + +When the ACL resource for `Vendor_ModuleName::view_additional` is enabled, the result is: + +![admin page full content]({{ site.baseurl }}/common/images/ext-best-practices/acl-admin-page-content-full-access.jpg) + +When the ACL resource is disabled, the content on the page differs: + +![admin page content limited]({{ site.baseurl }}/common/images/ext-best-practices/acl-admin-limited-page-content.jpg) + +## Step 3. Restrict web API access + +We can restrict users from accessing API endpoints by using the ACL rule. By creating a Web API configuration file (`etc/webapi.xml`), the rules defined in `acl.xml` can restrict the access to API endpoints. + +```xml + + + + + + + + + +``` + +### Related topics + +* [Creating a Magento admin page]({{ page.baseurl }}/ext-best-practices/extension-coding/example-module-adminpage.html) + +* [Authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication.html) + +* [Layout block dynamic visibility using ACL Resource]({{ page.baseurl }}/frontend-dev-guide/layouts/xml-manage.html#ref_config_block) diff --git a/src/guides/v2.4/ext-best-practices/tutorials/create-integration-with-api.md b/src/guides/v2.4/ext-best-practices/tutorials/create-integration-with-api.md deleted file mode 120000 index f364ed542eb..00000000000 --- a/src/guides/v2.4/ext-best-practices/tutorials/create-integration-with-api.md +++ /dev/null @@ -1 +0,0 @@ -../../../../guides/v2.3/ext-best-practices/tutorials/create-integration-with-api.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/tutorials/create-integration-with-api.md b/src/guides/v2.4/ext-best-practices/tutorials/create-integration-with-api.md new file mode 100644 index 00000000000..f9e1d3ba4b1 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/tutorials/create-integration-with-api.md @@ -0,0 +1,169 @@ +--- +group: extension-best-practices +title: Creating an integration with an external API +contributor_name: Atwix +contributor_link: https://www.atwix.com/ +--- + +This tutorial shows you how to create an integration with an external API using [GuzzleHttp](http://docs.guzzlephp.org/en/stable/quickstart.html) library, that is included into Magento package. + +Guzzle is a PHP HTTP client that makes it easy to create some integrations with some web services. +Its implementation code is more simpler, cleaner and readable, in comparision with cURL. + +GuzzleHttp uses cURL by default, but it can use any HTTP client that you want other than cURL like PHP's stream wrapper or sockets, in case `curl` isn't installed on your Web Server. + +{:.bs-callout-info} +It's much easier to cover a GuzzleHttp implementation by [Unit Tests]({{ page.baseurl }}/test/unit/writing_testable_code.html), as you're able to mock the HTTP requests. + +## Request options + +| Option | Description | Type | +| --- | --- | --- | +| `method` | HTTP method, any of `GET`, `POST`, `PUT`, `DELETE` | String | +| `uri` | The API endpoint that needs to be called | String | +| `params` | A list of parameters that needs to be passed to the API | Array | + +## Create a Github API integration + +In the following example, we're using the [Github API](https://api.github.com/) as web service, and will fetch some data regarding the Magento 2 Git repository. + +```php +clientFactory = $clientFactory; + $this->responseFactory = $responseFactory; + } + + /** + * Fetch some data from API + */ + public function execute(): void + { + $repositoryName = 'magento/magento2'; + $response = $this->doRequest(static::API_REQUEST_ENDPOINT . $repositoryName); + $status = $response->getStatusCode(); // 200 status code + $responseBody = $response->getBody(); + $responseContent = $responseBody->getContents(); // here you will have the API response in JSON format + // Add your logic using $responseContent + } + + /** + * Do API request with provided params + * + * @param string $uriEndpoint + * @param array $params + * @param string $requestMethod + * + * @return Response + */ + private function doRequest( + string $uriEndpoint, + array $params = [], + string $requestMethod = Request::HTTP_METHOD_GET + ): Response { + /** @var Client $client */ + $client = $this->clientFactory->create(['config' => [ + 'base_uri' => self::API_REQUEST_URI + ]]); + + try { + $response = $client->request( + $requestMethod, + $uriEndpoint, + $params + ); + } catch (GuzzleException $exception) { + /** @var Response $response */ + $response = $this->responseFactory->create([ + 'status' => $exception->getCode(), + 'reason' => $exception->getMessage() + ]); + } + + return $response; + } +} +``` + +## Result + +As result, you get all the available information regarding the Magento repository. + +```json +{ + ... + "name": "magento2", + "full_name": "magento/magento2", + "private": false, + "html_url": "https://github.com/magento/magento2", + "description": "All Submissions you make to Magento Inc. (\"Magento\") through GitHub are subject to the following terms and conditions: (1) You grant Magento a perpetual, worldwide, non-exclusive, no charge, royalty free, irrevocable license under your applicable copyrights and patents to reproduce, prepare derivative works of, display, publically perform, sublicense and distribute any feedback, ideas, code, or other information (“Submission\") you submit through GitHub. (2) Your Submission is an original work of authorship and you are the owner or are legally entitled to grant the license stated above. (3) You agree to the Contributor License Agreement found here: https://github.com/magento/magento2/blob/master/CONTRIBUTOR_LICENSE_AGREEMENT.html", + "fork": false, + "url": "https://api.github.com/repos/magento/magento2", + "homepage": "http://www.magento.com", + "size": 559209, + "stargazers_count": 8379, + "watchers_count": 8379, + "language": "PHP", + "has_issues": true, + "has_projects": false, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 7405, + "archived": false, + "disabled": false, + "open_issues_count": 1535, + "forks": 7405, + "open_issues": 1535, + "watchers": 8379, + "default_branch": "2.4-develop", + "subscribers_count": 1421, + ... +} +``` diff --git a/src/guides/v2.4/ext-best-practices/tutorials/custom-import-entity.md b/src/guides/v2.4/ext-best-practices/tutorials/custom-import-entity.md deleted file mode 120000 index 47dc120fa76..00000000000 --- a/src/guides/v2.4/ext-best-practices/tutorials/custom-import-entity.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/tutorials/custom-import-entity.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/tutorials/custom-import-entity.md b/src/guides/v2.4/ext-best-practices/tutorials/custom-import-entity.md new file mode 100644 index 00000000000..f99d4e8d5bb --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/tutorials/custom-import-entity.md @@ -0,0 +1,465 @@ +--- +group: extension-best-practices +title: Custom import entity +contributor_name: Atwix +contributor_link: https://www.atwix.com/ +--- + +This tutorial shows you how to extend the [Magento/ImportExport/Model/Import/Entity/AbstractEntity][0] class to import data into your custom module's table. +The current import entities can be found in **System** > **Import**: + +- Advanced Pricing +- Products +- Customers and Addresses (single file) +- Customers Main File +- Customer Addresses + +To begin, suppose we have a custom table with the following structure: + +| entity_id | name | duration | +| --- | --- | --- | +| | | | + +## Step 1: Adding a new entity type + +Declare the new import entity: + +> `etc/import.xml` + +```xml + + + +``` + +Extending the **Magento_ImportExport** module, we create a dependency to it in the `module.xml` file. + +> `etc/module.xml` + +```xml +... + + + +... +``` + +## Step 2: Defining the import model + +As we extend the [Magento/ImportExport/Model/Import/Entity/AbstractEntity][0], we implement the following abstract methods: + +- `_importData` - Import data rows +- `getEntityTypeCode` - EAV entity type code getter +- `validateRow` - Validating the row + +> `ExampleCorp/Learning/Model/Import/Courses.php` + +{% collapsible File content for Courses.php %} + +```php +namespace ExampleCorp\Learning\Model\Import; + +use Exception; +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\Json\Helper\Data as JsonHelper; +use Magento\ImportExport\Helper\Data as ImportHelper; +use Magento\ImportExport\Model\Import; +use Magento\ImportExport\Model\Import\Entity\AbstractEntity; +use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface; +use Magento\ImportExport\Model\ResourceModel\Helper; +use Magento\ImportExport\Model\ResourceModel\Import\Data; + +/** + * Class Courses + */ +class Courses extends AbstractEntity +{ + const ENTITY_CODE = 'learning'; + const TABLE = 'learning_courses'; + const ENTITY_ID_COLUMN = 'entity_id'; + + /** + * If we should check column names + */ + protected $needColumnCheck = true; + + /** + * Need to log in import history + */ + protected $logInHistory = true; + + /** + * Permanent entity columns. + */ + protected $_permanentAttributes = [ + 'entity_id' + ]; + + /** + * Valid column names + */ + protected $validColumnNames = [ + 'entity_id', + 'name', + 'duration' + ]; + + /** + * @var AdapterInterface + */ + protected $connection; + + /** + * @var ResourceConnection + */ + private $resource; + + /** + * Courses constructor. + * + * @param JsonHelper $jsonHelper + * @param ImportHelper $importExportData + * @param Data $importData + * @param ResourceConnection $resource + * @param Helper $resourceHelper + * @param ProcessingErrorAggregatorInterface $errorAggregator + */ + public function __construct( + JsonHelper $jsonHelper, + ImportHelper $importExportData, + Data $importData, + ResourceConnection $resource, + Helper $resourceHelper, + ProcessingErrorAggregatorInterface $errorAggregator + ) { + $this->jsonHelper = $jsonHelper; + $this->_importExportData = $importExportData; + $this->_resourceHelper = $resourceHelper; + $this->_dataSourceModel = $importData; + $this->resource = $resource; + $this->connection = $resource->getConnection(ResourceConnection::DEFAULT_CONNECTION); + $this->errorAggregator = $errorAggregator; + } + + /** + * Entity type code getter. + * + * @return string + */ + public function getEntityTypeCode() + { + return static::ENTITY_CODE; + } + + /** + * Get available columns + * + * @return array + */ + public function getValidColumnNames(): array + { + return $this->validColumnNames; + } + + /** + * Row validation + * + * @param array $rowData + * @param int $rowNum + * + * @return bool + */ + public function validateRow(array $rowData, $rowNum): bool + { + if (isset($this->_validatedRows[$rowNum])) { + return !$this->getErrorAggregator()->isRowInvalid($rowNum); + } + + $this->_validatedRows[$rowNum] = true; + + return !$this->getErrorAggregator()->isRowInvalid($rowNum); + } + + /** + * Import data + * + * @return bool + * + * @throws Exception + */ + protected function _importData(): bool + { + switch ($this->getBehavior()) { + case Import::BEHAVIOR_DELETE: + $this->deleteEntity(); + break; + case Import::BEHAVIOR_REPLACE: + $this->saveAndReplaceEntity(); + break; + case Import::BEHAVIOR_APPEND: + $this->saveAndReplaceEntity(); + break; + } + + return true; + } + + /** + * Delete entities + * + * @return bool + */ + private function deleteEntity(): bool + { + $rows = []; + while ($bunch = $this->_dataSourceModel->getNextBunch()) { + foreach ($bunch as $rowNum => $rowData) { + $this->validateRow($rowData, $rowNum); + + if (!$this->getErrorAggregator()->isRowInvalid($rowNum)) { + $rowId = $rowData[static::ENTITY_ID_COLUMN]; + $rows[] = $rowId; + } + + if ($this->getErrorAggregator()->hasToBeTerminated()) { + $this->getErrorAggregator()->addRowToSkip($rowNum); + } + } + } + + if ($rows) { + return $this->deleteEntityFinish(array_unique($rows)); + } + + return false; + } + + /** + * Save and replace entities + * + * @return void + */ + private function saveAndReplaceEntity() + { + $behavior = $this->getBehavior(); + $rows = []; + while ($bunch = $this->_dataSourceModel->getNextBunch()) { + $entityList = []; + + foreach ($bunch as $rowNum => $row) { + if (!$this->validateRow($row, $rowNum)) { + continue; + } + + if ($this->getErrorAggregator()->hasToBeTerminated()) { + $this->getErrorAggregator()->addRowToSkip($rowNum); + + continue; + } + + $rowId = $row[static::ENTITY_ID_COLUMN]; + $rows[] = $rowId; + $columnValues = []; + + foreach ($this->getAvailableColumns() as $columnKey) { + $columnValues[$columnKey] = $row[$columnKey]; + } + + $entityList[$rowId][] = $columnValues; + $this->countItemsCreated += (int) !isset($row[static::ENTITY_ID_COLUMN]); + $this->countItemsUpdated += (int) isset($row[static::ENTITY_ID_COLUMN]); + } + + if (Import::BEHAVIOR_REPLACE === $behavior) { + if ($rows && $this->deleteEntityFinish(array_unique($rows))) { + $this->saveEntityFinish($entityList); + } + } elseif (Import::BEHAVIOR_APPEND === $behavior) { + $this->saveEntityFinish($entityList); + } + } + } + + /** + * Save entities + * + * @param array $entityData + * + * @return bool + */ + private function saveEntityFinish(array $entityData): bool + { + if ($entityData) { + $tableName = $this->connection->getTableName(static::TABLE); + $rows = []; + + foreach ($entityData as $entityRows) { + foreach ($entityRows as $row) { + $rows[] = $row; + } + } + + if ($rows) { + $this->connection->insertOnDuplicate($tableName, $rows, $this->getAvailableColumns()); + + return true; + } + + return false; + } + } + + /** + * Delete entities + * + * @param array $entityIds + * + * @return bool + */ + private function deleteEntityFinish(array $entityIds): bool + { + if ($entityIds) { + try { + $this->countItemsDeleted += $this->connection->delete( + $this->connection->getTableName(static::TABLE), + $this->connection->quoteInto(static::ENTITY_ID_COLUMN . ' IN (?)', $entityIds) + ); + + return true; + } catch (Exception $e) { + return false; + } + } + + return false; + } + + /** + * Get available columns + * + * @return array + */ + private function getAvailableColumns(): array + { + return $this->validColumnNames; + } +} +``` + +{% endcollapsible %} + +### Data validation + +Sometimes, there is a need to validate data before inserting it into table. To do that, we have to add all our validation rules to `validateRow` method. + +```php +/** + * Row validation + * + * @param array $rowData + * @param int $rowNum + * + * @return bool + */ +public function validateRow(array $rowData, $rowNum): bool +{ + $name = $rowData['name'] ?? ''; + $duration = (int) $rowData['duration'] ?? 0; + + if (!$name) { + $this->addRowError('NameIsRequired', $rowNum); + } + + if (!$duration) { + $this->addRowError('DurationIsRequired', $rowNum); + } + + if (isset($this->_validatedRows[$rowNum])) { + return !$this->getErrorAggregator()->isRowInvalid($rowNum); + } + + $this->_validatedRows[$rowNum] = true; + + return !$this->getErrorAggregator()->isRowInvalid($rowNum); +} +``` + +We need to instantiate our new validation rules: + +```php +/** + * Init Error Messages + */ +private function initMessageTemplates() +{ + $this->addMessageTemplate( + 'NameIsRequired', + __('The name cannot be empty.') + ); + $this->addMessageTemplate( + 'DurationIsRequired', + __('Duration should be greater than 0.') + ); +} +``` + +And finally, call the `initMessageTemplates` method within `__construct` method: + +```php +public function __construct( + ... +) { + ... + + $this->initMessageTemplates(); +} +``` + +The validation rules will be checking for a required **name** and a greater than 0 **duration**. + +![Validating Data]({{ site.baseurl }}/common/images/ext-best-practices/import-validation.png) + +## Step 3. Providing the sample file + +To add the ability to download a sample csv file for our new entity, create the following file: + +``ExampleCorp/Learning/Files/Sample/learning.csv`` + +With the following content: + +```text +entity_id,name,duration +,"First Course",90 +,"Second Course",120 +``` + +{:.bs-callout-info} +When updating the table's data, you must provide the `entity_id` value for each row. + +Next, register the sample file for our entity. + +> `etc/di.xml` + +```xml + + + + + ExampleCorp_Learning + + + + +``` + +## Result + +As result, the new Entity Type and the sample CSV are available: + +![Import Entity]({{ site.baseurl }}/common/images/ext-best-practices/import-entity.png) + +[0]: {{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php diff --git a/src/guides/v2.4/ext-best-practices/tutorials/custom-widget.md b/src/guides/v2.4/ext-best-practices/tutorials/custom-widget.md deleted file mode 120000 index 1733ad1af29..00000000000 --- a/src/guides/v2.4/ext-best-practices/tutorials/custom-widget.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/tutorials/custom-widget.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/tutorials/custom-widget.md b/src/guides/v2.4/ext-best-practices/tutorials/custom-widget.md new file mode 100644 index 00000000000..d965372b6cd --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/tutorials/custom-widget.md @@ -0,0 +1,172 @@ +--- +group: extension-best-practices +title: Custom widget +contributor_name: Atwix +contributor_link: https://www.atwix.com/ +--- + +Widgets provide powerful features in Magento 2, that are used to add dynamic or static content to store's pages. +Here are the widgets that are available by default: + +- CMS Page Link +- CMS Static Block +- Catalog Category Link +- Catalog New Products List +- Catalog Product Link +- Catalog Products List +- Orders and Returns +- Recently Compared Products +- Recently Viewed Products + +## Configuration options + +| Option | Description | Type | Required | +| -------- | --------------------- | --------------------- | ---- | +| `label` | The name of the widget | String | `Yes` | +| `description` | Contains a concise explanation of the widget's purpose | String | `Yes` | +| `parameters` | A list of widget's options | Object | `No` | +| `containers` | A list of layout containers, where the widget may be injected | Object | `No` | + +This tutorial shows you how to create and insert your own widget on the frontend. + +## Step 1. Declaring the widget + +> `etc/widget.xml` + +```xml + + + + This is a test widget!!! + + ... + + + ... + + + +``` + +We need to also add a dependency to **Magento_Widget** in the `module.xml` file. + +> `etc/module.xml` + +```xml +... + + + +... +``` + +### Step 2. Adding widget parameters + +As a parameter, we are able to use any of these field types: + +- text +- select +- multiselect +- block + +Add a text and a select field: + +```xml + + + ... + + + + + + + + + + + + + + + +``` + +### Step 3. Check the widget + +Run the following commands to apply the module dependency declared in `module.xml`. + +```bash +bin/magento module:disable Vendor_Module +``` + +```bash +bin/magento module:enable Vendor_Module +``` + +where `Vendor_Module` is replaced with the module name. + +After clearing the cache, the new widget `My New Widget` should be available. + +![Custom Widget]({{ site.baseurl }}/common/images/ext-best-practices/custom-widget.png) + +To add it to the homepage, below the page content: + +After selecting the widget type and the layout location, we should be able to see the widget's options. + +![Widget Options]({{ site.baseurl }}/common/images/ext-best-practices/custom-widget-options.png) + +### Step 4. Create the block + +Create the block class that we provided on the widget's initialization, responsible for +rendering it on the frontend. + +> `ExampleCorp/Learning/Block/Widget/Test` + +```php +namespace ExampleCorp\Learning\Block\Widget; + +use Magento\Framework\View\Element\Template; +use Magento\Widget\Block\BlockInterface; + +class Test extends Template implements BlockInterface +{ + protected $_template = "widget/test.phtml"; +} +``` + +### Step 5. Create the template + +And finally, create the template that will be used for showing the widget's data on the frontend. + +> `ExampleCorp/Learning/view/frontend/templates/widget/test.phtml` + +```php + +

    escapeHtml($block->getData('title')) ?>

    +

    escapeHtml(__('Size:')) ?> escapeHtml($block->getData('size')) ?>

    +``` + +### Step 6. Clean Cache + +Clean the Magento cache with the following command: + +```bash +bin/magento cache:clean +``` + +## Result + +The widget is now shown on the frontend. + +![Widget Options]({{ site.baseurl }}/common/images/ext-best-practices/custom-widget-result.png) diff --git a/src/guides/v2.4/ext-best-practices/tutorials/dynamic-row-system-config.md b/src/guides/v2.4/ext-best-practices/tutorials/dynamic-row-system-config.md deleted file mode 120000 index 69ae182c04c..00000000000 --- a/src/guides/v2.4/ext-best-practices/tutorials/dynamic-row-system-config.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/ext-best-practices/tutorials/dynamic-row-system-config.md \ No newline at end of file diff --git a/src/guides/v2.4/ext-best-practices/tutorials/dynamic-row-system-config.md b/src/guides/v2.4/ext-best-practices/tutorials/dynamic-row-system-config.md new file mode 100644 index 00000000000..9074c1283b1 --- /dev/null +++ b/src/guides/v2.4/ext-best-practices/tutorials/dynamic-row-system-config.md @@ -0,0 +1,257 @@ +--- +group: extension-best-practices +subgroup: 02_Extension-Coding +title: Creating a dynamic row system config +menu_title: Creating a dynamic row system config +menu_order: 1010 +functional_areas: + - Standards +--- + +This tutorial shows you how to add a new dynamic rows system configuration in the [Magento admin](https://glossary.magento.com/magento-admin), by extending the [Magento/Config/Block/System/Config/Form/Field/FieldArray/AbstractFieldArray][0] class. + +## Step 1: Add a new system field + +> `etc/adminhtml/system.xml` + +```xml + + +
    + + + + + Vendor\Module\Block\Adminhtml\Form\Field\Ranges + Magento\Config\Model\Config\Backend\Serialized\ArraySerialized + + +
    +
    +
    +``` + +This code adds a new system configuration in **STORES** > Settings > **Configuration** > GENERAL > **General** > **Quantity Ranges**. + +## Step 2: Create the block class to describe custom field columns + +> `File: app/code/Vendor/Module/Block/Adminhtml/Form/Field/Ranges.php` + +```php +addColumn('from_qty', ['label' => __('From'), 'class' => 'required-entry']); + $this->addColumn('to_qty', ['label' => __('To'), 'class' => 'required-entry']); + $this->addColumn('price', ['label' => __('Price'), 'class' => 'required-entry']); + $this->addColumn('tax', [ + 'label' => __('Tax'), + 'renderer' => $this->getTaxRenderer() + ]); + $this->_addAfter = false; + $this->_addButtonLabel = __('Add'); + } + + /** + * Prepare existing row data object + * + * @param DataObject $row + * @throws LocalizedException + */ + protected function _prepareArrayRow(DataObject $row): void + { + $options = []; + + $tax = $row->getTax(); + if ($tax !== null) { + $options['option_' . $this->getTaxRenderer()->calcOptionHash($tax)] = 'selected="selected"'; + } + + $row->setData('option_extra_attrs', $options); + } + + /** + * @return TaxColumn + * @throws LocalizedException + */ + private function getTaxRenderer() + { + if (!$this->taxRenderer) { + $this->taxRenderer = $this->getLayout()->createBlock( + TaxColumn::class, + '', + ['data' => ['is_render_to_js_template' => true]] + ); + } + return $this->taxRenderer; + } +} +``` + +This block prepares the desired columns for inclusion in the new configuration. + +## Step 3: Create the block class to describe a column with drop-down input + +> `File: app/code/Vendor/Module/Block/Adminhtml/Form/Field/TaxColumn.php` + +```php + element + * + * @param string $value + * @return $this + */ + public function setInputName($value) + { + return $this->setName($value); + } + + /** + * Set "id" for + +image_de +``` + + {:.bs-callout-info} +The original templates of all form field types are located in the `app/code/Magento/Ui/view/base/web/templates/form/element` directory. + +## Step 2: Specify the new template in layout {#layout} + +In your custom module directory, create a new `/view/frontend/layout/checkout_index_index.xml` file. +In this file, add content similar to the following: + +```xml + + + + + + + + + + + + + + + + + + + + + + + %Vendor_Module%/form/element/%your_template% + + + + + + + + + + + + + + + + + + +``` + +## Step 3: Clear files after modification {#modify} + +If you modify your custom `.html` template after it was applied on the store pages, the changes will not apply until you do the following: + +1. Delete all files in the `pub/static/frontend` and `var/view_preprocessed` directories. +1. Reload the pages. diff --git a/src/guides/v2.4/howdoi/checkout/checkout_form.md b/src/guides/v2.4/howdoi/checkout/checkout_form.md deleted file mode 120000 index f8398000a12..00000000000 --- a/src/guides/v2.4/howdoi/checkout/checkout_form.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/howdoi/checkout/checkout_form.md \ No newline at end of file diff --git a/src/guides/v2.4/howdoi/checkout/checkout_form.md b/src/guides/v2.4/howdoi/checkout/checkout_form.md new file mode 100644 index 00000000000..eeb90c6bb1f --- /dev/null +++ b/src/guides/v2.4/howdoi/checkout/checkout_form.md @@ -0,0 +1,289 @@ +--- +layout: tutorial +group: how-do-i +subgroup: +title: Add a new input form to checkout +subtitle: Customize Checkout +menu_order: 9 +level3_subgroup: checkout-tutorial +functional_areas: + - Checkout +--- + +This topic describes how to add a custom input form (implemented as a UI component) to the [Checkout](https://glossary.magento.com/checkout) page. + +![The input form with four fields]({{ site.baseurl }}/common/images/how_checkout_form.png) + +Most of the elements, including the default forms on the Checkout page are implemented as UI components. And we recommend your custom form to be a UI component, extending the default [Magento_Ui/js/form/form]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Ui/view/base/web/js/form/form.js) component. + +Magento provides the ability to add a custom form to any of the checkout steps: Shipping Information, Review and Payment Information, or custom. In order to add a custom form that is a UI component, take the following steps: + +1. [Create the JS implementation of the form UI component](#component). +1. [Create the knockout.js HTML template for rendering the form](#template). +1. [Declare the form in the checkout page layout](#layout). + +## Prerequisites + +[Set Magento to developer mode]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-mode.html) while you perform all customizations and debugging. + +For the sake of compatibility, upgradability, and easy maintenance, do not edit the default Magento code. Instead, add your customizations in a separate module. For your checkout customization to be applied correctly, your custom module should [depend]({{ page.baseurl }}/extension-dev-guide/build/composer-integration.html) on the `Magento_Checkout` module. + +Do not use `Ui` for your custom module name, because `%Vendor%_Ui` notation, required when specifying paths, might cause issues. + +## Step 1: Create the JS implementation of the form UI component {#component} + +In your `/view/frontend/web/js/view/` directory, create a `custom-checkout-form.js` file implementing the form. + +Example of extending the default form component: + +```js +/*global define*/ +define([ + 'Magento_Ui/js/form/form' +], function(Component) { + 'use strict'; + return Component.extend({ + initialize: function () { + this._super(); + // component initialization logic + return this; + }, + + /** + * Form submit handler + * + * This method can have any name. + */ + onSubmit: function() { + // trigger form validation + this.source.set('params.invalid', false); + this.source.trigger('customCheckoutForm.data.validate'); + + // verify that form data is valid + if (!this.source.get('params.invalid')) { + // data is retrieved from data provider by value of the customScope property + var formData = this.source.get('customCheckoutForm'); + // do something with form data + console.dir(formData); + } + } + }); +}); +``` + +## Step 2: Create the HTML template {#template} + +Add the `knockout.js` HTML template for the form component under the `/view/frontend/web/template` directory called `custom-checkout-form.html`. + +Example: + +```html +
    +
    +
    + + + + +
    + + +
    +
    +``` + +## Step 3: Declare the form in the checkout page layout {#layout} + +Certain default checkout templates declare regions where additional content can be inserted. You can add your custom form in any of these regions. These regions are provided with corresponding comments in the default Checkout page layout file `/view/frontend/layout/checkout_index_index.xml`. + +Also you locate the regions in the `.html` templates of the blocks used in this [layout](https://glossary.magento.com/layout) file. +For example, the shipping JS component (see `/view/frontend/web/template/shipping.html`) provides the `before-form` region and corresponding UI container. + +Any content added here is rendered before the Shipping Address form on the Shipping Information step. To add content to this region, create a `checkout_index_index.xml` layout update in the `/view/frontend/layout/`. + +It should be similar to the following: + +```xml + + + + + + + + + + + + + + + + + + + + VendorName_ModuleName/js/view/custom-checkout-form + checkoutProvider + + + VendorName_ModuleName/custom-checkout-form + + + + + + + + + + + + + + + + + + + + + +``` + +### Clear files after modification {#modify} + +If you modify your custom `.html` template after it was applied on the store pages, the changes will not apply until you do the following: + +1. Delete all files in the `pub/static/frontend` and `var/view_preprocessed` directories. +1. Reload the pages. + +### Static forms {#static_form} + +The term static refers to the forms where all the fields are already known/predefined and do not depend on any settings in the [Admin](https://glossary.magento.com/admin). Compare to [dynamic forms](#dynamic_form). + +The fields of static forms are not generated dynamically, so they can be defined in a layout. + +The following code sample shows the configuration of the `custom-checkout-form-container` form, defined in the previous step. It contains four fields: a text input, a select, a checkbox, and a date field. This form uses the checkout data provider (`checkoutProvider`) that was introduced in the `Magento_Checkout` module: + +```xml +... + + ... + + + + uiComponent + + custom-checkout-form-fields + + + Magento_Ui/js/form/element/abstract + + + customCheckoutForm + ui/form/field + ui/form/element/input + + checkoutProvider + customCheckoutForm.text_field + Text Field + 1 + + true + + + + Magento_Ui/js/form/element/boolean + + + customCheckoutForm + ui/form/field + ui/form/element/checkbox + + checkoutProvider + customCheckoutForm.checkbox_field + Checkbox Field + 3 + + + Magento_Ui/js/form/element/select + + + customCheckoutForm + ui/form/field + ui/form/element/select + + + + Please select value + + + + Value 1 + value_1 + + + Value 2 + value_2 + + + + value_2 + checkoutProvider + customCheckoutForm.select_field + Select Field + 2 + + + Magento_Ui/js/form/element/date + + + customCheckoutForm + ui/form/field + ui/form/element/date + + checkoutProvider + customCheckoutForm.date_field + Date Field + + true + + + + + + +... +``` + +### Dynamically defined forms {#dynamic_form} + +Dynamically defined, or dynamic, forms are the forms where the set or type of fields can change. For example, the fields displayed on the checkout form depend on the Admin settings: depending on the **Admin > Stores > Settings > Configuration > Customers > Customer Configuration > Name and Address Options**. + +For such forms, you must implement a [plugin]({{ page.baseurl }}/extension-dev-guide/plugins.html) for the `\Magento\Checkout\Block\Checkout\LayoutProcessor::process` method. +A plugin can add custom fields definitions to layout at runtime. The format of the field definition is the same as for fields defined in layout. + +For example: + +```php?start_inline=1 +$textField = [ + 'component' => 'Magento_Ui/js/form/element/abstract', + 'config' => [ + 'customScope' => 'customCheckoutForm', + 'template' => 'ui/form/field', + 'elementTmpl' => 'ui/form/element/input', + ], + 'provider' => 'checkoutProvider', + 'dataScope' => 'customCheckoutForm.text_field', + 'label' => 'Text Field', + 'sortOrder' => 1, + 'validation' => [ + 'required-entry' => true, + ], +]; +``` diff --git a/src/guides/v2.4/howdoi/checkout/checkout_new_field.md b/src/guides/v2.4/howdoi/checkout/checkout_new_field.md deleted file mode 120000 index 7e88b96fc69..00000000000 --- a/src/guides/v2.4/howdoi/checkout/checkout_new_field.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/howdoi/checkout/checkout_new_field.md \ No newline at end of file diff --git a/src/guides/v2.4/howdoi/checkout/checkout_new_field.md b/src/guides/v2.4/howdoi/checkout/checkout_new_field.md new file mode 100644 index 00000000000..4e5f0d4593b --- /dev/null +++ b/src/guides/v2.4/howdoi/checkout/checkout_new_field.md @@ -0,0 +1,230 @@ +--- +layout: tutorial +group: how-do-i +subgroup: +title: Add a new field in address form +subtitle: Customize Checkout +menu_order: 9 +level3_subgroup: checkout-tutorial +functional_areas: + - Checkout +--- + +You can add new fields to default [checkout](https://glossary.magento.com/checkout) forms, such as shipping address or billing address forms. To illustrate this ability, this topic describes adding a field to the shipping address form. + +To add your custom field to the checkout address form and access its value on the client side: + +1. [Add the field to layout](#add). +1. [Add a JS mixin to modify data submission](#mixin). +1. [Load your mixin](#load_mixin). +1. [Add the field to address model](#field). +1. [Access the value of the custom field on server side](#access). + +## Step 1: Add the field to layout {#add} + +Both shipping address and billing address forms are [generated dynamically]({{ page.baseurl }}/howdoi/checkout/checkout_form.html#dynamic_form). To modify their layouts, create a [plugin]({{ page.baseurl }}/extension-dev-guide/plugins.html) for the `\Magento\Checkout\Block\Checkout\LayoutProcessor::process` method and declare it in the `di.xml` file in your module. + +The following code snippet enumerates sample logic for adding a field named `Custom Attribute` to the shipping address form: + +```php?start_inline=1 +$customAttributeCode = 'custom_field'; +$customField = [ + 'component' => 'Magento_Ui/js/form/element/abstract', + 'config' => [ + // customScope is used to group elements within a single form (e.g. they can be validated separately) + 'customScope' => 'shippingAddress.custom_attributes', + 'customEntry' => null, + 'template' => 'ui/form/field', + 'elementTmpl' => 'ui/form/element/input', + 'tooltip' => [ + 'description' => 'this is what the field is for', + ], + ], + 'dataScope' => 'shippingAddress.custom_attributes' . '.' . $customAttributeCode, + 'label' => 'Custom Attribute', + 'provider' => 'checkoutProvider', + 'sortOrder' => 0, + 'validation' => [ + 'required-entry' => true + ], + 'options' => [], + 'filterBy' => null, + 'customEntry' => null, + 'visible' => true, + 'value' => '' // value field is used to set a default value of the attribute +]; + +$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']['children'][$customAttributeCode] = $customField; +``` + +Via the previous example, the field is added to the `customAttributes` property of `'Magento_Checkout/js/model/new-customer-address.js`, a JavaScript object that lists all predefined address attributes and matches the corresponding server-side interface `\Magento\Quote\Api\Data\AddressInterface`. + +The `customAttributes` property was designed to contain custom EAV address attributes and is related to the `\Magento\Quote\Model\Quote\Address\CustomAttributeListInterface::getAttributes` method. The sample code above will automatically handle local storage persistence on the [frontend](https://glossary.magento.com/frontend). + +Optionally, instead of adding a plugin, you can use a [dependency injection (DI)]({{ page.baseurl }}/extension-dev-guide/depend-inj.html). To use a DI, add the `LayoutProcessor`, which adds the custom field to the address form class, to the `/Block/Checkout/` directory. The class must implement the `\Magento\Checkout\Block\Checkout\LayoutProcessorInterface` interface. Use the code sample above as an example of the `\Magento\Checkout\Block\Checkout\LayoutProcessorInterface::process()` method implementation. + +To add your `LayoutProcessor` class the corresponding pool of processors, specify the following (where `%unique_name%` and `%path\to\your\LayoutProcessor%` must be replaced by your real values) in the `/etc/frontend/di.xml` file: + +```xml + + + + %path\to\your\LayoutProcessor% + + + +``` + +## Step 2: Add a JS mixin to modify data submission {#mixin} + +Add a JS [mixin](https://glossary.magento.com/mixin), to the [server side](https://glossary.magento.com/server-side), to change the behavior of the component responsible for the data submission. + +In your custom module, define a mixin as a separate AMD module that returns a callback function. Add the mixin file anywhere in the `/view/frontend/web` directory. There are no strict requirements for the mixin file naming. + +The following code sample is a sample mixin modifying the behavior of `Magento_Checkout/js/action/set-shipping-information`, the component responsible for data submission between shipping and billing checkout steps: + +```js +/*jshint browser:true jquery:true*/ +/*global alert*/ +define([ + 'jquery', + 'mage/utils/wrapper', + 'Magento_Checkout/js/model/quote' +], function ($, wrapper, quote) { + 'use strict'; + + return function (setShippingInformationAction) { + + return wrapper.wrap(setShippingInformationAction, function (originalAction) { + var shippingAddress = quote.shippingAddress(); + if (shippingAddress['extension_attributes'] === undefined) { + shippingAddress['extension_attributes'] = {}; + } + + var attribute = shippingAddress.customAttributes.find( + function (element) { + return element.attribute_code === 'custom_field'; + } + ); + + shippingAddress['extension_attributes']['custom_field'] = attribute.value; + // pass execution to original action ('Magento_Checkout/js/action/set-shipping-information') + return originalAction(); + }); + }; +}); +``` + +When adding a field to the billing address form, you must modify the behavior of the `Magento_Checkout/js/action/place-order` or `Magento_Checkout/js/action/set-payment-information` component, depending on when do you need the custom field valued to be passed to the server side. + +To see an example of a mixing that modifies one of these components, see the [place-order-mixin.js]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/CheckoutAgreements/view/frontend/web/js/model/place-order-mixin.js) in the Magento_CheckoutAgreements [module](https://glossary.magento.com/module). + +## Step 3: Load your mixin {#load_mixin} + +Tell Magento to load your mixin for the corresponding JS component by adding the `requirejs-config.js` to the `/view/frontend/` directory. + +The following code sample shows an example utilizing the sample mixin added earlier: + +```js +var config = { + config: { + mixins: { + 'Magento_Checkout/js/action/set-shipping-information': { + '/js/action/set-shipping-information-mixin': true + } + } + } +}; +``` + +## Step 4: Add field to address model {#field} + +To add the field to the address model on the server side, add the `extension_attributes.xml` file in the `/etc/` directory. + +The following code is an example of an `extension_attributes.xml` file: + +```xml + + + + + + + +``` + +Clear the `generated/code` directory when you run the `setup:di:compile` command. New getter and setter methods will be added in `generated/code/Magento/Quote/Api/Data/AddressExtension.php` file. + +## Step 5: Access the value of the custom field on server side {#access} + +If you completed all the steps described in the previous sections, Magento will generate the interface that includes your custom attribute and you can access your field value. + +You can set/get these attributes values by creating an instance of the `Magento/Quote/Api/Data/AddressInterface.php` interface. + +```php +_addressInformation = $addressInformation; + parent::__construct($context, $data); + } + + /** + * Get custom Shipping Charge + * + * @return String + */ + public function getShippingCharge() + { + $extAttributes = $this->_addressInformation->getExtensionAttributes(); + return $extAttributes->getCustomField(); //get custom attribute data. + } +} +``` + +## Step 6: Run CLI commands + +1. Compile the code with: + + ```bash + bin/magento setup:di:compile + ``` + +1. Next, deploy static content: + + ```bash + bin/magento setup:static-content:deploy + ``` + +1. Then clean the cache: + + ```bash + bin/magento cache:clean + ``` + +{:.ref-header} +Related topic + +[EAV and extension attributes]({{ page.baseurl }}/extension-dev-guide/attributes.html) diff --git a/src/guides/v2.4/howdoi/checkout/checkout_new_step.md b/src/guides/v2.4/howdoi/checkout/checkout_new_step.md deleted file mode 120000 index 5b621357f1d..00000000000 --- a/src/guides/v2.4/howdoi/checkout/checkout_new_step.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/howdoi/checkout/checkout_new_step.md \ No newline at end of file diff --git a/src/guides/v2.4/howdoi/checkout/checkout_new_step.md b/src/guides/v2.4/howdoi/checkout/checkout_new_step.md new file mode 100644 index 00000000000..db8b552ca4d --- /dev/null +++ b/src/guides/v2.4/howdoi/checkout/checkout_new_step.md @@ -0,0 +1,235 @@ +--- +layout: tutorial +group: how-do-i +subgroup: +title: Add a new checkout step +subtitle: Customize Checkout +menu_order: 1 +level3_subgroup: checkout-tutorial +functional_areas: + - Checkout +--- + +This topic describes how to create the [frontend](https://glossary.magento.com/frontend) part of the component, implementing a checkout step, and how to add it to the checkout flow. + +The default Magento [Checkout](https://glossary.magento.com/checkout) consists of two steps: + +- Shipping Information +- Review and Payments Information + +You can add a custom checkout step, it should be implemented as a [UI component](https://glossary.magento.com/ui-component). For the sake of compatibility, upgradability and easy maintenance, do not edit the default Magento code, add your customizations in a separate [module](https://glossary.magento.com/module). + +1. [Create the view part of the checkout step component](#create-view). +1. [Add your step to the Checkout page layout](#checkout). +1. [Create mixins for payment and shipping steps (optional)](#create-mixin). + +## Step 1: Create the view part of the checkout step component {#create-view} + +To create the view part of the new checkout step: + +1. Add a module directory (not covered in this topic). See [Build your module]({{ page.baseurl }}/extension-dev-guide/build/build.html) for details). All custom files must be stored there. For your checkout customization to be applied correctly, your custom module should depend on the `Magento_Checkout` module. Do not use `Ui` for your custom module name, because `%Vendor%_Ui` notation, required when specifying paths, might cause issues. +1. [Create the `.js` file implementing the view model](#component). +1. [Create a `.html` template for the component](#html-template). + +### Add the JavaScript file implementing the new step {#component} + +A new checkout step must be implemented as UI component. That is, its [JavaScript](https://glossary.magento.com/javascript) implementation must be a JavaScript module. + +The file must be stored under the `/view/frontend/web/js/view` directory. + +{:.bs-callout-info} +`` notation stands for the path to your module directory from the root directory. Usually it will be one of the following: `app/code//` or `vendor//module--`. For more details see [Conventional notations for paths to modules and themes]({{ page.baseurl }}/frontend-dev-guide/conventions.html) + +A sample `my-step-view.js` with comments follows: + +```js +define([ + 'ko', + 'uiComponent', + 'underscore', + 'Magento_Checkout/js/model/step-navigator' +], function (ko, Component, _, stepNavigator) { + 'use strict'; + + /** + * mystep - is the name of the component's .html template, + * _ - is the name of your module directory. + */ + return Component.extend({ + defaults: { + template: '_/mystep' + }, + + // add here your logic to display step, + isVisible: ko.observable(true), + + /** + * @returns {*} + */ + initialize: function () { + this._super(); + + // register your step + stepNavigator.registerStep( + // step code will be used as step content id in the component template + 'step_code', + // step alias + null, + // step title value + 'Step Title', + // observable property with logic when display step or hide step + this.isVisible, + + _.bind(this.navigate, this), + + /** + * sort order value + * 'sort order value' < 10: step displays before shipping step; + * 10 < 'sort order value' < 20 : step displays between shipping and payment step + * 'sort order value' > 20 : step displays after payment step + */ + 15 + ); + + return this; + }, + + /** + * The navigate() method is responsible for navigation between checkout steps + * during checkout. You can add custom logic, for example some conditions + * for switching to your custom step + * When the user navigates to the custom step via url anchor or back button we_must show step manually here + */ + navigate: function () { + this.isVisible(true); + }, + + /** + * @returns void + */ + navigateToNextStep: function () { + stepNavigator.next(); + } + }); +}); +``` + +### Add the .html template {#html-template} + +In the module directory, add the `.html` template for the component. It must be located under the `/view/frontend/web/template` directory. + +A sample `mystep.html` follows: + +```html + +
  • +
    +
    + +
    +
    +
    + +
    +
    +
    +
    +
  • +``` + +## Step 2: Add your step to the Checkout page layout {#checkout} + +For the new step to be displayed on the page, you need to declare it in the Checkout page layout, which is defined in `checkout_index_index.xml`. + +So you need to add an [extending]({{ page.baseurl }}/frontend-dev-guide/layouts/layout-extend.html) `checkout_index_index.xml` layout file in the following location: `/view/frontend/layout/checkout_index_index.xml` + +A sample `checkout_index_index.xml` follows: + +```xml + + + + + + + + + + + + + %Vendor%_%Module%/js/view/my-step-view + + + + 2 + + + + + + + + + + + + + + +``` + +## Step 3: Create mixins for payment and shipping steps (optional) {#create-mixin} + +If your new step is the first step, you have to create mixins for the payment and shipping steps. Otherwise, two steps will be activated on the loading of the checkout. + +Create a mixin as follows: + +1. Create a `Vendor/Module/view/base/requirejs-config.js` file with these contents; + + ```js + var config = { + 'config': { + 'mixins': { + 'Magento_Checkout/js/view/shipping': { + 'Vendor_Module/js/view/shipping-payment-mixin': true + }, + 'Magento_Checkout/js/view/payment': { + 'Vendor_Module/js/view/shipping-payment-mixin': true + } + } + } + } + ``` + +1. Create the mixin. We'll use the same mixin for both payment and shipping: + + ```js + define([ + 'ko' + ], function (ko) { + 'use strict'; + + var mixin = { + + initialize: function () { + // set visible to be initially false to have your step show first + this.visible = ko.observable(false); + this._super(); + + return this; + } + }; + + return function (target) { + return target.extend(mixin); + }; + }); + ``` + +{:.bs-callout-info} +For your changes to be applied, you might need to [clean layout cache]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-cache.html ) and [static view file cache]({{ page.baseurl }}/frontend-dev-guide/cache_for_frontdevs.html#clean_static_cache). For more info on mixins, see [JS Mixins]({{ page.baseurl }}/javascript-dev-guide/javascript/js_mixins.html). diff --git a/src/guides/v2.4/howdoi/checkout/checkout_order.md b/src/guides/v2.4/howdoi/checkout/checkout_order.md deleted file mode 120000 index f631734e496..00000000000 --- a/src/guides/v2.4/howdoi/checkout/checkout_order.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/howdoi/checkout/checkout_order.md \ No newline at end of file diff --git a/src/guides/v2.4/howdoi/checkout/checkout_order.md b/src/guides/v2.4/howdoi/checkout/checkout_order.md new file mode 100644 index 00000000000..0a022f723df --- /dev/null +++ b/src/guides/v2.4/howdoi/checkout/checkout_order.md @@ -0,0 +1,129 @@ +--- +layout: tutorial +group: how-do-i +subgroup: +title: Add custom validations before order placement +subtitle: Customize Checkout +menu_order: 4 +level3_subgroup: checkout-tutorial +functional_areas: + - Checkout +--- + +This topic describes how to add custom validations to be performed before the order is placed during [checkout](https://glossary.magento.com/checkout). Namely, the validations which are performed after a shopper clicks the **Place Order** button. Writing the validation logic itself is not covered in this topic. + +To add custom validations before the order placement action, you must do the following: + +1. [Create the validator](#validator). +1. [Add validator to the validators pool](#pool). +1. [Declare the validation in the checkout layout](#layout). + +## Step 1: Create the validator {#validator} + +For the sake of compatibility, upgradability and easy maintenance, do not edit the default Magento code, add your customizations in a separate module. For your checkout customization to be applied correctly, your custom module should [depend]({{ page.baseurl }}/extension-dev-guide/build/composer-integration.html) on the `Magento_Checkout` module. Do not use `Ui` for your custom module name, because `%Vendor%_Ui` notation, required when specifying paths, might cause issues. + +In your custom module directory, create a `.js` file implementing the validator. It should be located under `/view/frontend/web/js/model` directory. + +Following is a sample of the validator `.js` file. It must necessarily implement the `validate()` method: + +```js +define( + ['mage/translate', 'Magento_Ui/js/model/messageList'], + function ($t, messageList) { + 'use strict'; + return { + validate: function () { + const isValid = false; //Put your validation logic here + + if (!isValid) { + messageList.addErrorMessage({ message: $t('a possible failure message ... ') }); + } + + return isValid; + } + } + } +); +``` + +## Step 2: Add validator to the validators pool {#pool} + +Your custom validator must be added to the pool of "additional validators". To do this, in the `/view/frontend/web/js/view` directory create a new `.js` file with the following content: + +```js +define( + [ + 'uiComponent', + 'Magento_Checkout/js/model/payment/additional-validators', + '/js/model/your-validator' + ], + function (Component, additionalValidators, yourValidator) { + 'use strict'; + additionalValidators.registerValidator(yourValidator); + return Component.extend({}); + } +); +``` + +## Step 3: Declare the validation in the checkout layout {#layout} + +In your custom module directory, create a new `/view/frontend/layout/checkout_index_index.xml` file. + +In this file, add the following: + +```xml + + + + + + + + + + + + + + + + + + + %your_module_dir%/js/view/%your-validation% + + + + + + + + + + + + + + + + + + +``` + +## Step 4: Deploy static content and clean cache + +{:.bs-callout-info} +These commands are for production mode. They are not necessary when in developer mode. + +1. Deploy static content: + + ```bash + bin/magento setup:static-content:deploy + ``` + +1. Clean cache: + + ```bash + bin/magento cache:clean + ``` diff --git a/src/guides/v2.4/howdoi/checkout/checkout_overview.md b/src/guides/v2.4/howdoi/checkout/checkout_overview.md deleted file mode 120000 index 6f1ba76c550..00000000000 --- a/src/guides/v2.4/howdoi/checkout/checkout_overview.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/howdoi/checkout/checkout_overview.md \ No newline at end of file diff --git a/src/guides/v2.4/howdoi/checkout/checkout_overview.md b/src/guides/v2.4/howdoi/checkout/checkout_overview.md new file mode 100644 index 00000000000..da468936397 --- /dev/null +++ b/src/guides/v2.4/howdoi/checkout/checkout_overview.md @@ -0,0 +1,42 @@ +--- +layout: tutorial +group: how-do-i +subgroup: checkout +title: Customize Checkout +menu_title: Initial Tasks +menu_node: +level3_subgroup: checkout-tutorial +menu_order: 0 +functional_areas: + - Checkout +--- + +Magento [checkout](https://glossary.magento.com/checkout) is implemented using the [UI components]({{ page.baseurl }}/ui_comp_guide/bk-ui_comps.html). +Out of the box, the checkout consists of two steps: + +- Shipping Information +- Review and Payment Information + +The checkout totals and the corresponding side-bar are only displayed after the first step is completed. + +The only [exception](https://glossary.magento.com/exception) is checkout of virtual and/or downloadable products: if there are only these types of products in the shopping cart, checkout is automatically transformed to one-step procedure, because shipping information is not required. + + {:.bs-callout-info} +For the sake of compatibility, upgradability, and easy maintenance, do not edit the default Magento code. Add your customizations in a custom [module](https://glossary.magento.com/module). + +## List of available customizations + +You can customize the default checkout in multiple ways. This tutorial includes the following customizations: + +- [Add a new checkout step]({{ page.baseurl }}/howdoi/checkout/checkout_new_step.html) +- [Customize the view of an existing step]({{ page.baseurl }}/howdoi/checkout/checkout_customize.html) +- [Add a custom payment method to checkout]({{ page.baseurl }}/howdoi/checkout/checkout_payment.html) +- [Add custom validations before order placement]({{ page.baseurl }}/howdoi/checkout/checkout_order.html) +- [Add custom shipping carrier]({{ page.baseurl }}/howdoi/checkout/checkout-add-custom-carrier.html) +- [Add custom shipping carrier validations]({{ page.baseurl }}/howdoi/checkout/checkout_carrier.html) +- [Add custom input mask for ZIP code]({{ page.baseurl }}/howdoi/checkout/checkout_zip.html) +- [Add a custom template for a form field on Checkout page]({{ page.baseurl }}/howdoi/checkout/checkout_edit_form.html) +- [Add a new input form to checkout]({{ page.baseurl }}/howdoi/checkout/checkout_form.html) +- [Add a new field in address form]({{ page.baseurl }}/howdoi/checkout/checkout_new_field.html) +- [Add custom shipping address renderer]({{ page.baseurl }}/howdoi/checkout/checkout_address.html) +- [Add a custom field for an offline payment method]({{ page.baseurl }}/howdoi/checkout/checkout_payment_new_field.html) diff --git a/src/guides/v2.4/howdoi/checkout/checkout_payment_new_field.md b/src/guides/v2.4/howdoi/checkout/checkout_payment_new_field.md deleted file mode 120000 index ffb492f20f6..00000000000 --- a/src/guides/v2.4/howdoi/checkout/checkout_payment_new_field.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/howdoi/checkout/checkout_payment_new_field.md \ No newline at end of file diff --git a/src/guides/v2.4/howdoi/checkout/checkout_payment_new_field.md b/src/guides/v2.4/howdoi/checkout/checkout_payment_new_field.md new file mode 100644 index 00000000000..9de6a58c3a6 --- /dev/null +++ b/src/guides/v2.4/howdoi/checkout/checkout_payment_new_field.md @@ -0,0 +1,362 @@ +--- +layout: tutorial +group: how-do-i +subgroup: +title: Add a custom field for an offline payment method +contributor_name: Ziffity +contributor_link: https://www.ziffity.com/ +subtitle: Customize Checkout +menu_order: 101 +level3_subgroup: checkout-tutorial +functional_areas: + - Checkout +--- + +This topic describes how to add a custom field to an offline payment method in the payment step of the checkout. The custom field allows the buyer to enter a comment about a purchase order. + +## Prerequisites + +{:.bs-callout-info} +The `Purchase Order` payment method must be enabled in the storefront for this task. Ensure this payment method is enabled by navigating to **Stores** > **Settings** > **Configuration** > **Sales** > **Payment Methods** > **Other Payment Methods** > **Purchase Order** in the Admin. + +You must perform following steps to add a custom field to an offline payment method: + +1. [Create a new module](#create-module). +1. [Add a `db_schema.xml` file](#add-db-schema). +1. [Add a `requirejs` file to the module](#add-require-js). +1. [Override the vendor files](#override-vendor-files). +1. [Add an Observer](#add-observer). +1. [Compile and deploy the module](#compile-deploy). +1. [Verify that the module works](#verify-implementation). + +Let’s go through each step. + +## Step 1: Create a new module {#create-module} + +[Create a new module]({{ site.baseurl }}/videos/fundamentals/create-a-new-module/) named `Learning/CustomField` and register it. + +## Step 2 Add a `db_schema.xml` file {#add-db-schema} + +Add the `paymentpocomment` column in the `quote_payment` and `sales_order_payment` tables using the [declarative schema]({{page.baseurl}}/extension-dev-guide/declarative-schema/db-schema.html) method. + +Create the `app/code/Learning/CustomField/etc/db_schema.xml` and define the declarative schema as follows: + +```xml + + + +
    + + +
    +
    +``` + +## Step 3: Add a requirejs file to the module {#add-require-js} + +Create the `app/code/Learning/CustomField/view/frontend/requirejs-config.js` file and add the following code: + +```js + var config = { + map: { + '*': { + 'Magento_OfflinePayments/js/view/payment/offline-payments':'Learning_CustomField/js/view/payment/offline-payments', + } + } +} +``` + +## Step 4: Override the vendor files {#override-vendor-files} + +We must override the behavior of the following files to display the custom field: + +- [Magento_OfflinePayments/view/frontend/web/js/view/payment/offline-payments.js](#offline-payment) +- [Magento_OfflinePayments/view/frontend/web/js/view/payment/method-renderer/purchaseorder-method.js](#purchaseorder-method) +- [Magento_OfflinePayments/view/frontend/web/template/payment/purchaseorder-form.html](#purchaseorder-form) + +### Override the `offline-payments.js` {#offline-payment} + +Override the `Magento_OfflinePayments/view/frontend/web/js/view/payment/offline-payments.js` file to change the renderer of the Purchase Order payment method. + +Create the `app/code/Learning/CustomField/view/frontend/web/js/view/payment/offline-payments.js` file and add the following code: + +```js +define( + [ + 'uiComponent', + 'Magento_Checkout/js/model/payment/renderer-list' + ], + function ( + Component, + rendererList + ) { + 'use strict'; + rendererList.push( + { + type: 'checkmo', + component: 'Magento_OfflinePayments/js/view/payment/method-renderer/checkmo-method' + }, + { + type: 'banktransfer', + component: 'Magento_OfflinePayments/js/view/payment/method-renderer/banktransfer-method' + }, + { + type: 'cashondelivery', + component: 'Magento_OfflinePayments/js/view/payment/method-renderer/cashondelivery-method' + }, + { + type: 'purchaseorder', + component: 'Learning_CustomField/js/view/payment/method-renderer/purchaseorder-method' + } + ); + /** Add view logic here if needed */ + return Component.extend({}); + } +); +``` + +### Override the `purchaseorder-method.js` {#purchaseorder-method} + +It is also necessary to override the `Magento_OfflinePayments/view/frontend/web/js/view/payment/method-renderer/purchaseorder-method.js` file. + +The `template` path value used in this file must be altered to use the custom template. Also, the logic to get the `additional_data` is implemented in this file. + +Create the `app/code/Learning/CustomField/view/frontend/web/js/view/payment/method-renderer/purchaseorder-method.js` file and add the following code: + +```js +define([ + 'Magento_Checkout/js/view/payment/default', + 'jquery', + 'mage/validation' +], function (Component, $) { + 'use strict'; + + return Component.extend({ + defaults: { + template: 'Learning_CustomField/payment/purchaseorder-form', + purchaseOrderNumber: '' + }, + + /** @inheritdoc */ + initObservable: function () { + this._super() + .observe('purchaseOrderNumber'); + + return this; + }, + + /** + * @return {Object} + */ + getData: function () { + return { + method: this.item.method, + 'po_number': this.purchaseOrderNumber(), + 'additional_data': { + 'po_number': $('#po_number').val(), + 'paymentpocomment': $('#purchaseorder_paymentpocomment').val(), + } + }; + }, + + /** + * @return {jQuery} + */ + validate: function () { + var form = 'form[data-role=purchaseorder-form]'; + + return $(form).validation() && $(form).validation('isValid'); + } + }); +}); +``` + +### Override the `purchaseorder-form.html` {#purchaseorder-form} + +We must override the `Magento_OfflinePayments/view/frontend/web/template/payment/purchaseorder-form.html` template file to add the custom input field (**Purchase Order Comment**). + +Create the `app/code/Learning/CustomField/view/frontend/web/template/payment/purchaseorder-form.html` file and add the following code: + +{% collapsible Show code %} + +```html +
    +
    + + +
    + +
    + + + +
    + + + +
    +
    +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    + + + +
    +
    +
    + +
    +
    +
    +
    +``` +{% endcollapsible %} + +## Step 5: Add an Observer {#add-observer} + +Create an Observer file to save the custom field data to the order. For the Observer file an `events.xml` file is required to call the observer for a particular event. For this example, the `checkout_onepage_controller_success_action` event is used. + +Create the `app/code/Learning/CustomField/etc/frontend/events.xml` file and add the following code: + +```xml + + + + + + + +``` + +Then create the `app/code/Learning/CustomField/Observer/Frontend/Sales/OrderPaymentSaveBefore.php` file. + +{% collapsible Show code %} + +```php +order = $order; + $this->quoteRepository = $quoteRepository; + $this->logger = $logger; + $this->_serialize = $serialize; + } + /** + * Execute observer + * + * @param \Magento\Framework\Event\Observer $observer + * @return void + */ + public function execute(\Magento\Framework\Event\Observer $observer) + { + $orderids = $observer->getEvent()->getOrderIds(); + if(!$orderids){ + foreach ($orderids as $orderid) { + $order = $this->_order->load($orderid); + $method = $order->getPayment()->getMethod(); + if($method == 'purchaseorder') { + $quote_id = $order->getQuoteId(); + $quote = $this->quoteRepository->get($quote_id); + $paymentQuote = $quote->getPayment(); + $paymentOrder = $order->getPayment(); + $paymentOrder->setData('paymentpocomment',$paymentQuote->getPaymentpocomment()); + $paymentOrder->save(); + } + } + } + } +} +``` +{% endcollapsible %} + +## Step 6: Compile and deploy the module {#compile-deploy} + +Run the following sequence of commands to compile and deploy your custom module. + +1. Enable the new module. + + ```bash + bin/magento module:enable Learning_CustomField + ``` + +1. Install the new module. + + ```bash + bin/magento setup:upgrade + ``` + +1. Compile the code. + + ```bash + bin/magento setup:di:compile + ``` + +1. Deploy the static files. + + ```bash + bin/magento setup:static-content:deploy + ``` + +## Step 7: Verify that the module works {#verify-implementation} + +Use the following steps to verify your changes work as expected. + +1. Go to the storefront as a guest user and add a product to the cart. + +1. Go to the checkout page and select the **Purchase Order** payment. + +1. Verify that the **Purchase Order Comment** field is visible. + + ![Custom field in checkout page]({{ site.baseurl }}/common/images/custom_field_payment.png) + +1. Fill the purchase order comment field in the checkout and place an order. + +1. Verify that the entered value is stored in the `paymentpocomment` column of the `sales_order_payment` table. diff --git a/src/guides/v2.4/howdoi/checkout/checkout_shipping_methods.md b/src/guides/v2.4/howdoi/checkout/checkout_shipping_methods.md deleted file mode 120000 index c2b20658e19..00000000000 --- a/src/guides/v2.4/howdoi/checkout/checkout_shipping_methods.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/howdoi/checkout/checkout_shipping_methods.md \ No newline at end of file diff --git a/src/guides/v2.4/howdoi/checkout/checkout_shipping_methods.md b/src/guides/v2.4/howdoi/checkout/checkout_shipping_methods.md new file mode 100644 index 00000000000..f8a4fd2e640 --- /dev/null +++ b/src/guides/v2.4/howdoi/checkout/checkout_shipping_methods.md @@ -0,0 +1,137 @@ +--- +layout: tutorial +group: how-do-i +subgroup: checkout +title: Customize the list of shipping methods +subtitle: Customize Checkout +menu_order: 100 +level3_subgroup: checkout-tutorial +--- + +This topic describes how to customize list of shipping methods displayed on the checkout page. + +Let's consider a case where you need to add a collapsible text field with description for each shipping method in this list. To achieve this, you need to take the following steps: + +1. [Create a new template for the shipping method item](#method-item). +1. [Create a new template for the shipping method list](#method-list). +1. [Override the shipping step configuration](#shipping). + +## Step 1: Create new template for shipping method item {#method-item} + +In your custom module directory, create a new file: `/view/frontend/web/template/custom-method-item-template.html`. In this file, add the following code. + +It is copied from the `/view/frontend/web/template/shipping-address/shipping-method-item.html` template, with the following modifications: + +* A `` element added to contain the shipping method description +* A column with trigger elements that provide the collapse/expand functionality added +* The entire sample wrapped in `` to provide the general collapsible context for rows + +```html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +## Step 2: Create new template for shipping methods list {#method-list} + +In your custom module directory, create a new file: `/view/frontend/web/template/custom-method-list-template.html`. In this file, add the following code. It uses the code from the `app/code/Magento/Checkout/view/frontend/web/template/shipping-address/shipping-method-list.html` template, with the following modifications: + +* A column for triggers added in `` +* `tbody` moved to the item template for collapsible context + +```html +
    + + + +
    + + + + + +
    +
    +``` + +## Step 3: Override shipping step configuration {#shipping} + +In your custom module directory, create a new file: `/view/frontend/layout/checkout_index_index.xml`. In this file, add the following code. + +It overrides the `shippingMethodListTemplate` and `shippingMethodItemTemplate` properties of `/view/frontend/web/js/view/shipping.js`: + +```html + + + + + + + + + + + + + + + Vendor_Checkout/custom-method-item-template + Vendor_Checkout/custom-method-list-template + + + + + + + + + + + + + + +``` diff --git a/src/guides/v2.4/howdoi/checkout/checkout_zip.md b/src/guides/v2.4/howdoi/checkout/checkout_zip.md deleted file mode 120000 index 5b278d7b919..00000000000 --- a/src/guides/v2.4/howdoi/checkout/checkout_zip.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/howdoi/checkout/checkout_zip.md \ No newline at end of file diff --git a/src/guides/v2.4/howdoi/checkout/checkout_zip.md b/src/guides/v2.4/howdoi/checkout/checkout_zip.md new file mode 100644 index 00000000000..e053683879e --- /dev/null +++ b/src/guides/v2.4/howdoi/checkout/checkout_zip.md @@ -0,0 +1,117 @@ +--- +layout: tutorial +group: how-do-i +subgroup: +title: Add custom input mask for ZIP code +subtitle: Customize Checkout +menu_order: 7 +level3_subgroup: checkout-tutorial +functional_areas: + - Checkout +--- + +This topic describes how a developer can add custom input masks. + +When a shopper specifies the country and ZIP code in the shipping address during [checkout](https://glossary.magento.com/checkout) or in the shopping cart, Magento checks if the format of the entered code is valid for the specified country. This validation is implemented using the input masks for the ZIP code field. In Magento, these input masks are regular expressions which define which format is allowed. + +In Magento the input masks for the **ZIP code** field are specified in the `/etc/zip_codes.xml`. Input masks are specified per country, and are entered in the form of regular expressions. +The syntax of defined by the [zip_code.xsd]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Directory/etc/zip_codes.xsd) scheme. + +The following table defines the `zip` node attributes: + + Attribute name | Required | Description +--- | --- | --- +`countryCode` | Yes | The country code (Alpha-2 format) for which the zip is defined + +```xml + + + +``` + +The following table defines the `code` node attributes: + + Attribute name | Required | Description +--- | --- | --- +`id` | Yes | A random unique name within the same list. +`example` | Yes | An example of the allowed pattern. +`active` | No | Defines if this zip pattern is active or not. + +You can define several zip `code` patterns for the same country, by passing a list of `codes`. +```xml + + ^[0-9]{5}$ + ^[a-zA-z]{2}[0-9]{4}$ + +``` + +For the sake of compatibility, upgradability, and easy maintenance, do not edit the default Magento code. Add your customizations in a separate, custom module. For your ZIP code input mask customization to be applied correctly, your custom module should depend on the `Magento_Directory` module. Do not use `Ui` for your custom module name, because `%Vendor%_Ui` notation, required when specifying paths, might cause issues. + +## Add custom ZIP code input masks {#add} + +To add custom ZIP code input masks or change the default ones, create a new `zip_codes.xml` in the `/etc` directory. + +The content of the file should be similar to the following sample: + +```xml + + + + + + + + + ^[0-9]{5}\-[0-9]{4}$ + ^[0-9]{5}$ + + + +``` + +## Modify default values in existing mask {#modify} + +To change (override the default value) the existing mask: + +1. Open `zip_codes.xml`. +1. Copy in the related nodes. +1. Change the regular expression defining the mask and the value of `example` correspondingly. + +Example of changing the default input mask: + +In the default `/etc/zip_codes.xml` the following mask is set for France: + +```xml + + + +... + + + ^[0-9]{5}$ + + +... + +``` + +To change this mask, add the following code in your `zip_codes.xml`: + +```xml + + + +... + + + + ^[a-zA-Z]{1}[0-9]{3}$ + + +... + +``` + +## Remove a mask {#remove} + +To remove a mask, in your `zip_codes.xml` add the corresponding node and set `active` attribute of `` to `false`. diff --git a/src/guides/v2.4/howdoi/custom-attributes/introduction.md b/src/guides/v2.4/howdoi/custom-attributes/introduction.md deleted file mode 120000 index 3b33f824c20..00000000000 --- a/src/guides/v2.4/howdoi/custom-attributes/introduction.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/howdoi/custom-attributes/introduction.md \ No newline at end of file diff --git a/src/guides/v2.4/howdoi/custom-attributes/introduction.md b/src/guides/v2.4/howdoi/custom-attributes/introduction.md new file mode 100644 index 00000000000..cfbffb05a40 --- /dev/null +++ b/src/guides/v2.4/howdoi/custom-attributes/introduction.md @@ -0,0 +1,13 @@ +--- +layout: tutorial +group: how-do-i +subgroup: +title: Custom attributes +menu_node: +level3_subgroup: custom-attributes +menu_order: 1 +contributor_name: Adarsh Manickam +contributor_link: https://github.com/drpayyne +--- + +The tutorials under this section guide Magento developers on setting up and configuring custom attributes. diff --git a/src/guides/v2.4/howdoi/custom-attributes/text-field.md b/src/guides/v2.4/howdoi/custom-attributes/text-field.md deleted file mode 120000 index d46108f3610..00000000000 --- a/src/guides/v2.4/howdoi/custom-attributes/text-field.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/howdoi/custom-attributes/text-field.md \ No newline at end of file diff --git a/src/guides/v2.4/howdoi/custom-attributes/text-field.md b/src/guides/v2.4/howdoi/custom-attributes/text-field.md new file mode 100644 index 00000000000..020d8af7c00 --- /dev/null +++ b/src/guides/v2.4/howdoi/custom-attributes/text-field.md @@ -0,0 +1,348 @@ +--- +layout: tutorial +group: how-do-i +subgroup: +title: Add a custom text field attribute +menu_node: +level3_subgroup: custom-attributes +menu_order: 2 +contributor_name: Adarsh Manickam +contributor_link: https://github.com/drpayyne +--- + +## Overview + +This tutorial describes how a developer can create a custom text field attribute for the Customer entity using code. This will reflect in both the [Customer Grid]({{ site.user_guide_url }}/customers/customer-account-manage.html) and the [Customer Form]({{ site.user_guide_url }}/customers/customer-account-update.html) in the Admin. + +This Customer attribute will be used to save and view the customer's ID in an external system, as an example. It will be created as an EAV attribute in a data patch. The EAV model allows a developer to add custom functionality to the Magento entities without modifying the core databases and schemas. Data patches are run just once, so this code will create the custom attribute and will never run again, which could cause issues. + +## Code + +### Create the data patch class + +Create a data patch class called `ExternalId` under the `\ExampleCorp\Customer\Setup\Patch\Data` namespace. This makes Magento execute the data patch automatically when `bin/magento setup:upgrade` is run. All data patches must implement the `\Magento\Framework\Setup\Patch\DataPatchInterface` interface. + +```php +moduleDataSetup = $moduleDataSetup; + $this->customerSetup = $customerSetupFactory->create(['setup' => $moduleDataSetup]); + $this->attributeResource = $attributeResource; + $this->logger = $logger; + } + ``` + +### Implement the apply method + +There are five steps in developing a data patch. All the steps below are written inside the `apply` method. + +1. Starting and ending the setup execution. This turns off foreign key checks and sets the SQL mode. + + ```php + $this->moduleDataSetup->getConnection()->startSetup(); + + /* + Attribute creation code must be run between these two lines + to ensure that the attribute is created smoothly. + */ + + $this->moduleDataSetup->getConnection()->endSetup(); + ``` + +1. Add the text field customer attribute with the required settings. + + The third parameter for `addAttribute` is an array of settings required to configure the attribute. Passing an empty array uses all the default values for each possible setting. To keep the code to a minimum, just declare the settings needing to be overridden and the rest of the settings will be used from the Magento defaults. The settings overrides can be done as described below. + + {:.bs-callout-info} + For creating a simple text field, it is not necessary to override the settings for `backend` (database field type) and `input` (frontend HTML input type), as they default to `varchar` and `text` respectively. + + {:.bs-callout-info} + The `\Magento\Customer\Api\CustomerMetadataInterface` interface contains constants like the customer entity's code and the default attribute set code, which can be referenced. + + ```php + $this->customerSetup->addAttribute( + CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, // entity type code + 'externalcorp_external_id', // unique attribute code + [ + 'label' => 'External ID', + 'required' => 0, + 'position' => 200, + 'system' => 0, + 'user_defined' => 1, + 'is_used_in_grid' => 1, + 'is_visible_in_grid' => 1, + 'is_filterable_in_grid' => 1, + 'is_searchable_in_grid' => 1, + ] + ); + ``` + + | Setting Key | Description | + | --- | --- | + | `label` | `External ID` - Label for displaying the attribute value | + | `required` | `0` - Attribute will be an optional field in the customer form | + | `position` | `200` - Sort order in the customer form | + | `system` | `0` - Not a system-defined attribute | + | `user_defined` | `1` - A user-defined attribute | + | `is_used_in_grid` | `1` - Ready for use in the customer grid | + | `is_visible_in_grid` | `1` - Visible in the customer grid | + | `is_filterable_in_grid` | `1` - Filterable in the customer grid | + | `is_searchable_in_grid` | `1` - Searchable in the customer grid | + +1. Add attribute to an attribute set and group. + + {:.bs-callout-info} + There is only one attribute set and group for the customer entity. The default attribute set ID is a constant defined the `CustomerMetadataInterface` interface and setting the attribute group ID to null makes Magento use the default attribute group ID for the customer entity. + + ```php + $this->customerSetup->addAttributeToSet( + CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, // entity type code + CustomerMetadataInterface::ATTRIBUTE_SET_ID_CUSTOMER, // attribute set ID + null, // attribute group ID + 'externalcorp_external_id' // unique attribute code + ); + ``` + +1. Make the attribute visible in the customer form. + + ```php + // Get the newly created attribute's model + $attribute = $this->customerSetup->getEavConfig() + ->getAttribute(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, 'externalcorp_external_id'); + + // Make attribute visible in Admin customer form + $attribute->setData('used_in_forms', [ + 'adminhtml_customer' + ]); + + // Save modified attribute model using its resource model + $this->attributeResource->save($attribute); + ``` + +1. Gracefully handle exceptions. + + ```php + try { + // All the code inside the apply method goes into the try block. + } catch (Exception $exception) { + $this->logger->err($exception->getMessage()); + } + ``` + +### Implement rest of the interface + +This data patch does not have any other patch as a dependency, and this data patch was not renamed earlier, so both `getDependencies` and `getAliases` can return an empty array. + +```php +public static function getDependencies(): array +{ + return []; +} + +public function getAliases(): array +{ + return []; +} +``` + +### Execute the data patch + +Run `bin/magento setup:upgrade` from the Magento root to execute the newly added data patch. + +- The attribute is created in the customer form under the _Account Information_ section. + +![Custom attribute in the customer form]({{ site.baseurl }}/common/images/custom-attributes/customer-text-form.png){:width="600px"} + +- The attribute is displayed in the customer grid. + +![Custom attribute in the customer grid]({{ site.baseurl }}/common/images/custom-attributes/customer-text-grid.png){:width="600px"} + +### Code reference + +```php +moduleDataSetup = $moduleDataSetup; + $this->customerSetup = $customerSetupFactory->create(['setup' => $moduleDataSetup]); + $this->attributeResource = $attributeResource; + $this->logger = $logger; + } + + /** + * Get array of patches that have to be executed prior to this. + * + * Example of implementation: + * + * [ + * \Vendor_Name\Module_Name\Setup\Patch\Patch1::class, + * \Vendor_Name\Module_Name\Setup\Patch\Patch2::class + * ] + * + * @return string[] + */ + public static function getDependencies(): array + { + return []; + } + + /** + * Get aliases (previous names) for the patch. + * + * @return string[] + */ + public function getAliases(): array + { + return []; + } + + /** + * Run code inside patch + */ + public function apply() + { + // Start setup + $this->moduleDataSetup->getConnection()->startSetup(); + + try { + // Add customer attribute with settings + $this->customerSetup->addAttribute( + CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + 'externalcorp_external_id', + [ + 'label' => 'External ID', + 'required' => 0, + 'position' => 100, + 'system' => 0, + 'user_defined' => 1, + 'is_used_in_grid' => 1, + 'is_visible_in_grid' => 1, + 'is_filterable_in_grid' => 1, + 'is_searchable_in_grid' => 1, + ] + ); + + // Add attribute to default attribute set and group + $this->customerSetup->addAttributeToSet( + CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + CustomerMetadataInterface::ATTRIBUTE_SET_ID_CUSTOMER, + null, + 'externalcorp_external_id' + ); + + // Get the newly created attribute's model + $attribute = $this->customerSetup->getEavConfig() + ->getAttribute(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, 'externalcorp_external_id'); + + // Make attribute visible in Admin customer form + $attribute->setData('used_in_forms', [ + 'adminhtml_customer' + ]); + + // Save attribute using its resource model + $this->attributeResource->save($attribute); + } catch (Exception $e) { + $this->logger->err($e->getMessage()); + } + + // End setup + $this->moduleDataSetup->getConnection()->endSetup(); + } +} +``` diff --git a/src/guides/v2.4/howdoi/customize-form-configuration.md b/src/guides/v2.4/howdoi/customize-form-configuration.md deleted file mode 120000 index c66115620b1..00000000000 --- a/src/guides/v2.4/howdoi/customize-form-configuration.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/howdoi/customize-form-configuration.md \ No newline at end of file diff --git a/src/guides/v2.4/howdoi/customize-form-configuration.md b/src/guides/v2.4/howdoi/customize-form-configuration.md new file mode 100644 index 00000000000..75da160a50e --- /dev/null +++ b/src/guides/v2.4/howdoi/customize-form-configuration.md @@ -0,0 +1,83 @@ +--- +layout: tutorial +group: how-do-i +subgroup: +title: Customize the form configuration +subtitle: Customize Product Creation Form +menu_node: +level3_subgroup: product-creation-form +menu_order: 2 +--- + +Customizing the form config file (that is, declarative customization) is preferable for changes like introducing new fields, field sets and modals. + +To customize the product creation form, take the following steps: + +1. In your custom module, add an empty `product_form.xml` in the `/view/adminhtml/ui_component/` directory. + +1. In this file, add content similar to the following: + +```xml +
    + +... + +
    + + + %field set label as displayed in UI% + %order for displaying% + + + +
    + + + %Nested fieldset Label as displayed in UI% + true + + + + + + %value% + %value% +.... + + + +
    +
    +... +
    +``` + +## Add new elements {#add-elements} + +By default, the new elements (fields, field sets, modals, grids) which you add in the form configuration file, are displayed on the form whatever product is created; that is, for all [product types](https://glossary.magento.com/product-types). + +In the [modifier class described further]({{page.baseurl}}/howdoi/customize-modifier-class.html), you can set the conditions for displaying certain elements for certain product types. + +## Customize existing fields and field sets {#customize} + +Your `product_form.xml` is merged with the same files from the other modules. So there is no need to copy their content, you only need to define changes. Even if you want to customize the existing entities, you only have to mention those options, the values of which are customized. + +To customize an existing entity, declare only those options, the values of which are customized, do not copy its entire configuration. + +To delete an existing field, or field set, in your `product_form.xml` use the following construction: + +```xml +... +
    + + true + +
    +... +``` + +For reference, view the product form configuration files of the Magento modules: + +* `/view/adminhtml/ui_component/product_form.xml` +* `/view/adminhtml/ui_component/product_form.xml` +* `/view/adminhtml/ui_component/product_form.xml` diff --git a/src/guides/v2.4/howdoi/customize-modifier-class.md b/src/guides/v2.4/howdoi/customize-modifier-class.md deleted file mode 120000 index 61a61bc6417..00000000000 --- a/src/guides/v2.4/howdoi/customize-modifier-class.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/howdoi/customize-modifier-class.md \ No newline at end of file diff --git a/src/guides/v2.4/howdoi/customize-modifier-class.md b/src/guides/v2.4/howdoi/customize-modifier-class.md new file mode 100644 index 00000000000..8a414ae0000 --- /dev/null +++ b/src/guides/v2.4/howdoi/customize-modifier-class.md @@ -0,0 +1,127 @@ +--- +layout: tutorial +group: how-do-i +subgroup: +title: Customize using a modifier class +subtitle: Customize Product Creation Form +menu_node: +level3_subgroup: product-creation-form +menu_order: 3 +--- + +[Modifier classes]({{ page.baseurl }}/ui_comp_guide/concepts/ui_comp_modifier_concept.html) should be used when static declaration is not applicable. For example, in cases when additional data should be loaded from database. Also, modifier is a place where you add validations to display only certain fields for certain product types. + +In the run time, the form structure set in the modifier is merged with the configuration that comes from the `product_form.xml` configuration. + +The `Magento\Catalog\Ui\DataProvider\Product\Form\ProductDataProvider` data provider class is responsible for data and metadata preparation for the product form. The pool of modifiers `Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool` (virtual type) is injected to this data provider using the `__construct()` method. The pool's preference is defined in `di.xml`. + +To add your custom modifier, you need to do the following: + +1. [Add the modifier code.](#modifier) +1. [Add it to the modifiers' pool in `di.xml`](#pool) + +## Add your modifier {#modifier} + +In your custom module directory, add the modifier class that implements the `Magento\UI\DataProvider\Modifier\ModifierInterface` interface or extends the `Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier`class. In your modifier, the `modifyData()` and the `modifyMeta()` methods must be implemented. + +In the modifier class, you can add UI elements using the same structure as in the [XML](https://glossary.magento.com/xml) configuration. + +For example: + +```php + [ + 'data' => [ + 'config' => [ + 'label' => __('Label For Fieldset'), + 'sortOrder' => 50, + 'collapsible' => true, + 'componentType' => Fieldset::NAME + ] + ] + ], + 'children' => [ + 'test_field_name' => [ + 'arguments' => [ + 'data' => [ + 'config' => [ + 'formElement' => 'select', + 'componentType' => Field::NAME, + 'options' => [ + ['value' => 'test_value_1', 'label' => 'Test Value 1'], + ['value' => 'test_value_2', 'label' => 'Test Value 2'], + ['value' => 'test_value_3', 'label' => 'Test Value 3'], + ], + 'visible' => 1, + 'required' => 1, + 'label' => __('Label For Element') + ] + ] + ] + ] + ] + ]; + + return $meta; + } + + /** + * {@inheritdoc} + */ + public function modifyData(array $data) + { + return $data; + } +} +``` + +You can create nested structures of elements by adding them to the `children` key of any element. + +## Add modifier to the pool {#pool} + +In `/etc/adminhtml/di.xml` define your modifier as a dependency for `Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool`. + +The following is an example of such a definition: + +`app/code/Magento/CatalogInventory/etc/adminhtml/di.xml`: + +```xml + + + + + Magento\CatalogInventory\Ui\DataProvider\Product\Form\Modifier\AdvancedInventory + 20 + + + + +``` + +The `sortOrder` parameter defines the order of invocation for your `modifyData()` and `modifyMeta()` methods among other these methods of other modifiers in the pool. If a modifier is first in a pool, its `modifyData()` and `modifyMeta()` are invoked with empty arguments. + +To access product model within your modifier, it's recommended to use an instance of `Magento\Catalog\Model\Locator\LocatorInterface`. + +For reference, view the modifier classes in the Magento modules, for example: + +- [`Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing`]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php) +- [`Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AttributeSet`]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AttributeSet.php) +- [`Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav`]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php) +- [`Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProducts`]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProducts.php) + +For reference about setting conditions for displaying certain elements for certain product types, view `/Ui/DataProvider/Product/Form/Modifier/Eav.php#L476`. diff --git a/src/guides/v2.4/howdoi/customize_product.md b/src/guides/v2.4/howdoi/customize_product.md deleted file mode 120000 index fd8625ac5ad..00000000000 --- a/src/guides/v2.4/howdoi/customize_product.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/howdoi/customize_product.md \ No newline at end of file diff --git a/src/guides/v2.4/howdoi/customize_product.md b/src/guides/v2.4/howdoi/customize_product.md new file mode 100644 index 00000000000..286c2c884b2 --- /dev/null +++ b/src/guides/v2.4/howdoi/customize_product.md @@ -0,0 +1,38 @@ +--- +layout: tutorial +group: how-do-i +subgroup: product-create-page +title: Customize product creation form +menu_title: Initial Tasks +menu_node: +level3_subgroup: product-creation-form +menu_order: 1 +--- + +This tutorial describes how developers can customize the product creation form used on the product creation and product edit pages in [Admin](https://glossary.magento.com/admin). The product creation form is implemented using the [form UI component]({{ page.baseurl }}/ui_comp_guide/components/ui-form.html). + +Product attributes and attribute sets available in the form, can be customized and added under **STORES** > **Attributes** in the Admin. But you can also customize the form view and behavior in code. The following sections describe what files define the form and how they can be customized in your [module](https://glossary.magento.com/module). + +## Prerequisites {#prereqs} + +[Set Magento to developer mode]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-mode.html) while you perform all customizations and debugging. + +For the sake of compatibility, upgradability, and easy maintenance, do not edit the default Magento code. Instead, add your customizations in a separate module. + +## List of customization methods + +This tutorial includes the following customizations: + +* [Customize the form configuration]({{ page.baseurl }}/howdoi/customize-form-configuration.html) +* [Customize using a modifier class]({{ page.baseurl }}/howdoi/customize-modifier-class.html) + +{:.ref-header} +Related topics + +* [Form UI component]({{ page.baseurl }}/ui_comp_guide/components/ui-form.html) +* [About PHP modifiers in UI components]({{ page.baseurl }}/ui_comp_guide/concepts/ui_comp_modifier_concept.html) +* [Dependency injection]({{ page.baseurl }}/extension-dev-guide/depend-inj.html) + +The following image is an illustration of the default view of the form on the **New Product** page: + +![The product creation page in Admin]({{ site.baseurl }}/common/images/product_pmg.png) From 83729f2ad11fae0112451b0fbb975b698a844933 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Thu, 9 Jun 2022 09:54:55 -0500 Subject: [PATCH 144/776] Added migration metadata --- src/guides/v2.4/howdoi/admin/customize_admin.md | 2 ++ src/guides/v2.4/howdoi/checkout/checkout-add-custom-carrier.md | 2 ++ src/guides/v2.4/howdoi/checkout/checkout_address.md | 2 ++ src/guides/v2.4/howdoi/checkout/checkout_carrier.md | 2 ++ src/guides/v2.4/howdoi/checkout/checkout_custom_checkbox.md | 2 ++ src/guides/v2.4/howdoi/checkout/checkout_customize.md | 2 ++ src/guides/v2.4/howdoi/checkout/checkout_edit_form.md | 2 ++ src/guides/v2.4/howdoi/checkout/checkout_form.md | 2 ++ src/guides/v2.4/howdoi/checkout/checkout_new_field.md | 2 ++ src/guides/v2.4/howdoi/checkout/checkout_new_step.md | 2 ++ src/guides/v2.4/howdoi/checkout/checkout_order.md | 2 ++ src/guides/v2.4/howdoi/checkout/checkout_overview.md | 2 ++ src/guides/v2.4/howdoi/checkout/checkout_payment.md | 2 ++ src/guides/v2.4/howdoi/checkout/checkout_payment_new_field.md | 2 ++ src/guides/v2.4/howdoi/checkout/checkout_shipping_methods.md | 2 ++ src/guides/v2.4/howdoi/checkout/checkout_zip.md | 2 ++ src/guides/v2.4/howdoi/custom-attributes/introduction.md | 2 ++ src/guides/v2.4/howdoi/custom-attributes/text-field.md | 2 ++ src/guides/v2.4/howdoi/customize-form-configuration.md | 2 ++ src/guides/v2.4/howdoi/customize-modifier-class.md | 2 ++ src/guides/v2.4/howdoi/customize_product.md | 2 ++ 21 files changed, 42 insertions(+) diff --git a/src/guides/v2.4/howdoi/admin/customize_admin.md b/src/guides/v2.4/howdoi/admin/customize_admin.md index c5364c29060..0bfc52b111a 100644 --- a/src/guides/v2.4/howdoi/admin/customize_admin.md +++ b/src/guides/v2.4/howdoi/admin/customize_admin.md @@ -1,6 +1,8 @@ --- group: how-do-i title: Customize the design +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-admin-design/ +layout: migrated --- Learn how to customize (add, delete, change) the configuration options available in the Admin. These options define the various aspects of storefront design. diff --git a/src/guides/v2.4/howdoi/checkout/checkout-add-custom-carrier.md b/src/guides/v2.4/howdoi/checkout/checkout-add-custom-carrier.md index 8cfb842da6b..557c419b7aa 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout-add-custom-carrier.md +++ b/src/guides/v2.4/howdoi/checkout/checkout-add-custom-carrier.md @@ -10,6 +10,8 @@ menu_order: 5 level3_subgroup: checkout-tutorial functional_areas: - Checkout +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-shipping-carrier/ +layout: migrated --- This topic describes how to add a custom shipping carrier. diff --git a/src/guides/v2.4/howdoi/checkout/checkout_address.md b/src/guides/v2.4/howdoi/checkout/checkout_address.md index e7f0cd7bd4c..468eabda7aa 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_address.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_address.md @@ -8,6 +8,8 @@ menu_order: 11 level3_subgroup: checkout-tutorial functional_areas: - Checkout +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-address-renderer/ +layout: migrated --- This topic describes how to implement a custom shipping address renderer. diff --git a/src/guides/v2.4/howdoi/checkout/checkout_carrier.md b/src/guides/v2.4/howdoi/checkout/checkout_carrier.md index a9409259a3f..320484e48f4 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_carrier.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_carrier.md @@ -8,6 +8,8 @@ menu_order: 6 level3_subgroup: checkout-tutorial functional_areas: - Checkout +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-carrier-validation/ +layout: migrated --- This topic describes how to add shipping address validations for a custom [shipping carrier](https://glossary.magento.com/shipping-carrier) to the Magento [checkout](https://glossary.magento.com/checkout). This is an essential part of the bigger task of adding a custom shipping method to your Magento store. diff --git a/src/guides/v2.4/howdoi/checkout/checkout_custom_checkbox.md b/src/guides/v2.4/howdoi/checkout/checkout_custom_checkbox.md index 0d12627b3ba..bf118a7b9a5 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_custom_checkbox.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_custom_checkbox.md @@ -8,6 +8,8 @@ menu_order: 90 level3_subgroup: checkout-tutorial functional_areas: - Checkout +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-checkbox/ +layout: migrated --- This topic describes how to add a custom field that influences other fields on the checkout page. diff --git a/src/guides/v2.4/howdoi/checkout/checkout_customize.md b/src/guides/v2.4/howdoi/checkout/checkout_customize.md index e258f985bca..184b57753c7 100755 --- a/src/guides/v2.4/howdoi/checkout/checkout_customize.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_customize.md @@ -8,6 +8,8 @@ menu_order: 2 level3_subgroup: checkout-tutorial functional_areas: - Checkout +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/customize-view/ +layout: migrated --- This topic contains the basic information about how to customize the view of an existing [checkout](https://glossary.magento.com/checkout) step. In the Magento application, checkout is implemented using UI components. You can customize each step by [changing the JavaScript implementation or template](#change-component) for a component, [adding](#add), [disabling](#disable), or [removing](#remove) a component. diff --git a/src/guides/v2.4/howdoi/checkout/checkout_edit_form.md b/src/guides/v2.4/howdoi/checkout/checkout_edit_form.md index abd62dced5e..58b98205951 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_edit_form.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_edit_form.md @@ -8,6 +8,8 @@ menu_order: 8 level3_subgroup: checkout-tutorial functional_areas: - Checkout +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-template/ +layout: migrated --- This topic describes how to replace the [HTML](https://glossary.magento.com/html) template for a form field on the [Checkout](https://glossary.magento.com/checkout) page. You might need to replace the template in order to add elements displayed with the field, change the [CSS](https://glossary.magento.com/css) class assigned to it, add attributes and so on. diff --git a/src/guides/v2.4/howdoi/checkout/checkout_form.md b/src/guides/v2.4/howdoi/checkout/checkout_form.md index eeb90c6bb1f..4dd47386187 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_form.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_form.md @@ -8,6 +8,8 @@ menu_order: 9 level3_subgroup: checkout-tutorial functional_areas: - Checkout +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-form/ +layout: migrated --- This topic describes how to add a custom input form (implemented as a UI component) to the [Checkout](https://glossary.magento.com/checkout) page. diff --git a/src/guides/v2.4/howdoi/checkout/checkout_new_field.md b/src/guides/v2.4/howdoi/checkout/checkout_new_field.md index 4e5f0d4593b..12ed93be5c8 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_new_field.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_new_field.md @@ -8,6 +8,8 @@ menu_order: 9 level3_subgroup: checkout-tutorial functional_areas: - Checkout +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-address-field/ +layout: migrated --- You can add new fields to default [checkout](https://glossary.magento.com/checkout) forms, such as shipping address or billing address forms. To illustrate this ability, this topic describes adding a field to the shipping address form. diff --git a/src/guides/v2.4/howdoi/checkout/checkout_new_step.md b/src/guides/v2.4/howdoi/checkout/checkout_new_step.md index db8b552ca4d..4a10540d76a 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_new_step.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_new_step.md @@ -8,6 +8,8 @@ menu_order: 1 level3_subgroup: checkout-tutorial functional_areas: - Checkout +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-new-step/ +layout: migrated --- This topic describes how to create the [frontend](https://glossary.magento.com/frontend) part of the component, implementing a checkout step, and how to add it to the checkout flow. diff --git a/src/guides/v2.4/howdoi/checkout/checkout_order.md b/src/guides/v2.4/howdoi/checkout/checkout_order.md index 0a022f723df..f0c93586544 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_order.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_order.md @@ -8,6 +8,8 @@ menu_order: 4 level3_subgroup: checkout-tutorial functional_areas: - Checkout +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-order-validation/ +layout: migrated --- This topic describes how to add custom validations to be performed before the order is placed during [checkout](https://glossary.magento.com/checkout). Namely, the validations which are performed after a shopper clicks the **Place Order** button. Writing the validation logic itself is not covered in this topic. diff --git a/src/guides/v2.4/howdoi/checkout/checkout_overview.md b/src/guides/v2.4/howdoi/checkout/checkout_overview.md index da468936397..966c92934c5 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_overview.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_overview.md @@ -9,6 +9,8 @@ level3_subgroup: checkout-tutorial menu_order: 0 functional_areas: - Checkout +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/ +layout: migrated --- Magento [checkout](https://glossary.magento.com/checkout) is implemented using the [UI components]({{ page.baseurl }}/ui_comp_guide/bk-ui_comps.html). diff --git a/src/guides/v2.4/howdoi/checkout/checkout_payment.md b/src/guides/v2.4/howdoi/checkout/checkout_payment.md index 955d12e39c5..9632608b126 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_payment.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_payment.md @@ -8,6 +8,8 @@ menu_order: 3 level3_subgroup: checkout-tutorial functional_areas: - Checkout +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-payment-method/ +layout: migrated --- Out of the box, Magento [checkout](https://glossary.magento.com/checkout) consists of two steps: diff --git a/src/guides/v2.4/howdoi/checkout/checkout_payment_new_field.md b/src/guides/v2.4/howdoi/checkout/checkout_payment_new_field.md index 9de6a58c3a6..8838b2c1598 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_payment_new_field.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_payment_new_field.md @@ -10,6 +10,8 @@ menu_order: 101 level3_subgroup: checkout-tutorial functional_areas: - Checkout +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-payment-field/ +layout: migrated --- This topic describes how to add a custom field to an offline payment method in the payment step of the checkout. The custom field allows the buyer to enter a comment about a purchase order. diff --git a/src/guides/v2.4/howdoi/checkout/checkout_shipping_methods.md b/src/guides/v2.4/howdoi/checkout/checkout_shipping_methods.md index f8a4fd2e640..ba8b7a50122 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_shipping_methods.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_shipping_methods.md @@ -6,6 +6,8 @@ title: Customize the list of shipping methods subtitle: Customize Checkout menu_order: 100 level3_subgroup: checkout-tutorial +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-shipping-methods/ +layout: migrated --- This topic describes how to customize list of shipping methods displayed on the checkout page. diff --git a/src/guides/v2.4/howdoi/checkout/checkout_zip.md b/src/guides/v2.4/howdoi/checkout/checkout_zip.md index e053683879e..e7c2a517374 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_zip.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_zip.md @@ -8,6 +8,8 @@ menu_order: 7 level3_subgroup: checkout-tutorial functional_areas: - Checkout +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-input-mask/ +layout: migrated --- This topic describes how a developer can add custom input masks. diff --git a/src/guides/v2.4/howdoi/custom-attributes/introduction.md b/src/guides/v2.4/howdoi/custom-attributes/introduction.md index cfbffb05a40..caaa4daa5f6 100644 --- a/src/guides/v2.4/howdoi/custom-attributes/introduction.md +++ b/src/guides/v2.4/howdoi/custom-attributes/introduction.md @@ -8,6 +8,8 @@ level3_subgroup: custom-attributes menu_order: 1 contributor_name: Adarsh Manickam contributor_link: https://github.com/drpayyne +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-attributes/ +layout: migrated --- The tutorials under this section guide Magento developers on setting up and configuring custom attributes. diff --git a/src/guides/v2.4/howdoi/custom-attributes/text-field.md b/src/guides/v2.4/howdoi/custom-attributes/text-field.md index 020d8af7c00..1c4f60837e8 100644 --- a/src/guides/v2.4/howdoi/custom-attributes/text-field.md +++ b/src/guides/v2.4/howdoi/custom-attributes/text-field.md @@ -8,6 +8,8 @@ level3_subgroup: custom-attributes menu_order: 2 contributor_name: Adarsh Manickam contributor_link: https://github.com/drpayyne +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-attributes/text-field/ +layout: migrated --- ## Overview diff --git a/src/guides/v2.4/howdoi/customize-form-configuration.md b/src/guides/v2.4/howdoi/customize-form-configuration.md index 75da160a50e..71685c0a045 100644 --- a/src/guides/v2.4/howdoi/customize-form-configuration.md +++ b/src/guides/v2.4/howdoi/customize-form-configuration.md @@ -7,6 +7,8 @@ subtitle: Customize Product Creation Form menu_node: level3_subgroup: product-creation-form menu_order: 2 +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-product-creation-form/configuration/ +layout: migrated --- Customizing the form config file (that is, declarative customization) is preferable for changes like introducing new fields, field sets and modals. diff --git a/src/guides/v2.4/howdoi/customize-modifier-class.md b/src/guides/v2.4/howdoi/customize-modifier-class.md index 8a414ae0000..57632674c41 100644 --- a/src/guides/v2.4/howdoi/customize-modifier-class.md +++ b/src/guides/v2.4/howdoi/customize-modifier-class.md @@ -7,6 +7,8 @@ subtitle: Customize Product Creation Form menu_node: level3_subgroup: product-creation-form menu_order: 3 +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-product-creation-form/modifier-class/ +layout: migrated --- [Modifier classes]({{ page.baseurl }}/ui_comp_guide/concepts/ui_comp_modifier_concept.html) should be used when static declaration is not applicable. For example, in cases when additional data should be loaded from database. Also, modifier is a place where you add validations to display only certain fields for certain product types. diff --git a/src/guides/v2.4/howdoi/customize_product.md b/src/guides/v2.4/howdoi/customize_product.md index 286c2c884b2..59d45bdf110 100644 --- a/src/guides/v2.4/howdoi/customize_product.md +++ b/src/guides/v2.4/howdoi/customize_product.md @@ -7,6 +7,8 @@ menu_title: Initial Tasks menu_node: level3_subgroup: product-creation-form menu_order: 1 +migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-product-creation-form/ +layout: migrated --- This tutorial describes how developers can customize the product creation form used on the product creation and product edit pages in [Admin](https://glossary.magento.com/admin). The product creation form is implemented using the [form UI component]({{ page.baseurl }}/ui_comp_guide/components/ui-form.html). From 9dc1ed40d62f9950604c42748564e2bd31bcbdc8 Mon Sep 17 00:00:00 2001 From: Buba Suma Date: Thu, 9 Jun 2022 10:17:55 -0500 Subject: [PATCH 145/776] ACP2E-782: Introduce an alternative way to define fixtures using PHP8 Attributes --- .../integration/parameterized_data_fixture.md | 58 +++++++++---------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/src/guides/v2.4/test/integration/parameterized_data_fixture.md b/src/guides/v2.4/test/integration/parameterized_data_fixture.md index c5aaa2b88d3..99c9b2ed971 100644 --- a/src/guides/v2.4/test/integration/parameterized_data_fixture.md +++ b/src/guides/v2.4/test/integration/parameterized_data_fixture.md @@ -8,13 +8,14 @@ Parameterized Data Fixture is currently only available for Magento Open Source c ## Overview -Parameterized data fixture is a dynamic and scalable data fixture that accepts parameters directly from annotations. It eliminates the need to create almost identical fixtures every time you need a slight change. +Parameterized data fixture is a dynamic and scalable data fixture that accepts parameters directly from the fixture declaration. It eliminates the need to create almost identical fixtures every time you need a slight change. ## Principles 1. Parameterized Data Fixture class MUST implement `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface` if the data created by the fixture is revertible. For instance, a fixture that creates an entity (for example, product). 1. Parameterized Data Fixture class MUST be placed in the `/Test/Fixture` folder of the corresponding module with namespace: `\\Test\Fixture` (for example, `Magento\Catalog\Test\Fixture`). 1. Parameterized Data Fixture class SHOULD follow single responsibility principle. +1. Parameterized Data Fixture class MUST depend only on services from modules that are declared in the `require` section of its module's composer.json. 1. Parameterized Data Fixture MUST NOT depend on another fixture. 1. Parameterized Data Fixture SHOULD be implemented using service APIs. 1. Parameterized Data Fixture SHOULD have dynamic default data to allow generating unique fixtures. @@ -28,12 +29,12 @@ In order to generate multiple fixtures of the same type without having to manual In the following example, a unique `sku` is automatically generated for the first fixture (for example, `simple-product61c10b2e86f991`) and the second fixture (for example, `simple-product61c10b2e86f992`). The sequence is random and therefore unpredictable. ```php?start_inline=1 -class ProductsList extends \PHPUnit\Framework\TestCase +class ProductsListTest extends \PHPUnit\Framework\TestCase { - /** - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product - */ + #[ + DataFixture(ProductFixture::class), + DataFixture(ProductFixture::class) + ] public function testGetProductsCount(): void { } @@ -54,14 +55,13 @@ Example 1: class QuoteTest extends \PHPUnit\Framework\TestCase { - /** - * @magentoApiDataFixture Magento\Catalog\Test\Fixture\Product as:product - * @magentoApiDataFixture Magento\Quote\Test\Fixture\GuestCart as:cart - * @magentoApiDataFixture Magento\Quote\Test\Fixture\AddProductToCart as:item1 - * @magentoApiDataFixture Magento\Quote\Test\Fixture\SetBillingAddress with:{"cart_id":"$cart.id$"} - * @magentoApiDataFixture Magento\Quote\Test\Fixture\SetShippingAddress with:{"cart_id":"$cart.id$"} - * @magentoDataFixtureDataProvider {"item1":{"cart_id":"$cart.id$","product_id":"$product.id$","qty":2}} - */ + #[ + DataFixture(ProductFixture::class, as: 'p'), + DataFixture(GuestCartFixture::class, as: 'cart'), + DataFixture(AddProductToCartFixture::class, ['cart_id' => '$cart.id$', 'product_id' => '$p.id$', 'qty' => 2]), + DataFixture(SetBillingAddressFixture::class, ['cart_id' => '$cart.id$']), + DataFixture(SetShippingAddressFixture::class, ['cart_id' => '$cart.id$']), + ] public function testCollectTotals(): void { } @@ -73,22 +73,20 @@ Example 2: ```php?start_inline=1 class PriceTest extends \PHPUnit\Framework\TestCase { - /** - * Test for bundle with fixed price - * - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product with:{"price":10} as:p1 - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product with:{"price":20} as:p2 - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product with:{"price":30} as:p3 - * @magentoDataFixture Magento\Bundle\Test\Fixture\Link with:{"sku":"$p1.sku$","price":10,"price_type":0} as:link1 - * @magentoDataFixture Magento\Bundle\Test\Fixture\Link with:{"sku":"$p2.sku$","price":25,"price_type":1} as:link2 - * @magentoDataFixture Magento\Bundle\Test\Fixture\Link with:{"sku":"$p3.sku$","price":25,"price_type":0} as:link3 - * @magentoDataFixture Magento\Bundle\Test\Fixture\Option as:opt1 - * @magentoDataFixture Magento\Bundle\Test\Fixture\Product as:bundle1 - * @magentoDataFixtureDataProvider {"opt1":{"product_links":["$link1$","$link2$","$link3$"]}} - * @magentoDataFixtureDataProvider {"bundle1":{"price":50,"price_type":1,"_options":["$opt1$"]}} - * - * @return void - */ + #[ + DataFixture(ProductFixture::class, ['sku' => 'simple1', 'price' => 10], 'p1'), + DataFixture(ProductFixture::class, ['sku' => 'simple2', 'price' => 20], 'p2'), + DataFixture(ProductFixture::class, ['sku' => 'simple3', 'price' => 30], 'p3'), + DataFixture(BundleSelectionFixture::class, ['sku' => '$p1.sku$', 'price' => 10, 'price_type' => 0], 'link1'), + DataFixture(BundleSelectionFixture::class, ['sku' => '$p2.sku$', 'price' => 25, 'price_type' => 1], 'link2'), + DataFixture(BundleSelectionFixture::class, ['sku' => '$p3.sku$', 'price' => 25, 'price_type' => 0], 'link3'), + DataFixture(BundleOptionFixture::class, ['product_links' => ['$link1$', '$link2$', '$link3$']], 'opt1'), + DataFixture( + BundleProductFixture::class, + ['sku' => 'bundle1','price' => 50,'price_type' => 1,'_options' => ['$opt1$']], + 'bundle1' + ), + ] public function testBundleWithFixedPrice(): void { From 9dc9a4301646f2bb1f6951ffbe2dbfd78090cbc6 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Thu, 9 Jun 2022 11:14:50 -0500 Subject: [PATCH 146/776] Fixed blog link --- src/release/policy/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/release/policy/index.md b/src/release/policy/index.md index 9ab016847f7..ea15bf4c1b7 100644 --- a/src/release/policy/index.md +++ b/src/release/policy/index.md @@ -45,7 +45,7 @@ With security patch releases, you can keep your site more secure without app Each security patch release is based on the prior full patch release, hence it contains quality and security fixes from prior patch release and security fixes created between the prior full patch release and the security patch release. -With the announcement of our [new release strategy and updated lifecycle policy](https://magento.com/blog/accelerating-innovation-through-simplified-release-strategy) (9/16/2021), our security patch releases are differentiated based on whether they are applicable to the latest-supported minor release or a part of a still-supported previous minor release line: +With the announcement of our [new release strategy and updated lifecycle policy](https://business.adobe.com/blog/how-to/accelerating-innovation-through-simplified-release-strategy) (9/16/2021), our security patch releases are differentiated based on whether they are applicable to the latest-supported minor release or a part of a still-supported previous minor release line: - **Security patch releases for the latest-supported minor release**: From 3c7a6ad7df8b7b9cdac19e1f1e52218f24e212b1 Mon Sep 17 00:00:00 2001 From: gregory-marshall Date: Thu, 9 Jun 2022 17:57:44 -0700 Subject: [PATCH 147/776] Fixed version num 36424 --- src/quality-patches/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quality-patches/release-notes.md b/src/quality-patches/release-notes.md index 6a1e0bac192..16fd01ddf61 100644 --- a/src/quality-patches/release-notes.md +++ b/src/quality-patches/release-notes.md @@ -266,7 +266,7 @@ For information about quality patches created by the Community for {{site.data.v - **MDVA-36615** _(for Magento `2.4.2`)_-Fixes the issue with incorrect product count in admin product grid. - **MDVA-36464** _(for Magento `>=2.4.0 <=2.4.2`)_-Fixes the issue where the email notification configuration is not working at store-view level. - **MDVA-36138** _(for Magento `^2.3.2`)_-Fixes the issue where the shipping price is not adjusted and full shipping price is shown to customers if not all items in the cart qualify for the free shipping cart rule. -- **MDVA-36424** _(for Magento `>=1.3.0 <=1.3.3-p1 || >=2.0.0 <2.2.0`)_-Fixes the issue where media images, attached to page builder elements, disappear when the content is being edited repeatedly, if the backend base URL is different from the storefront base URL. +- **MDVA-36424** _(for Magento `>=2.3.0 <=2.3.3-p1 || >=2.0.0 <2.2.0`)_-Fixes the issue where media images, attached to page builder elements, disappear when the content is being edited repeatedly, if the backend base URL is different from the storefront base URL. - **MDVA-35984** _(for Magento `^2.4.0`)_-Fixes the issue with incorrect product quantity and sellable quantity, after creating multiple concurrent shipments for the same product. ## v1.0.20 From 0c4eb2df8260cf6c2f99253affebe189d256386b Mon Sep 17 00:00:00 2001 From: jasperzeinstra Date: Fri, 10 Jun 2022 10:54:50 +0200 Subject: [PATCH 148/776] targetWidget parameter and return was missing As stated in https://devdocs.magento.com/guides/v2.4/javascript-dev-guide/javascript/js_mixins.html#examples, when writing a mixin for jQuery widgets you should have a parameter "targetWidget" and also return a jQuery widget. In this case about adding validation rules we don't change the targetWidget, so we should just return this. Not returning the targetWidget will throw a JS error. --- .../v2.3/frontend-dev-guide/validations/custom-validation.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/guides/v2.3/frontend-dev-guide/validations/custom-validation.md b/src/guides/v2.3/frontend-dev-guide/validations/custom-validation.md index 312b5960f7a..a4942bd4325 100644 --- a/src/guides/v2.3/frontend-dev-guide/validations/custom-validation.md +++ b/src/guides/v2.3/frontend-dev-guide/validations/custom-validation.md @@ -39,7 +39,7 @@ var config = { define(['jquery'], function($) { 'use strict'; - return function() { + return function(targetWidget) { $.validator.addMethod( 'validate-five-words', function(value, element) { @@ -47,6 +47,8 @@ define(['jquery'], function($) { }, $.mage.__('Please enter exactly five words') ) + + return targetWidget; } }); ``` From de4f6b0f3997a0395562d24cbcf11f100e2f2dfe Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Fri, 10 Jun 2022 08:33:26 -0500 Subject: [PATCH 149/776] Clarify pro configuration notes across cloud docs --- .../note-pro-missing-self-service-options.md | 9 ++++++-- src/cloud/env/environments.md | 9 ++------ src/cloud/project/project-multi-sites.md | 7 +++--- .../project/project-routes-more-redir.md | 22 +++++++++++-------- src/cloud/project/routes.md | 6 +++-- 5 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/_includes/cloud/note-pro-missing-self-service-options.md b/src/_includes/cloud/note-pro-missing-self-service-options.md index 1d665e74811..0622e65c9d6 100644 --- a/src/_includes/cloud/note-pro-missing-self-service-options.md +++ b/src/_includes/cloud/note-pro-missing-self-service-options.md @@ -1,2 +1,7 @@ - {:.bs-callout-info} -On Pro projects, we recommend updating YAML configuration files in an Integration environment and testing the changes before pushing the updates to Staging and Production environments. If you discover that configuration changes are not applied to Staging and Production sites after you redeploy and do not see any related error messages in the log, submit a [Support ticket](http://support.magento.com) that describes the attempted configuration changes. Include any updated YAML configuration files in the ticket. +For {{site.data.var.ece}} Pro Staging and Production environments, you can update many configuration options in your local development environment and commit the changes to apply them to these environments. However, you must [Support ticket](http://support.magento.com) to update the following configuration options: + +- Install or update services in the `.magento/services.yaml` file. +- Change the configuration for the `mounts` and `disk` properties in the `.magento.app.yaml` file. + +{:.bs-callout-warning} +Some **Pro projects** require a support ticket to update the route configuration in the `routes.yaml` file and the cron configuration in the `.magento.app.yaml` file. Adobe recommends updating and testing YAML configuration files in an Integration environment, then deploying changes to the Staging environment. If you discover that your configuration changes are not applied to Staging sites after you redeploy and do not see any related error messages in the log, then you **MUST** submit a [Support ticket](http://support.magento.com) that describes the attempted configuration changes. Include any updated YAML configuration files in the ticket. diff --git a/src/cloud/env/environments.md b/src/cloud/env/environments.md index 07035fb505d..f828249f214 100644 --- a/src/cloud/env/environments.md +++ b/src/cloud/env/environments.md @@ -18,11 +18,6 @@ You can configure application settings, routes, build and deploy actions, and no When you push code changes, the active environment provisions container updates using the YAML configuration files. -## Update Pro Staging and Production environment configuration +## Configuration updates to Pro environments -For {{site.data.var.ece}} Pro Staging and Production environments, you can update many configuration options in your local development environment and commit the changes to apply them to these environments. However, you must submit a support ticket to update the following configuration options: - -- Install or update services in the `.magento/services.yaml` file. -- Change the configuration for the `mounts` and `disk` properties in the `.magento.app.yaml` file. - -Some Pro projects might also require a support ticket to update the [route configuration]({{site.baseurl}}/cloud/project/routes.html) in the `routes.yaml` file, and the [cron configuration]({{site.baseurl}}/cloud/configure/setup-cron-jobs.html) in the `.magento.app.yaml` file. +{% include cloud/note-pro-missing-self-service-options.md %} diff --git a/src/cloud/project/project-multi-sites.md b/src/cloud/project/project-multi-sites.md index aa6970b9ffa..09c8269a408 100644 --- a/src/cloud/project/project-multi-sites.md +++ b/src/cloud/project/project-multi-sites.md @@ -64,13 +64,14 @@ After successfully creating and testing the local installation to use multiple s {:.bs-callout-tip} You can also use a local {{site.data.var.mcd-prod}} environment to set up multiple websites or stores. See the Cloud Docker instructions to [Set up multiple websites or stores]({{site.baseurl}}/cloud/docker/docker-multi-website.html). +### Configuration updates to Pro environments + +{% include cloud/note-pro-missing-self-service-options.md %} + ### Configure routes for separate domains {#routes} Routes define how to process incoming URLs. Multiple stores with unique domains require you to define each domain in the `routes.yaml` file. The way you configure routes depends on how you want your site to operate. -{:.bs-callout-info} -For Pro, if your route configurations are not setting properly, you can create a [Support ticket]({{ site.baseurl }}/cloud/trouble/trouble.html) and include "enable self-service routes" in your request. - {:.procedure} To configure routes in an integration environment: diff --git a/src/cloud/project/project-routes-more-redir.md b/src/cloud/project/project-routes-more-redir.md index 3f6b7eebc62..aaf6530cec3 100644 --- a/src/cloud/project/project-routes-more-redir.md +++ b/src/cloud/project/project-routes-more-redir.md @@ -12,10 +12,14 @@ The following demonstrates how to manage redirection rules on your {{site.data.v {% include cloud/note-route-all-placeholder.md %} +## Updates to Pro environments + +{% include cloud/note-pro-missing-self-service-options.md %} + {:.bs-callout-warning} For {{ site.data.var.ece }} projects, configuring large numbers of non-regex redirects and rewrites in the `routes.yaml` file can cause performance issues. If your `routes.yaml` file is 32KB or larger, offload your non-regex redirects and rewrites to Fastly. See [Offload non-regex redirects to Fastly instead of Nginx (routes)](https://support.magento.com/hc/en-us/articles/360035192891-Offload-non-regex-redirects-to-Fastly-instead-of-Nginx-routes-) in the _{{site.data.var.ee}} Help Center_. -## Whole-route redirects {#cloud-route-whole} +## Whole-route redirects Using whole-route redirects, you can define simple routes using the `routes.yaml` file. For example, you can redirect from an apex domain to a `www` subdomain as follows: @@ -25,7 +29,7 @@ http://{default}/: to: http://www.{default}/ ``` -## Partial-route redirects {#cloud-route-partial} +## Partial-route redirects In the [`.magento/routes.yaml`]({{ site.baseurl }}/cloud/project/routes.html) file, you can also add partial redirect rules to existing routes based on pattern matching: @@ -59,11 +63,11 @@ Two keys are available under `redirects`: `code` | Specifies the HTTP status code. Valid status codes are [`301` (Moved Permanently)](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.2), [`302`](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.3), [`307`](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.8), and [`308`](https://tools.ietf.org/html/rfc7238). Defaults to `302`. `expires`| Optional, specifies the amount of time to cache the redirect in the browser. Defaults to the `expires` value defined directly under the `redirects` key, but at this level you can fine-tune the cache expiration for individual partial redirects. -### Examples +## Examples of partial-route redirects The following examples show how to specify partial-route redirects in the `routes.yaml` file using various `paths` configuration options. -#### Regular expression pattern matching {#redirect-with-regex} +### Regular expression pattern matching Use the following format to configure redirect requests based on a regular expression. @@ -77,7 +81,7 @@ http://{default}/: This configuration filters request paths against a regular expression and redirects matching requests to `https://example.com`. For example, a request to `https://example.com/regexp/a/b/c/match` redirects to `https://example.com/a/b/c`. -#### Prefix pattern matching {#redirect-with-prefix} +### Prefix pattern matching Use the following format to configure redirect requests for paths that begin with a specified prefix pattern. @@ -97,7 +101,7 @@ This configuration works as follows: - If you change the `prefix` property to `false`, requests that match the pattern `/from` trigger a redirect, but requests that match the pattern `/from/another/path` does not. -#### Suffix pattern matching {#redirect-with-suffix} +### Suffix pattern matching Use the following format to configure redirect requests which append the path suffix from the request to the target destination. @@ -114,7 +118,7 @@ This configuration works as follows: - If you change the `append_suffix` property to `true`, then requests that match `/from/path/suffix` redirect to the path `https://{default}/to/path/suffix`. -#### Path-specific cache configuration {#redirect-with-custom-cache} +### Path-specific cache configuration Use the following format to customize the time to cache a redirect from a specific path: @@ -130,6 +134,6 @@ http://{default}/: This configuration works as follows: -- Redirects from the first path (`/from`) are cached for 1 day. +- Redirects from the first path (`/from`) are cached for one day. -- Redirects from the second path (`/here`) are cached for 2 weeks. +- Redirects from the second path (`/here`) are cached for two weeks. diff --git a/src/cloud/project/routes.md b/src/cloud/project/routes.md index 7daed31a86e..ffa02b2ba2b 100644 --- a/src/cloud/project/routes.md +++ b/src/cloud/project/routes.md @@ -10,8 +10,6 @@ redirect_from: The `routes.yaml` file in the `.magento/routes.yaml` directory defines routes for your {{ site.data.var.ece }} Integration, Staging, and Production environments. Routes determine how the application processes incoming HTTP and HTTPS requests. -{% include cloud/note-pro-missing-self-service-options.md %} - The default `routes.yaml` file specifies the route templates for processing HTTP requests as HTTPS on projects that have a single default domain and on projects configured for multiple domains: ```yaml @@ -36,6 +34,10 @@ magento-cloud environment:routes ``` {:.no-copy} +## Configuration updates to Pro environments + +{% include cloud/note-pro-missing-self-service-options.md %} + ## Route templates The `routes.yaml` file is a list of templated routes and their configurations. You can use the following placeholders in route templates: From bdf5149ce885f0ba1501cf40cd84d8fdda66e768 Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Fri, 10 Jun 2022 08:42:49 -0500 Subject: [PATCH 150/776] Update magento-app.md --- src/cloud/project/magento-app.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cloud/project/magento-app.md b/src/cloud/project/magento-app.md index 34f5ff630a3..c360acba8f4 100644 --- a/src/cloud/project/magento-app.md +++ b/src/cloud/project/magento-app.md @@ -19,3 +19,7 @@ Use the `.magento.app.yaml` file to define the following configuration values: - [PHP Application]({{ site.baseurl }}/cloud/project/magento-app-php-application.html)—Configure runtime PHP options. - [Workers]({{ site.baseurl }}/cloud/project/magento-app-workers.html)—Create a worker instance and understand background tasks. - [Set Cache For Static Files]({{ site.baseurl }}/cloud/project/set-cache.html)—Set cache time-to-live (TTL) for your media and static files. + +## Configuration updates to Pro environments + +{% include cloud/note-pro-missing-self-service-options.md %} From 7f42ec5440f8bc7a8aa1a874a901174746fec7a2 Mon Sep 17 00:00:00 2001 From: hguthrie Date: Fri, 10 Jun 2022 09:39:58 -0500 Subject: [PATCH 151/776] Apply suggestions from code review Co-authored-by: Jeff Matthews --- src/_includes/cloud/note-pro-missing-self-service-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_includes/cloud/note-pro-missing-self-service-options.md b/src/_includes/cloud/note-pro-missing-self-service-options.md index 0622e65c9d6..abedf6e2e19 100644 --- a/src/_includes/cloud/note-pro-missing-self-service-options.md +++ b/src/_includes/cloud/note-pro-missing-self-service-options.md @@ -1,4 +1,4 @@ -For {{site.data.var.ece}} Pro Staging and Production environments, you can update many configuration options in your local development environment and commit the changes to apply them to these environments. However, you must [Support ticket](http://support.magento.com) to update the following configuration options: +For {{site.data.var.ece}} Pro Staging and Production environments, you can update many configuration options in your local development environment and commit the changes to apply them to these environments. However, you must submit a [Support ticket](http://support.magento.com) to update the following configuration options: - Install or update services in the `.magento/services.yaml` file. - Change the configuration for the `mounts` and `disk` properties in the `.magento.app.yaml` file. From 06b49219a240a2717a93a5d9f6bc802db0048e1d Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Fri, 10 Jun 2022 12:42:32 -0500 Subject: [PATCH 152/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- src/_data/toc/testing.yml | 31 ++- src/_data/whats-new.yml | 15 -- .../v2.4/test/integration/annotations.md | 4 + .../magento-data-fixture-data-provider.md | 120 --------- .../annotations/magento-data-fixture.md | 98 +------ .../v2.4/test/integration/attributes.md | 48 ++++ .../attributes/magento-app-area.md | 112 ++++++++ .../attributes/magento-app-isolation.md | 73 ++++++ .../integration/attributes/magento-cache.md | 96 +++++++ .../attributes/magento-components-dir.md | 80 ++++++ .../attributes/magento-config-fixture.md | 241 ++++++++++++++++++ .../attributes/magento-data-fixture.md | 213 ++++++++++++++++ .../attributes/magento-db-isolation.md | 88 +++++++ 13 files changed, 986 insertions(+), 233 deletions(-) delete mode 100644 src/guides/v2.4/test/integration/annotations/magento-data-fixture-data-provider.md create mode 100644 src/guides/v2.4/test/integration/attributes.md create mode 100644 src/guides/v2.4/test/integration/attributes/magento-app-area.md create mode 100644 src/guides/v2.4/test/integration/attributes/magento-app-isolation.md create mode 100644 src/guides/v2.4/test/integration/attributes/magento-cache.md create mode 100644 src/guides/v2.4/test/integration/attributes/magento-components-dir.md create mode 100644 src/guides/v2.4/test/integration/attributes/magento-config-fixture.md create mode 100644 src/guides/v2.4/test/integration/attributes/magento-data-fixture.md create mode 100644 src/guides/v2.4/test/integration/attributes/magento-db-isolation.md diff --git a/src/_data/toc/testing.yml b/src/_data/toc/testing.yml index f46d64c298a..07a9c492287 100644 --- a/src/_data/toc/testing.yml +++ b/src/_data/toc/testing.yml @@ -34,13 +34,36 @@ pages: - label: '@magentoDataFixture' url: /test/integration/annotations/magento-data-fixture.html - - label: '@magentoDataFixtureDataProvider' - url: /test/integration/annotations/magento-data-fixture-data-provider.html - exclude_versions: ["2.3"] - - label: '@magentoDbIsolation' url: /test/integration/annotations/magento-db-isolation.html + - label: Using PHP8 attributes + url: /test/integration/attributes.html + exclude_versions: [ "2.3" ] + + children: + + - label: 'AppArea' + url: /test/integration/attributes/magento-app-area.html + + - label: 'AppIsolation' + url: /test/integration/attributes/magento-app-isolation.html + + - label: 'Cache' + url: /test/integration/attributes/magento-cache.html + + - label: 'ComponentsDir' + url: /test/integration/attributes/magento-components-dir.html + + - label: 'ConfigFixture' + url: /test/integration/attributes/magento-config-fixture.html + + - label: 'DataFixture' + url: /test/integration/attributes/magento-data-fixture.html + + - label: 'DbIsolation' + url: /test/integration/attributes/magento-db-isolation.html + - label: Parameterized Data Fixture url: /test/integration/parameterized_data_fixture.html exclude_versions: ["2.3"] diff --git a/src/_data/whats-new.yml b/src/_data/whats-new.yml index f082de6a6ea..ae41ddd0999 100644 --- a/src/_data/whats-new.yml +++ b/src/_data/whats-new.yml @@ -1085,21 +1085,6 @@ entries: labels: - Major Update - 2.4.4 -- description: Added new [parameterized data fixture](https://devdocs.magento.com/guides/v2.4/test/integration/parameterized_data_fixture.html) - and [data fixture data provider annotation](https://devdocs.magento.com/guides/v2.4/test/integration/annotations/magento-data-fixture-data-provider.html) - documentation for writing tests. - versions: 2.4.x - type: New Topic - date: January 4, 2022 - link: https://github.com/magento/devdocs/pull/9273 - merge_commit: ad816f5435223fd1bbdf8187f458fe1582193cb0 - contributor: thiaramus - membership: true - labels: - - Internal Dev - - New Topic - - 2.4.x - - 'Progress: done' - description: Published [release notes](https://devdocs.magento.com/quality-patches/release-notes.html) for the 1.1.8 Quality Patches Tool (QPT) package release. versions: 2.x diff --git a/src/guides/v2.4/test/integration/annotations.md b/src/guides/v2.4/test/integration/annotations.md index 80608d75553..3336459b144 100644 --- a/src/guides/v2.4/test/integration/annotations.md +++ b/src/guides/v2.4/test/integration/annotations.md @@ -6,6 +6,9 @@ title: Using DocBlock Annotations DocBlock annotations help to declare context in your code. In addition to built-in [PHPUnit annotations][] , the Integration testing framework provides custom annotations described in this topic. +{:.bs-callout-info} +Native PHP8 Attributes can be used instead or together with DocBlock annotations. This new method offers more flexibility and improve readability of the code. See the [Attributes section][] to find out more. This feature is currently only available for Magento Open Source contributors. It will be released for general use with Magento Open Source 2.4.5. + ### Quick overview The following annotations are available in integration tests: @@ -45,3 +48,4 @@ This order is necessary to meet the requirement of setting up the store-scoped c [PHPUnit annotations]: https://phpunit.readthedocs.io/en/9.1/annotations.html +[Attributes section]: {{ page.baseurl }}/test/integration/attributes.html diff --git a/src/guides/v2.4/test/integration/annotations/magento-data-fixture-data-provider.md b/src/guides/v2.4/test/integration/annotations/magento-data-fixture-data-provider.md deleted file mode 100644 index f01ae8c78dd..00000000000 --- a/src/guides/v2.4/test/integration/annotations/magento-data-fixture-data-provider.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -group: testing -title: Data fixture data provider annotation ---- - -{:.bs-callout-info} -Data Fixture Data Provider is only applicable to Parameterized Data Fixture and is currently only available for Magento Open Source contributors. It will be released for general use with Magento Open Source 2.4.5. - -Data Fixture Data Provider is any valid PHP callable or valid JSON string that returns an associative array with fixture aliases as key and their respective parameters. - -Use Data Fixture Data Provider if the parameters exceeds the maximum characters limit on the line with the directive `with`. - -The following example shows the case when the parameters list exceeds the maximum characters limit on the line with the directive `with`. - -```php?start_inline=1 -class ProductTest extends \PHPUnit\Framework\TestCase -{ - /** - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product with:{"price":"12","special_price":10,"tier_prices":[{"customer_group_id":1,"qty":1,"price":9}]} - */ - public function testSpecialPrice(): void - { - } -} -``` - -## Format - -`@magentoDataFixtureDataProvider` takes an argument that points to a callable or contains inline JSON string. - -```php?start_inline=1 -/** - * @magentoDataFixtureDataProvider |{} - */ -``` - -## Principles - -1. Callable Data Fixture Data Provider MUST be publicly accessible. -1. Data Fixture Data Provider MUST return an associative array with fixture aliases as key. -1. Data Fixture Data Providers declared at a test method level have a higher priority than Data Fixture Data Providers declared at a test class level. - -## Usage - -### Inline JSON as Data Provider - -Inline JSON data provider is a JSON string with fixture aliases as keys. - -The following example shows how to use inline JSON as data provider: - -```php?start_inline=1 -class ProductsList extends \PHPUnit\Framework\TestCase -{ - /** - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product as:product1 - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product as:product2 - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product as:product3 - * @magentoDataFixtureDataProvider {"product1":{"sku":"simple1"}} - * @magentoDataFixtureDataProvider {"product2":{"sku":"simple2"}} - * @magentoDataFixtureDataProvider {"product2":{"sku":"simple3","status":2}} - */ - public function testGetProductsCount(): void - { - } -} -``` - -### A callable as data provider - -A callable data provider is any valid PHP callable that is publicly accessible. The following formats are supported: - -- `methodName` a public method declared in the current test class -- `Namespace\Class::method` an external static method - -The following example shows how to use test class method as data provider: - -```php?start_inline=1 -class ProductsList extends \PHPUnit\Framework\TestCase -{ - /** - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product as:product1 - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product as:product2 - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product as:product3 - * @magentoDataFixtureDataProvider getProductsCountFixtureDataProvider - */ - public function testGetProductsCount(): void - { - } - - public function getProductsCountFixtureDataProvider(): array - { - return [ - [ - 'product1' => [ - 'sku' => 'simple1' - ], - 'product2' => [ - 'sku' => 'simple2' - ], - 'product3' => [ - 'sku' => 'simple3', - 'status' => Status::STATUS_DISABLED, - ], - ] - ]; - } -} -``` - -### Test case and test method scopes - -The `@magentoDataFixtureDataProvider` can be specified for a particular test or for an entire test case. -The basic rules for Data Fixture Data Provider annotation at different levels are: - -- `@magentoDataFixtureDataProvider` at a test case level, applies to all fixtures in the test case. -- `@magentoDataFixtureDataProvider` for a particular test, only applies to the fixtures declared at a test method level. - -### Restrictions - -`@magentoDataFixtureDataProvider` does not recursively merge fixtures data, thus if the fixture alias is defined in multiple `@magentoDataFixtureDataProvider`, only the last value will be used. `@magentoDataFixtureDataProvider` will not apply to a fixture that has an inline data provider with `with` directive. diff --git a/src/guides/v2.4/test/integration/annotations/magento-data-fixture.md b/src/guides/v2.4/test/integration/annotations/magento-data-fixture.md index fe930d69a95..adbedbc3e3f 100644 --- a/src/guides/v2.4/test/integration/annotations/magento-data-fixture.md +++ b/src/guides/v2.4/test/integration/annotations/magento-data-fixture.md @@ -4,7 +4,7 @@ title: Data fixture annotation --- A data fixture is a PHP script that sets data you want to reuse in your test. -The script can be defined in a separate PHP file, class, or as a local test case method. +The script can be defined in a separate file or as a local test case method. Use data fixtures to prepare a database for tests. The Integration Testing Framework (ITF) reverts the database to its initial state automatically. @@ -12,18 +12,16 @@ To set up a date fixture, use the `@magentoDataFixture` annotation. ## Format -`@magentoDataFixture` takes an argument that points to the data fixture as a filename, full class name, or local method. +`@magentoDataFixture` takes an argument that points to the data fixture as a filename or local method. ```php?start_inline=1 /** - * @magentoDataFixture || [as:alias | with:{}] + * @magentoDataFixture | */ ``` - `` is the filename of the PHP script. - `` is the name of the method declared in the current class. -- `` is the fully qualified name of a class that implements - `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. ## Principles @@ -33,16 +31,13 @@ To set up a date fixture, use the `@magentoDataFixture` annotation. 1. Fixtures declared at a test level have a higher priority than fixtures declared at a test case level. 1. Test case fixtures are applied to each test in the test case, unless a test has its own fixtures declared. 1. Annotation declaration at a test case level does not affect tests that have their own annotation declarations. -1. Fixture alias SHOULD be camelcase. -1. Fixture data provider MUST be a valid JSON string. ## Usage -As mentioned above, there are three ways to declare fixtures: +As mentioned above, there are two ways to declare fixtures: - as a PHP script file that is used by other tests and test cases. - as a local method that is used by other tests in the test cases. -- as a [Class][parameterizedDataFixture] that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. ### Fixture as a separate file @@ -87,89 +82,6 @@ Test case that uses the above data fixture: [`dev/tests/integration/testsuite/Ma [`dev/tests/integration/testsuite/Magento/Cms/Controller/PageTest.php`][] demonstrates an example of the `testCreatePageWithSameModuleName()` test method that uses data from the `cmsPageWithSystemRouteFixture()` data fixture. -### Data Fixture Data Provider - -{:.bs-callout-info} -Data Fixture Data Provider is only applicable to Parameterized Data Fixture and is currently only available for Magento Open Source contributors. It will be released for general use with Magento Open Source 2.4.5. - -There are two types of data providers: - -- Inline JSON as data provider -- [`@magentoDataFixtureDataProvider`][magentoDataFixtureDataProvider] annotation - -#### Inline JSON as data provider - -Data can be passed to the [Parameterized Data Fixture][parameterizedDataFixture] using the `with` directive as follows: - -Example: - -```php?start_inline=1 -class ProductsList extends \PHPUnit\Framework\TestCase -{ - /** - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product with:{"price": 5.0} - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product with:{"price": 10.0} - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product with:{"price": 15.0} - */ - public function testGetProductsCount(): void - { - } -} -``` - -### Fixture Alias - -{:.bs-callout-info} -Fixture Alias is only applicable to Parameterized Data Fixture and is currently only available for Magento Open Source contributors. It will be released for general use with Magento Open Source 2.4.5. - -You can give [Parameterized Data Fixture][parameterizedDataFixture] an alias using the `as` directive. The fixture alias is used as a reference to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. - -#### Retrieve fixture data in the test - -A test can retrieve data that was returned by a [Parameterized Data Fixture][parameterizedDataFixture] using `Magento\TestFramework\Fixture\DataFixtureStorageManager` and the fixture alias. - -The following example shows how to retrieve data that was returned by the fixtures: - -```php?start_inline=1 -class ProductsList extends \PHPUnit\Framework\TestCase -{ - /** - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product as:product1 - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product as:product2 - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product as:product3 - */ - public function testGetProductsCount(): void - { - $fixtures = DataFixtureStorageManager::getStorage(); - $product1 = $fixtures->get('product1'); - $product2 = $fixtures->get('product2'); - $product3 = $fixtures->get('product3'); - } -} -``` - -#### Supply data to parameterized data fixture as a variable - -It is possible to supply data as a variable from one fixture to another using the fixture alias in one of the following formats: - -- `$fixtureAlias$` is a reference to the data that was returned by the fixture with alias `fixtureAlias`. -- `$fixtureAlias.snake_case_property_name$` is a reference to the property `snake_case_property_name` in the data that was returned by the fixture with alias `fixtureAlias`. - -The following example shows how a fixture can use the data of another fixture: - -```php?start_inline=1 -class QuoteTest extends \PHPUnit\Framework\TestCase -{ - /** - * @magentoApiDataFixture Magento\Quote\Test\Fixture\GuestCart as:cart - * @magentoApiDataFixture Magento\Quote\Test\Fixture\SetBillingAddress with:{"cart_id":"$cart.id$"} - */ - public function testGetBillingAddress(): void - { - } -} -``` - ### Test case and test method scopes The `@magentoDataFixture` can be specified for a particular test or for an entire test case. @@ -208,8 +120,6 @@ Do not rely on and do not modify an application state from within a fixture, bec [magentoAppIsolation]: magento-app-isolation.html -[magentoDataFixtureDataProvider]: magento-data-fixture-data-provider.html -[parameterizedDataFixture]: ../parameterized_data_fixture.html [`dev/tests/integration/testsuite/Magento/Cms/_files/pages.php`]: {{ site.mage2bloburl }}/{{ page.guide_version }}/dev/tests/integration/testsuite/Magento/Cms/_files/pages.php [`dev/tests/integration/testsuite/Magento/Cms/Block/PageTest.php`]: {{ site.mage2bloburl }}/{{ page.guide_version }}/dev/tests/integration/testsuite/Magento/Cms/Block/PageTest.php [`dev/tests/integration/testsuite/Magento/Cms/Controller/PageTest.php`]: {{ site.mage2bloburl }}/{{ page.guide_version }}/dev/tests/integration/testsuite/Magento/Cms/Controller/PageTest.php diff --git a/src/guides/v2.4/test/integration/attributes.md b/src/guides/v2.4/test/integration/attributes.md new file mode 100644 index 00000000000..4458aa1e310 --- /dev/null +++ b/src/guides/v2.4/test/integration/attributes.md @@ -0,0 +1,48 @@ +--- +group: testing +title: Using PHP8 Attributes +--- + +[PHP8 Attributes][] help to declare context in your code. Attributes can be used alone or together with Annotations to help to declare context in your code. + +{:.bs-callout-info} +Native PHP8 Attributes is available now for the developers, and will be publicly available with Magento 2.4.5 release. +[PHPUnit annotations][] are still available for use with Magento. + + +### Quick overview + +The following annotations are available in integration tests: + +| Name | Attribute | Format | Description | +|---------------------------------|--------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Application Isolation | `AppIsolation` | `AppIsolation((bool))` | Enables or disables application isolation when you run tests. When enabled, an application state after a test run will be the same as before the test run. For example, you should enable it, when you want to create sessions in a test, but you don't want them to affect other tests. | +| Configuration Fixture | `Config` | `Config((string), (string), (string), ...)` | Sets up configuration settings for a particular test. The list of settings is stored in the `core_config_data` database table. Multiple configuration parameters can be set with a signle command. After the test execution, the settings revert to their original state. | +| Database Isolation | `DbIsolation` | `DbIsolation((bool))` | Enables or disables database isolation. Disabled by default, unless you are using `DataFixture()` attribute, in which case it is enabled by default. All data, required for a test, live during transaction only. Any test results won't be written in a database. | +| Data Fixture | `DataFixture` | `DataFixture((string), (array)[, ], (string), as:(string))` | Points to a class or a method which creates testing entities (fixtures) for test execution. These are applied during the transaction. | +| Data Fixture Before Transaction | `DataFixtureBeforeTransaction` | `DataFixtureBeforeTransaction((string), (array)[, ], (string), as:(string))` | Points to a class or a method which creates testing entities (fixtures) for test execution before the transaction has begun. You will need to implement a rollback method changes made here. | +| Application Area | `AppArea` | `AppArea((string)<'adminhtml'/'frontend'/'global'>)` | Configures test environment in the context of specified application area. | +| Enable/Disable Cache | `Cache` | `Cache((string)<'all'/'enabled'/'disabled>')` | Enables or disables certain cache segment or all of them to prevent isolation problems. | +| Indexer Dimension Mode | `IndexerDimensionMode` | `IndexerDimensionMode(string),(string))` | Sets the indexer dimension mode for the test run. More information can be found in the [DevBlog](https://community.magento.com/t5/Magento-DevBlog/Indexers-parallelization-and-optimization/ba-p/104922). | +| Register Components | `ComponentsDir` | `ComponentsDir((string),...)` | Registers fixture components from specified directory (recursively). Unregisters the components after the test is finished. | + +### Applying annotations + +The Magento-specific annotations for integration tests are applied in the following order: + +1. `AppIsolation` +1. `DbIsolation` +1. `DataFixtureBeforeTransaction` +1. `DataFixture` +1. `IndexerDimensionMode` +1. `ComponentsDir` +1. `AppArea` +1. `Cache` +1. `Config` + +This order is necessary to meet the requirement of setting up the store-scoped configuration values for fixture stores (stores that are created by data fixtures). + + + +[PHPUnit annotations]: {{ page.baseurl }}/test/integration/annotations.html +[PHP8 Attributes]: https://www.php.net/manual/en/language.attributes.overview.php diff --git a/src/guides/v2.4/test/integration/attributes/magento-app-area.md b/src/guides/v2.4/test/integration/attributes/magento-app-area.md new file mode 100644 index 00000000000..d994ef60742 --- /dev/null +++ b/src/guides/v2.4/test/integration/attributes/magento-app-area.md @@ -0,0 +1,112 @@ +--- +group: testing +title: Application Area attribute in the Integration Testing Framework +--- + +Configure a test environment in scope of the particular [application area][] with the `@magentoAppArea` annotation. + +## Format + +```php?start_inline=1 +#[ + AppArea((string) ) +] +``` + +## Fallback sequence + +1. Test annotation +1. Test case annotation +1. Default application area, which is `global` + +## Test case attribute + +A test case attribute enables the specified application area for all tests in the test case. + +{:.bs-callout-info} +Test attribute override test case attribute. + +Example: + +```php?start_inline=1 +#[ + AppArea('adminhtml') +] +namespace Vendor\Module; +class ClassToTest extends \PHPUnit\Framework\TestCase +{ + public function testOne() + { + //... + } + + #[ + AppArea('frontend') + ] + public function testTwo() + { + //... + } + + public function testThree() + { + //... + } +} +``` + +`testOne()` and `testThree()` are set to run in scope of the `adminhtml` application area, whereas `testTwo()` is set to run in scope of the `frontend` area. + +## Test attribute + +A test attribute is used to configure the environment in scope of the specified application area for the test. +Magento is reinitialized in the corresponding scope each time you specify a different area. + +Example: + +```php?start_inline=1 +namespace \Vendor\Module; + +class ClassToTest extends \PHPUnit\Framework\TestCase +{ + // executes the test in scope of the global area + public function testOne() + { + //... + } + + // reinitializes the application and executes the test in scope of the frontend area + #[ + AppArea('frontend') + ] + public function testTwo() + { + //... + } + + // reinitializes the application and executes the test in scope of the adminhtml area + #[ + AppArea('adminhtml') + ] + public function testThree() + { + //... + } + + // reinitializes the application and executes the test in scope of the global area + public function testFour() + { + //... + } + + // executes in scope of the global area + public function testFive() + { + //... + } +} +``` + + + +[application area]: {{page.baseurl}}/architecture/archi_perspectives/components/modules/mod_and_areas.html diff --git a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md new file mode 100644 index 00000000000..ee6c29f828a --- /dev/null +++ b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md @@ -0,0 +1,73 @@ +--- +group: testing +title: Application isolation attribute +--- + +An application state can be changed during test execution. +Such changes can cause a false test failure. +The integration testing framework keeps the tests isolated and provides optimal performance by default. +Isolation is managed using the `AppIsolation` attribute. + +{:.bs-callout-info} +Test execution order can vary depending on a PHPUnit version. + +## Format + +Application isolation annotation: + +```php?start_inline=1 +#[ + AppIsolation((bool)) +] +``` + +## Test case attribute + +The application and related objects are reinitialized after each test case execution. +This behavior helps to isolate application objects in different test cases. +The test case isolation is mandatory and cannot be disabled. + +{:.bs-callout-warning} +Do not share and do not rely on sharing the application objects between test cases. + +## Test annotation + +By default, the application isolation (that is automatic reinitialization) in tests is disabled. +To enable the application isolation for a test, use the `AppIsolation` attribute. + +Example: + +```php?start_inline=1 +#[ + AppIsolation(true) +] +public function testGetAddressById() +{ + $addressId = 2; + $address = $this->repository->getById($addressId); + $this->assertEquals($this->_expectedAddresses[1], $address); +} +``` + +{:.bs-callout-info} +In most cases, controller tests depend on the application state and require reinitialization in each test. +Thus, the test cases inherited from the `\Magento\TestFramework\TestCase\AbstractController` behave as if `AppIsolation` is enabled for each test. + +## Defaults + +Default values for the `AppIsolation` attribute: + +| Test class ancestors | Test case (class) | Test (method) | +|------------------------------------------------------|-------------------|---------------| +| `\PHPUnit\Framework\TestCase` | enabled | disabled | +| `\Magento\TestFramework\TestCase\AbstractController` | enabled | enabled | + +`AppIsolation` cannot be disabled at the test case level. + +You can use non-isolated tests unless they do not modify or utilize the same application areas such as: + +- same attributes of an application object. +- same paths in a current configuration or current scope (for example "store"). + +{:.bs-callout-tip} +Set up application isolation if any application objects were intentionally modified within the test case. \ No newline at end of file diff --git a/src/guides/v2.4/test/integration/attributes/magento-cache.md b/src/guides/v2.4/test/integration/attributes/magento-cache.md new file mode 100644 index 00000000000..2bbe8bee4eb --- /dev/null +++ b/src/guides/v2.4/test/integration/attributes/magento-cache.md @@ -0,0 +1,96 @@ +--- +group: testing +title: Cache attribute +--- + +Enable or disable a [cache type][] using the `Cache` attribute. + +## Format + +```php?start_inline=1 +#[ + Cache((string)<'all'/'enabled'/'disabled>') +] +``` + +Here, + +- `` is a placeholder for a cache type +- `all` is a value for any cache type +- `enabled` or `disabled` to enable or disable the cache respectively + +## Principles + +1. You can use more than one attribute for a test case or a test method. +1. Multiple attributes are applied in the given order. +1. attributes from different scopes are not merged. +1. A test method attribute completely overrides a test case attribute. +1. All cache types are disabled by default. + +## Test case + +`Cache` attribute at the test case level is applied to all tests. + +## Test method + +`Cache` attribute at a test method level configures the test only. +It completely overrides the attribute specified for the test case. + +## Example + +Cache attributes example: + +```php + + +[cache type]: {{page.baseurl}}/config-guide/cli/config-cli-subcommands-cache.html#config-cli-subcommands-cache-clean-over diff --git a/src/guides/v2.4/test/integration/attributes/magento-components-dir.md b/src/guides/v2.4/test/integration/attributes/magento-components-dir.md new file mode 100644 index 00000000000..eacfb0a61a8 --- /dev/null +++ b/src/guides/v2.4/test/integration/attributes/magento-components-dir.md @@ -0,0 +1,80 @@ +--- +group: testing +title: Component registration attribute +--- + +When your test design requires to register fixture components and unregister them after the test execution, use the `ComponentsDir` attribute. +It enables you to register all the components at a specified directory recursively. + +## Format + +```php?start_inline=1 +#[ + ComponentsDir((string)) +] +``` + +Here, `` is a path to the directory with fixture components. +Each component must be registered using `registration.php` file. + +## Test case + +`ComponentsDir` attribute for a test case is applied to all test methods in the test case. + +## Test method + +`ComponentsDir` attribute for a test method configures the test to run with registered components located in a specified directory. +If the parent test case also declares a `ComponentsDir`, both attribute are merged. + +## Example + +The following example demonstrates `ComponentsDir` attribute in different scopes. + +```php?start_inline=1 +namespace Magento\Foo; + +#[ + ComponentsDir('Magento/Foo/_files/code/Magento') +] +class BarTest extends \PHPUnit\Framework\TestCase +{ + #[ + ComponentsDir('Magento/Foo/_files/themes') + ] + public function testOne() + { + ... // Here you can use registered components from 'Magento/Foo/_files/code/Magento' and 'Magento/Foo/_files/themes' + } + + #[ + ComponentsDir('Magento/Foo/_files/libs', 'Magento/Baz/_files/languages') + ] + public function testTwo() + { + ... // Here you can use the registered components from 'Magento/Foo/_files/code/Magento', 'Magento/Foo/_files/libs', and 'Magento/Baz/_files/languages' + } +} +``` + +Each path declared in attribute must contain a registration file in the specified directory or its subdirectories. +For example, the `MagentoFooTest_MyModule` component at `ComponentsDir('Magento/Foo/_files/code/Magento')` can be registered in `Magento/Foo/_files/code/Magento/MyModule/registration.php`: + +```php?start_inline=1 + +use Magento\Framework\Component\ComponentRegistrar; + +\Magento\Framework\Component\ComponentRegistrar::register( + \Magento\Framework\Component\ComponentRegistrar::MODULE, + 'MagentoFooTest_MyModule', + __DIR__ +); +``` + + {:.bs-callout-info} +A theme must be registered in the database. +Each time you register a theme, reset the entire application. +Use the [`DbIsolation`][] attribute to keep the database integrity safe. + + + +[`DbIsolation`]: ./magento-db-isolation.html \ No newline at end of file diff --git a/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md new file mode 100644 index 00000000000..5143e110a1d --- /dev/null +++ b/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md @@ -0,0 +1,241 @@ +--- +group: testing +title: Configuration fixture attribute +--- + +To set Magento configuration values for individual tests and revert them after the test execution, use the `Config` attribute. + +## Format + +```php +#[ + Config((string), (string), (string), ...) +] +``` + +- `` is the code of the store to be configured. + When a global scope is required, this should be omitted and the `config path` is prefixed with `default/`. See below for an example. + To specify the current store, use `current`. +- `` is the XPath to the configuration option. + See [configuration reference][] for available options. +- `` is a fixture value for the configuration option. + +## Principles + +1. The `Config` attribute is available at the test method level only. + It is not available on the test case level. +1. A test may contain several configuration options. + +## Example + +```php +_object = $this->createPartialMock( + \Magento\TestFramework\attribute\ConfigFixture::class, + ['_getConfigValue', '_setConfigValue'] + ); + } + + #[ + Config('current_store', 'web/unsecure/base_url', 'http://example.com/') + ] + public function testGlobalConfig() + { + $this->_object->expects( + $this->at(0) + )->method( + '_getConfigValue' + )->with( + 'web/unsecure/base_url' + )->will( + $this->returnValue('http://localhost/') + ); + $this->_object->expects( + $this->at(1) + )->method( + '_setConfigValue' + )->with( + 'web/unsecure/base_url', + 'http://example.com/' + ); + $this->_object->startTest($this); + + $this->_object->expects( + $this->once() + )->method( + '_setConfigValue' + )->with( + 'web/unsecure/base_url', + 'http://localhost/' + ); + $this->_object->endTest($this); + } + + #[ + Config('current_store', 'dev/restrict/allow_ips', '192.168.0.1') + ] + public function testCurrentStoreConfig() + { + $this->_object->expects( + $this->at(0) + )->method( + '_getConfigValue' + )->with( + 'dev/restrict/allow_ips', + '' + )->will( + $this->returnValue('127.0.0.1') + ); + $this->_object->expects( + $this->at(1) + )->method( + '_setConfigValue' + )->with( + 'dev/restrict/allow_ips', + '192.168.0.1', + '' + ); + $this->_object->startTest($this); + + $this->_object->expects( + $this->once() + )->method( + '_setConfigValue' + )->with( + 'dev/restrict/allow_ips', + '127.0.0.1', + '' + ); + $this->_object->endTest($this); + } + + #[ + Config('admin_store', 'dev/restrict/allow_ips', '192.168.0.2') + ] + public function testSpecificStoreConfig() + { + $this->_object->expects( + $this->at(0) + )->method( + '_getConfigValue' + )->with( + 'dev/restrict/allow_ips', + 'admin' + )->will( + $this->returnValue('192.168.0.1') + ); + $this->_object->expects( + $this->at(1) + )->method( + '_setConfigValue' + )->with( + 'dev/restrict/allow_ips', + '192.168.0.2', + 'admin' + ); + $this->_object->startTest($this); + + $this->_object->expects( + $this->once() + )->method( + '_setConfigValue' + )->with( + 'dev/restrict/allow_ips', + '192.168.0.1', + 'admin' + ); + $this->_object->endTest($this); + } + + #[ + Config('default/dev/restrict/allow_ips', '192.168.0.2') + ] + public function testGlobalStoreConfig() + { + $this->_object->expects( + $this->at(0) + )->method( + '_getConfigValue' + )->with( + 'dev/restrict/allow_ips', + 'admin' + )->will( + $this->returnValue('192.168.0.1') + ); + $this->_object->expects( + $this->at(1) + )->method( + '_setConfigValue' + )->with( + 'dev/restrict/allow_ips', + '192.168.0.2', + 'admin' + ); + $this->_object->startTest($this); + + $this->_object->expects( + $this->once() + )->method( + '_setConfigValue' + )->with( + 'dev/restrict/allow_ips', + '192.168.0.1', + 'admin' + ); + $this->_object->endTest($this); + } + + public function testInitStoreAfterOfScope() + { + $this->_object->expects($this->never())->method('_getConfigValue'); + $this->_object->expects($this->never())->method('_setConfigValue'); + $this->_object->initStoreAfter(); + } + + #[ + Config('current_store', 'web/unsecure/base_url', 'http://example.com/') + ] + public function testInitStoreAfter() + { + $this->_object->startTest($this); + $this->_object->expects( + $this->at(0) + )->method( + '_getConfigValue' + )->with( + 'web/unsecure/base_url' + )->will( + $this->returnValue('http://localhost/') + ); + $this->_object->expects( + $this->at(1) + )->method( + '_setConfigValue' + )->with( + 'web/unsecure/base_url', + 'http://example.com/' + ); + $this->_object->initStoreAfter(); + } +} + +``` + + + +[configuration reference]: {{ page.baseurl }}/config-guide/prod/config-reference-sens.html diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md new file mode 100644 index 00000000000..0d50fdb7b3d --- /dev/null +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md @@ -0,0 +1,213 @@ +--- +group: testing +title: Data fixture attribute +--- + +A data fixture is a PHP script that sets data you want to reuse in your test. +The script can be defined in a separate PHP file, class, or as a local test case method. + +Use data fixtures to prepare a database for tests. +The Integration Testing Framework (ITF) reverts the database to its initial state automatically. +To set up a date fixture, use the `DataFixture` attribute. + +## Format + +`DataFixture` takes an argument that points to the data fixture as a filename, full class name, or local method, and an optional alias. + +```php?start_inline=1 +#[ + DataFixture((string), (array)[, ], (string), as:(string)) +] +``` + +- `` is the fully qualified name of a class that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. +- `` is the name of the method declared in the current class. + + +## Principles + +1. Do not use a direct database connection in fixtures to avoid dependencies on the database structure and vendor. +1. Use an application API to implement your data fixtures. +1. A method that implements a data fixture must be declared as `public` and `static`. +1. Fixtures declared at a test level have a higher priority than fixtures declared at a test case level. +1. Test case fixtures are applied to each test in the test case, unless a test has its own fixtures declared. +1. attribute declaration at a test case level does not affect tests that have their own attribute declarations. +1. Fixture alias SHOULD be camelcase. +1. Fixture data provider MUST be a valid JSON string. + +## Usage + +As mentioned above, there are three ways to declare fixtures: + +- as a PHP script file that is used by other tests and test cases. +- as a local method that is used by other tests in the test cases. +- as a [Class][parameterizedDataFixture] that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. + +### Fixture as a separate file + +Define the fixture in a separate file when you want to reuse it in different test cases. +To declare the fixture, use one of the following conventions: + +- Fixture declaration as a path relative to the test suite directory + - Relative to `dev/tests/integration/` + - With forward slashes `/` + - No leading slash + + Example: + + ```php + #[ + DataFixture('Magento/Cms/_files/pages.php') + ] + ``` + +- Fixture declaration as a path relative to a module + - Relative to the directory of a module available in the project + - With forward slashes `/` + - No leading slash in the path part of the declaration + + Example: + + ```php + #[ + DataFixture('VendorName_ModuleName::Test/Integration/_files/fixture_name.php') + ] + ``` + +The ITF includes the declared PHP script to your test and executes it during the test run. + +The following example demonstrates a simple implementation of a Cms module page test from the Magento codebase. + +Data fixture to test a Cms module page: [`dev/tests/integration/testsuite/Magento/Cms/_files/pages.php`][]. + +Test case that uses the above data fixture: [`dev/tests/integration/testsuite/Magento/Cms/Block/PageTest.php`][]. + +### Fixture as a method + +[`dev/tests/integration/testsuite/Magento/Cms/Controller/PageTest.php`][] demonstrates an example of the `testCreatePageWithSameModuleName()` test method that uses data from the `cmsPageWithSystemRouteFixture()` data fixture. + +### Data Fixture Data Provider + +{:.bs-callout-info} +Data Fixture Data Provider is only applicable to Parameterized Data Fixture and is currently only available for Magento Open Source contributors. It will be released for general use with Magento Open Source 2.4.5. + +There are two types of data providers: + +- Inline JSON as data provider +- @magentoDataFixtureDataProvider magentoDataFixtureDataProvider attribute + +#### Inline JSON as data provider + +Data can be passed to the [Parameterized Data Fixture][parameterizedDataFixture] using the `with` directive as follows: + +Example: + +```php?start_inline=1 +class ProductsList extends \PHPUnit\Framework\TestCase +{ + /** + * @magentoDataFixture Magento\Catalog\Test\Fixture\Product with:{"price": 5.0} + * @magentoDataFixture Magento\Catalog\Test\Fixture\Product with:{"price": 10.0} + * @magentoDataFixture Magento\Catalog\Test\Fixture\Product with:{"price": 15.0} + */ + public function testGetProductsCount(): void + { + } +} +``` + +### Fixture Alias + +{:.bs-callout-info} +Fixture Alias is only applicable to Parameterized Data Fixture and is currently only available for Magento Open Source contributors. It will be released for general use with Magento Open Source 2.4.5. + +You can give [Parameterized Data Fixture][parameterizedDataFixture] an alias using the `as` directive. The fixture alias is used as a reference to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. + +#### Retrieve fixture data in the test + +A test can retrieve data that was returned by a [Parameterized Data Fixture][parameterizedDataFixture] using `Magento\TestFramework\Fixture\DataFixtureStorageManager` and the fixture alias. + +The following example shows how to retrieve data that was returned by the fixtures: + +```php?start_inline=1 +class ProductsList extends \PHPUnit\Framework\TestCase +{ + /** + * @magentoDataFixture Magento\Catalog\Test\Fixture\Product as:product1 + * @magentoDataFixture Magento\Catalog\Test\Fixture\Product as:product2 + * @magentoDataFixture Magento\Catalog\Test\Fixture\Product as:product3 + */ + public function testGetProductsCount(): void + { + $fixtures = DataFixtureStorageManager::getStorage(); + $product1 = $fixtures->get('product1'); + $product2 = $fixtures->get('product2'); + $product3 = $fixtures->get('product3'); + } +} +``` + +#### Supply data to parameterized data fixture as a variable + +It is possible to supply data as a variable from one fixture to another using the fixture alias in one of the following formats: + +- `$fixtureAlias$` is a reference to the data that was returned by the fixture with alias `fixtureAlias`. +- `$fixtureAlias.snake_case_property_name$` is a reference to the property `snake_case_property_name` in the data that was returned by the fixture with alias `fixtureAlias`. + +The following example shows how a fixture can use the data of another fixture: + +```php?start_inline=1 +class QuoteTest extends \PHPUnit\Framework\TestCase +{ + /** + * @magentoApiDataFixture Magento\Quote\Test\Fixture\GuestCart as:cart + * @magentoApiDataFixture Magento\Quote\Test\Fixture\SetBillingAddress with:{"cart_id":"$cart.id$"} + */ + public function testGetBillingAddress(): void + { + } +} +``` + +### Test case and test method scopes + +The `@magentoDataFixture` can be specified for a particular test or for an entire test case. +The basic rules for fixture attribute at different levels are: + +- `@magentoDataFixture` at a test case level, makes the framework to apply the declared fixtures to each test in the test case. + When the final test is complete, all class-level fixtures are reverted. +- `@magentoDataFixture` for a particular test, signals the framework to revert the fixtures declared on a test case level and applies the fixtures declared at a test method level instead. + When the test is complete, the ITF reverts the applied fixtures. + + {:.bs-callout-info} +The integration testing framework interacts with a database to revert the applied fixtures. + +### Fixture rollback + +A fixture that contains database transactions only, are reverted automatically. +Otherwise, when a fixture creates files or performs any actions other than database transaction, provide the corresponding rollback logic. +Rollbacks are run after reverting all the fixtures related to database transactions. + +A fixture rollback must be of the same format as the corresponding fixture, a script or a method: + +- A rollback script must be named according to the corresponding fixture suffixed with `_rollback` and stored in the same directory. +- Rollback methods must be of the same class as the corresponding fixture and suffixed with `Rollback`. + +Examples: + +Fixture/Rollback | Fixture name | Rollback name +-----------------|------------------------------------------------------|------------------------------------------------------------- +Script | `Magento/Catalog/_files/categories.php` | `Magento/Catalog/_files/categories_rollback.php` +Method | `\Magento\Catalog\Model\ProductTest::prepareProduct` | `\Magento\Catalog\Model\ProductTest::prepareProductRollback` + +### Restrictions + +Do not rely on and do not modify an application state from within a fixture, because [application isolation attribute][magentoAppIsolation] can reset the application state at any time. + + + +[magentoAppIsolation]: magento-app-isolation.html +[parameterizedDataFixture]: ../parameterized_data_fixture.html +[`dev/tests/integration/testsuite/Magento/Cms/_files/pages.php`]: {{ site.mage2bloburl }}/{{ page.guide_version }}/dev/tests/integration/testsuite/Magento/Cms/_files/pages.php +[`dev/tests/integration/testsuite/Magento/Cms/Block/PageTest.php`]: {{ site.mage2bloburl }}/{{ page.guide_version }}/dev/tests/integration/testsuite/Magento/Cms/Block/PageTest.php +[`dev/tests/integration/testsuite/Magento/Cms/Controller/PageTest.php`]: {{ site.mage2bloburl }}/{{ page.guide_version }}/dev/tests/integration/testsuite/Magento/Cms/Controller/PageTest.php diff --git a/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md b/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md new file mode 100644 index 00000000000..89be9c2420e --- /dev/null +++ b/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md @@ -0,0 +1,88 @@ +--- +group: testing +title: Database isolation attribute +--- + +To isolate database changes between tests, the Integration testing framework (ITF) implements the `DbIsolation` attribute. +When the `DbIsolation` is enabled, the ITF: + +- starts a database transaction before the test/test case. +- avoids a database commit during the test/test case. +- restores the database after the test/test case. + +## Format + +Database isolation attribute: + +```php?start_inline=1 +#[ +DbIsolation((bool)) +] +``` + +## Test case declaration + +Use test case declarations when a sequence of tests introduces changes to the database and relies on the changes made by each other. +For example, typical CRUD tests: _create -> read -> update -> delete_. +Every next test relies on a database state after the previous one. +If at any point of that sequence (after creation) the test fails, the database will be polluted with test data. +To apply a database rollback after the test case, create a separate test case with `@magentoDbIsolation` enabled at a class level. + +Example: + +```php?start_inline=1 +#[ + DbIsolation(true) +] +class Some\EntityTest extends \PHPUnit\Framework\TestCase +{ + public function testCreate() + { + $this->object->setData($this->initialData)->save(); + $this->assertNotEmpty($this->object->getId()); + return $this->object->getId(); + } + + public function testRead($objectId) + { + $this->object->load($objectId); + $this->assertEquals($this->initialData, $this->object->getData()); + return $objectId; + } + + public function testUpdate($objectId) + { + $this->object->setData($newData)->save(); + $object = new Some_Entity(); + $object->load($objectId); + $this->assertEquals($newData, $object->getData()); + return $objectId; + } + + public function testDelete($objectId) + { + $this->object->delete(); + $object = new Some_Entity(); + $object->load($objectId); + $this->assertEmpty($object->getData()); + } +} +``` + +## Test declaration + +To isolate changes made to database by a single test, enable the `DbIsolation` for the test. + +```php?start_inline=1 +#[ + DbIsolation(true) +] +public function testSave() +{ + $taxClassDataObject = $this->taxClassFactory->create(); + $taxClassDataObject->setClassName(self::SAMPLE_TAX_CLASS_NAME) + ->setClassType(TaxClassManagementInterface::TYPE_CUSTOMER); + $taxClassId = $this->taxClassRepository->save($taxClassDataObject); + $this->assertEquals(self::SAMPLE_TAX_CLASS_NAME, $this->taxClassModel->load($taxClassId)->getClassName()); +} +``` From 83e4cf022f4b35a8c02656dd31a41bf7b0e8d1d2 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Fri, 10 Jun 2022 13:38:07 -0500 Subject: [PATCH 153/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- src/_data/whats-new.yml | 15 +++++++++++++++ src/guides/v2.4/test/integration/annotations.md | 2 +- src/guides/v2.4/test/integration/attributes.md | 5 ++--- .../integration/attributes/magento-app-area.md | 10 +++++----- .../attributes/magento-app-isolation.md | 4 ++-- .../test/integration/attributes/magento-cache.md | 10 +++++----- .../attributes/magento-components-dir.md | 4 ++-- .../attributes/magento-config-fixture.md | 6 +++--- .../attributes/magento-data-fixture.md | 2 +- 9 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/_data/whats-new.yml b/src/_data/whats-new.yml index ae41ddd0999..f082de6a6ea 100644 --- a/src/_data/whats-new.yml +++ b/src/_data/whats-new.yml @@ -1085,6 +1085,21 @@ entries: labels: - Major Update - 2.4.4 +- description: Added new [parameterized data fixture](https://devdocs.magento.com/guides/v2.4/test/integration/parameterized_data_fixture.html) + and [data fixture data provider annotation](https://devdocs.magento.com/guides/v2.4/test/integration/annotations/magento-data-fixture-data-provider.html) + documentation for writing tests. + versions: 2.4.x + type: New Topic + date: January 4, 2022 + link: https://github.com/magento/devdocs/pull/9273 + merge_commit: ad816f5435223fd1bbdf8187f458fe1582193cb0 + contributor: thiaramus + membership: true + labels: + - Internal Dev + - New Topic + - 2.4.x + - 'Progress: done' - description: Published [release notes](https://devdocs.magento.com/quality-patches/release-notes.html) for the 1.1.8 Quality Patches Tool (QPT) package release. versions: 2.x diff --git a/src/guides/v2.4/test/integration/annotations.md b/src/guides/v2.4/test/integration/annotations.md index 3336459b144..6e001d5efa2 100644 --- a/src/guides/v2.4/test/integration/annotations.md +++ b/src/guides/v2.4/test/integration/annotations.md @@ -47,5 +47,5 @@ This order is necessary to meet the requirement of setting up the store-scoped c -[PHPUnit annotations]: https://phpunit.readthedocs.io/en/9.1/annotations.html +[PHPUnit annotations]: https://phpunit.readthedocs.io/en/9.5/annotations.html [Attributes section]: {{ page.baseurl }}/test/integration/attributes.html diff --git a/src/guides/v2.4/test/integration/attributes.md b/src/guides/v2.4/test/integration/attributes.md index 4458aa1e310..8b04a406aff 100644 --- a/src/guides/v2.4/test/integration/attributes.md +++ b/src/guides/v2.4/test/integration/attributes.md @@ -9,16 +9,15 @@ title: Using PHP8 Attributes Native PHP8 Attributes is available now for the developers, and will be publicly available with Magento 2.4.5 release. [PHPUnit annotations][] are still available for use with Magento. - ### Quick overview -The following annotations are available in integration tests: +The following attributes are available in integration tests: | Name | Attribute | Format | Description | |---------------------------------|--------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Application Isolation | `AppIsolation` | `AppIsolation((bool))` | Enables or disables application isolation when you run tests. When enabled, an application state after a test run will be the same as before the test run. For example, you should enable it, when you want to create sessions in a test, but you don't want them to affect other tests. | | Configuration Fixture | `Config` | `Config((string), (string), (string), ...)` | Sets up configuration settings for a particular test. The list of settings is stored in the `core_config_data` database table. Multiple configuration parameters can be set with a signle command. After the test execution, the settings revert to their original state. | -| Database Isolation | `DbIsolation` | `DbIsolation((bool))` | Enables or disables database isolation. Disabled by default, unless you are using `DataFixture()` attribute, in which case it is enabled by default. All data, required for a test, live during transaction only. Any test results won't be written in a database. | +| Database Isolation | `DbIsolation` | `DbIsolation((bool))` | Enables or disables database isolation. Disabled by default, unless you are using `DataFixture()` attribute, in which case it is enabled by default. All data, required for a test, live during transaction only. Any test results won't be written in a database. | | Data Fixture | `DataFixture` | `DataFixture((string), (array)[, ], (string), as:(string))` | Points to a class or a method which creates testing entities (fixtures) for test execution. These are applied during the transaction. | | Data Fixture Before Transaction | `DataFixtureBeforeTransaction` | `DataFixtureBeforeTransaction((string), (array)[, ], (string), as:(string))` | Points to a class or a method which creates testing entities (fixtures) for test execution before the transaction has begun. You will need to implement a rollback method changes made here. | | Application Area | `AppArea` | `AppArea((string)<'adminhtml'/'frontend'/'global'>)` | Configures test environment in the context of specified application area. | diff --git a/src/guides/v2.4/test/integration/attributes/magento-app-area.md b/src/guides/v2.4/test/integration/attributes/magento-app-area.md index d994ef60742..00195c85dc9 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-app-area.md +++ b/src/guides/v2.4/test/integration/attributes/magento-app-area.md @@ -9,7 +9,7 @@ Configure a test environment in scope of the particular [application area][] wit ```php?start_inline=1 #[ - AppArea((string) ) + AppArea((string)<'adminhtml'/'frontend'/'global'>) ] ``` @@ -31,7 +31,7 @@ Example: ```php?start_inline=1 #[ AppArea('adminhtml') -] +] namespace Vendor\Module; class ClassToTest extends \PHPUnit\Framework\TestCase { @@ -42,7 +42,7 @@ class ClassToTest extends \PHPUnit\Framework\TestCase #[ AppArea('frontend') - ] + ] public function testTwo() { //... @@ -78,7 +78,7 @@ class ClassToTest extends \PHPUnit\Framework\TestCase // reinitializes the application and executes the test in scope of the frontend area #[ AppArea('frontend') - ] + ] public function testTwo() { //... @@ -87,7 +87,7 @@ class ClassToTest extends \PHPUnit\Framework\TestCase // reinitializes the application and executes the test in scope of the adminhtml area #[ AppArea('adminhtml') - ] + ] public function testThree() { //... diff --git a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md index ee6c29f828a..6a4fe758bf0 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md +++ b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md @@ -18,7 +18,7 @@ Application isolation annotation: ```php?start_inline=1 #[ AppIsolation((bool)) -] +] ``` ## Test case attribute @@ -40,7 +40,7 @@ Example: ```php?start_inline=1 #[ AppIsolation(true) -] +] public function testGetAddressById() { $addressId = 2; diff --git a/src/guides/v2.4/test/integration/attributes/magento-cache.md b/src/guides/v2.4/test/integration/attributes/magento-cache.md index 2bbe8bee4eb..4145cc95c48 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-cache.md +++ b/src/guides/v2.4/test/integration/attributes/magento-cache.md @@ -10,7 +10,7 @@ Enable or disable a [cache type][] using the `Cache` attribute. ```php?start_inline=1 #[ Cache((string)<'all'/'enabled'/'disabled>') -] +] ``` Here, @@ -47,7 +47,7 @@ namespace Magento\Foo; #[ Cache('all', true) -] +] class BarTest extends \PHPUnit\Framework\TestCase { public function testOne() @@ -57,7 +57,7 @@ class BarTest extends \PHPUnit\Framework\TestCase #[ Cache('config', false) - ] + ] public function testTwo() { ... @@ -65,7 +65,7 @@ class BarTest extends \PHPUnit\Framework\TestCase #[ Cache('all', true, 'config', false) - ] + ] public function testThree() { ... @@ -73,7 +73,7 @@ class BarTest extends \PHPUnit\Framework\TestCase #[ Cache('config', false, 'all', true) - ] + ] public function testFour() { ... diff --git a/src/guides/v2.4/test/integration/attributes/magento-components-dir.md b/src/guides/v2.4/test/integration/attributes/magento-components-dir.md index eacfb0a61a8..8d00fa77fbb 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-components-dir.md +++ b/src/guides/v2.4/test/integration/attributes/magento-components-dir.md @@ -11,7 +11,7 @@ It enables you to register all the components at a specified directory recursive ```php?start_inline=1 #[ ComponentsDir((string)) -] +] ``` Here, `` is a path to the directory with fixture components. @@ -35,7 +35,7 @@ namespace Magento\Foo; #[ ComponentsDir('Magento/Foo/_files/code/Magento') -] +] class BarTest extends \PHPUnit\Framework\TestCase { #[ diff --git a/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md index 5143e110a1d..113e70cf0f1 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md @@ -10,7 +10,7 @@ To set Magento configuration values for individual tests and revert them after t ```php #[ Config((string), (string), (string), ...) -] +] ``` - `` is the code of the store to be configured. @@ -164,7 +164,7 @@ class ConfigFixtureTest extends \PHPUnit\Framework\TestCase #[ Config('default/dev/restrict/allow_ips', '192.168.0.2') - ] + ] public function testGlobalStoreConfig() { $this->_object->expects( @@ -209,7 +209,7 @@ class ConfigFixtureTest extends \PHPUnit\Framework\TestCase #[ Config('current_store', 'web/unsecure/base_url', 'http://example.com/') - ] + ] public function testInitStoreAfter() { $this->_object->startTest($this); diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md index 0d50fdb7b3d..a311737cc6c 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md @@ -1,6 +1,7 @@ --- group: testing title: Data fixture attribute +redirect_from: /guides/v2.4/test/integration/annotations/magento-data-fixture-data-provider.html --- A data fixture is a PHP script that sets data you want to reuse in your test. @@ -22,7 +23,6 @@ To set up a date fixture, use the `DataFixture` attribute. - `` is the fully qualified name of a class that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. - `` is the name of the method declared in the current class. - ## Principles From e8b0b737292c836e42e7d4df4653eaa58465f2ef Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Fri, 10 Jun 2022 14:00:56 -0500 Subject: [PATCH 154/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- .../v2.4/test/integration/attributes.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/guides/v2.4/test/integration/attributes.md b/src/guides/v2.4/test/integration/attributes.md index 8b04a406aff..535d808a330 100644 --- a/src/guides/v2.4/test/integration/attributes.md +++ b/src/guides/v2.4/test/integration/attributes.md @@ -13,17 +13,17 @@ Native PHP8 Attributes is available now for the developers, and will be publicly The following attributes are available in integration tests: -| Name | Attribute | Format | Description | -|---------------------------------|--------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Application Isolation | `AppIsolation` | `AppIsolation((bool))` | Enables or disables application isolation when you run tests. When enabled, an application state after a test run will be the same as before the test run. For example, you should enable it, when you want to create sessions in a test, but you don't want them to affect other tests. | -| Configuration Fixture | `Config` | `Config((string), (string), (string), ...)` | Sets up configuration settings for a particular test. The list of settings is stored in the `core_config_data` database table. Multiple configuration parameters can be set with a signle command. After the test execution, the settings revert to their original state. | -| Database Isolation | `DbIsolation` | `DbIsolation((bool))` | Enables or disables database isolation. Disabled by default, unless you are using `DataFixture()` attribute, in which case it is enabled by default. All data, required for a test, live during transaction only. Any test results won't be written in a database. | -| Data Fixture | `DataFixture` | `DataFixture((string), (array)[, ], (string), as:(string))` | Points to a class or a method which creates testing entities (fixtures) for test execution. These are applied during the transaction. | -| Data Fixture Before Transaction | `DataFixtureBeforeTransaction` | `DataFixtureBeforeTransaction((string), (array)[, ], (string), as:(string))` | Points to a class or a method which creates testing entities (fixtures) for test execution before the transaction has begun. You will need to implement a rollback method changes made here. | -| Application Area | `AppArea` | `AppArea((string)<'adminhtml'/'frontend'/'global'>)` | Configures test environment in the context of specified application area. | -| Enable/Disable Cache | `Cache` | `Cache((string)<'all'/'enabled'/'disabled>')` | Enables or disables certain cache segment or all of them to prevent isolation problems. | -| Indexer Dimension Mode | `IndexerDimensionMode` | `IndexerDimensionMode(string),(string))` | Sets the indexer dimension mode for the test run. More information can be found in the [DevBlog](https://community.magento.com/t5/Magento-DevBlog/Indexers-parallelization-and-optimization/ba-p/104922). | -| Register Components | `ComponentsDir` | `ComponentsDir((string),...)` | Registers fixture components from specified directory (recursively). Unregisters the components after the test is finished. | +| Name | Attribute | Format | Description | +|---------------------------------|--------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Application Isolation | `AppIsolation` | `AppIsolation((bool))` | Enables or disables application isolation when you run tests. When enabled, an application state after a test run will be the same as before the test run. For example, you should enable it, when you want to create sessions in a test, but you don't want them to affect other tests. | +| Configuration Fixture | `Config` | `Config((string), (string), (mixed), ...)` | Sets up configuration settings for a particular test. The list of settings is stored in the `core_config_data` database table. Multiple configuration parameters can be set with a signle command. After the test execution, the settings revert to their original state. | +| Database Isolation | `DbIsolation` | `DbIsolation((bool))` | Enables or disables database isolation. Disabled by default, unless you are using `DataFixture()` attribute, in which case it is enabled by default. All data, required for a test, live during transaction only. Any test results won't be written in a database. | +| Data Fixture | `DataFixture` | `DataFixture((string), (array)[, ], (string), as:(string))` | Points to a class or a method which creates testing entities (fixtures) for test execution. These are applied during the transaction. | +| Data Fixture Before Transaction | `DataFixtureBeforeTransaction` | `DataFixtureBeforeTransaction((string), (array)[ => ], (string), as:(string))` | Points to a class or a method which creates testing entities (fixtures) for test execution before the transaction has begun. You will need to implement a rollback method changes made here. | +| Application Area | `AppArea` | `AppArea((string)<'adminhtml'/'frontend'/'global'>)` | Configures test environment in the context of specified application area. | +| Enable/Disable Cache | `Cache` | `Cache((string)<'all'/'enabled'/'disabled>')` | Enables or disables certain cache segment or all of them to prevent isolation problems. | +| Indexer Dimension Mode | `IndexerDimensionMode` | `IndexerDimensionMode(string),(string))` | Sets the indexer dimension mode for the test run. More information can be found in the [DevBlog](https://community.magento.com/t5/Magento-DevBlog/Indexers-parallelization-and-optimization/ba-p/104922). | +| Register Components | `ComponentsDir` | `ComponentsDir((string),...)` | Registers fixture components from specified directory (recursively). Unregisters the components after the test is finished. | ### Applying annotations From ad64ab99aac1b1bc96deff69af06b5b120899cba Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Fri, 10 Jun 2022 14:22:08 -0500 Subject: [PATCH 155/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- src/guides/v2.4/test/integration/attributes/magento-app-area.md | 2 +- .../v2.4/test/integration/attributes/magento-db-isolation.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/guides/v2.4/test/integration/attributes/magento-app-area.md b/src/guides/v2.4/test/integration/attributes/magento-app-area.md index 00195c85dc9..228ee6ee97e 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-app-area.md +++ b/src/guides/v2.4/test/integration/attributes/magento-app-area.md @@ -3,7 +3,7 @@ group: testing title: Application Area attribute in the Integration Testing Framework --- -Configure a test environment in scope of the particular [application area][] with the `@magentoAppArea` annotation. +Configure a test environment in scope of the particular [application area][] with the `AppArea` annotation. ## Format diff --git a/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md b/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md index 89be9c2420e..2097c6e4324 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md +++ b/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md @@ -26,7 +26,7 @@ Use test case declarations when a sequence of tests introduces changes to the da For example, typical CRUD tests: _create -> read -> update -> delete_. Every next test relies on a database state after the previous one. If at any point of that sequence (after creation) the test fails, the database will be polluted with test data. -To apply a database rollback after the test case, create a separate test case with `@magentoDbIsolation` enabled at a class level. +To apply a database rollback after the test case, create a separate test case with `DbIsolation` enabled at a class level. Example: From b3c95aeed7cbd5ca1c76d5dcc8249236b8ebe47c Mon Sep 17 00:00:00 2001 From: Dmytro Shevtsov Date: Fri, 10 Jun 2022 12:37:17 -0500 Subject: [PATCH 156/776] Update migrated log Add a number of migrated topics and the total number of topics to be migrated --- _plugins/generators/migrated_log.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/_plugins/generators/migrated_log.rb b/_plugins/generators/migrated_log.rb index e35101005f1..fb95444de76 100644 --- a/_plugins/generators/migrated_log.rb +++ b/_plugins/generators/migrated_log.rb @@ -14,15 +14,17 @@ class MigratedLog < Generator def generate(site) # Make the site object available in any scope in this class. @site = site - migrated_pages = @site.pages.filter { |page| page.data['layout'] == 'migrated' } - + pages = @site.pages + migrated_pages = pages.filter { |page| page.data['layout'] == 'migrated' } + number_of_staying_pages = pages.count { |page| page.data['guide_version'] == '2.3' || page.data['group'].nil? } url_prefix = site.config['url'] + site.config['baseurl'] migrated_pages_data = [] migrated_pages.each do |page| migrated_page = { path: page.path, title: page.data['title'] || abort("Error in '#{page.path}'.\n Check 'title' in the file's frontmatter.".red), - guide: @site.data.dig('toc', page.data['group'], 'label') || abort("Error in '#{page.path}'.\n Check 'group' in the file's frontmatter or 'label' in the corresponding TOC.".red), + guide: @site.data.dig('toc', page.data['group'], + 'label') || abort("Error in '#{page.path}'.\n Check 'group' in the file's frontmatter or 'label' in the corresponding TOC.".red), migrated_from: url_prefix + page.url, migrated_to: page.data['migrated_to'] || abort("Error in '#{page.path}'.\n Check 'migrated_to' in the file's frontmatter.".red), migrated_to_source: if page.data['migrated_to'].start_with?('https://experienceleague.adobe.com') @@ -35,9 +37,8 @@ def generate(site) } migrated_pages_data << migrated_page end - migrated_pages_by_group = migrated_pages_data.group_by { |page| page[:guide] }.sort.to_h - content = "The folowing is the list of topics that have been migrated and will be redirected soon.\n\n" + content = "The folowing #{migrated_pages.size} topics out of #{pages.size - number_of_staying_pages} have been migrated and will be redirected soon.\n\n" migrated_pages_by_group.each do |guide, topics| content += "\n## #{guide}\n\n\n" topics.sort_by { |topic| topic[:title] } @@ -65,7 +66,7 @@ def generate(site) # Add the newly constructed page object to the rest of pages # on the site. - @site.pages << topic + pages << topic end end end From 80cda0c0d5d71cd6f89559e5b714adb3918e535e Mon Sep 17 00:00:00 2001 From: jfrontain Date: Sat, 11 Jun 2022 22:05:55 -0500 Subject: [PATCH 157/776] added new fixed issue descriptions --- src/guides/v2.3/inventory/release-notes.md | 4 +- .../v2.4/release-notes/b2b-release-notes.md | 8 + .../v2.4/release-notes/commerce-2-4-5.md | 178 ++++++++++++++++-- 3 files changed, 170 insertions(+), 20 deletions(-) diff --git a/src/guides/v2.3/inventory/release-notes.md b/src/guides/v2.3/inventory/release-notes.md index f7aa0cd5c50..21e32913992 100644 --- a/src/guides/v2.3/inventory/release-notes.md +++ b/src/guides/v2.3/inventory/release-notes.md @@ -24,7 +24,7 @@ The release notes include: {{site.data.var.im}} 1.2.x (module version: `magento/inventory-metapackage = 1.2.4`) is supported with version 2.4.4 and compatible with version 2.4.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. -- {:.fix} The default inventory stock status of bundle and grouped products updates as expected when a merchant creates a shipment from the Admin. Previously, the status of these products remained unchanged after a shipment was created. +- {:.fix} The default inventory stock status of bundle and grouped products is now updated as expected when a merchant creates a shipment from the Admin. Previously, the status of these products remained unchanged after a shipment was created. - {:.fix} Configurable products are now returned back to stock when one of these conditions is met: the parent product has at least one saved child in stock, or the configurable product itself was updated and set as **in stock** and had at least one child in stock @@ -36,7 +36,7 @@ The release notes include: - {:.fix} Product stock status is now always **in stock** on the storefront when infinite back orders are enabled and the product is assigned to a custom stock, regardless of the quantity backordered. Previously, products went out of stock even when back orders were enabled. -- {:.fix} Configurable product parent and child product stock is now updated correctly after the source item is updated with `POST /V1/inventory/source-items`. +- {:.fix} Configurable product parent and child product stock is now updated correctly after the source item is updated with `POST /V1/inventory/source-items`. After the child product has been updated through the API, a new Inventory plugin for default stock checks and updates configurable product quantity and status. - {:.fix} Out-of-stock grouped products are no longer listed on the storefront Category page. diff --git a/src/guides/v2.4/release-notes/b2b-release-notes.md b/src/guides/v2.4/release-notes/b2b-release-notes.md index d513ffd9df6..fe4746b0c12 100644 --- a/src/guides/v2.4/release-notes/b2b-release-notes.md +++ b/src/guides/v2.4/release-notes/b2b-release-notes.md @@ -25,6 +25,14 @@ These release notes can include: - {:.fix} The **Account Created in** field for a company administrator now retains its value as expected after you save the company. +- {:.fix} customer queries to retrieve customer requisition lists that are filtered by `uid` no longer return empty results. + +- {:.fix} Added a plugin before the `collectQuoteTotals` call to ensure that store credits are applied only once. + +- {:.fix} Customers are now redirected to the login page when their account is deleted by an administrator from the Admin. Previously, {{ site.data.var.ee }} threw an error. The plugin (`SessionPlugin`) code block is now inside the `try…catch` block. Previously, this code was not wrapped inside the generic exception handling block. + +- {:.fix} Pressing **Enter** on the Quick Order page in mobile mode after entering a valid product name or SKU now takes the shopper to the next field as expected. + ## {{ site.data.var.ee }} B2B - Adobe Commerce 2.4.4 - {:.fix} The time required to upgrade from {{ site.data.var.ee }} 2.3.x to {{ site.data.var.ee }} 2.4.x in deployments with more than 100,000 company roles has been substantially reduced. diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md index 25c0d71a43d..39308095c81 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-5.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -108,8 +108,6 @@ This release brings increased conformance to standard accessibility guidelines. ## Fixed issues - - We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. ### Installation, upgrade, deployment @@ -122,6 +120,10 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * {{ site.data.var.ee }} no longer throws an exception when you try to change the Admin URL to a custom URL from the Admin. Previously, after changing the Admin URL, you could not log in. [GitHub-35416](https://github.com/magento/magento2/issues/35416) + + +* Merchants can now successfully upgrade from an {{ site.data.var.ee }} 2.4.2 deployment with Klarna to {{ site.data.var.ee }} 2.4.3. [GitHub-33760](https://github.com/magento/magento2/issues/33760) + ### Accessibility @@ -138,7 +140,7 @@ The **Shopping bag** button now provides a programmatic or textual indication of -* Filter and sort button text now meet the WCAG 2.0 required minimum color contrast ratio of 4.5:1 for standard text of 18pt (24px) or 14pt (19px) if bolded. Previously, navigation buttons for carousels did not meet these minimum contrast requirements. +* **Filter** and **Sort** button text now meet the WCAG 2.0 required minimum color contrast ratio of 4.5:1 for standard text of 18pt (24px) or 14pt (19px) if bolded. Previously, navigation buttons for carousels did not meet these minimum contrast requirements. @@ -168,8 +170,16 @@ The **Shopping bag** button now provides a programmatic or textual indication of * You can now use the REST API to update product price attributes for a specific website. Previously, if some product attributes were overridden for a specific store view, you could not update a price attribute for that product in that same store view. + + +* {{ site.data.var.ee }} now correctly calculates the cart total for a bundle product when the Product Subselect rule is applied. + ### Cache + + +* Full page cache is no longer shown as disabled in the Admin when the Magento cache is flushed and `use_stale_cache` is enabled. + ### Cart and checkout @@ -206,7 +216,7 @@ The **Shopping bag** button now provides a programmatic or textual indication of -* `cart` query responses no longer return null responses when a product is out of stock. Previously, when you ran a query with an out-of-stock product, {{ site.data.var.ee }}displayed a `null` value under the `items` section in the response. +* `cart` query responses no longer return null responses when a product is out of stock, and a new `errors` element containing the error message was introduced to the response. Previously, when you ran a query with an out-of-stock product, Magento displayed a `null` value under the `items` section in the response. See [cart query](https://devdocs.magento.com/guides/v2.4/graphql/queries/cart.html). @@ -230,7 +240,15 @@ The **Shopping bag** button now provides a programmatic or textual indication of -* Unassigning inventory sources through bulk action (**Catalog** > **Products** > **Select Products** > **Actions - Unassign Inventory Source**) now works as expected when sources include SKUs that are duplicate with the exception of a leading zero (for example, `01234` and `1234`). Previously, {{ site.data.var.ee }}did not unassign inventory sources and threw an error. +* Unassigning inventory sources through bulk action (**Catalog** > **Products** > **Select Products** > **Actions - Unassign Inventory Source**) now works as expected when sources include SKUs that are duplicate with the exception of a leading zero (for example, `01234` and `1234`). Previously, {{ site.data.var.ee }} did not unassign inventory sources and threw an error. + + + +* Store credit is now unavailable when the Zero Subtotal Checkout payment method is disabled. Previously, the Store Credit checkbox was not functional during order placement from Admin. {{ site.data.var.ee }} did not place the order with the store credit and displayed this error: `The requested Payment Method is not available`. + + + +* Merchants can now create a credit memo in which **Refund Shipping (Incl. Tax)** is set to -0.01 and can now set this amount to 0. Previously, the credit memo could not be created under these conditions. ### Cart price rule @@ -282,7 +300,7 @@ The **Shopping bag** button now provides a programmatic or textual indication of -* {{ site.data.var.ee }} no longer throws an error when a category rule assigns a product to a category that is subsequently sorted. +* {{ site.data.var.ee }} no longer throws an error when a category rule assigns a product to a category that is subsequently sorted in a multi-site deployment. @@ -294,7 +312,7 @@ The **Shopping bag** button now provides a programmatic or textual indication of -* Products are now enabled as expected after a schedule update completes. +* Products can now be enabled using a scheduled update. @@ -330,12 +348,28 @@ The **Shopping bag** button now provides a programmatic or textual indication of -* Page Cache is now cleared as expected for the configurable product parent when changes to a child product are saved. Previously, because the cache was not cleared, changes were not selected on the storefront configuration product page. [GitHub-34508](https://github.com/magento/magento2/issues/34508) +* Page cache is now cleared as expected for the configurable product parent when changes to a child product are saved. Previously, because the cache was not cleared, changes were not selected on the storefront configuration product page. [GitHub-34508](https://github.com/magento/magento2/issues/34508) * Product lists are now rendered correctly in the Admin. Previously, the product list did not render, and {{ site.data.var.ee }} displayed this error: `Item (Magento\Catalog\Model\Product\Interceptor) with the same ID "" already exists`. [GitHub-33145](https://github.com/magento/magento2/issues/33145) + + +* Product prices are now the same on the product detail page and in storefront search in multi-store deployments after Catalogue Price Scope changes from **website** to **global**. Previously, the Catalog Search Results page displayed the **global** price, and the product details page displayed the **website** price. [GitHub-34074](https://github.com/magento/magento2/issues/34074) + + + +* Layered navigation now displays products with the highest prices as expected when **Price Navigation Step Calculation** is set to **Manual**. + + + +* You can now change the per-page product limit displayed within a category when **Remember Category Pagination** is enabled. Previously, the cookie `form_key` and UI `form_key` differed, and {{ site.data.var.ee }} displayed this error: `Invalid Form Key. Please refresh the page`. + + + +* The EAV indexer now processes product IDs as type `int` to prevent possible performance issues. + ### Catalog rule ### CMS content @@ -378,6 +412,10 @@ The **Shopping bag** button now provides a programmatic or textual indication of * Configurable products are now moved to the last position in the product listing after stock is updated when the **Move out of stock to the bottom** setting is enabled. A new custom database query has been implemented to negate Elasticsearch index sort order, which disregards Admin-enabled sort order. Previously, configurable products and their child products were not moved to the bottom of the list when this setting was enabled. + + +* {{ site.data.var.ee }} now correctly displays a configurable product’s stock status, available configurations, and displayed price when the availability of one of the configurable product’s child product is changed by a scheduled update. Previously, when a configurable product had two children and the availability of one child product was disabled with a scheduled update, the parent product’s stock status was incorrectly displayed as **Out of Stock** when the update was active, After the update completed, the displayed price and the availability of its configurations was miscalculated. + ### Customer @@ -410,11 +448,11 @@ The **Shopping bag** button now provides a programmatic or textual indication of -* The `bin/magento setup:config:set` command no longer overrides already set cache ID prefixes. +* The `bin/magento setup:config:set` command no longer overrides already set cache ID prefixes in `app/etc/env.php`. -* `setup:static-content:deploy -s compact` now includes styles from child themes as expected. Previously, these themes were not present on the storefront after deployment. +* `setup:static-content:deploy -s compact` now includes styles from child themes as expected. Previously, theme CSS files were not present on the storefront after deployment. @@ -452,6 +490,10 @@ The **Shopping bag** button now provides a programmatic or textual indication of * {{ site.data.var.ee }} now returns a 404 error instead of a 500 error when you navigate to `/checkout/sidebar/updateItemQty/?item_qty=error` on the storefront. Previously, this error was thrown: `Warning: A non-numeric value encountered in /vendor/magento/module-checkout/Controller/Sidebar/UpdateItemQty.php on line 69`. [GitHub-34380](https://github.com/magento/magento2/issues/34380) + + +* Magento no longer triggers a `trim(): Passing null to parameter #1 ($string) of type string is deprecated` error when the AMPQ connection is configured without SSL configuration. + ### General fixes @@ -514,6 +556,14 @@ The **Shopping bag** button now provides a programmatic or textual indication of * {{ site.data.var.ee }} no longer throws an error when an administrator with roles scoped to a single website adds product to Content Elements using PageBuilder. Previously, {{ site.data.var.ee }} threw an SQL error. + + +* Validation has been added to the second line of the street address on the edit and add address pages. The minimum and maximum text lengths that are specified on the second are now enforced. + + + +* Magento no longer throws the following error during the creation of a catalog rule in the Admin after upgrade: `A technical problem with the server created an error. Try again to continue what you were doing. If the problem persists, try again later`. + ### Gift cards @@ -596,7 +646,7 @@ The **Shopping bag** button now provides a programmatic or textual indication of -* `products` queries now return only the categories associated with the website passed in the request. +* `products` queries now return only the categories associated with the store passed in the request. @@ -694,7 +744,7 @@ The **Shopping bag** button now provides a programmatic or textual indication of -* Images on product details page no longer flicker, and the image remains centered as expected. Previously, after a product detail page completed loading an image, the image visibly shifted downwards. +* Images on product details pages no longer flicker, and images remain centered as expected. Previously, after a product detail page completed loading an image, the image visibly shifted downwards. ### Import/export @@ -708,7 +758,7 @@ The **Shopping bag** button now provides a programmatic or textual indication of -* {{ site.data.var.ee }} now successfully imports images with a long file name. Previously, {{ site.data.var.ee }} did not import the image and threw this error: `Imported resource (image) could not be downloaded from external resource due to timeout or access permissions in row(s):`. +* {{ site.data.var.ee }} now successfully imports images with long file names. Previously, {{ site.data.var.ee }} did not import the image and threw this error: `Imported resource (image) could not be downloaded from external resource due to timeout or access permissions in row(s):`. @@ -718,6 +768,10 @@ The **Shopping bag** button now provides a programmatic or textual indication of * Bundle products that contain a question mark (?) in the option title can now be imported successfully because of improvements to the query builder inside `populateExistingOptions` method. The option title is also displayed correctly. Previously, after the initial import, successive imports resulted in corrupted behavior and doubled options. Shoppers could not add the product to the cart, either. + + +* Added validation for category names during import. Previously, {{ site.data.var.ee }} did not validate category names, which lead to errors when category names exceeded 255 characters. + ### Index ### Infrastructure @@ -764,6 +818,10 @@ Repetitive actions have been replaced with action groups in these tests: * The newsletter subscription confirmation email now has the correct, store-specific email address in the **From** field if the customer is assigned to a non-default store and subscribed or unsubscribed from the Admin. Previously, the customer received an email with default email in **From** header. [GitHub-34963](https://github.com/magento/magento2/issues/34963) + + +* Customers added through the `createCustomer/createCustomerV2/updateCustomer/updateCustomerV2` mutation are now added with active newsletter subscriptions. Previously, customers were unsubscribed from newsletters even when the request contained proper input parameters. [GitHub-33599](https://github.com/magento/magento2/issues/33599) + ### Order @@ -798,6 +856,14 @@ Repetitive actions have been replaced with action groups in these tests: * {{ site.data.var.ee }} now displays credit memos on the credit memo grid page for orders created from store views whose name is prepended with numbers. Previously, {{ site.data.var.ee }} displayed the error: `The store that was requested wasn't found. Verify the store and try again. Exception in /var/www/html/vendor/magento/module-store/Model/StoreRepository.php:75`. [GitHub-35122](https://github.com/magento/magento2/issues/35122) + + +* {{ site.data.var.ee }} now displays the free shipping cost (0) on the Admin and storefront invoice page totals. Previously, when shipping was zero for an order, {{ site.data.var.ee }} did not display the shipping amount in total on the invoice page shipping total. + + + +* Magento now displays correct order status during checkout when customer store credit is used. + ### Payment methods @@ -822,7 +888,11 @@ Repetitive actions have been replaced with action groups in these tests: -* Redis cache management has been improved by the addition of TTL (expiration date) for configurable product associated products data caches. Previously, these caches were not evicted due to missing TTL if redis keys eviction policy is configured to any of volatile eviction policies. +* Redis cache management has been improved by the addition of TTL (expiration date) for configurable products’ associated product data caches. Previously, these caches were not evicted due to missing TTL values if Redis key eviction policy was configured to a volatile eviction policy. + + + +* The new `Grid Filter Condition Type` customer/customer address attribute controls how an attribute filter is matched against the attribute values in the database, Options include `Partial Match`, `Prefix Match`, and `Full Match`. ### Pricing @@ -838,6 +908,16 @@ Repetitive actions have been replaced with action groups in these tests: ### Product video +### Promotions + + + +* The **Times Used** value for a discount is no longer incremented twice when a guest customer places an order with a discount and subsequently registers an account. + +### ReCAPTCHA + +* The **Submit** button on the Login and Create an Account pages is now inactive until ReCaptcha is fully loaded. + ### Return Merchandise Authorizations (RMA) @@ -846,10 +926,24 @@ Repetitive actions have been replaced with action groups in these tests: -* The **Use Default** checkbox to enable RMA on the product edit page now works as expected for Default Store. Previously, the checkbox was cleared immediately after the product was saved. +* The **Use Default** checkbox, which is used to enable RMA on the product edit page, now works as expected for Default Store. Previously, the checkbox was cleared immediately after the product was saved. ### Reviews +### Rewards + + + +* Reward points can now be refunded when store credit functionality is disabled. + + + +* Checkout performance has been improved when reward points are applied. When `entity` is null, then the database query will not be executed because querying the `magento_reward_history` table is not mandatory under the circumstances. + + + +* Credit memos for guest orders no longer check for `customer_id`, which skips querying the `magento_reward_history' database table table for reward points. This change has improved performance. + ### Sales ### Sales Rule @@ -910,7 +1004,7 @@ Repetitive actions have been replaced with action groups in these tests: -* Merchants can now remove an end date for a schedule update or delete and recreate an update. Previously, when an end date was removed, an entity remained scheduled for that time. {{ site.data.var.ee }} now removes the outdated update for removed rollback. +* Merchants can now remove an end date for a scheduled update or delete and recreate an update. Previously, when an end date was removed, an entity remained scheduled for that time. {{ site.data.var.ee }} now removes the outdated update for removed rollback. @@ -918,16 +1012,32 @@ Repetitive actions have been replaced with action groups in these tests: -* The `custom_design_to` attribute value is now updated as expected when a schedule update is changed. Previously, two separate category design updates with no end time were treated as one. When one of the schedule updates was deleted while the first one was running, the `custom_design_from` time value became greater than the `custom_design_to` time values in the next schedule update. +* The `custom_design_to` attribute value is now updated as expected when a scheduled update is changed. Previously, two separate category design updates with no end time were treated as one. When one of the scheduled updates was deleted while the first one was running, the `custom_design_from` time value became greater than the `custom_design_to` time values in the next scheduled update. -* {{ site.data.var.ee }} now displays a form populated with data from the previous scheduled update as expected when you try to create the second schedule update for a product. Previously, {{ site.data.var.ee }} displayed this error when you tried to create the second update with a past start date: `The Start Time of this Update cannot be changed. It's been already started`. +* Forms are now populated with data as expected after a scheduled update is edited. * The `vendor/magento/module-catalog-staging/Setup/Patch/Data/MigrateCatalogProducts.php` data patch no longer fails when the database includes product with custom options and the `special_from_date` attribute is set. + + +* Changes are now saved during a second scheduled update when the changes are added by the running update. Previously, changes were not saved, and merchants needed to re-enter and save changes. + + + +* The Bulk actions log now displays information about failed `to be moved` scheduled updates. Previously, information about these failures was available in the `cron.log` file only. + + + +* Merchants are now restricted to using comma-separated prices when editing a product price in a scheduled update regardless of locale. Previously, prices that contained commas in a scheduled update were divided by 1000 depending on the locale. + + + +* Problems with DHL domestic shipping in deployments running PHP 8.1 have been resolved by requiring dutiable tags for international shipments only. + ### Store ### Tax @@ -960,6 +1070,10 @@ Repetitive actions have been replaced with action groups in these tests: * The `getCartDetails` query no longer includes tax when returning `subtotal_with_discount_excluding_tax`. [GitHub-33905](https://github.com/magento/magento2/issues/33905) + + +* Web API requests for order data (`rest/V1/orders/`) no longer returns negative values for row totals. + ### Test @@ -988,6 +1102,18 @@ Repetitive actions have been replaced with action groups in these tests: * The Admin date-time format for Brazilian Portuguese and French locales is now valid. + + +* Added a grave accent [ ` ] character to the name validator so that customer account can be created for first or last names that include this accent. + + + +* The text on the **Add to cart** button on the Product Details page now remains translated into the language specified in the associated locale. Translation files are now converted to corresponding JavaScript files based on the areas, themes, and locales when `translate_strategy=embedded`. Previously, the text reverted to English after the product was added to the cart. + + + +* Search Synonyms now respect their assigned store scope. Previously, a synonym assigned to a specific store was searchable on any other store. + ### UI @@ -1038,6 +1164,18 @@ Repetitive actions have been replaced with action groups in these tests: * Administrators can now set the current user’s expiration date higher than 2038 and save the user successfully. Previously, the user whose expiration date was changed could not log back in after logging out. + + +* {{ site.data.var.ee }} now displays an informative error message when an administrator tries to save an address with excessive street lines in Admin **Store** > **Attributes** > **Customer Address**. The administrator can now delete the extra address information and successfully save the address. Previously, {{ site.data.var.ee }} committed the extra lines but did not save the data. + + + +* The product listing view configuration in the database and local storage has been updated. Custom grid views are now saved during page reload and view changes. + + + +* You can now switch between store views when website restrictions are enabled. Previously, problems with the store view switcher prevented switching store views. + ### URL rewrites @@ -1088,6 +1226,10 @@ Repetitive actions have been replaced with action groups in these tests: * REST API bulk PUT and DELETE requests now work as expected when the `Magento_ReCaptchaWebapiRest` module is enabled. [GitHub-35348](https://github.com/magento/magento2/issues/35348) + + +* The Bulk Rest API now works with the `bySku` option for configurable products. Previously, it returned a 500 error. + ### Wish list From 26f9768c6c830c99d712b34953814a9dfe299ca5 Mon Sep 17 00:00:00 2001 From: jfrontain Date: Sun, 12 Jun 2022 21:02:45 -0500 Subject: [PATCH 158/776] added platform upgrade highlights --- .../v2.4/release-notes/commerce-2-4-5.md | 65 +++++++++++++++++-- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md index 39308095c81..884b76e6e00 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-5.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -54,13 +54,50 @@ Security improvements for this release improve compliance with the latest securi * Composer 2.2 -* Elasticsearch v7.17 +* Elasticsearch (~7.17.0 with constraint) -* The `TinyMCE` library has been upgraded to v5.10.0. +* TinyMCE (5.10.2) -* `PHPStan` has been upgraded to v1.5. +* jQueryUI (1.13.1) -* The `league/fly` Composer dependencies have been to v2.4.3. +* `PHPStan` (^1.5.7 with constraint) + +#### Composer dependency updates + + + +The following Composer dependencies have been updated to the latest versions with constraint: + +`colinmollenhour/credis` (1.13.0 or 1.12.2)? +`guzzlehttp/guzzle` (^7.4.2) +`laminas/laminas-captcha` (updated with a constraint ^2.12) +`laminas/laminas-db` (^2.15.0) +`laminas/laminas-di` (^3.4.0) +`laminas/laminas-escaper` (~2.10.0) +`laminas/laminas-eventmanager` (^3.5.0) +`laminas/laminas-feed` (^2.17.0) +`laminas/laminas-mail` (^2.16.0) +`laminas/laminas-mvc` (^3.3.3) +`laminas/laminas-server` (^2.11.1) +`laminas/laminas-servicemanager` (^3.11.0) +`laminas/laminas-session` (^2.12.1) +`laminas/laminas-validator` (^2.17.0) +`league/fly` (2.4.3) +`monolog/monolog` (^2.5) +`phpmd/phpmd` (^2.12.0) +`phpstan/phpstan` (^1.5.7) +`phpunit/phpunit` (~9.5.20) +`phpunit/phpunit` (^9.4) +`php-cs-fixer` (^3.4.0) +`webonyx/graphql-php` (14.11.6) + +The `laminas/laminas-session`, `laminas/laminas-text`, and `laminas/laminas-view` dependencies have been removed. + +#### Other upgrades and replacements + +* The default Gateway URL for USPS shipping has been updated to use `https` instead of `http`. + +* The `Froogaloop` library has been replaced with the Vimeo `Player.js` library (2.16.4). * The `grunt-eslint` (NPM) library has been upgraded to the latest version. @@ -68,9 +105,17 @@ Security improvements for this release improve compliance with the latest securi * The `php-cs-fixer` and `phpcs` static code analysis tools are now compatible with PHP 8.x. -* The `php-cs-fixer` Composer dependency has been updated to ^3.4.0. +* `glob.js` dependency (upgraded with constraint to ~7.2.0) -* The `phpunit/phpunit` Composer dependency updated to version ^9.4. +* `serve-static.js` dependency (upgraded with constraint ~1.14.2) + +* `underscore.js` dependency (NPM) (1.14.2) + +* `moment-timezone-with-data.js` (0.5.34) + +* The library `jquery/jquery-cookie` has been replaced with `js-cookie/js-cookie`. + +* The `jarallax.js` and `jaralax-video.js` libraries have been updated to the latest versions (2.0.3). ### Performance and scalability enhancements @@ -780,6 +825,14 @@ The **Shopping bag** button now provides a programmatic or textual indication of * The SQL query that updates affected quotes after a cart price rule is disabled has been optimized to avoid locking the entire quote table. + + +* A deprecated Context Menu plugin has been removed from plugins list. + + + +* The TinyMCE editor toolbar-related logic in the Page Builder module has been updated as a result of introducing `delayedRender` logic for the toolbar in TinyMCE. + #### Library removals and deprecations #### Library upgrades From 8317ae0ba2ab9cdd25f1c7ee60f2688d21a67921 Mon Sep 17 00:00:00 2001 From: magedocs Date: Mon, 13 Jun 2022 14:38:48 +0000 Subject: [PATCH 159/776] Update News data --- src/_data/whats-new.yml | 67 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/src/_data/whats-new.yml b/src/_data/whats-new.yml index f082de6a6ea..e4df24b7ca4 100644 --- a/src/_data/whats-new.yml +++ b/src/_data/whats-new.yml @@ -4,8 +4,73 @@ description: This page contains recent changes that we think you'd like to know We exclude from this list proofreading, spelling checks, and all minor updates. link: "/whats-new.html" thread: "/whatsnew-feed.xml" -updated: Mon Jun 6 14:38:47 2022 +updated: Mon Jun 13 14:38:46 2022 entries: +- description: Clarified notes throughout the Cloud guide about updating configurations + in Pro projects. See [Configure environments](https://devdocs.magento.com/cloud/env/environments.html) + as an example. + versions: 2.x + type: Technical + date: June 10, 2022 + link: https://github.com/magento-commerce/devdocs/pull/3007 + merge_commit: 16b2bb8e7c6a152e87b191f6b1388135e47d2e1b + contributor: hguthrie + membership: true + labels: + - 2.x + - Technical +- description: The [Extension Developer Best Practices Guide](https://devdocs.magento.com/guides/v2.4/ext-best-practices/bk-ext-best-practices.html) + topics moved to the [Adobe Developer documentation](https://developer.adobe.com/commerce/php/best-practices/) + and will be redirected soon. + versions: 2.4.x + type: Major Update + date: June 10, 2022 + link: https://github.com/magento-commerce/devdocs/pull/2996 + merge_commit: 2e00f287e51463a4ee32efe66b8943b9f7971928 + contributor: jeff-matthews + membership: true + labels: + - Major Update + - 2.4.x + - migration +- description: The [Module reference guide](https://devdocs.magento.com/guides/v2.4/mrg/intro.html) + has moved to the [Adobe Developer documentation](https://developer.adobe.com/commerce/php/module-reference/) + and will be redirected soon. + versions: 2.4.x + type: Technical + date: June 8, 2022 + link: https://github.com/magento-commerce/devdocs/pull/2999 + merge_commit: d73fc1686f4bcb99d042361e2ed0391554b928b8 + contributor: dshevtsov + membership: true + labels: + - Technical + - 2.4.x +- description: 'Cloud guide: updated the [CRON_CONSUMERS_RUNNER](https://devdocs.magento.com/cloud/env/variables-deploy.html#cron_consumers_runner) + deploy variable to show an example of an empty array that runs all consumers.' + versions: 2.x + type: Technical + date: June 8, 2022 + link: https://github.com/magento-commerce/devdocs/pull/3002 + merge_commit: 8709c3516cbb3c1db60ff04b871ffeeda148d298 + contributor: hguthrie + membership: true + labels: + - 2.x + - Technical +- description: Published [release notes](https://devdocs.magento.com/quality-patches/release-notes.html) + for the 1.1.15 Quality Patches Tool (QPT) package release. + versions: 2.3.x, 2.4.x + type: Major Update + date: June 8, 2022 + link: https://github.com/magento-commerce/devdocs/pull/3000 + merge_commit: 25fb4ad8863972827bbc4d623bfc8d3e980767e4 + contributor: katmoon + membership: true + labels: + - Major Update + - 2.3.x + - 2.4.x - description: Added missing versions for Amazon Web Services on the [system requirements](https://devdocs.magento.com/guides/v2.4/install-gde/system-requirements.html) page. versions: 2.4.x From bb997da37e4c162b1dfce088312efdb21f8163f1 Mon Sep 17 00:00:00 2001 From: Thiaramus Date: Mon, 13 Jun 2022 13:58:27 -0500 Subject: [PATCH 160/776] Apply suggestions from code review Co-authored-by: Buba Soumah --- src/_data/toc/testing.yml | 2 +- .../v2.4/test/integration/attributes/magento-app-isolation.md | 4 ++-- src/guides/v2.4/test/integration/attributes/magento-cache.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/_data/toc/testing.yml b/src/_data/toc/testing.yml index 07a9c492287..c529618d0e9 100644 --- a/src/_data/toc/testing.yml +++ b/src/_data/toc/testing.yml @@ -37,7 +37,7 @@ pages: - label: '@magentoDbIsolation' url: /test/integration/annotations/magento-db-isolation.html - - label: Using PHP8 attributes + - label: Using PHP built-in attributes url: /test/integration/attributes.html exclude_versions: [ "2.3" ] diff --git a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md index 6a4fe758bf0..3189ce1f39f 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md +++ b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md @@ -21,7 +21,7 @@ Application isolation annotation: ] ``` -## Test case attribute +## Test class attribute The application and related objects are reinitialized after each test case execution. This behavior helps to isolate application objects in different test cases. @@ -30,7 +30,7 @@ The test case isolation is mandatory and cannot be disabled. {:.bs-callout-warning} Do not share and do not rely on sharing the application objects between test cases. -## Test annotation +## Test method attribute By default, the application isolation (that is automatic reinitialization) in tests is disabled. To enable the application isolation for a test, use the `AppIsolation` attribute. diff --git a/src/guides/v2.4/test/integration/attributes/magento-cache.md b/src/guides/v2.4/test/integration/attributes/magento-cache.md index 4145cc95c48..6c961a72a19 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-cache.md +++ b/src/guides/v2.4/test/integration/attributes/magento-cache.md @@ -9,7 +9,7 @@ Enable or disable a [cache type][] using the `Cache` attribute. ```php?start_inline=1 #[ - Cache((string)<'all'/'enabled'/'disabled>') + Cache((string)'', (string)') ] ``` From 68995f4ca958eb52b1d861cd48b563f338a0874f Mon Sep 17 00:00:00 2001 From: Shrie Spangler Date: Mon, 13 Jun 2022 14:30:09 -0500 Subject: [PATCH 161/776] Add Pay Services info --- src/_data/features.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/_data/features.yml b/src/_data/features.yml index 0adb2af3b68..feaaab1efa2 100644 --- a/src/_data/features.yml +++ b/src/_data/features.yml @@ -48,6 +48,14 @@ features: 2.2: false 2.3: true 2.4: true + - + name: Payment Services delivers best-in-class shopper experience + support: + 2.0: false + 2.1: false + 2.2: false + 2.3: false + 2.4: true - name: PayPal Smart Buttons support: @@ -179,6 +187,14 @@ features: 2.2: true 2.3: true 2.4: true + - + name: Payment Services payments, reporting, and reconciliation + support: + 2.0: false + 2.1: false + 2.2: false + 2.3: false + 2.4: true - name: Platform, performance, and security enhancements versions: From 022579b7f3e0d0daf038b2af6160b35892e8109c Mon Sep 17 00:00:00 2001 From: Shrie Spangler Date: Mon, 13 Jun 2022 14:36:45 -0500 Subject: [PATCH 162/776] Clean up wording --- src/_data/features.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_data/features.yml b/src/_data/features.yml index feaaab1efa2..f692de1f625 100644 --- a/src/_data/features.yml +++ b/src/_data/features.yml @@ -49,7 +49,7 @@ features: 2.3: true 2.4: true - - name: Payment Services delivers best-in-class shopper experience + name: Payment Services flexible payment options support: 2.0: false 2.1: false @@ -188,7 +188,7 @@ features: 2.3: true 2.4: true - - name: Payment Services payments, reporting, and reconciliation + name: Payment Services reporting and reconciliation dashboard support: 2.0: false 2.1: false From 0ff897f84b93bb76c5460eafea012fc2798785c4 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Mon, 13 Jun 2022 16:55:18 -0500 Subject: [PATCH 163/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- src/_data/toc/testing.yml | 4 - .../v2.4/test/integration/attributes.md | 21 ++- .../attributes/magento-data-fixture.md | 172 ++++++------------ .../integration/parameterized_data_fixture.md | 99 ---------- 4 files changed, 74 insertions(+), 222 deletions(-) delete mode 100644 src/guides/v2.4/test/integration/parameterized_data_fixture.md diff --git a/src/_data/toc/testing.yml b/src/_data/toc/testing.yml index c529618d0e9..0f2c3b70fda 100644 --- a/src/_data/toc/testing.yml +++ b/src/_data/toc/testing.yml @@ -64,10 +64,6 @@ pages: - label: 'DbIsolation' url: /test/integration/attributes/magento-db-isolation.html - - label: Parameterized Data Fixture - url: /test/integration/parameterized_data_fixture.html - exclude_versions: ["2.3"] - - label: JavaScript Unit Testing children: diff --git a/src/guides/v2.4/test/integration/attributes.md b/src/guides/v2.4/test/integration/attributes.md index 535d808a330..4a490d38d06 100644 --- a/src/guides/v2.4/test/integration/attributes.md +++ b/src/guides/v2.4/test/integration/attributes.md @@ -1,15 +1,15 @@ --- group: testing -title: Using PHP8 Attributes +title: Using PHP built-in attributes --- -[PHP8 Attributes][] help to declare context in your code. Attributes can be used alone or together with Annotations to help to declare context in your code. +[PHP built-in attributes][] help to declare context in your code. Attributes can be used alone or together with Annotations to help to declare context in your code. {:.bs-callout-info} -Native PHP8 Attributes is available now for the developers, and will be publicly available with Magento 2.4.5 release. +Using PHP built-in attributes is available now for the developers, and will be publicly available with Magento 2.4.5 release. [PHPUnit annotations][] are still available for use with Magento. -### Quick overview +## Quick overview The following attributes are available in integration tests: @@ -25,7 +25,13 @@ The following attributes are available in integration tests: | Indexer Dimension Mode | `IndexerDimensionMode` | `IndexerDimensionMode(string),(string))` | Sets the indexer dimension mode for the test run. More information can be found in the [DevBlog](https://community.magento.com/t5/Magento-DevBlog/Indexers-parallelization-and-optimization/ba-p/104922). | | Register Components | `ComponentsDir` | `ComponentsDir((string),...)` | Registers fixture components from specified directory (recursively). Unregisters the components after the test is finished. | -### Applying annotations +### Format + +- `AppIsolation(bool $isolationEnabled = false)` +- `Config(string $storeCode, string $configPath, mixed $configValue, ...)` + + +## Applying annotations The Magento-specific annotations for integration tests are applied in the following order: @@ -41,7 +47,10 @@ The Magento-specific annotations for integration tests are applied in the follow This order is necessary to meet the requirement of setting up the store-scoped configuration values for fixture stores (stores that are created by data fixtures). +{:.bs-callout-info} +[PHP built-in attributes][] are only available with PHP8 and above. + [PHPUnit annotations]: {{ page.baseurl }}/test/integration/annotations.html -[PHP8 Attributes]: https://www.php.net/manual/en/language.attributes.overview.php +[PHP built-in attributes]: https://www.php.net/manual/en/language.attributes.overview.php diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md index a311737cc6c..b065fec5dbd 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md @@ -1,125 +1,78 @@ --- group: testing title: Data fixture attribute -redirect_from: /guides/v2.4/test/integration/annotations/magento-data-fixture-data-provider.html +redirect_from: + - /guides/v2.4/test/integration/annotations/magento-data-fixture-data-provider.html + - /guides/v2.4/test/integration/parameterized_data_fixture.html --- -A data fixture is a PHP script that sets data you want to reuse in your test. -The script can be defined in a separate PHP file, class, or as a local test case method. +## Overview + +Parameterized data fixture is a dynamic and scalable data fixture that accepts parameters directly from the fixture declaration. It eliminates the need to create almost identical fixtures every time you need a slight change. -Use data fixtures to prepare a database for tests. -The Integration Testing Framework (ITF) reverts the database to its initial state automatically. +A data fixture is a PHP script that sets data you want to reuse in your test. +Use data fixtures to prepare a database for tests. The Integration Testing Framework (ITF) reverts the database to its initial state automatically. To set up a date fixture, use the `DataFixture` attribute. ## Format -`DataFixture` takes an argument that points to the data fixture as a filename, full class name, or local method, and an optional alias. +`DataFixture` takes following arguments. ```php?start_inline=1 #[ - DataFixture((string), (array)[, ], (string), as:(string)) + DataFixture(string $type, array $data = [], ?string $as = null) ] ``` -- `` is the fully qualified name of a class that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. -- `` is the name of the method declared in the current class. - -## Principles - -1. Do not use a direct database connection in fixtures to avoid dependencies on the database structure and vendor. -1. Use an application API to implement your data fixtures. -1. A method that implements a data fixture must be declared as `public` and `static`. -1. Fixtures declared at a test level have a higher priority than fixtures declared at a test case level. -1. Test case fixtures are applied to each test in the test case, unless a test has its own fixtures declared. -1. attribute declaration at a test case level does not affect tests that have their own attribute declarations. -1. Fixture alias SHOULD be camelcase. -1. Fixture data provider MUST be a valid JSON string. - -## Usage - -As mentioned above, there are three ways to declare fixtures: - -- as a PHP script file that is used by other tests and test cases. -- as a local method that is used by other tests in the test cases. -- as a [Class][parameterizedDataFixture] that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. - -### Fixture as a separate file - -Define the fixture in a separate file when you want to reuse it in different test cases. -To declare the fixture, use one of the following conventions: - -- Fixture declaration as a path relative to the test suite directory - - Relative to `dev/tests/integration/` - - With forward slashes `/` - - No leading slash - - Example: - - ```php - #[ - DataFixture('Magento/Cms/_files/pages.php') - ] - ``` - -- Fixture declaration as a path relative to a module - - Relative to the directory of a module available in the project - - With forward slashes `/` - - No leading slash in the path part of the declaration - - Example: +### Parameters - ```php - #[ - DataFixture('VendorName_ModuleName::Test/Integration/_files/fixture_name.php') - ] - ``` - -The ITF includes the declared PHP script to your test and executes it during the test run. - -The following example demonstrates a simple implementation of a Cms module page test from the Magento codebase. - -Data fixture to test a Cms module page: [`dev/tests/integration/testsuite/Magento/Cms/_files/pages.php`][]. +- **type** + - The fully qualified name of a class that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. +- **data** + - The optional array of data passed on to the fixture. +- **as** + - The fixture alias that will be used as a reference to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. -Test case that uses the above data fixture: [`dev/tests/integration/testsuite/Magento/Cms/Block/PageTest.php`][]. +## Creating the fixture -### Fixture as a method +### Principles -[`dev/tests/integration/testsuite/Magento/Cms/Controller/PageTest.php`][] demonstrates an example of the `testCreatePageWithSameModuleName()` test method that uses data from the `cmsPageWithSystemRouteFixture()` data fixture. +1. Parameterized Data Fixture class MUST implement `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface` if the data created by the fixture is revertible. For instance, a fixture that creates an entity (for example, product). +1. Parameterized Data Fixture class MUST be placed in the `/Test/Fixture` folder of the corresponding module with namespace: `\\Test\Fixture` (for example, `Magento\Catalog\Test\Fixture`). +1. Parameterized Data Fixture class SHOULD follow single responsibility principle. +1. Parameterized Data Fixture class MUST depend only on services from modules that are declared in the `require` section of its module's composer.json. +1. Parameterized Data Fixture MUST NOT depend on another fixture. +1. Parameterized Data Fixture SHOULD be implemented using service APIs. +1. Parameterized Data Fixture SHOULD have dynamic default data to allow generating unique fixtures. -### Data Fixture Data Provider +### Dynamic default data -{:.bs-callout-info} -Data Fixture Data Provider is only applicable to Parameterized Data Fixture and is currently only available for Magento Open Source contributors. It will be released for general use with Magento Open Source 2.4.5. +In order to generate multiple fixtures of the same type without having to manually configure unique fields, you can use the placeholder `%uniqid%` in the default value of unique fields and `Magento\TestFramework\Fixture\Data\ProcessorInterface` to substitute the placeholder with unique sequence. -There are two types of data providers: +[`Magento\Catalog\Test\Fixture\Product`][] demonstrates the usage of `%uniqid%` (`sku`: `simple-product%uniqid%`) in the fixture default data. -- Inline JSON as data provider -- @magentoDataFixtureDataProvider magentoDataFixtureDataProvider attribute - -#### Inline JSON as data provider - -Data can be passed to the [Parameterized Data Fixture][parameterizedDataFixture] using the `with` directive as follows: - -Example: +In the following example, a unique `sku` is automatically generated for the first fixture (for example, `simple-product61c10b2e86f991`) and the second fixture (for example, `simple-product61c10b2e86f992`). The sequence is random and therefore unpredictable. ```php?start_inline=1 -class ProductsList extends \PHPUnit\Framework\TestCase +class ProductsListTest extends \PHPUnit\Framework\TestCase { - /** - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product with:{"price": 5.0} - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product with:{"price": 10.0} - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product with:{"price": 15.0} - */ + #[ + DataFixture(ProductFixture::class), + DataFixture(ProductFixture::class) + ] public function testGetProductsCount(): void { } } ``` -### Fixture Alias +### Decoupling fixtures + +Fixtures must be written in the way that they only use one API to generate data. For example, the fixture that creates +a product should only invoke "Create Product" API and return the product created. This fixture should not add any extra +logic beyond the "create product" API capabilities, such logic should be implemented in a separate fixture. -{:.bs-callout-info} -Fixture Alias is only applicable to Parameterized Data Fixture and is currently only available for Magento Open Source contributors. It will be released for general use with Magento Open Source 2.4.5. +### Fixture Alias You can give [Parameterized Data Fixture][parameterizedDataFixture] an alias using the `as` directive. The fixture alias is used as a reference to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. @@ -132,11 +85,11 @@ The following example shows how to retrieve data that was returned by the fixtur ```php?start_inline=1 class ProductsList extends \PHPUnit\Framework\TestCase { - /** - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product as:product1 - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product as:product2 - * @magentoDataFixture Magento\Catalog\Test\Fixture\Product as:product3 - */ + #[ + DataFixture(ProductFixture::class, as: 'product1'), + DataFixture(ProductFixture::class, as: 'product2'), + DataFixture(ProductFixture::class, as: 'product3') + ] public function testGetProductsCount(): void { $fixtures = DataFixtureStorageManager::getStorage(); @@ -159,11 +112,11 @@ The following example shows how a fixture can use the data of another fixture: ```php?start_inline=1 class QuoteTest extends \PHPUnit\Framework\TestCase { - /** - * @magentoApiDataFixture Magento\Quote\Test\Fixture\GuestCart as:cart - * @magentoApiDataFixture Magento\Quote\Test\Fixture\SetBillingAddress with:{"cart_id":"$cart.id$"} - */ - public function testGetBillingAddress(): void + #[ + DataFixture(GuestCartFixture::class, as: 'cart'), + DataFixture(SetBillingAddressFixture::class, ['cart_id' => '$cart.id$']), + ] + public function testCollectTotals(): void { } } @@ -171,12 +124,12 @@ class QuoteTest extends \PHPUnit\Framework\TestCase ### Test case and test method scopes -The `@magentoDataFixture` can be specified for a particular test or for an entire test case. +The `DataFixture` can be specified for a particular test or for an entire test case. The basic rules for fixture attribute at different levels are: -- `@magentoDataFixture` at a test case level, makes the framework to apply the declared fixtures to each test in the test case. +- `DataFixture` at a test case level, makes the framework to apply the declared fixtures to each test in the test case. When the final test is complete, all class-level fixtures are reverted. -- `@magentoDataFixture` for a particular test, signals the framework to revert the fixtures declared on a test case level and applies the fixtures declared at a test method level instead. +- `DataFixture` for a particular test, signals the framework to revert the fixtures declared on a test case level and applies the fixtures declared at a test method level instead. When the test is complete, the ITF reverts the applied fixtures. {:.bs-callout-info} @@ -188,17 +141,13 @@ A fixture that contains database transactions only, are reverted automatically. Otherwise, when a fixture creates files or performs any actions other than database transaction, provide the corresponding rollback logic. Rollbacks are run after reverting all the fixtures related to database transactions. -A fixture rollback must be of the same format as the corresponding fixture, a script or a method: - -- A rollback script must be named according to the corresponding fixture suffixed with `_rollback` and stored in the same directory. -- Rollback methods must be of the same class as the corresponding fixture and suffixed with `Rollback`. +Rollback methods must be of the same class as the corresponding fixture and suffixed with `Rollback`. Examples: -Fixture/Rollback | Fixture name | Rollback name ------------------|------------------------------------------------------|------------------------------------------------------------- -Script | `Magento/Catalog/_files/categories.php` | `Magento/Catalog/_files/categories_rollback.php` -Method | `\Magento\Catalog\Model\ProductTest::prepareProduct` | `\Magento\Catalog\Model\ProductTest::prepareProductRollback` +| Fixture/Rollback | Fixture name | Rollback name | +|------------------|------------------------------------------------------|--------------------------------------------------------------| +| Method | `\Magento\Catalog\Model\ProductTest::prepareProduct` | `\Magento\Catalog\Model\ProductTest::prepareProductRollback` | ### Restrictions @@ -207,7 +156,4 @@ Do not rely on and do not modify an application state from within a fixture, bec [magentoAppIsolation]: magento-app-isolation.html -[parameterizedDataFixture]: ../parameterized_data_fixture.html -[`dev/tests/integration/testsuite/Magento/Cms/_files/pages.php`]: {{ site.mage2bloburl }}/{{ page.guide_version }}/dev/tests/integration/testsuite/Magento/Cms/_files/pages.php -[`dev/tests/integration/testsuite/Magento/Cms/Block/PageTest.php`]: {{ site.mage2bloburl }}/{{ page.guide_version }}/dev/tests/integration/testsuite/Magento/Cms/Block/PageTest.php -[`dev/tests/integration/testsuite/Magento/Cms/Controller/PageTest.php`]: {{ site.mage2bloburl }}/{{ page.guide_version }}/dev/tests/integration/testsuite/Magento/Cms/Controller/PageTest.php +[`Magento\Catalog\Test\Fixture\Product`]: {{ site.mage2bloburl }}/{{ page.guide_version }}-develop/app/code/Magento/Catalog/Test/Fixture/Product.php \ No newline at end of file diff --git a/src/guides/v2.4/test/integration/parameterized_data_fixture.md b/src/guides/v2.4/test/integration/parameterized_data_fixture.md deleted file mode 100644 index 99c9b2ed971..00000000000 --- a/src/guides/v2.4/test/integration/parameterized_data_fixture.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -group: testing -title: Parameterized Data Fixture ---- - -{:.bs-callout-info} -Parameterized Data Fixture is currently only available for Magento Open Source contributors. It will be released for general use with Magento Open Source 2.4.5. - -## Overview - -Parameterized data fixture is a dynamic and scalable data fixture that accepts parameters directly from the fixture declaration. It eliminates the need to create almost identical fixtures every time you need a slight change. - -## Principles - -1. Parameterized Data Fixture class MUST implement `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface` if the data created by the fixture is revertible. For instance, a fixture that creates an entity (for example, product). -1. Parameterized Data Fixture class MUST be placed in the `/Test/Fixture` folder of the corresponding module with namespace: `\\Test\Fixture` (for example, `Magento\Catalog\Test\Fixture`). -1. Parameterized Data Fixture class SHOULD follow single responsibility principle. -1. Parameterized Data Fixture class MUST depend only on services from modules that are declared in the `require` section of its module's composer.json. -1. Parameterized Data Fixture MUST NOT depend on another fixture. -1. Parameterized Data Fixture SHOULD be implemented using service APIs. -1. Parameterized Data Fixture SHOULD have dynamic default data to allow generating unique fixtures. - -## Dynamic default data - -In order to generate multiple fixtures of the same type without having to manually configure unique fields, you can use the placeholder `%uniqid%` in the default value of unique fields and `Magento\TestFramework\Fixture\Data\ProcessorInterface` to substitute the placeholder with unique sequence. - -[`Magento\Catalog\Test\Fixture\Product`][] demonstrates the usage of `%uniqid%` (`sku`: `simple-product%uniqid%`) in the fixture default data. - -In the following example, a unique `sku` is automatically generated for the first fixture (for example, `simple-product61c10b2e86f991`) and the second fixture (for example, `simple-product61c10b2e86f992`). The sequence is random and therefore unpredictable. - -```php?start_inline=1 -class ProductsListTest extends \PHPUnit\Framework\TestCase -{ - #[ - DataFixture(ProductFixture::class), - DataFixture(ProductFixture::class) - ] - public function testGetProductsCount(): void - { - } -} -``` - -## Decoupling fixtures - -Fixtures must be written in the way that they only use one API to generate data. For example, the fixture that creates -a product should only invoke "Create Product" API and return the product created. This fixture should not add any extra -logic beyond the "create product" API capabilities, such logic should be implemented in a separate fixture. - -### Examples - -Example 1: - -```php?start_inline=1 -class QuoteTest extends \PHPUnit\Framework\TestCase -{ - - #[ - DataFixture(ProductFixture::class, as: 'p'), - DataFixture(GuestCartFixture::class, as: 'cart'), - DataFixture(AddProductToCartFixture::class, ['cart_id' => '$cart.id$', 'product_id' => '$p.id$', 'qty' => 2]), - DataFixture(SetBillingAddressFixture::class, ['cart_id' => '$cart.id$']), - DataFixture(SetShippingAddressFixture::class, ['cart_id' => '$cart.id$']), - ] - public function testCollectTotals(): void - { - } -} -``` - -Example 2: - -```php?start_inline=1 -class PriceTest extends \PHPUnit\Framework\TestCase -{ - #[ - DataFixture(ProductFixture::class, ['sku' => 'simple1', 'price' => 10], 'p1'), - DataFixture(ProductFixture::class, ['sku' => 'simple2', 'price' => 20], 'p2'), - DataFixture(ProductFixture::class, ['sku' => 'simple3', 'price' => 30], 'p3'), - DataFixture(BundleSelectionFixture::class, ['sku' => '$p1.sku$', 'price' => 10, 'price_type' => 0], 'link1'), - DataFixture(BundleSelectionFixture::class, ['sku' => '$p2.sku$', 'price' => 25, 'price_type' => 1], 'link2'), - DataFixture(BundleSelectionFixture::class, ['sku' => '$p3.sku$', 'price' => 25, 'price_type' => 0], 'link3'), - DataFixture(BundleOptionFixture::class, ['product_links' => ['$link1$', '$link2$', '$link3$']], 'opt1'), - DataFixture( - BundleProductFixture::class, - ['sku' => 'bundle1','price' => 50,'price_type' => 1,'_options' => ['$opt1$']], - 'bundle1' - ), - ] - public function testBundleWithFixedPrice(): void - { - - } -} -``` - - - -[`Magento\Catalog\Test\Fixture\Product`]: {{ site.mage2bloburl }}/{{ page.guide_version }}-develop/app/code/Magento/Catalog/Test/Fixture/Product.php \ No newline at end of file From 483f51d28bebf4c5dc49a3a09902bb106840c754 Mon Sep 17 00:00:00 2001 From: Thiaramus Date: Mon, 13 Jun 2022 16:57:40 -0500 Subject: [PATCH 164/776] Apply suggestions from code review Co-authored-by: Buba Soumah --- .../attributes/magento-app-isolation.md | 6 +++--- .../test/integration/attributes/magento-cache.md | 15 ++++++++------- .../attributes/magento-components-dir.md | 4 ++-- .../attributes/magento-config-fixture.md | 16 ++++++++-------- .../attributes/magento-db-isolation.md | 4 ++-- 5 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md index 3189ce1f39f..0f693891c63 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md +++ b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md @@ -17,11 +17,11 @@ Application isolation annotation: ```php?start_inline=1 #[ - AppIsolation((bool)) + AppIsolation() ] ``` -## Test class attribute +## Test class The application and related objects are reinitialized after each test case execution. This behavior helps to isolate application objects in different test cases. @@ -30,7 +30,7 @@ The test case isolation is mandatory and cannot be disabled. {:.bs-callout-warning} Do not share and do not rely on sharing the application objects between test cases. -## Test method attribute +## Test method By default, the application isolation (that is automatic reinitialization) in tests is disabled. To enable the application isolation for a test, use the `AppIsolation` attribute. diff --git a/src/guides/v2.4/test/integration/attributes/magento-cache.md b/src/guides/v2.4/test/integration/attributes/magento-cache.md index 6c961a72a19..cab57de88df 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-cache.md +++ b/src/guides/v2.4/test/integration/attributes/magento-cache.md @@ -9,15 +9,14 @@ Enable or disable a [cache type][] using the `Cache` attribute. ```php?start_inline=1 #[ - Cache((string)'', (string)') + Cache(, ) ] ``` Here, -- `` is a placeholder for a cache type -- `all` is a value for any cache type -- `enabled` or `disabled` to enable or disable the cache respectively +- `` is the cache type. Or "all" to change the status of all cache types. +- `` accepts TRUE or FALSE to enable or disable cache respectively ## Principles @@ -27,7 +26,7 @@ Here, 1. A test method attribute completely overrides a test case attribute. 1. All cache types are disabled by default. -## Test case +## Test class `Cache` attribute at the test case level is applied to all tests. @@ -64,7 +63,8 @@ class BarTest extends \PHPUnit\Framework\TestCase } #[ - Cache('all', true, 'config', false) + Cache('all', true), + Cache('config', false) ] public function testThree() { @@ -72,7 +72,8 @@ class BarTest extends \PHPUnit\Framework\TestCase } #[ - Cache('config', false, 'all', true) + Cache('config', false), + Cache('all', true) ] public function testFour() { diff --git a/src/guides/v2.4/test/integration/attributes/magento-components-dir.md b/src/guides/v2.4/test/integration/attributes/magento-components-dir.md index 8d00fa77fbb..5c063ea3702 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-components-dir.md +++ b/src/guides/v2.4/test/integration/attributes/magento-components-dir.md @@ -10,14 +10,14 @@ It enables you to register all the components at a specified directory recursive ```php?start_inline=1 #[ - ComponentsDir((string)) + ComponentsDir() ] ``` Here, `` is a path to the directory with fixture components. Each component must be registered using `registration.php` file. -## Test case +## Test class `ComponentsDir` attribute for a test case is applied to all test methods in the test case. diff --git a/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md index 113e70cf0f1..32e6c72fa52 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md @@ -9,16 +9,16 @@ To set Magento configuration values for individual tests and revert them after t ```php #[ - Config((string), (string), (string), ...) + Config(, , , ) ] ``` -- `` is the code of the store to be configured. - When a global scope is required, this should be omitted and the `config path` is prefixed with `default/`. See below for an example. - To specify the current store, use `current`. - `` is the XPath to the configuration option. See [configuration reference][] for available options. - `` is a fixture value for the configuration option. +- `` is the scope to use to set config value. Allowed values: default, store, group and website. Default: default +- `` is the code of the scope to be configured. + If "default" scope is provided, this parameter can be omitted. If the scope type is store, group or website, the default value of this parameter is the current value of the specified scope. ## Principles @@ -52,7 +52,7 @@ class ConfigFixtureTest extends \PHPUnit\Framework\TestCase } #[ - Config('current_store', 'web/unsecure/base_url', 'http://example.com/') + Config('web/unsecure/base_url', 'http://example.com/', 'store') ] public function testGlobalConfig() { @@ -87,7 +87,7 @@ class ConfigFixtureTest extends \PHPUnit\Framework\TestCase } #[ - Config('current_store', 'dev/restrict/allow_ips', '192.168.0.1') + Config( 'dev/restrict/allow_ips', '192.168.0.1', 'store') ] public function testCurrentStoreConfig() { @@ -125,7 +125,7 @@ class ConfigFixtureTest extends \PHPUnit\Framework\TestCase } #[ - Config('admin_store', 'dev/restrict/allow_ips', '192.168.0.2') + Config('dev/restrict/allow_ips', '192.168.0.2', 'store', 'admin') ] public function testSpecificStoreConfig() { @@ -163,7 +163,7 @@ class ConfigFixtureTest extends \PHPUnit\Framework\TestCase } #[ - Config('default/dev/restrict/allow_ips', '192.168.0.2') + Config('dev/restrict/allow_ips', '192.168.0.2') ] public function testGlobalStoreConfig() { diff --git a/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md b/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md index 2097c6e4324..91b1fcad2ee 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md +++ b/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md @@ -20,7 +20,7 @@ DbIsolation((bool)) ] ``` -## Test case declaration +## Test class Use test case declarations when a sequence of tests introduces changes to the database and relies on the changes made by each other. For example, typical CRUD tests: _create -> read -> update -> delete_. @@ -69,7 +69,7 @@ class Some\EntityTest extends \PHPUnit\Framework\TestCase } ``` -## Test declaration +## Test method To isolate changes made to database by a single test, enable the `DbIsolation` for the test. From 5aa884d49c1b91f49fd61d8851dfef4e4018aa7b Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Mon, 13 Jun 2022 16:59:31 -0500 Subject: [PATCH 165/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- .../v2.4/test/integration/attributes/magento-app-isolation.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md index 0f693891c63..7b26cea5862 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md +++ b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md @@ -21,6 +21,10 @@ Application isolation annotation: ] ``` +### Parameters + + - `` accepts TRUE or FALSE to enable or disable app isolation respectively + ## Test class The application and related objects are reinitialized after each test case execution. From 64bb04e4efd9d83f723b7d968bb7a5bf6cf35370 Mon Sep 17 00:00:00 2001 From: gregory-marshall Date: Mon, 13 Jun 2022 15:06:15 -0700 Subject: [PATCH 166/776] Include origin cloaking enabled on Pro --- src/cloud/cdn/cloud-fastly.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/cloud/cdn/cloud-fastly.md b/src/cloud/cdn/cloud-fastly.md index a3e5d907f54..f5432606f31 100644 --- a/src/cloud/cdn/cloud-fastly.md +++ b/src/cloud/cdn/cloud-fastly.md @@ -12,7 +12,7 @@ To maintain PCI compliance for {{site.data.var.ee}} sites deployed on the Cloud Fastly provides the following services to optimize and secure content delivery operations for your {{ site.data.var.ece }} projects. These services are included with your {{ site.data.var.ece }} subscription at no additional cost. -- **Content delivery network (CDN)**—Varnish-based service that caches your site pages, assets, CSS, and more in backend data centers you set up. As customers access your site and stores, the requests hit Fastly to load cached pages faster. The CDN service provides the following features: +- **Content Delivery Network (CDN)**—Varnish-based service that caches your site pages, assets, CSS, and more in backend data centers you set up. As customers access your site and stores, the requests hit Fastly to load cached pages faster. The CDN service provides the following features: - Cache your site pages, assets, CSS, and more in back-end data centers that you set up to reduce bandwidth load and costs @@ -28,24 +28,25 @@ Fastly provides the following services to optimize and secure content delivery o - Create [custom error response pages] -- **Security**—After you set up your {{ site.data.var.ece }} project to use the Fastly CDN, additional security features are available to protect your sites and network. - - [**DDoS protection**](#ddos-protection)—Built-in protection against common attacks like Ping of Death, Smurf attacks, as well as other ICMP-based floods. +- **Security**—After you set up your {{ site.data.var.ece }} project to use the Fastly CDN, additional security features are available to protect your sites and network: - - **[Web Application Firewall]**—Managed web application firewall service that provides PCI-compliant protection to block malicious traffic before it can damage your production {{ site.data.var.ece }} sites and network. The WAF service is available on Pro and Starter Production environments only. + - [Web Application Firewall (WAF)](https://devdocs.magento.com/cloud/cdn/fastly-waf-service.html)—Managed web application firewall service that provides PCI-compliant protection to block malicious traffic before it can damage your production {{ site.data.var.ece }} sites and network. The WAF service is available on Pro and Starter Production environments only. - - **SSL/TLS certificates**–The Fastly service requires an SSL/TLS certificate to serve secure traffic over HTTPS. {{site.data.var.ee}} provides a Domain-validated Let's Encrypt SSL/TLS certificate for each Staging and Production environment. {{site.data.var.ee}} completes domain validation and certificate provisioning during the Fastly set up process. See [TLS and Fastly]. + - [Distributed Denial of Service (DDoS) protection](#ddos-protection)—Built-in DDoS protection against common attacks like Ping of Death, Smurf attacks, as well as other ICMP-based floods. - - **Origin cloaking**–Adobe can enable Origin Cloaking for all {{ site.data.var.ece }} projects. This option hides the IP addresses of your origin servers to protect them from direct access. When this feature is enabled, all traffic to your Cloud infrastructure must route through the Fastly CDN or another secure channel. Any traffic sent directly to the Origin servers is blocked. If you have traffic that does not require caching, you can customize the Fastly service configuration to allow requests to [bypass the Fastly cache]. + - [SSL/TLS certificates](https://devdocs.magento.com/cloud/cdn/configure-fastly.html#provision-ssltls-certificates)–The Fastly service requires an SSL/TLS certificate to serve secure traffic over HTTPS. {{site.data.var.ee}} provides a Domain-validated Let's Encrypt SSL/TLS certificate for each Staging and Production environment. {{site.data.var.ee}} completes domain validation and certificate provisioning during the Fastly set up process. -- **Image optimization**—Offloads image processing and resizing load to the Fastly service freeing servers to process orders and conversions efficiently. See [Fastly image optimization]. + - **Origin cloaking**–Prevents traffic from bypassing the Fastly WAF and hides the IP addresses of your origin servers to protect them from direct access and DDoS attacks. Origin cloaking is enabled by default on {{ site.data.var.ece }} Pro Production projects. To enable origin cloaking on {{ site.data.var.ece }} Starter Production projects, submit a [{{site.data.var.ee}} support ticket](https://support.magento.com/hc/en-us/articles/360019088251). If you have traffic that does not require caching, you can customize the Fastly service configuration to allow requests to [bypass the Fastly cache](https://devdocs.magento.com/cloud/cdn/fastly-vcl-bypass-to-origin.html). -- **Fastly CDN and WAF logs**–For {{ site.data.var.ece }} Pro projects, you can use the New Relic Logs service to review and analyze Fastly CDN and WAF log data. See [New Relic]. +- [Image optimization](https://devdocs.magento.com/cloud/cdn/fastly-image-optimization.html)—Offloads image processing and resizing load to the Fastly service freeing servers to process orders and conversions efficiently. + +- **Fastly CDN and WAF logs**–For {{ site.data.var.ece }} Pro projects, you can use the New Relic Logs service to review and analyze Fastly CDN and WAF log data. See [New Relic](https://devdocs.magento.com/cloud/project/new-relic.html#new-relic-logs). ## Fastly CDN module for Magento 2 Fastly services for {{ site.data.var.ece }} use the [Fastly CDN module for Magento 2] installed in the following environments: Pro Staging and Production, Starter Production (`master` branch). -On initial provisioning or upgrade of your {{ site. data.var.ece }} project, we install the latest version of the Fastly CDN module in your Staging and Production environments. When Fastly releases module updates, you receive notifications in the Admin UI for your environments. We recommend that you update your environments to use the latest release. See [Upgrade Fastly]. +On initial provisioning or upgrade of your {{ site. data.var.ece }} project, Adobe installs the latest version of the Fastly CDN module in your Staging and Production environments. When Fastly releases module updates, you receive notifications in the Admin UI for your environments. Adobe recommends that you update your environments to use the latest release. See [Upgrade Fastly]. ## Fastly service account and credentials @@ -115,7 +116,7 @@ DDOS protection is built-in to the Fastly CDN service. After you enable and conf [Fastly CDN module for Magento 2]: https://github.com/fastly/fastly-magento2 [Fastly credentials configuration]: {{site.baseurl}}/cloud/cdn/configure-fastly.html#test-the-fastly-credentials [Fastly custom VCL snippets]: {{site.baseurl}}/cloud/cdn/cloud-vcl-custom-snippets.html -[Fastly image optimization]: {{site.baseurl}}/cloud/cdn/fastly-image-optimization.html +[Image optimization]: {{site.baseurl}}/cloud/cdn/fastly-image-optimization.html [Fastly support ticket]: https://docs.fastly.com/products/support-description-and-sla#support-requests [Force unencrypted requests over to TLS]: {{site.baseurl}}/cloud/cdn/configure-fastly-customize-cache.html#force-tls [GeoIP service support]: {{site.baseurl}}/cloud/cdn/configure-fastly-customize-cache.html#configure-geoip-handling From add55c6aaa02b509595a86421a507ac75bfabd3a Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Mon, 13 Jun 2022 17:32:01 -0500 Subject: [PATCH 167/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- .../integration/attributes/magento-app-area.md | 14 +++++++++++++- .../attributes/magento-app-isolation.md | 5 +++-- .../test/integration/attributes/magento-cache.md | 10 ++++++---- .../attributes/magento-components-dir.md | 8 +++++--- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/guides/v2.4/test/integration/attributes/magento-app-area.md b/src/guides/v2.4/test/integration/attributes/magento-app-area.md index 228ee6ee97e..9868037a972 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-app-area.md +++ b/src/guides/v2.4/test/integration/attributes/magento-app-area.md @@ -9,10 +9,22 @@ Configure a test environment in scope of the particular [application area][] wit ```php?start_inline=1 #[ - AppArea((string)<'adminhtml'/'frontend'/'global'>) + AppArea(string $area) ] ``` +### Parameters + +- **area** + - Can take any value from the list below + - `\Magento\Framework\App\Area::AREA_GLOBAL` + - `\Magento\Framework\App\Area::AREA_ADMINHTML` + - `\Magento\Framework\App\Area::AREA_FRONTEND` + - `\Magento\Framework\App\Area::AREA_WEBAPI_REST` + - `\Magento\Framework\App\Area::AREA_WEBAPI_SOAP` + - `\Magento\Framework\App\Area::AREA_CRONTAB` + - `\Magento\Framework\App\Area::AREA_GRAPHQL` + ## Fallback sequence 1. Test annotation diff --git a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md index 7b26cea5862..f530684bada 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md +++ b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md @@ -17,13 +17,14 @@ Application isolation annotation: ```php?start_inline=1 #[ - AppIsolation() + AppIsolation(bool $state = true) ] ``` ### Parameters - - `` accepts TRUE or FALSE to enable or disable app isolation respectively + - **state** + - Accepts TRUE or FALSE to enable or disable app isolation respectively. ## Test class diff --git a/src/guides/v2.4/test/integration/attributes/magento-cache.md b/src/guides/v2.4/test/integration/attributes/magento-cache.md index cab57de88df..91d78e3b9a5 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-cache.md +++ b/src/guides/v2.4/test/integration/attributes/magento-cache.md @@ -9,14 +9,16 @@ Enable or disable a [cache type][] using the `Cache` attribute. ```php?start_inline=1 #[ - Cache(, ) + Cache(string $type, bool $status) ] ``` -Here, +### Parameters -- `` is the cache type. Or "all" to change the status of all cache types. -- `` accepts TRUE or FALSE to enable or disable cache respectively +- **type** + - The cache type. Or "all" to change the status of all cache types. +- **status** + - Accepts TRUE or FALSE to enable or disable cache respectively. ## Principles diff --git a/src/guides/v2.4/test/integration/attributes/magento-components-dir.md b/src/guides/v2.4/test/integration/attributes/magento-components-dir.md index 5c063ea3702..3628d8d9e30 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-components-dir.md +++ b/src/guides/v2.4/test/integration/attributes/magento-components-dir.md @@ -10,12 +10,14 @@ It enables you to register all the components at a specified directory recursive ```php?start_inline=1 #[ - ComponentsDir() + ComponentsDir(string $path) ] ``` -Here, `` is a path to the directory with fixture components. -Each component must be registered using `registration.php` file. +### Parameters + +- **path** + - A path to the directory with fixture components. Each component must be registered using `registration.php` file. ## Test class From 862a9ca108dcd53ff79855fd6ce0a9d3a7a7df54 Mon Sep 17 00:00:00 2001 From: Kevin Harper Date: Mon, 13 Jun 2022 23:36:53 -0500 Subject: [PATCH 168/776] Add GraphQL session configuration command --- src/_data/toc/graphql.yml | 2 +- .../v2.4/graphql/authorization-tokens.md | 36 +++++++++++++++---- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/_data/toc/graphql.yml b/src/_data/toc/graphql.yml index a0011a66906..345a5156e00 100644 --- a/src/_data/toc/graphql.yml +++ b/src/_data/toc/graphql.yml @@ -9,7 +9,7 @@ pages: - label: GraphQL requests url: /graphql/send-request.html - - label: Authorization tokens + - label: GraphQL Authorization url: /graphql/authorization-tokens.html - label: Protected mutations diff --git a/src/guides/v2.4/graphql/authorization-tokens.md b/src/guides/v2.4/graphql/authorization-tokens.md index 3ce58c4f040..0e80070e4c3 100644 --- a/src/guides/v2.4/graphql/authorization-tokens.md +++ b/src/guides/v2.4/graphql/authorization-tokens.md @@ -1,17 +1,27 @@ --- group: graphql -title: Authorization tokens +title: GraphQL Authorization contributor_name: Atwix contributor_link: https://www.atwix.com/ redirect_from: - /guides/v2.4/graphql/get-customer-authorization-token.html --- -Magento provides separate token services for customers and administrators. When you request a token from one of these services, the service returns a unique access token in exchange for the username and password for a Magento account. +Adobe Commerce and Magento Open Source provide two mechanisms for authorizing GraphQL calls: -Magento GraphQL provides a mutation that returns a token on behalf of a logged-in customer. You must use a REST call to fetch an admin token. Use this token in the Authorization request header field for any queries and mutations. See [Request headers]({{page.baseurl}}/graphql/send-request.html#headers) +* **Authorization tokens**. Commerce generates a JSON Web Token (JWT), a set of cryptographically signed credentials. All calls that perform an action on behalf of a logged-in customer or admin provide an authorization token. Authorization tokens are stateless. Commerce does not need to know the state of a client to execute a request--the token contains all of the information needed for authorization. -## Customer tokens +* **Session cookies**. A session cookie is information generated by Commerce that is stored in the client's browser. It contains details about the session, including the time period the user can access resources. Cookies are stateful, thereby increasing complexity and possibly latency. + +Adobe recommends that you use authorization tokens instead of session cookies for GraphQL requests. By default, session cookies are enabled. As of Commerce 2.4.5, you can disable session cookies, eliminating the chances of encountering problems caused by the differences between the two authorization methods. However, merchants with existing implementations that rely on cookies can continue using this method. [Session cookies](#Session-cookies) describes how to enable or disable cookies for GraphQL. + +## Authorization tokens + +Adobe Commerce provides separate token services for customers and administrators. When you request a token from one of these services, the service returns a unique access token in exchange for the account's username and password. + +GraphQL provides a mutation that returns a token on behalf of a logged-in customer. You must use a REST call to fetch an admin token. Use this token in the Authorization request header field for any queries and mutations. See [Request headers]({{page.baseurl}}/graphql/send-request.html#headers) + +### Customer tokens The [`generateCustomerToken` mutation]({{page.baseurl}}/graphql/mutations/generate-customer-token.html) requires the customer email address and password in the payload, as shown in the following example. @@ -43,7 +53,7 @@ You can now use this token in the Authorization request header field for any que ![GraphQL Authorization Bearer]({{site.baseurl}}/common/images/graphql/graphql-authorization.png) -If necessary, you also can [revoke the customer's token]({{ page.baseurl }}/graphql/mutations/revoke-customer-token.html +If necessary, you also can [revoke the customer's token]({{ page.baseurl }}/graphql/mutations/revoke-customer-token.html). The [`generateCustomerTokenAsAdmin`]({{page.baseurl}}/graphql/mutations/generate-customer-token-as-admin.html) mutation generates a new customer token as an admin so that an administrator can perform remote shopping assistance. The customer must have enabled the `allow_remote_shopping_assistance` feature while creating the customer profile. The mutation requires the customer email address in the payload, as shown in the following example. @@ -72,10 +82,24 @@ mutation{ } ``` -## Admin tokens +### Admin tokens In Magento GraphQL, you specify an admin token only if you need to query products, categories, price rules, or other entities that are scheduled to be in a campaign (staged content). Staging is supported in {{site.data.var.ee}} only. See [Staging queries]({{page.baseurl}}/graphql/queries/index.html#staging) for more information. Magento does not provide a GraphQL mutation that generates an admin token. You must use a REST endpoint such as `POST /V1/tfa/provider/google/authenticate` instead. [Generate the admin token]({{page.baseurl}}/rest/tutorials/prerequisite-tasks/create-admin-token.html) shows how to use this endpoint. By default, an admin token is valid for 4 hours. You can change these values from Admin by selecting **Stores** > **Settings** > **Configuration** > **Services** > **OAuth** > **Access Token Expiration** > **Admin Token Lifetime**. + +## Session cookies + +The client's browser will use a session cookie if the server provides one. Prior to version 2.4.5, Commerce automatically provided these cookies, even if an authorization token was specified. + +Multi-page applications that make GraphQL calls can continue implementing these cookies without changing the default setting. However, most merchants should disable these cookies. As a result, Commerce will be fast more secure. In addition, disabling cookies will prevent a situation in which unnecessary sessions locking HTTP GET requests. + +Run the following command to disable session cookies for GraphQL: + +`bin/magento config:set graphql/session/disable 1` + +To re-enable these cookies, run: + +`bin/magento config:set graphql/session/disable 1` From b4e035c098cc81fb33aa618da93b4d018315b8d1 Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Tue, 14 Jun 2022 08:51:42 -0500 Subject: [PATCH 169/776] Update configuration-guide.yml --- src/_data/toc/configuration-guide.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_data/toc/configuration-guide.yml b/src/_data/toc/configuration-guide.yml index 25cb79a0053..e6ef86ddfb3 100644 --- a/src/_data/toc/configuration-guide.yml +++ b/src/_data/toc/configuration-guide.yml @@ -356,7 +356,7 @@ pages: url: /config-guide/mq/manage-message-queues.html - label: Using AWS Message Queues - url: /config-guide/mq/manage-message-queues.html + url: /config-guide/mq/aws-mq.html exclude_versions: ["2.3"] - label: Split database performance solution (Adobe Commerce only) From 6c2eca612e7f85b38f85ba1c86e1a116dc849d1b Mon Sep 17 00:00:00 2001 From: Kyrylo <64845469+guentur@users.noreply.github.com> Date: Tue, 14 Jun 2022 17:04:07 +0300 Subject: [PATCH 170/776] Update src/guides/v2.3/config-guide/cli/logging.md Co-authored-by: hguthrie --- src/guides/v2.3/config-guide/cli/logging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.3/config-guide/cli/logging.md b/src/guides/v2.3/config-guide/cli/logging.md index 5c0c49929ab..3022cd0c648 100644 --- a/src/guides/v2.3/config-guide/cli/logging.md +++ b/src/guides/v2.3/config-guide/cli/logging.md @@ -67,7 +67,7 @@ By default, Magento writes database activity logs to the `var/debug/db.log` file bin/magento app:config:import ``` -3. Flush the cache. +1. Flush the cache. ```bash bin/magento cache:flush From 6978fa549da85451e75f77780a97af99de19d2bc Mon Sep 17 00:00:00 2001 From: Kyrylo <64845469+guentur@users.noreply.github.com> Date: Tue, 14 Jun 2022 17:06:32 +0300 Subject: [PATCH 171/776] Update src/guides/v2.3/config-guide/cli/logging.md Changed links in code Co-authored-by: hguthrie --- src/guides/v2.3/config-guide/cli/logging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.3/config-guide/cli/logging.md b/src/guides/v2.3/config-guide/cli/logging.md index 3022cd0c648..6ee8388f112 100644 --- a/src/guides/v2.3/config-guide/cli/logging.md +++ b/src/guides/v2.3/config-guide/cli/logging.md @@ -61,7 +61,7 @@ By default, Magento writes database activity logs to the `var/debug/db.log` file bin/magento dev:query-log:disable ``` -2. In the [production mode](https://devdocs.magento.com/guides/v2.4/config-guide/cli/config-cli-subcommands-mode.html#config-mode-show) run the command for [import configuration](https://devdocs.magento.com/guides/v2.4/config-guide/cli/config-cli-subcommands-config-mgmt-import.html), because the command `bin/magento dev:query-log:disable` adds settings to the `app/etc/env.php` file: +1. In the [production mode]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-mode.html#config-mode-show), run the command for [import configuration]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-config-mgmt-import.html), because the `bin/magento dev:query-log:disable` command adds settings to the `app/etc/env.php` file: ```bash bin/magento app:config:import From 01f59ba3b5d12769f26dace7a3b6f85d43eb29d5 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Tue, 14 Jun 2022 09:20:51 -0500 Subject: [PATCH 172/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- src/_data/toc/testing.yml | 6 ++++ .../v2.4/test/integration/attributes.md | 36 ++++++++++--------- .../attributes/magento-app-area.md | 16 ++++----- .../attributes/magento-app-isolation.md | 32 ++++++++--------- .../integration/attributes/magento-cache.md | 14 ++++---- .../attributes/magento-components-dir.md | 4 +-- .../attributes/magento-config-fixture.md | 20 ++++++----- ...magento-data-fixture-before-transaction.md | 23 ++++++++++++ .../attributes/magento-data-fixture.md | 14 ++++---- .../attributes/magento-db-isolation.md | 22 ++++++------ .../magento-indexer-dimension-mode.md | 21 +++++++++++ 11 files changed, 132 insertions(+), 76 deletions(-) create mode 100644 src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md create mode 100644 src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md diff --git a/src/_data/toc/testing.yml b/src/_data/toc/testing.yml index 0f2c3b70fda..6e36a9dc70d 100644 --- a/src/_data/toc/testing.yml +++ b/src/_data/toc/testing.yml @@ -61,9 +61,15 @@ pages: - label: 'DataFixture' url: /test/integration/attributes/magento-data-fixture.html + - label: 'DataFixtureBeforeTransaction' + url: /test/integration/attributes/magento-data-fixture-before-transaction.html + - label: 'DbIsolation' url: /test/integration/attributes/magento-db-isolation.html + - label: 'IndexerDimensionMode' + url: /test/integration/attributes/magento-indexer-dimension-mode.html + - label: JavaScript Unit Testing children: diff --git a/src/guides/v2.4/test/integration/attributes.md b/src/guides/v2.4/test/integration/attributes.md index 4a490d38d06..8d0450982cc 100644 --- a/src/guides/v2.4/test/integration/attributes.md +++ b/src/guides/v2.4/test/integration/attributes.md @@ -13,22 +13,17 @@ Using PHP built-in attributes is available now for the developers, and will be p The following attributes are available in integration tests: -| Name | Attribute | Format | Description | -|---------------------------------|--------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Application Isolation | `AppIsolation` | `AppIsolation((bool))` | Enables or disables application isolation when you run tests. When enabled, an application state after a test run will be the same as before the test run. For example, you should enable it, when you want to create sessions in a test, but you don't want them to affect other tests. | -| Configuration Fixture | `Config` | `Config((string), (string), (mixed), ...)` | Sets up configuration settings for a particular test. The list of settings is stored in the `core_config_data` database table. Multiple configuration parameters can be set with a signle command. After the test execution, the settings revert to their original state. | -| Database Isolation | `DbIsolation` | `DbIsolation((bool))` | Enables or disables database isolation. Disabled by default, unless you are using `DataFixture()` attribute, in which case it is enabled by default. All data, required for a test, live during transaction only. Any test results won't be written in a database. | -| Data Fixture | `DataFixture` | `DataFixture((string), (array)[, ], (string), as:(string))` | Points to a class or a method which creates testing entities (fixtures) for test execution. These are applied during the transaction. | -| Data Fixture Before Transaction | `DataFixtureBeforeTransaction` | `DataFixtureBeforeTransaction((string), (array)[ => ], (string), as:(string))` | Points to a class or a method which creates testing entities (fixtures) for test execution before the transaction has begun. You will need to implement a rollback method changes made here. | -| Application Area | `AppArea` | `AppArea((string)<'adminhtml'/'frontend'/'global'>)` | Configures test environment in the context of specified application area. | -| Enable/Disable Cache | `Cache` | `Cache((string)<'all'/'enabled'/'disabled>')` | Enables or disables certain cache segment or all of them to prevent isolation problems. | -| Indexer Dimension Mode | `IndexerDimensionMode` | `IndexerDimensionMode(string),(string))` | Sets the indexer dimension mode for the test run. More information can be found in the [DevBlog](https://community.magento.com/t5/Magento-DevBlog/Indexers-parallelization-and-optimization/ba-p/104922). | -| Register Components | `ComponentsDir` | `ComponentsDir((string),...)` | Registers fixture components from specified directory (recursively). Unregisters the components after the test is finished. | - -### Format - -- `AppIsolation(bool $isolationEnabled = false)` -- `Config(string $storeCode, string $configPath, mixed $configValue, ...)` +| Name | Attribute | Description | +|---------------------------------|----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Application Isolation | [AppIsolation][] | Enables or disables application isolation when you run tests. When enabled, an application state after a test run will be the same as before the test run. For example, you should enable it, when you want to create sessions in a test, but you don't want them to affect other tests. | +| Configuration Fixture | [Config][] | Sets up configuration settings for a particular test. The list of settings is stored in the `core_config_data` database table. Multiple configuration parameters can be set with a signle command. After the test execution, the settings revert to their original state. | +| Database Isolation | [DbIsolation][] | Enables or disables database isolation. Disabled by default, unless you are using `DataFixture()` attribute, in which case it is enabled by default. All data, required for a test, live during transaction only. Any test results won't be written in a database. | +| Data Fixture | [DataFixture][] | Points to a class or a method which creates testing entities (fixtures) for test execution. These are applied during the transaction. | +| Data Fixture Before Transaction | [DataFixtureBeforeTransaction][] | Points to a class or a method which creates testing entities (fixtures) for test execution before the transaction has begun. You will need to implement a rollback method changes made here. | +| Application Area | [AppArea][] | Configures test environment in the context of specified application area. | +| Enable/Disable Cache | [Cache][] | Enables or disables certain cache segment or all of them to prevent isolation problems. | +| Indexer Dimension Mode | [IndexerDimensionMode][] | Sets the indexer dimension mode for the test run. More information can be found in the [DevBlog](https://community.magento.com/t5/Magento-DevBlog/Indexers-parallelization-and-optimization/ba-p/104922). | +| Register Components | [ComponentsDir][] | Registers fixture components from specified directory (recursively). Unregisters the components after the test is finished. | ## Applying annotations @@ -54,3 +49,12 @@ This order is necessary to meet the requirement of setting up the store-scoped c [PHPUnit annotations]: {{ page.baseurl }}/test/integration/annotations.html [PHP built-in attributes]: https://www.php.net/manual/en/language.attributes.overview.php +[AppIsolation]: {{ page.baseurl }}/test/integration/attributes/magento-app-isolation.html +[Config]: {{ page.baseurl }}/test/integration/attributes/magento-config-fixture.html +[DbIsolation]: {{ page.baseurl }}/test/integration/attributes/magento-db-isolation.html +[DataFixture]: {{ page.baseurl }}/test/integration/attributes/magento-data-fixture.html +[DataFixtureBeforeTransaction]: {{ page.baseurl }}/test/integration/attributes/magento-data-fixture-before-transaction.html +[AppArea]: {{ page.baseurl }}/test/integration/attributes/magento-app-area.html +[Cache]: {{ page.baseurl }}/test/integration/attributes/magento-cache.html +[IndexerDimensionMode]: {{ page.baseurl }}/test/integration/attributes/magento-indexer-dimension-mode.html +[ComponentsDir]: {{ page.baseurl }}/test/integration/attributes/magento-components-dir.html \ No newline at end of file diff --git a/src/guides/v2.4/test/integration/attributes/magento-app-area.md b/src/guides/v2.4/test/integration/attributes/magento-app-area.md index 9868037a972..06e87a313cf 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-app-area.md +++ b/src/guides/v2.4/test/integration/attributes/magento-app-area.md @@ -1,6 +1,6 @@ --- group: testing -title: Application Area attribute in the Integration Testing Framework +title: Application Area attribute --- Configure a test environment in scope of the particular [application area][] with the `AppArea` annotation. @@ -27,16 +27,16 @@ Configure a test environment in scope of the particular [application area][] wit ## Fallback sequence -1. Test annotation -1. Test case annotation +1. Test method +1. Test class 1. Default application area, which is `global` -## Test case attribute +## Test class attribute -A test case attribute enables the specified application area for all tests in the test case. +A test class attribute enables the specified application area for all tests in the test class. {:.bs-callout-info} -Test attribute override test case attribute. +Test class attribute override test method attribute. Example: @@ -69,9 +69,9 @@ class ClassToTest extends \PHPUnit\Framework\TestCase `testOne()` and `testThree()` are set to run in scope of the `adminhtml` application area, whereas `testTwo()` is set to run in scope of the `frontend` area. -## Test attribute +## Test method attribute -A test attribute is used to configure the environment in scope of the specified application area for the test. +A test method attribute is used to configure the environment in scope of the specified application area for the test method. Magento is reinitialized in the corresponding scope each time you specify a different area. Example: diff --git a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md index f530684bada..523e8ce7760 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md +++ b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md @@ -13,8 +13,6 @@ Test execution order can vary depending on a PHPUnit version. ## Format -Application isolation annotation: - ```php?start_inline=1 #[ AppIsolation(bool $state = true) @@ -26,19 +24,19 @@ Application isolation annotation: - **state** - Accepts TRUE or FALSE to enable or disable app isolation respectively. -## Test class +## Test class attribute -The application and related objects are reinitialized after each test case execution. -This behavior helps to isolate application objects in different test cases. -The test case isolation is mandatory and cannot be disabled. +The application and related objects are reinitialized after each test class execution. +This behavior helps to isolate application objects in different test classes. +The test class isolation is mandatory and cannot be disabled. {:.bs-callout-warning} -Do not share and do not rely on sharing the application objects between test cases. +Do not share and do not rely on sharing the application objects between test methods. ## Test method -By default, the application isolation (that is automatic reinitialization) in tests is disabled. -To enable the application isolation for a test, use the `AppIsolation` attribute. +By default, the application isolation (that is automatic reinitialization) in tests method is disabled. +To enable the application isolation for a test method, use the `AppIsolation` attribute. Example: @@ -55,19 +53,19 @@ public function testGetAddressById() ``` {:.bs-callout-info} -In most cases, controller tests depend on the application state and require reinitialization in each test. -Thus, the test cases inherited from the `\Magento\TestFramework\TestCase\AbstractController` behave as if `AppIsolation` is enabled for each test. +In most cases, controller tests depend on the application state and require reinitialization in each test method. +Thus, the test classes inherited from the `\Magento\TestFramework\TestCase\AbstractController` behave as if `AppIsolation` is enabled for each test method. ## Defaults Default values for the `AppIsolation` attribute: -| Test class ancestors | Test case (class) | Test (method) | -|------------------------------------------------------|-------------------|---------------| -| `\PHPUnit\Framework\TestCase` | enabled | disabled | -| `\Magento\TestFramework\TestCase\AbstractController` | enabled | enabled | +| Test class ancestors | Test class | Test method | +|------------------------------------------------------|------------|-------------| +| `\PHPUnit\Framework\TestCase` | enabled | disabled | +| `\Magento\TestFramework\TestCase\AbstractController` | enabled | enabled | -`AppIsolation` cannot be disabled at the test case level. +`AppIsolation` cannot be disabled at the test class level. You can use non-isolated tests unless they do not modify or utilize the same application areas such as: @@ -75,4 +73,4 @@ You can use non-isolated tests unless they do not modify or utilize the same app - same paths in a current configuration or current scope (for example "store"). {:.bs-callout-tip} -Set up application isolation if any application objects were intentionally modified within the test case. \ No newline at end of file +Set up application isolation if any application objects were intentionally modified within the test class. \ No newline at end of file diff --git a/src/guides/v2.4/test/integration/attributes/magento-cache.md b/src/guides/v2.4/test/integration/attributes/magento-cache.md index 91d78e3b9a5..a662e8c308b 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-cache.md +++ b/src/guides/v2.4/test/integration/attributes/magento-cache.md @@ -24,18 +24,18 @@ Enable or disable a [cache type][] using the `Cache` attribute. 1. You can use more than one attribute for a test case or a test method. 1. Multiple attributes are applied in the given order. -1. attributes from different scopes are not merged. -1. A test method attribute completely overrides a test case attribute. +1. Attributes from different scopes are not merged. +1. A test method attribute completely overrides a test class attribute. 1. All cache types are disabled by default. -## Test class +## Test class annotation `Cache` attribute at the test case level is applied to all tests. -## Test method +## Test method annotation -`Cache` attribute at a test method level configures the test only. -It completely overrides the attribute specified for the test case. +`Cache` attribute at a test method level configures the test method only. +It completely overrides the attribute specified for the test class. ## Example @@ -88,7 +88,7 @@ class BarTest extends \PHPUnit\Framework\TestCase - `testOne()` is run with all cache types enabled. - `testTwo()` is run with all cache types disabled. - The `Cache('config', false)` completely overrides the test case attribute. The test case attribute wasn't applied in this case. By default, all cache types are disabled. Thus disabling any attributes does not make much sense here. + The `Cache('config', false)` completely overrides the test method attribute. The test method attribute wasn't applied in this case. By default, all cache types are disabled. Thus disabling any attributes does not make much sense here. - `testThree()` is run with all but `config` cache type enabled. - `testFour()` is run with all the cache types enabled. diff --git a/src/guides/v2.4/test/integration/attributes/magento-components-dir.md b/src/guides/v2.4/test/integration/attributes/magento-components-dir.md index 3628d8d9e30..1e2b39592d6 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-components-dir.md +++ b/src/guides/v2.4/test/integration/attributes/magento-components-dir.md @@ -19,11 +19,11 @@ It enables you to register all the components at a specified directory recursive - **path** - A path to the directory with fixture components. Each component must be registered using `registration.php` file. -## Test class +## Test class attribute `ComponentsDir` attribute for a test case is applied to all test methods in the test case. -## Test method +## Test method attribute `ComponentsDir` attribute for a test method configures the test to run with registered components located in a specified directory. If the parent test case also declares a `ComponentsDir`, both attribute are merged. diff --git a/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md index 32e6c72fa52..14c933edca2 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md @@ -7,18 +7,22 @@ To set Magento configuration values for individual tests and revert them after t ## Format -```php +```php?start_inline=1 #[ - Config(, , , ) + Config(string $path, mixed $value, string $scopeType = 'default', string? $scopeValue = null) ] ``` -- `` is the XPath to the configuration option. - See [configuration reference][] for available options. -- `` is a fixture value for the configuration option. -- `` is the scope to use to set config value. Allowed values: default, store, group and website. Default: default -- `` is the code of the scope to be configured. - If "default" scope is provided, this parameter can be omitted. If the scope type is store, group or website, the default value of this parameter is the current value of the specified scope. +### Parameters + +- **path** + - The XPath to the configuration option. See [configuration reference][] for available options. +- **value** + - A fixture value for the configuration option. +- **scopeType** + - The scope to use to set config value. Allowed values: default, store, group and website. Default value: default. +- **scopeValue** + - The code of the scope to be configured. If "default" scope is provided, this parameter can be omitted. If the scope type is store, group or website, the default value of this parameter is the current value of the specified scope. ## Principles diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md new file mode 100644 index 00000000000..2252cb986d8 --- /dev/null +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md @@ -0,0 +1,23 @@ +--- +group: testing +title: Data fixture before transaction attribute +--- + +## Overview + +## Format + +```php?start_inline=1 +#[ + DataFixtureBeforeTransaction(string $type, array $data = [], ?string $as = null) +] +``` + +### Parameters + + - **type** + - The fully qualified name of a class that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. + - **data** + - The optional array of data passed on to the fixture. + - **as** + - The fixture alias that will be used as a reference to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md index b065fec5dbd..4e8b4a75cdb 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md @@ -16,8 +16,6 @@ To set up a date fixture, use the `DataFixture` attribute. ## Format -`DataFixture` takes following arguments. - ```php?start_inline=1 #[ DataFixture(string $type, array $data = [], ?string $as = null) @@ -26,12 +24,12 @@ To set up a date fixture, use the `DataFixture` attribute. ### Parameters -- **type** - - The fully qualified name of a class that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. -- **data** - - The optional array of data passed on to the fixture. -- **as** - - The fixture alias that will be used as a reference to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. + - **type** + - The fully qualified name of a class that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. + - **data** + - The optional array of data passed on to the fixture. + - **as** + - The fixture alias that will be used as a reference to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. ## Creating the fixture diff --git a/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md b/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md index 91b1fcad2ee..0842aabe730 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md +++ b/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md @@ -12,21 +12,23 @@ When the `DbIsolation` is enabled, the ITF: ## Format -Database isolation attribute: - ```php?start_inline=1 #[ -DbIsolation((bool)) + DbIsolation(bool $state = true) ] ``` -## Test class +### Parameters + - **state** + - Enables or disables database isolation. + +## Test class attribute -Use test case declarations when a sequence of tests introduces changes to the database and relies on the changes made by each other. +Use test class declarations when a sequence of tests introduces changes to the database and relies on the changes made by each other. For example, typical CRUD tests: _create -> read -> update -> delete_. -Every next test relies on a database state after the previous one. -If at any point of that sequence (after creation) the test fails, the database will be polluted with test data. -To apply a database rollback after the test case, create a separate test case with `DbIsolation` enabled at a class level. +Every next test method relies on a database state after the previous one. +If at any point of that sequence (after creation) the test method fails, the database will be polluted with test data. +To apply a database rollback after the test class, create a separate test class with `DbIsolation` enabled at a class level. Example: @@ -69,9 +71,9 @@ class Some\EntityTest extends \PHPUnit\Framework\TestCase } ``` -## Test method +## Test method attribute -To isolate changes made to database by a single test, enable the `DbIsolation` for the test. +To isolate changes made to database by a single test, enable the `DbIsolation` for the test method. ```php?start_inline=1 #[ diff --git a/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md b/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md new file mode 100644 index 00000000000..288effbc446 --- /dev/null +++ b/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md @@ -0,0 +1,21 @@ +--- +group: testing +title: Indexer dimension mode +--- + +## Overview + +## Format + +```php?start_inline=1 +#[ + IndexerDimensionMode(string $indexer, string $dimension) +] +``` + +### Parameters + + - **indexer** + - The name of the indexer. + - **dimension** + - The name of the dimension. From 293cd12beccc700613d76ea563a2eef1d45cb56c Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Tue, 14 Jun 2022 09:52:45 -0500 Subject: [PATCH 173/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- .../attributes/magento-data-fixture.md | 92 +++++++++---------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md index 4e8b4a75cdb..f26b2b5c456 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md @@ -31,50 +31,11 @@ To set up a date fixture, use the `DataFixture` attribute. - **as** - The fixture alias that will be used as a reference to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. -## Creating the fixture - -### Principles - -1. Parameterized Data Fixture class MUST implement `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface` if the data created by the fixture is revertible. For instance, a fixture that creates an entity (for example, product). -1. Parameterized Data Fixture class MUST be placed in the `/Test/Fixture` folder of the corresponding module with namespace: `\\Test\Fixture` (for example, `Magento\Catalog\Test\Fixture`). -1. Parameterized Data Fixture class SHOULD follow single responsibility principle. -1. Parameterized Data Fixture class MUST depend only on services from modules that are declared in the `require` section of its module's composer.json. -1. Parameterized Data Fixture MUST NOT depend on another fixture. -1. Parameterized Data Fixture SHOULD be implemented using service APIs. -1. Parameterized Data Fixture SHOULD have dynamic default data to allow generating unique fixtures. - -### Dynamic default data - -In order to generate multiple fixtures of the same type without having to manually configure unique fields, you can use the placeholder `%uniqid%` in the default value of unique fields and `Magento\TestFramework\Fixture\Data\ProcessorInterface` to substitute the placeholder with unique sequence. - -[`Magento\Catalog\Test\Fixture\Product`][] demonstrates the usage of `%uniqid%` (`sku`: `simple-product%uniqid%`) in the fixture default data. - -In the following example, a unique `sku` is automatically generated for the first fixture (for example, `simple-product61c10b2e86f991`) and the second fixture (for example, `simple-product61c10b2e86f992`). The sequence is random and therefore unpredictable. - -```php?start_inline=1 -class ProductsListTest extends \PHPUnit\Framework\TestCase -{ - #[ - DataFixture(ProductFixture::class), - DataFixture(ProductFixture::class) - ] - public function testGetProductsCount(): void - { - } -} -``` - -### Decoupling fixtures - -Fixtures must be written in the way that they only use one API to generate data. For example, the fixture that creates -a product should only invoke "Create Product" API and return the product created. This fixture should not add any extra -logic beyond the "create product" API capabilities, such logic should be implemented in a separate fixture. - -### Fixture Alias +## Fixture Alias You can give [Parameterized Data Fixture][parameterizedDataFixture] an alias using the `as` directive. The fixture alias is used as a reference to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. -#### Retrieve fixture data in the test +### Retrieve fixture data in the test A test can retrieve data that was returned by a [Parameterized Data Fixture][parameterizedDataFixture] using `Magento\TestFramework\Fixture\DataFixtureStorageManager` and the fixture alias. @@ -98,7 +59,7 @@ class ProductsList extends \PHPUnit\Framework\TestCase } ``` -#### Supply data to parameterized data fixture as a variable +## Supply data to parameterized data fixture as a variable It is possible to supply data as a variable from one fixture to another using the fixture alias in one of the following formats: @@ -120,19 +81,58 @@ class QuoteTest extends \PHPUnit\Framework\TestCase } ``` -### Test case and test method scopes +## Test case and test method scopes The `DataFixture` can be specified for a particular test or for an entire test case. The basic rules for fixture attribute at different levels are: - `DataFixture` at a test case level, makes the framework to apply the declared fixtures to each test in the test case. - When the final test is complete, all class-level fixtures are reverted. + When the final test is complete, all class-level fixtures are reverted. - `DataFixture` for a particular test, signals the framework to revert the fixtures declared on a test case level and applies the fixtures declared at a test method level instead. - When the test is complete, the ITF reverts the applied fixtures. + When the test is complete, the ITF reverts the applied fixtures. - {:.bs-callout-info} +{:.bs-callout-info} The integration testing framework interacts with a database to revert the applied fixtures. +## Creating the fixture + +### Principles + +1. Parameterized Data Fixture class MUST implement `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface` if the data created by the fixture is revertible. For instance, a fixture that creates an entity (for example, product). +1. Parameterized Data Fixture class MUST be placed in the `/Test/Fixture` folder of the corresponding module with namespace: `\\Test\Fixture` (for example, `Magento\Catalog\Test\Fixture`). +1. Parameterized Data Fixture class SHOULD follow single responsibility principle. +1. Parameterized Data Fixture class MUST depend only on services from modules that are declared in the `require` section of its module's composer.json. +1. Parameterized Data Fixture MUST NOT depend on another fixture. +1. Parameterized Data Fixture SHOULD be implemented using service APIs. +1. Parameterized Data Fixture SHOULD have dynamic default data to allow generating unique fixtures. + +### Dynamic default data + +In order to generate multiple fixtures of the same type without having to manually configure unique fields, you can use the placeholder `%uniqid%` in the default value of unique fields and `Magento\TestFramework\Fixture\Data\ProcessorInterface` to substitute the placeholder with unique sequence. + +[`Magento\Catalog\Test\Fixture\Product`][] demonstrates the usage of `%uniqid%` (`sku`: `simple-product%uniqid%`) in the fixture default data. + +In the following example, a unique `sku` is automatically generated for the first fixture (for example, `simple-product61c10b2e86f991`) and the second fixture (for example, `simple-product61c10b2e86f992`). The sequence is random and therefore unpredictable. + +```php?start_inline=1 +class ProductsListTest extends \PHPUnit\Framework\TestCase +{ + #[ + DataFixture(ProductFixture::class), + DataFixture(ProductFixture::class) + ] + public function testGetProductsCount(): void + { + } +} +``` + +### Decoupling fixtures + +Fixtures must be written in the way that they only use one API to generate data. For example, the fixture that creates +a product should only invoke "Create Product" API and return the product created. This fixture should not add any extra +logic beyond the "create product" API capabilities, such logic should be implemented in a separate fixture. + ### Fixture rollback A fixture that contains database transactions only, are reverted automatically. From 21909be48a84969367faeba864a717ce08025073 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 14 Jun 2022 10:19:59 -0500 Subject: [PATCH 174/776] Updated links --- src/guides/v2.4/howdoi/admin/customize_admin.md | 2 +- src/guides/v2.4/howdoi/checkout/checkout-add-custom-carrier.md | 2 +- src/guides/v2.4/howdoi/checkout/checkout_address.md | 2 +- src/guides/v2.4/howdoi/checkout/checkout_carrier.md | 2 +- src/guides/v2.4/howdoi/checkout/checkout_custom_checkbox.md | 2 +- src/guides/v2.4/howdoi/checkout/checkout_customize.md | 2 +- src/guides/v2.4/howdoi/checkout/checkout_edit_form.md | 2 +- src/guides/v2.4/howdoi/checkout/checkout_form.md | 2 +- src/guides/v2.4/howdoi/checkout/checkout_new_field.md | 2 +- src/guides/v2.4/howdoi/checkout/checkout_new_step.md | 2 +- src/guides/v2.4/howdoi/checkout/checkout_order.md | 2 +- src/guides/v2.4/howdoi/checkout/checkout_overview.md | 2 +- src/guides/v2.4/howdoi/checkout/checkout_payment.md | 2 +- src/guides/v2.4/howdoi/checkout/checkout_payment_new_field.md | 2 +- src/guides/v2.4/howdoi/checkout/checkout_shipping_methods.md | 2 +- src/guides/v2.4/howdoi/checkout/checkout_zip.md | 2 +- src/guides/v2.4/howdoi/custom-attributes/introduction.md | 2 +- src/guides/v2.4/howdoi/custom-attributes/text-field.md | 2 +- src/guides/v2.4/howdoi/customize-form-configuration.md | 2 +- src/guides/v2.4/howdoi/customize-modifier-class.md | 2 +- src/guides/v2.4/howdoi/customize_product.md | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/guides/v2.4/howdoi/admin/customize_admin.md b/src/guides/v2.4/howdoi/admin/customize_admin.md index 0bfc52b111a..632a504a629 100644 --- a/src/guides/v2.4/howdoi/admin/customize_admin.md +++ b/src/guides/v2.4/howdoi/admin/customize_admin.md @@ -1,7 +1,7 @@ --- group: how-do-i title: Customize the design -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-admin-design/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/admin/custom-admin-design/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/checkout/checkout-add-custom-carrier.md b/src/guides/v2.4/howdoi/checkout/checkout-add-custom-carrier.md index 557c419b7aa..81426ab828d 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout-add-custom-carrier.md +++ b/src/guides/v2.4/howdoi/checkout/checkout-add-custom-carrier.md @@ -10,7 +10,7 @@ menu_order: 5 level3_subgroup: checkout-tutorial functional_areas: - Checkout -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-shipping-carrier/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/frontend/custom-checkout/add-shipping-carrier/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/checkout/checkout_address.md b/src/guides/v2.4/howdoi/checkout/checkout_address.md index 468eabda7aa..44a31c3c922 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_address.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_address.md @@ -8,7 +8,7 @@ menu_order: 11 level3_subgroup: checkout-tutorial functional_areas: - Checkout -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-address-renderer/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/frontend/custom-checkout/add-address-renderer/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/checkout/checkout_carrier.md b/src/guides/v2.4/howdoi/checkout/checkout_carrier.md index 320484e48f4..40c3ff341fe 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_carrier.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_carrier.md @@ -8,7 +8,7 @@ menu_order: 6 level3_subgroup: checkout-tutorial functional_areas: - Checkout -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-carrier-validation/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/frontend/custom-checkout/add-carrier-validation/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/checkout/checkout_custom_checkbox.md b/src/guides/v2.4/howdoi/checkout/checkout_custom_checkbox.md index bf118a7b9a5..c4d7fa6e539 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_custom_checkbox.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_custom_checkbox.md @@ -8,7 +8,7 @@ menu_order: 90 level3_subgroup: checkout-tutorial functional_areas: - Checkout -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-checkbox/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/frontend/custom-checkout/add-checkbox/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/checkout/checkout_customize.md b/src/guides/v2.4/howdoi/checkout/checkout_customize.md index 184b57753c7..a2b5a8c34c2 100755 --- a/src/guides/v2.4/howdoi/checkout/checkout_customize.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_customize.md @@ -8,7 +8,7 @@ menu_order: 2 level3_subgroup: checkout-tutorial functional_areas: - Checkout -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/customize-view/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/frontend/custom-checkout/customize-view/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/checkout/checkout_edit_form.md b/src/guides/v2.4/howdoi/checkout/checkout_edit_form.md index 58b98205951..b8f6ecaa9e5 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_edit_form.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_edit_form.md @@ -8,7 +8,7 @@ menu_order: 8 level3_subgroup: checkout-tutorial functional_areas: - Checkout -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-template/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/frontend/custom-checkout/add-template/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/checkout/checkout_form.md b/src/guides/v2.4/howdoi/checkout/checkout_form.md index 4dd47386187..f095f59dc0e 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_form.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_form.md @@ -8,7 +8,7 @@ menu_order: 9 level3_subgroup: checkout-tutorial functional_areas: - Checkout -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-form/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/frontend/custom-checkout/add-form/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/checkout/checkout_new_field.md b/src/guides/v2.4/howdoi/checkout/checkout_new_field.md index 12ed93be5c8..b7fcdfdb32d 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_new_field.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_new_field.md @@ -8,7 +8,7 @@ menu_order: 9 level3_subgroup: checkout-tutorial functional_areas: - Checkout -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-address-field/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/frontend/custom-checkout/add-address-field/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/checkout/checkout_new_step.md b/src/guides/v2.4/howdoi/checkout/checkout_new_step.md index 4a10540d76a..5e297b2d99a 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_new_step.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_new_step.md @@ -8,7 +8,7 @@ menu_order: 1 level3_subgroup: checkout-tutorial functional_areas: - Checkout -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-new-step/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/frontend/custom-checkout/add-new-step/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/checkout/checkout_order.md b/src/guides/v2.4/howdoi/checkout/checkout_order.md index f0c93586544..6507d863f27 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_order.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_order.md @@ -8,7 +8,7 @@ menu_order: 4 level3_subgroup: checkout-tutorial functional_areas: - Checkout -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-order-validation/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/frontend/custom-checkout/add-order-validation/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/checkout/checkout_overview.md b/src/guides/v2.4/howdoi/checkout/checkout_overview.md index 966c92934c5..c9869b4c155 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_overview.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_overview.md @@ -9,7 +9,7 @@ level3_subgroup: checkout-tutorial menu_order: 0 functional_areas: - Checkout -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/frontend/custom-checkout/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/checkout/checkout_payment.md b/src/guides/v2.4/howdoi/checkout/checkout_payment.md index 9632608b126..8b9566e5a31 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_payment.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_payment.md @@ -8,7 +8,7 @@ menu_order: 3 level3_subgroup: checkout-tutorial functional_areas: - Checkout -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-payment-method/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/frontend/custom-checkout/add-payment-method/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/checkout/checkout_payment_new_field.md b/src/guides/v2.4/howdoi/checkout/checkout_payment_new_field.md index 8838b2c1598..1d872d4e6c0 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_payment_new_field.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_payment_new_field.md @@ -10,7 +10,7 @@ menu_order: 101 level3_subgroup: checkout-tutorial functional_areas: - Checkout -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-payment-field/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/frontend/custom-checkout/add-payment-field/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/checkout/checkout_shipping_methods.md b/src/guides/v2.4/howdoi/checkout/checkout_shipping_methods.md index ba8b7a50122..9a0fd60646a 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_shipping_methods.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_shipping_methods.md @@ -6,7 +6,7 @@ title: Customize the list of shipping methods subtitle: Customize Checkout menu_order: 100 level3_subgroup: checkout-tutorial -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-shipping-methods/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/frontend/custom-checkout/add-shipping-methods/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/checkout/checkout_zip.md b/src/guides/v2.4/howdoi/checkout/checkout_zip.md index e7c2a517374..a012b9b6e90 100644 --- a/src/guides/v2.4/howdoi/checkout/checkout_zip.md +++ b/src/guides/v2.4/howdoi/checkout/checkout_zip.md @@ -8,7 +8,7 @@ menu_order: 7 level3_subgroup: checkout-tutorial functional_areas: - Checkout -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-checkout/add-input-mask/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/frontend/custom-checkout/add-input-mask/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/custom-attributes/introduction.md b/src/guides/v2.4/howdoi/custom-attributes/introduction.md index caaa4daa5f6..bef35d58acc 100644 --- a/src/guides/v2.4/howdoi/custom-attributes/introduction.md +++ b/src/guides/v2.4/howdoi/custom-attributes/introduction.md @@ -8,7 +8,7 @@ level3_subgroup: custom-attributes menu_order: 1 contributor_name: Adarsh Manickam contributor_link: https://github.com/drpayyne -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-attributes/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/admin/custom-text-field-attribute/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/custom-attributes/text-field.md b/src/guides/v2.4/howdoi/custom-attributes/text-field.md index 1c4f60837e8..76e4280bd61 100644 --- a/src/guides/v2.4/howdoi/custom-attributes/text-field.md +++ b/src/guides/v2.4/howdoi/custom-attributes/text-field.md @@ -8,7 +8,7 @@ level3_subgroup: custom-attributes menu_order: 2 contributor_name: Adarsh Manickam contributor_link: https://github.com/drpayyne -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-attributes/text-field/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/admin/custom-text-field-attribute/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/customize-form-configuration.md b/src/guides/v2.4/howdoi/customize-form-configuration.md index 71685c0a045..ebaf86baa33 100644 --- a/src/guides/v2.4/howdoi/customize-form-configuration.md +++ b/src/guides/v2.4/howdoi/customize-form-configuration.md @@ -7,7 +7,7 @@ subtitle: Customize Product Creation Form menu_node: level3_subgroup: product-creation-form menu_order: 2 -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-product-creation-form/configuration/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/admin/custom-product-creation-form/configuration/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/customize-modifier-class.md b/src/guides/v2.4/howdoi/customize-modifier-class.md index 57632674c41..84fb13298b8 100644 --- a/src/guides/v2.4/howdoi/customize-modifier-class.md +++ b/src/guides/v2.4/howdoi/customize-modifier-class.md @@ -7,7 +7,7 @@ subtitle: Customize Product Creation Form menu_node: level3_subgroup: product-creation-form menu_order: 3 -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-product-creation-form/modifier-class/ +migrated_to: https://developer-stage.adobe.com/commerce/php/tutorials/admin/custom-product-creation-form/modifier-class/ layout: migrated --- diff --git a/src/guides/v2.4/howdoi/customize_product.md b/src/guides/v2.4/howdoi/customize_product.md index 59d45bdf110..8bafe8e0ee8 100644 --- a/src/guides/v2.4/howdoi/customize_product.md +++ b/src/guides/v2.4/howdoi/customize_product.md @@ -7,7 +7,7 @@ menu_title: Initial Tasks menu_node: level3_subgroup: product-creation-form menu_order: 1 -migrated_to: https://developer.adobe.com/commerce/php/tutorials/custom-product-creation-form/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/admin/custom-product-creation-form/ layout: migrated --- From 496aca39b0a7b7a0149f8e8e9e0af34fb4094a65 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 14 Jun 2022 10:24:23 -0500 Subject: [PATCH 175/776] Updated links to best practices tutorials --- src/guides/v2.4/ext-best-practices/tutorials/copy-fieldsets.md | 2 +- .../tutorials/create-access-control-list-rule.md | 2 +- .../v2.4/ext-best-practices/tutorials/create-custom-rest-api.md | 2 +- .../ext-best-practices/tutorials/create-integration-with-api.md | 2 +- .../v2.4/ext-best-practices/tutorials/custom-import-entity.md | 2 +- src/guides/v2.4/ext-best-practices/tutorials/custom-widget.md | 2 +- .../ext-best-practices/tutorials/dynamic-row-system-config.md | 2 +- .../tutorials/modify-image-library-permissions/index.md | 2 +- .../tutorials/serialized-to-json-data-upgrade.md | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/guides/v2.4/ext-best-practices/tutorials/copy-fieldsets.md b/src/guides/v2.4/ext-best-practices/tutorials/copy-fieldsets.md index 967a3e2fe4f..c6b43a1aa47 100644 --- a/src/guides/v2.4/ext-best-practices/tutorials/copy-fieldsets.md +++ b/src/guides/v2.4/ext-best-practices/tutorials/copy-fieldsets.md @@ -6,7 +6,7 @@ menu_title: Copying fieldsets menu_order: 1000 functional_areas: - Standards -migrated_to: https://developer.adobe.com/commerce/php/best-practices/tutorials/copy-fieldsets/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/backend/copy-fieldsets/ layout: migrated --- diff --git a/src/guides/v2.4/ext-best-practices/tutorials/create-access-control-list-rule.md b/src/guides/v2.4/ext-best-practices/tutorials/create-access-control-list-rule.md index 15caf0b98fd..3726f6be32a 100755 --- a/src/guides/v2.4/ext-best-practices/tutorials/create-access-control-list-rule.md +++ b/src/guides/v2.4/ext-best-practices/tutorials/create-access-control-list-rule.md @@ -3,7 +3,7 @@ group: extension-best-practices title: Creating an Access Control List (ACL) rule contributor_name: Ziffity contributor_link: https://www.Ziffity.com/ -migrated_to: https://developer.adobe.com/commerce/php/best-practices/tutorials/create-access-control-list-rule/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/backend/create-access-control-list-rule/ layout: migrated --- diff --git a/src/guides/v2.4/ext-best-practices/tutorials/create-custom-rest-api.md b/src/guides/v2.4/ext-best-practices/tutorials/create-custom-rest-api.md index f2ab35eeb84..ff2b91bc3e6 100644 --- a/src/guides/v2.4/ext-best-practices/tutorials/create-custom-rest-api.md +++ b/src/guides/v2.4/ext-best-practices/tutorials/create-custom-rest-api.md @@ -3,7 +3,7 @@ group: extension-best-practices title: Create a custom REST API contributor_name: Nitish Ranjan contributor_link: https://github.com/nitish-ranjan05 -migrated_to: https://developer.adobe.com/commerce/php/best-practices/tutorials/create-custom-rest-api/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/backend/create-custom-rest-api/ layout: migrated --- diff --git a/src/guides/v2.4/ext-best-practices/tutorials/create-integration-with-api.md b/src/guides/v2.4/ext-best-practices/tutorials/create-integration-with-api.md index 019d46c6297..08e9dc6c02a 100644 --- a/src/guides/v2.4/ext-best-practices/tutorials/create-integration-with-api.md +++ b/src/guides/v2.4/ext-best-practices/tutorials/create-integration-with-api.md @@ -3,7 +3,7 @@ group: extension-best-practices title: Creating an integration with an external API contributor_name: Atwix contributor_link: https://www.atwix.com/ -migrated_to: https://developer.adobe.com/commerce/php/best-practices/tutorials/create-api-integration/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/backend/create-api-integration/ layout: migrated --- diff --git a/src/guides/v2.4/ext-best-practices/tutorials/custom-import-entity.md b/src/guides/v2.4/ext-best-practices/tutorials/custom-import-entity.md index 91e845412e2..33222003a8c 100644 --- a/src/guides/v2.4/ext-best-practices/tutorials/custom-import-entity.md +++ b/src/guides/v2.4/ext-best-practices/tutorials/custom-import-entity.md @@ -3,7 +3,7 @@ group: extension-best-practices title: Custom import entity contributor_name: Atwix contributor_link: https://www.atwix.com/ -migrated_to: https://developer.adobe.com/commerce/php/best-practices/tutorials/create-custom-import-entity/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/backend/create-custom-import-entity/ layout: migrated --- diff --git a/src/guides/v2.4/ext-best-practices/tutorials/custom-widget.md b/src/guides/v2.4/ext-best-practices/tutorials/custom-widget.md index b3b3bd770c7..8137c28b957 100644 --- a/src/guides/v2.4/ext-best-practices/tutorials/custom-widget.md +++ b/src/guides/v2.4/ext-best-practices/tutorials/custom-widget.md @@ -3,7 +3,7 @@ group: extension-best-practices title: Custom widget contributor_name: Atwix contributor_link: https://www.atwix.com/ -migrated_to: https://developer.adobe.com/commerce/php/best-practices/tutorials/create-custom-widget/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/frontend/create-custom-widget/ layout: migrated --- diff --git a/src/guides/v2.4/ext-best-practices/tutorials/dynamic-row-system-config.md b/src/guides/v2.4/ext-best-practices/tutorials/dynamic-row-system-config.md index ac33a3b98c6..9ba27e1de8a 100644 --- a/src/guides/v2.4/ext-best-practices/tutorials/dynamic-row-system-config.md +++ b/src/guides/v2.4/ext-best-practices/tutorials/dynamic-row-system-config.md @@ -6,7 +6,7 @@ menu_title: Creating a dynamic row system config menu_order: 1010 functional_areas: - Standards -migrated_to: https://developer.adobe.com/commerce/php/best-practices/tutorials/create-dynamic-row-configuration/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/admin/create-dynamic-row-configuration/ layout: migrated --- diff --git a/src/guides/v2.4/ext-best-practices/tutorials/modify-image-library-permissions/index.md b/src/guides/v2.4/ext-best-practices/tutorials/modify-image-library-permissions/index.md index 5548d3bdb3c..2c6e2e7a1e4 100644 --- a/src/guides/v2.4/ext-best-practices/tutorials/modify-image-library-permissions/index.md +++ b/src/guides/v2.4/ext-best-practices/tutorials/modify-image-library-permissions/index.md @@ -1,7 +1,7 @@ --- group: extension-best-practices title: Modify Media Library folder permissions -migrated_to: https://developer.adobe.com/commerce/php/best-practices/tutorials/modify-image-library-permissions/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/backend/modify-image-library-permissions/ layout: migrated --- diff --git a/src/guides/v2.4/ext-best-practices/tutorials/serialized-to-json-data-upgrade.md b/src/guides/v2.4/ext-best-practices/tutorials/serialized-to-json-data-upgrade.md index af63ef3200b..a28e22cdc58 100644 --- a/src/guides/v2.4/ext-best-practices/tutorials/serialized-to-json-data-upgrade.md +++ b/src/guides/v2.4/ext-best-practices/tutorials/serialized-to-json-data-upgrade.md @@ -4,7 +4,7 @@ subgroup: Tutorials title: Serialized to JSON data upgrade menu_title: Serialized to JSON data upgrade menu_order: 1000 -migrated_to: https://developer.adobe.com/commerce/php/best-practices/tutorials/convert-serialized-data/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/backend/convert-serialized-data/ layout: migrated --- From b9698e87677be98a274a9e5e355c7acabd896846 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 14 Jun 2022 10:40:26 -0500 Subject: [PATCH 176/776] Fixed domain --- src/guides/v2.4/howdoi/customize-modifier-class.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/howdoi/customize-modifier-class.md b/src/guides/v2.4/howdoi/customize-modifier-class.md index 84fb13298b8..779a07f4961 100644 --- a/src/guides/v2.4/howdoi/customize-modifier-class.md +++ b/src/guides/v2.4/howdoi/customize-modifier-class.md @@ -7,7 +7,7 @@ subtitle: Customize Product Creation Form menu_node: level3_subgroup: product-creation-form menu_order: 3 -migrated_to: https://developer-stage.adobe.com/commerce/php/tutorials/admin/custom-product-creation-form/modifier-class/ +migrated_to: https://developer.adobe.com/commerce/php/tutorials/admin/custom-product-creation-form/modifier-class/ layout: migrated --- From 9c260d6d4107313f1cf6560d9927bb3716f55136 Mon Sep 17 00:00:00 2001 From: gregory-marshall Date: Tue, 14 Jun 2022 08:50:08 -0700 Subject: [PATCH 177/776] Addressed using vars in URLs --- src/cloud/cdn/cloud-fastly.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cloud/cdn/cloud-fastly.md b/src/cloud/cdn/cloud-fastly.md index f5432606f31..a8673ba5382 100644 --- a/src/cloud/cdn/cloud-fastly.md +++ b/src/cloud/cdn/cloud-fastly.md @@ -34,11 +34,11 @@ Fastly provides the following services to optimize and secure content delivery o - [Distributed Denial of Service (DDoS) protection](#ddos-protection)—Built-in DDoS protection against common attacks like Ping of Death, Smurf attacks, as well as other ICMP-based floods. - - [SSL/TLS certificates](https://devdocs.magento.com/cloud/cdn/configure-fastly.html#provision-ssltls-certificates)–The Fastly service requires an SSL/TLS certificate to serve secure traffic over HTTPS. {{site.data.var.ee}} provides a Domain-validated Let's Encrypt SSL/TLS certificate for each Staging and Production environment. {{site.data.var.ee}} completes domain validation and certificate provisioning during the Fastly set up process. + - [SSL/TLS certificates]({{site.baseurl}}/cloud/cdn/configure-fastly.html#provision-ssltls-certificates)–The Fastly service requires an SSL/TLS certificate to serve secure traffic over HTTPS. {{site.data.var.ee}} provides a Domain-validated Let's Encrypt SSL/TLS certificate for each Staging and Production environment. {{site.data.var.ee}} completes domain validation and certificate provisioning during the Fastly set up process. - - **Origin cloaking**–Prevents traffic from bypassing the Fastly WAF and hides the IP addresses of your origin servers to protect them from direct access and DDoS attacks. Origin cloaking is enabled by default on {{ site.data.var.ece }} Pro Production projects. To enable origin cloaking on {{ site.data.var.ece }} Starter Production projects, submit a [{{site.data.var.ee}} support ticket](https://support.magento.com/hc/en-us/articles/360019088251). If you have traffic that does not require caching, you can customize the Fastly service configuration to allow requests to [bypass the Fastly cache](https://devdocs.magento.com/cloud/cdn/fastly-vcl-bypass-to-origin.html). + - **Origin cloaking**–Prevents traffic from bypassing the Fastly WAF and hides the IP addresses of your origin servers to protect them from direct access and DDoS attacks. Origin cloaking is enabled by default on {{ site.data.var.ece }} Pro Production projects. To enable origin cloaking on {{ site.data.var.ece }} Starter Production projects, submit a [{{site.data.var.ee}} support ticket](https://support.magento.com/hc/en-us/articles/360019088251). If you have traffic that does not require caching, you can customize the Fastly service configuration to allow requests to [bypass the Fastly cache]({{site.baseurl}}/cloud/cdn/fastly-vcl-bypass-to-origin.html). -- [Image optimization](https://devdocs.magento.com/cloud/cdn/fastly-image-optimization.html)—Offloads image processing and resizing load to the Fastly service freeing servers to process orders and conversions efficiently. +- [Image optimization]({{site.baseurl}}/cloud/cdn/fastly-image-optimization.html)—Offloads image processing and resizing load to the Fastly service freeing servers to process orders and conversions efficiently. - **Fastly CDN and WAF logs**–For {{ site.data.var.ece }} Pro projects, you can use the New Relic Logs service to review and analyze Fastly CDN and WAF log data. See [New Relic](https://devdocs.magento.com/cloud/project/new-relic.html#new-relic-logs). From 30b1d7dfd17ebd31dfecf55e737a22edcf7b2fc6 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Tue, 14 Jun 2022 11:23:15 -0500 Subject: [PATCH 178/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- .../integration/attributes/magento-cache.md | 6 +-- ...magento-data-fixture-before-transaction.md | 9 +++++ .../attributes/magento-data-fixture.md | 37 +++++++------------ .../magento-indexer-dimension-mode.md | 37 ++++++++++++++++++- 4 files changed, 60 insertions(+), 29 deletions(-) diff --git a/src/guides/v2.4/test/integration/attributes/magento-cache.md b/src/guides/v2.4/test/integration/attributes/magento-cache.md index a662e8c308b..a69a3d1423e 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-cache.md +++ b/src/guides/v2.4/test/integration/attributes/magento-cache.md @@ -28,19 +28,17 @@ Enable or disable a [cache type][] using the `Cache` attribute. 1. A test method attribute completely overrides a test class attribute. 1. All cache types are disabled by default. -## Test class annotation +## Test class attribute `Cache` attribute at the test case level is applied to all tests. -## Test method annotation +## Test method attribute `Cache` attribute at a test method level configures the test method only. It completely overrides the attribute specified for the test class. ## Example -Cache attributes example: - ```php + +[Data Fixture attribute]: {{ page.baseurl }}/test/integration/attributes/magento-data-fixture.html diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md index f26b2b5c456..56619360b2c 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md @@ -8,7 +8,7 @@ redirect_from: ## Overview -Parameterized data fixture is a dynamic and scalable data fixture that accepts parameters directly from the fixture declaration. It eliminates the need to create almost identical fixtures every time you need a slight change. +Data fixture is a dynamic and scalable data fixture that accepts parameters directly from the fixture declaration. It eliminates the need to create almost identical fixtures every time you need a slight change. A data fixture is a PHP script that sets data you want to reuse in your test. Use data fixtures to prepare a database for tests. The Integration Testing Framework (ITF) reverts the database to its initial state automatically. @@ -31,13 +31,11 @@ To set up a date fixture, use the `DataFixture` attribute. - **as** - The fixture alias that will be used as a reference to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. -## Fixture Alias - -You can give [Parameterized Data Fixture][parameterizedDataFixture] an alias using the `as` directive. The fixture alias is used as a reference to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. +## Fixture Usage ### Retrieve fixture data in the test -A test can retrieve data that was returned by a [Parameterized Data Fixture][parameterizedDataFixture] using `Magento\TestFramework\Fixture\DataFixtureStorageManager` and the fixture alias. +A test can retrieve data that was returned by a Data Fixture using `Magento\TestFramework\Fixture\DataFixtureStorageManager` and the fixture alias. The following example shows how to retrieve data that was returned by the fixtures: @@ -59,7 +57,7 @@ class ProductsList extends \PHPUnit\Framework\TestCase } ``` -## Supply data to parameterized data fixture as a variable +### Supply data to data fixture as a variable It is possible to supply data as a variable from one fixture to another using the fixture alias in one of the following formats: @@ -81,7 +79,7 @@ class QuoteTest extends \PHPUnit\Framework\TestCase } ``` -## Test case and test method scopes +### Test class and test method scopes The `DataFixture` can be specified for a particular test or for an entire test case. The basic rules for fixture attribute at different levels are: @@ -98,13 +96,13 @@ The integration testing framework interacts with a database to revert the applie ### Principles -1. Parameterized Data Fixture class MUST implement `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface` if the data created by the fixture is revertible. For instance, a fixture that creates an entity (for example, product). -1. Parameterized Data Fixture class MUST be placed in the `/Test/Fixture` folder of the corresponding module with namespace: `\\Test\Fixture` (for example, `Magento\Catalog\Test\Fixture`). -1. Parameterized Data Fixture class SHOULD follow single responsibility principle. -1. Parameterized Data Fixture class MUST depend only on services from modules that are declared in the `require` section of its module's composer.json. -1. Parameterized Data Fixture MUST NOT depend on another fixture. -1. Parameterized Data Fixture SHOULD be implemented using service APIs. -1. Parameterized Data Fixture SHOULD have dynamic default data to allow generating unique fixtures. +1. Data Fixture class MUST implement `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface` if the data created by the fixture is revertible. For instance, a fixture that creates an entity (for example, product). +1. Data Fixture class MUST be placed in the `/Test/Fixture` folder of the corresponding module with namespace: `\\Test\Fixture` (for example, `Magento\Catalog\Test\Fixture`). +1. Data Fixture class SHOULD follow single responsibility principle. +1. Data Fixture class MUST depend only on services from modules that are declared in the `require` section of its module's composer.json. +1. Data Fixture MUST NOT depend on another fixture. +1. Data Fixture SHOULD be implemented using service APIs. +1. Data Fixture SHOULD have dynamic default data to allow generating unique fixtures. ### Dynamic default data @@ -136,17 +134,10 @@ logic beyond the "create product" API capabilities, such logic should be impleme ### Fixture rollback A fixture that contains database transactions only, are reverted automatically. -Otherwise, when a fixture creates files or performs any actions other than database transaction, provide the corresponding rollback logic. +Otherwise, when a fixture creates files or performs any actions other than database transaction, provide the corresponding rollback logic, +in the `revert()` method of the revertible data fixture. Rollbacks are run after reverting all the fixtures related to database transactions. -Rollback methods must be of the same class as the corresponding fixture and suffixed with `Rollback`. - -Examples: - -| Fixture/Rollback | Fixture name | Rollback name | -|------------------|------------------------------------------------------|--------------------------------------------------------------| -| Method | `\Magento\Catalog\Model\ProductTest::prepareProduct` | `\Magento\Catalog\Model\ProductTest::prepareProductRollback` | - ### Restrictions Do not rely on and do not modify an application state from within a fixture, because [application isolation attribute][magentoAppIsolation] can reset the application state at any time. diff --git a/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md b/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md index 288effbc446..28d04e5c40a 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md +++ b/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md @@ -5,6 +5,8 @@ title: Indexer dimension mode ## Overview +Sets the indexer dimension mode for the test run. + ## Format ```php?start_inline=1 @@ -16,6 +18,37 @@ title: Indexer dimension mode ### Parameters - **indexer** - - The name of the indexer. + - The name of the indexer code. - **dimension** - - The name of the dimension. + - The name of the dimension mode. + +## Principles + +1. You can use more than one attribute for a test case or a test method. +2. Multiple attributes are applied in the given order. +3. Attributes from different scopes are not merged. +4. A test method attribute completely overrides a test class attribute. + +## Test class attribute + +`IndexerDimensionMode` attribute at the test case level is applied to all tests. + +## Test method attribute + +`IndexerDimensionMode` attribute at a test method level configures the test method only. +It completely overrides the attribute specified for the test class. + +## Example + +```php?start_inline=1 +#[ + DbIsolation(false), + IndexerDimensionMode('catalog_product_price', 'website_and_customer_group') +] +class FixedBundlePriceCalculatorWithDimensionTest extends \PHPUnit\Framework\TestCase +{ + public function testPriceForFixedBundle(array $strategyModifiers, array $expectedResults) + { + } +} +``` \ No newline at end of file From 9fa05970d7e366d95fada5eba700877579368015 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Tue, 14 Jun 2022 11:28:06 -0500 Subject: [PATCH 179/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- .../integration/attributes/magento-app-area.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/guides/v2.4/test/integration/attributes/magento-app-area.md b/src/guides/v2.4/test/integration/attributes/magento-app-area.md index 06e87a313cf..1835e5fe714 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-app-area.md +++ b/src/guides/v2.4/test/integration/attributes/magento-app-area.md @@ -15,15 +15,15 @@ Configure a test environment in scope of the particular [application area][] wit ### Parameters -- **area** - - Can take any value from the list below - - `\Magento\Framework\App\Area::AREA_GLOBAL` - - `\Magento\Framework\App\Area::AREA_ADMINHTML` - - `\Magento\Framework\App\Area::AREA_FRONTEND` - - `\Magento\Framework\App\Area::AREA_WEBAPI_REST` - - `\Magento\Framework\App\Area::AREA_WEBAPI_SOAP` - - `\Magento\Framework\App\Area::AREA_CRONTAB` - - `\Magento\Framework\App\Area::AREA_GRAPHQL` +- **area** + - Can take any value from the list below + - `\Magento\Framework\App\Area::AREA_GLOBAL` + - `\Magento\Framework\App\Area::AREA_ADMINHTML` + - `\Magento\Framework\App\Area::AREA_FRONTEND` + - `\Magento\Framework\App\Area::AREA_WEBAPI_REST` + - `\Magento\Framework\App\Area::AREA_WEBAPI_SOAP` + - `\Magento\Framework\App\Area::AREA_CRONTAB` + - `\Magento\Framework\App\Area::AREA_GRAPHQL` ## Fallback sequence From 014c790e042a4de9f1595aa0aa234a3b4240b5fd Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Tue, 14 Jun 2022 11:38:27 -0500 Subject: [PATCH 180/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- src/guides/v2.4/test/integration/attributes.md | 3 +-- .../attributes/magento-app-isolation.md | 4 ++-- .../test/integration/attributes/magento-cache.md | 8 ++++---- .../attributes/magento-components-dir.md | 4 ++-- .../attributes/magento-config-fixture.md | 16 ++++++++-------- .../attributes/magento-data-fixture.md | 12 ++++++------ .../attributes/magento-db-isolation.md | 4 ++-- .../attributes/magento-indexer-dimension-mode.md | 8 ++++---- 8 files changed, 29 insertions(+), 30 deletions(-) diff --git a/src/guides/v2.4/test/integration/attributes.md b/src/guides/v2.4/test/integration/attributes.md index 8d0450982cc..19882e9484c 100644 --- a/src/guides/v2.4/test/integration/attributes.md +++ b/src/guides/v2.4/test/integration/attributes.md @@ -25,7 +25,6 @@ The following attributes are available in integration tests: | Indexer Dimension Mode | [IndexerDimensionMode][] | Sets the indexer dimension mode for the test run. More information can be found in the [DevBlog](https://community.magento.com/t5/Magento-DevBlog/Indexers-parallelization-and-optimization/ba-p/104922). | | Register Components | [ComponentsDir][] | Registers fixture components from specified directory (recursively). Unregisters the components after the test is finished. | - ## Applying annotations The Magento-specific annotations for integration tests are applied in the following order: @@ -43,7 +42,7 @@ The Magento-specific annotations for integration tests are applied in the follow This order is necessary to meet the requirement of setting up the store-scoped configuration values for fixture stores (stores that are created by data fixtures). {:.bs-callout-info} -[PHP built-in attributes][] are only available with PHP8 and above. +[PHP built-in attributes][] are only available with PHP8 and above. diff --git a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md index 523e8ce7760..cd8ce145b64 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md +++ b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md @@ -21,8 +21,8 @@ Test execution order can vary depending on a PHPUnit version. ### Parameters - - **state** - - Accepts TRUE or FALSE to enable or disable app isolation respectively. +- **state** + - Accepts TRUE or FALSE to enable or disable app isolation respectively. ## Test class attribute diff --git a/src/guides/v2.4/test/integration/attributes/magento-cache.md b/src/guides/v2.4/test/integration/attributes/magento-cache.md index a69a3d1423e..39e39f4b353 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-cache.md +++ b/src/guides/v2.4/test/integration/attributes/magento-cache.md @@ -15,10 +15,10 @@ Enable or disable a [cache type][] using the `Cache` attribute. ### Parameters -- **type** - - The cache type. Or "all" to change the status of all cache types. -- **status** - - Accepts TRUE or FALSE to enable or disable cache respectively. +- **type** + - The cache type. Or "all" to change the status of all cache types. +- **status** + - Accepts TRUE or FALSE to enable or disable cache respectively. ## Principles diff --git a/src/guides/v2.4/test/integration/attributes/magento-components-dir.md b/src/guides/v2.4/test/integration/attributes/magento-components-dir.md index 1e2b39592d6..ef9d630a26e 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-components-dir.md +++ b/src/guides/v2.4/test/integration/attributes/magento-components-dir.md @@ -16,8 +16,8 @@ It enables you to register all the components at a specified directory recursive ### Parameters -- **path** - - A path to the directory with fixture components. Each component must be registered using `registration.php` file. +- **path** + - A path to the directory with fixture components. Each component must be registered using `registration.php` file. ## Test class attribute diff --git a/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md index 14c933edca2..688a8f4b82e 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md @@ -15,14 +15,14 @@ To set Magento configuration values for individual tests and revert them after t ### Parameters -- **path** - - The XPath to the configuration option. See [configuration reference][] for available options. -- **value** - - A fixture value for the configuration option. -- **scopeType** - - The scope to use to set config value. Allowed values: default, store, group and website. Default value: default. -- **scopeValue** - - The code of the scope to be configured. If "default" scope is provided, this parameter can be omitted. If the scope type is store, group or website, the default value of this parameter is the current value of the specified scope. +- **path** + - The XPath to the configuration option. See [configuration reference][] for available options. +- **value** + - A fixture value for the configuration option. +- **scopeType** + - The scope to use to set config value. Allowed values: default, store, group and website. Default value: default. +- **scopeValue** + - The code of the scope to be configured. If "default" scope is provided, this parameter can be omitted. If the scope type is store, group or website, the default value of this parameter is the current value of the specified scope. ## Principles diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md index 56619360b2c..6557eb7a264 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md @@ -24,12 +24,12 @@ To set up a date fixture, use the `DataFixture` attribute. ### Parameters - - **type** - - The fully qualified name of a class that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. - - **data** - - The optional array of data passed on to the fixture. - - **as** - - The fixture alias that will be used as a reference to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. +- **type** + - The fully qualified name of a class that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. +- **data** + - The optional array of data passed on to the fixture. +- **as** + - The fixture alias that will be used as a reference to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. ## Fixture Usage diff --git a/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md b/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md index 0842aabe730..625f9759e8e 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md +++ b/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md @@ -19,8 +19,8 @@ When the `DbIsolation` is enabled, the ITF: ``` ### Parameters - - **state** - - Enables or disables database isolation. +- **state** + - Enables or disables database isolation. ## Test class attribute diff --git a/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md b/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md index 28d04e5c40a..126b7be7439 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md +++ b/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md @@ -17,10 +17,10 @@ Sets the indexer dimension mode for the test run. ### Parameters - - **indexer** - - The name of the indexer code. - - **dimension** - - The name of the dimension mode. +- **indexer** + - The name of the indexer code. +- **dimension** + - The name of the dimension mode. ## Principles From 0291afabfdd2e0a97428914736d2cb4741b35f43 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Tue, 14 Jun 2022 11:42:17 -0500 Subject: [PATCH 181/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- .../magento-data-fixture-before-transaction.md | 12 ++++++------ .../integration/attributes/magento-db-isolation.md | 1 + .../attributes/magento-indexer-dimension-mode.md | 6 +++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md index 7a3364bc956..95f2b206419 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md @@ -17,12 +17,12 @@ Points to a class or a method which creates testing entities (fixtures) for test ### Parameters - - **type** - - The fully qualified name of a class that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. - - **data** - - The optional array of data passed on to the fixture. - - **as** - - The fixture alias that will be used as a reference to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. +- **type** + - The fully qualified name of a class that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. +- **data** + - The optional array of data passed on to the fixture. +- **as** + - The fixture alias that will be used as a reference to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. {:.bs-callout-info} Data fixture before transaction attribute is identical to Data fixture attribute. For more details, please see the [Data Fixture attribute][] page. diff --git a/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md b/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md index 625f9759e8e..2badb1f5827 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md +++ b/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md @@ -19,6 +19,7 @@ When the `DbIsolation` is enabled, the ITF: ``` ### Parameters + - **state** - Enables or disables database isolation. diff --git a/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md b/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md index 126b7be7439..54f73568694 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md +++ b/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md @@ -25,9 +25,9 @@ Sets the indexer dimension mode for the test run. ## Principles 1. You can use more than one attribute for a test case or a test method. -2. Multiple attributes are applied in the given order. -3. Attributes from different scopes are not merged. -4. A test method attribute completely overrides a test class attribute. +1. Multiple attributes are applied in the given order. +1. Attributes from different scopes are not merged. +1. A test method attribute completely overrides a test class attribute. ## Test class attribute From f75e50493136e87896db3e9a79142d94024295fa Mon Sep 17 00:00:00 2001 From: hguthrie Date: Tue, 14 Jun 2022 11:44:00 -0500 Subject: [PATCH 182/776] remove extra spaces --- src/guides/v2.3/config-guide/cli/logging.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/guides/v2.3/config-guide/cli/logging.md b/src/guides/v2.3/config-guide/cli/logging.md index 6ee8388f112..c44744fab4e 100644 --- a/src/guides/v2.3/config-guide/cli/logging.md +++ b/src/guides/v2.3/config-guide/cli/logging.md @@ -60,12 +60,11 @@ By default, Magento writes database activity logs to the `var/debug/db.log` file ```bash bin/magento dev:query-log:disable ``` - + 1. In the [production mode]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-mode.html#config-mode-show), run the command for [import configuration]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-config-mgmt-import.html), because the `bin/magento dev:query-log:disable` command adds settings to the `app/etc/env.php` file: - - ```bash - bin/magento app:config:import - ``` + + ```bash + bin/magento app:config:import 1. Flush the cache. From 902c429bffb370c927f1ea5d3f0df8f1f12c022d Mon Sep 17 00:00:00 2001 From: Jared Hoover <98363870+jhadobe@users.noreply.github.com> Date: Tue, 14 Jun 2022 11:45:13 -0500 Subject: [PATCH 183/776] Update api-security.md --- src/guides/v2.4/get-started/api-security.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/get-started/api-security.md b/src/guides/v2.4/get-started/api-security.md index f1536edf037..0092a89b63e 100644 --- a/src/guides/v2.4/get-started/api-security.md +++ b/src/guides/v2.4/get-started/api-security.md @@ -29,7 +29,7 @@ When input limiting has been enabled, the system uses the default value for each Although some simple examples for configuring these values from the CLI are provided below, all of the values can be [configured per website and per store view]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-config-mgmt-set.html#config-cli-config-set) in addition to being configurable globally. In addition, these values can also be configured [via `env.php`]({{ page.baseurl }}/config-guide/prod/config-reference-configphp.html#system) as well as via [environment variables]({{ page.baseurl }}/config-guide/deployment/pipeline/example/environment-variables.html). - +{:.bs-callout-tip} In addition, the Admin provides a configuration setting for limiting session sizes for Admin users and storefront visitors. From add00e3bcee61b5d13d5ad46a37e4d23749a6154 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Tue, 14 Jun 2022 12:13:52 -0500 Subject: [PATCH 184/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- .../v2.4/test/integration/attributes/magento-data-fixture.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md index 6557eb7a264..2c2f16d04f0 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md @@ -135,9 +135,12 @@ logic beyond the "create product" API capabilities, such logic should be impleme A fixture that contains database transactions only, are reverted automatically. Otherwise, when a fixture creates files or performs any actions other than database transaction, provide the corresponding rollback logic, -in the `revert()` method of the revertible data fixture. +in the `revert` method of the revertible data fixture. Rollbacks are run after reverting all the fixtures related to database transactions. +{:.bs-callout-info} +Please refer to [`Magento\Catalog\Test\Fixture\Product`][] fixture to see the example. + ### Restrictions Do not rely on and do not modify an application state from within a fixture, because [application isolation attribute][magentoAppIsolation] can reset the application state at any time. From 7064447456d65a5b4691e4f56d7f1bb376cde8cd Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Tue, 14 Jun 2022 14:14:27 -0500 Subject: [PATCH 185/776] fixes from closed PRs --- src/guides/v2.3/config-guide/bootstrap/mage-dirs.md | 2 +- src/guides/v2.4/config-guide/mq/manage-message-queues.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/guides/v2.3/config-guide/bootstrap/mage-dirs.md b/src/guides/v2.3/config-guide/bootstrap/mage-dirs.md index 25169e3f4c1..0307ff90006 100644 --- a/src/guides/v2.3/config-guide/bootstrap/mage-dirs.md +++ b/src/guides/v2.3/config-guide/bootstrap/mage-dirs.md @@ -34,7 +34,7 @@ You can set `MAGE_DIRS` in any of the following ways: require __DIR__ . '/app/bootstrap.php'; $params = $_SERVER; $params[Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS] = [ - DirectoryList::PUB => [DirectoryList::URL_PATH => '', + DirectoryList::PUB => [DirectoryList::URL_PATH => ''], DirectoryList::MEDIA => [DirectoryList::PATH => '/mnt/nfs/media', DirectoryList::URL_PATH => ''], DirectoryList::STATIC_VIEW => [DirectoryList::URL_PATH => 'static'], DirectoryList::UPLOAD => [DirectoryList::URL_PATH => '/mnt/nfs/media/upload'], diff --git a/src/guides/v2.4/config-guide/mq/manage-message-queues.md b/src/guides/v2.4/config-guide/mq/manage-message-queues.md index 0ed23ea6d67..88514e699fc 100644 --- a/src/guides/v2.4/config-guide/mq/manage-message-queues.md +++ b/src/guides/v2.4/config-guide/mq/manage-message-queues.md @@ -67,7 +67,7 @@ Edit the `/app/etc/env.php` file to configure the cron job `consumers_runner`. * `multiple_processes` - An array of key-value pairs specifying which consumer to run in how many processes. {:.bs-callout-info} - It is not recommended to run multiple consumers on a MySQL-operated queue. See [Change message queue from MySQL to AMQP]({{ page.baseurl }}/guides/v2.4/extension-dev-guide/message-queues/message-queues.html#change-message-queue-from-mysql-to-amqp) for more information. + It is not recommended to run multiple consumers on a MySQL-operated queue. See [Change message queue from MySQL to AMQP](https://developer.adobe.com/commerce/php/development/components/message-queues/#change-message-queue-from-mysql-to-amqp) for more information. {:.bs-callout-info} If your {{ site.data.var.ee }} store is hosted on the Cloud platform, use the [`CONSUMERS_WAIT_FOR_MAX_MESSAGES`]({{ site.baseurl }}/cloud/env/variables-deploy.html#consumers_wait_for_max_messages) to configure how consumers process messages from the message queue. From d0016829b5e18c8b54765ba7d8c92a5a87604c34 Mon Sep 17 00:00:00 2001 From: gregory-marshall Date: Tue, 14 Jun 2022 13:25:33 -0700 Subject: [PATCH 186/776] Change URLS link to link definitions --- src/cloud/cdn/cloud-fastly.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/cloud/cdn/cloud-fastly.md b/src/cloud/cdn/cloud-fastly.md index a8673ba5382..6286a2ea330 100644 --- a/src/cloud/cdn/cloud-fastly.md +++ b/src/cloud/cdn/cloud-fastly.md @@ -30,17 +30,17 @@ Fastly provides the following services to optimize and secure content delivery o - **Security**—After you set up your {{ site.data.var.ece }} project to use the Fastly CDN, additional security features are available to protect your sites and network: - - [Web Application Firewall (WAF)](https://devdocs.magento.com/cloud/cdn/fastly-waf-service.html)—Managed web application firewall service that provides PCI-compliant protection to block malicious traffic before it can damage your production {{ site.data.var.ece }} sites and network. The WAF service is available on Pro and Starter Production environments only. + - [Web Application Firewall (WAF)]—Managed web application firewall service that provides PCI-compliant protection to block malicious traffic before it can damage your production {{ site.data.var.ece }} sites and network. The WAF service is available on Pro and Starter Production environments only. - - [Distributed Denial of Service (DDoS) protection](#ddos-protection)—Built-in DDoS protection against common attacks like Ping of Death, Smurf attacks, as well as other ICMP-based floods. + - [Distributed Denial of Service (DDoS) protection](#ddos-protection)-Built-in DDoS protection against common attacks like Ping of Death, Smurf attacks, and other ICMP-based flood attacks. - - [SSL/TLS certificates]({{site.baseurl}}/cloud/cdn/configure-fastly.html#provision-ssltls-certificates)–The Fastly service requires an SSL/TLS certificate to serve secure traffic over HTTPS. {{site.data.var.ee}} provides a Domain-validated Let's Encrypt SSL/TLS certificate for each Staging and Production environment. {{site.data.var.ee}} completes domain validation and certificate provisioning during the Fastly set up process. + - [SSL/TLS certificates]–The Fastly service requires an SSL/TLS certificate to serve secure traffic over HTTPS. {{site.data.var.ee}} provides a Domain-validated Let's Encrypt SSL/TLS certificate for each Staging and Production environment. {{site.data.var.ee}} completes domain validation and certificate provisioning during the Fastly set up process. - - **Origin cloaking**–Prevents traffic from bypassing the Fastly WAF and hides the IP addresses of your origin servers to protect them from direct access and DDoS attacks. Origin cloaking is enabled by default on {{ site.data.var.ece }} Pro Production projects. To enable origin cloaking on {{ site.data.var.ece }} Starter Production projects, submit a [{{site.data.var.ee}} support ticket](https://support.magento.com/hc/en-us/articles/360019088251). If you have traffic that does not require caching, you can customize the Fastly service configuration to allow requests to [bypass the Fastly cache]({{site.baseurl}}/cloud/cdn/fastly-vcl-bypass-to-origin.html). + - **Origin cloaking**–Prevents traffic from bypassing the Fastly WAF and hides the IP addresses of your origin servers to protect them from direct access and DDoS attacks. Origin cloaking is enabled by default on {{ site.data.var.ece }} Pro Production projects. To enable origin cloaking on {{ site.data.var.ece }} Starter Production projects, submit a [{{site.data.var.ee}} support ticket]. If you have traffic that does not require caching, you can customize the Fastly service configuration to allow requests to [bypass the Fastly cache]. -- [Image optimization]({{site.baseurl}}/cloud/cdn/fastly-image-optimization.html)—Offloads image processing and resizing load to the Fastly service freeing servers to process orders and conversions efficiently. +- [Image optimization]-Offloads image processing and resizing load to the Fastly service freeing servers to process orders and conversions efficiently. -- **Fastly CDN and WAF logs**–For {{ site.data.var.ece }} Pro projects, you can use the New Relic Logs service to review and analyze Fastly CDN and WAF log data. See [New Relic](https://devdocs.magento.com/cloud/project/new-relic.html#new-relic-logs). +- [Fastly CDN and WAF logs]-For {{ site.data.var.ece }} Pro projects, you can use the New Relic Logs service to review and analyze Fastly CDN and WAF log data. ## Fastly CDN module for Magento 2 @@ -124,12 +124,13 @@ DDOS protection is built-in to the Fastly CDN service. After you enable and conf [How to block malicious traffic]: https://support.magento.com/hc/en-us/articles/360039447892-How-to-block-malicious-traffic-for-Magento-Commerce-Cloud-on-Fastly-level [{{site.data.var.ee}} support ticket]: https://support.magento.com/hc/en-us/articles/360019088251 [New Relic]: {{site.baseurl}}/cloud/project/new-relic.html +[Fastly CDN and WAF logs]: {{site.baseurl}}/cloud/project/new-relic.html#new-relic-logs [Project Web UI environment configuration variables]: {{site.baseurl}}/cloud/project/projects.html#environment-configuration-variables [purge options]: {{site.baseurl}}/cloud/cdn/configure-fastly-customize-cache.html#configure-purge-options [set up Fastly]: {{site.baseurl}}/cloud/cdn/configure-fastly.html [Test the new credential]: {{site.baseurl}}/cloud/cdn/configure-fastly.html#test-the-fastly-credentials -[TLS and Fastly]: {{site.baseurl}}/cloud/cdn/configure-fastly.html#provision-ssltls-certificates +[SSL/TLS certificates]: {{site.baseurl}}/cloud/cdn/configure-fastly.html#provision-ssltls-certificates [Upgrade Fastly]: {{site.baseurl}}/cloud/cdn/configure-fastly.html#upgrade -[Web Application Firewall]: {{site.baseurl}}/cloud/cdn/fastly-waf-service.html +[Web Application Firewall (WAF)]: {{site.baseurl}}/cloud/cdn/fastly-waf-service.html [Working with Domains]: https://docs.fastly.com/en/guides/working-with-domains [test the Fastly credentials]: {{site.baseurl}}/cloud/cdn/configure-fastly.html#test-the-fastly-credentials From 99c10483a1d583e09bb35b2e5fd4d382704ea503 Mon Sep 17 00:00:00 2001 From: Kyrylo Peretiatko Date: Wed, 15 Jun 2022 11:19:25 +0300 Subject: [PATCH 187/776] Retrieved lost closing quotes --- src/guides/v2.3/config-guide/cli/logging.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/guides/v2.3/config-guide/cli/logging.md b/src/guides/v2.3/config-guide/cli/logging.md index c44744fab4e..0536c500dc8 100644 --- a/src/guides/v2.3/config-guide/cli/logging.md +++ b/src/guides/v2.3/config-guide/cli/logging.md @@ -65,6 +65,7 @@ By default, Magento writes database activity logs to the `var/debug/db.log` file ```bash bin/magento app:config:import + ``` 1. Flush the cache. From 4c8d1369ebbe9319332cffdd9c57b5809771f17e Mon Sep 17 00:00:00 2001 From: Thiaramus Date: Wed, 15 Jun 2022 08:21:17 -0500 Subject: [PATCH 188/776] Apply suggestions from code review Co-authored-by: Buba Soumah --- ...magento-data-fixture-before-transaction.md | 22 ++++++++++++++++--- .../attributes/magento-data-fixture.md | 4 ++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md index 95f2b206419..4ff92b4ed78 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md @@ -5,7 +5,7 @@ title: Data fixture before transaction attribute ## Overview -Points to a class or a method which creates testing entities (fixtures) for test execution before the transaction has begun. You will need to implement a rollback method changes made here. +Data fixture before transaction attribute is an extension of [Data Fixture attribute][] that applies fixtures before the transaction and reverts applied fixtures after the transaction. With disabled Db isolation, this attribute is identical to [Data Fixture attribute][] ## Format @@ -24,9 +24,25 @@ Points to a class or a method which creates testing entities (fixtures) for test - **as** - The fixture alias that will be used as a reference to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. -{:.bs-callout-info} -Data fixture before transaction attribute is identical to Data fixture attribute. For more details, please see the [Data Fixture attribute][] page. +### Example +In the following example, we fixtures supplied to `DataFixtureBeforeTransaction` attribute are applied before the transaction whereas fixtures supplied to `DataFixture` attribute are applied within the transaction + +```php?start_inline=1 +class CategoryTest extends TestCase +{ + #[ + DataFixtureBeforeTransaction(ScheduleMode::class, ['indexer' => 'catalog_category_product']), + DataFixtureBeforeTransaction(ScheduleMode::class, ['indexer' => 'catalog_product_category']), + DataFixture(Category::class, as: 'category'), + DataFixture(Product::class, ['category_ids' => ['$category.id$']], 'product1'), + DataFixture(Product::class, ['category_ids' => ['$category.id$']], 'product2'), + ] + public function testUpdateProductsPositionsWithIndexerOnSchedule(): void + { + + } +} [Data Fixture attribute]: {{ page.baseurl }}/test/integration/attributes/magento-data-fixture.html diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md index 2c2f16d04f0..ea5cf7ae370 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md @@ -25,7 +25,7 @@ To set up a date fixture, use the `DataFixture` attribute. ### Parameters - **type** - - The fully qualified name of a class that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. + - Name of a class that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. - **data** - The optional array of data passed on to the fixture. - **as** @@ -93,7 +93,7 @@ The basic rules for fixture attribute at different levels are: The integration testing framework interacts with a database to revert the applied fixtures. ## Creating the fixture - +Data Fixture is a PHP class that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. Its main purpose is to seed the database with the data needed to run a test. ### Principles 1. Data Fixture class MUST implement `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface` if the data created by the fixture is revertible. For instance, a fixture that creates an entity (for example, product). From 9a407c3b4abc695dba7251982db1ab8c5178cba6 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Wed, 15 Jun 2022 08:26:17 -0500 Subject: [PATCH 189/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- .../attributes/magento-data-fixture-before-transaction.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md index 4ff92b4ed78..6b688197930 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md @@ -43,6 +43,8 @@ class CategoryTest extends TestCase } } +``` + [Data Fixture attribute]: {{ page.baseurl }}/test/integration/attributes/magento-data-fixture.html From b01d153d6017bdaf58df4cd9e94854824e704043 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Wed, 15 Jun 2022 08:47:02 -0500 Subject: [PATCH 190/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- .../v2.4/test/integration/attributes/magento-data-fixture.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md index ea5cf7ae370..3ee6ceb18e4 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md @@ -93,7 +93,9 @@ The basic rules for fixture attribute at different levels are: The integration testing framework interacts with a database to revert the applied fixtures. ## Creating the fixture + Data Fixture is a PHP class that implements `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. Its main purpose is to seed the database with the data needed to run a test. + ### Principles 1. Data Fixture class MUST implement `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface` if the data created by the fixture is revertible. For instance, a fixture that creates an entity (for example, product). From 19b2aac8d057da7ffa7684a54c7fc8fa2d5bbbc4 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Wed, 15 Jun 2022 09:12:05 -0500 Subject: [PATCH 191/776] ACP2E-910: Update the documentation with new PHP8 Attributes features in integration tests annotations --- .../v2.4/test/integration/attributes/magento-data-fixture.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md index 3ee6ceb18e4..cba51a98de3 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md @@ -8,9 +8,10 @@ redirect_from: ## Overview -Data fixture is a dynamic and scalable data fixture that accepts parameters directly from the fixture declaration. It eliminates the need to create almost identical fixtures every time you need a slight change. +Data fixture attribute applies fixtures that implement `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. +It takes two more optional parameters alongside the fixture class name. +The second parameter is the data that is used to customize the fixture and the third parameter is the alias (ID) of the fixture that is used to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. -A data fixture is a PHP script that sets data you want to reuse in your test. Use data fixtures to prepare a database for tests. The Integration Testing Framework (ITF) reverts the database to its initial state automatically. To set up a date fixture, use the `DataFixture` attribute. From c26f09cafb51882435f429688ccad14f0e7d1a31 Mon Sep 17 00:00:00 2001 From: Kevin Harper Date: Wed, 15 Jun 2022 11:00:15 -0500 Subject: [PATCH 192/776] Review comments --- src/guides/v2.4/graphql/authorization-tokens.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/guides/v2.4/graphql/authorization-tokens.md b/src/guides/v2.4/graphql/authorization-tokens.md index 0e80070e4c3..7d9324155ee 100644 --- a/src/guides/v2.4/graphql/authorization-tokens.md +++ b/src/guides/v2.4/graphql/authorization-tokens.md @@ -13,13 +13,13 @@ Adobe Commerce and Magento Open Source provide two mechanisms for authorizing Gr * **Session cookies**. A session cookie is information generated by Commerce that is stored in the client's browser. It contains details about the session, including the time period the user can access resources. Cookies are stateful, thereby increasing complexity and possibly latency. -Adobe recommends that you use authorization tokens instead of session cookies for GraphQL requests. By default, session cookies are enabled. As of Commerce 2.4.5, you can disable session cookies, eliminating the chances of encountering problems caused by the differences between the two authorization methods. However, merchants with existing implementations that rely on cookies can continue using this method. [Session cookies](#Session-cookies) describes how to enable or disable cookies for GraphQL. +Adobe recommends that you use authorization tokens instead of session cookies for GraphQL requests. By default, session cookies are enabled. As of Commerce 2.4.5, you can disable session cookies, eliminating the chances of encountering problems caused by the differences between the two authorization methods. However, merchants with existing implementations that rely on cookies can continue using this method. [Session cookies](#Session-cookies) describes how to enable or disable cookies for GraphQL. ## Authorization tokens Adobe Commerce provides separate token services for customers and administrators. When you request a token from one of these services, the service returns a unique access token in exchange for the account's username and password. -GraphQL provides a mutation that returns a token on behalf of a logged-in customer. You must use a REST call to fetch an admin token. Use this token in the Authorization request header field for any queries and mutations. See [Request headers]({{page.baseurl}}/graphql/send-request.html#headers) +GraphQL provides a mutation that returns a token on behalf of a logged-in customer, but you must use a REST call to fetch an admin token. Any time you make a GraphQL or REST call that requires a token, specify the HTTP `Authorization` request header and assign the value as `Bearer `. [Request headers]({{page.baseurl}}/graphql/send-request.html#headers) provides an example. ### Customer tokens @@ -53,7 +53,7 @@ You can now use this token in the Authorization request header field for any que ![GraphQL Authorization Bearer]({{site.baseurl}}/common/images/graphql/graphql-authorization.png) -If necessary, you also can [revoke the customer's token]({{ page.baseurl }}/graphql/mutations/revoke-customer-token.html). +You can also [revoke the customer's token]({{ page.baseurl }}/graphql/mutations/revoke-customer-token.html) when the customer logs out or changes their password. The [`generateCustomerTokenAsAdmin`]({{page.baseurl}}/graphql/mutations/generate-customer-token-as-admin.html) mutation generates a new customer token as an admin so that an administrator can perform remote shopping assistance. The customer must have enabled the `allow_remote_shopping_assistance` feature while creating the customer profile. The mutation requires the customer email address in the payload, as shown in the following example. @@ -92,9 +92,11 @@ By default, an admin token is valid for 4 hours. You can change these values fro ## Session cookies -The client's browser will use a session cookie if the server provides one. Prior to version 2.4.5, Commerce automatically provided these cookies, even if an authorization token was specified. +The client's browser will use a session cookie if the server provides one. Prior to version 2.4.5, Commerce automatically provides/generated as session cookie even if an authorization token was specified. -Multi-page applications that make GraphQL calls can continue implementing these cookies without changing the default setting. However, most merchants should disable these cookies. As a result, Commerce will be fast more secure. In addition, disabling cookies will prevent a situation in which unnecessary sessions locking HTTP GET requests. +Browser-based applications that make GraphQL calls can continue implementing these cookies without changing the default setting. If you use cookies, avoid specifying Authorization headers to prevent problems caused by using two different authorization methods. + +Adobe recommends that apps should be implemented without cookies. In this case, you should configure GraphQL so that the server doesn't generate them. Disabling cookies also prevents the system file locks and racing conditions on server resources. These problems cause slower HTTP GET requests throughputs under peak traffic conditions. Run the following command to disable session cookies for GraphQL: From b5a549feb7df5cd2c6f58ae06dc95734158b85af Mon Sep 17 00:00:00 2001 From: Thiaramus Date: Wed, 15 Jun 2022 12:05:49 -0500 Subject: [PATCH 193/776] Apply suggestions from code review Co-authored-by: Jeff Matthews --- .../v2.4/test/integration/annotations.md | 2 +- .../v2.4/test/integration/attributes.md | 20 ++++++++-------- .../attributes/magento-app-area.md | 4 ++-- .../attributes/magento-app-isolation.md | 6 ++--- .../integration/attributes/magento-cache.md | 6 ++--- .../attributes/magento-components-dir.md | 10 ++++---- .../attributes/magento-config-fixture.md | 6 ++--- ...magento-data-fixture-before-transaction.md | 4 ++-- .../attributes/magento-data-fixture.md | 24 +++++++++---------- .../attributes/magento-db-isolation.md | 10 ++++---- .../magento-indexer-dimension-mode.md | 4 ++-- 11 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/guides/v2.4/test/integration/annotations.md b/src/guides/v2.4/test/integration/annotations.md index 6e001d5efa2..507885b66a4 100644 --- a/src/guides/v2.4/test/integration/annotations.md +++ b/src/guides/v2.4/test/integration/annotations.md @@ -7,7 +7,7 @@ DocBlock annotations help to declare context in your code. In addition to built- , the Integration testing framework provides custom annotations described in this topic. {:.bs-callout-info} -Native PHP8 Attributes can be used instead or together with DocBlock annotations. This new method offers more flexibility and improve readability of the code. See the [Attributes section][] to find out more. This feature is currently only available for Magento Open Source contributors. It will be released for general use with Magento Open Source 2.4.5. +Native PHP8 Attributes can be used instead or together with DocBlock annotations. This new method offers more flexibility and improves readability of the code. See the [Attributes][] to learn more. This feature is currently only available for {{site.data.var.ce}} contributors. It will be released for general use with {{site.data.var.ce}} 2.4.5. ### Quick overview diff --git a/src/guides/v2.4/test/integration/attributes.md b/src/guides/v2.4/test/integration/attributes.md index 19882e9484c..3288dd35bcc 100644 --- a/src/guides/v2.4/test/integration/attributes.md +++ b/src/guides/v2.4/test/integration/attributes.md @@ -6,8 +6,8 @@ title: Using PHP built-in attributes [PHP built-in attributes][] help to declare context in your code. Attributes can be used alone or together with Annotations to help to declare context in your code. {:.bs-callout-info} -Using PHP built-in attributes is available now for the developers, and will be publicly available with Magento 2.4.5 release. -[PHPUnit annotations][] are still available for use with Magento. +PHP built-in attributes are currently available to {{site.data.var.ce}} contributors only. They will be released for general use with {{site.data.var.ce}} 2.4.5. +[PHPUnit annotations][] are still available for use with {{site.data.var.ce}}. ## Quick overview @@ -15,19 +15,19 @@ The following attributes are available in integration tests: | Name | Attribute | Description | |---------------------------------|----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Application Isolation | [AppIsolation][] | Enables or disables application isolation when you run tests. When enabled, an application state after a test run will be the same as before the test run. For example, you should enable it, when you want to create sessions in a test, but you don't want them to affect other tests. | -| Configuration Fixture | [Config][] | Sets up configuration settings for a particular test. The list of settings is stored in the `core_config_data` database table. Multiple configuration parameters can be set with a signle command. After the test execution, the settings revert to their original state. | -| Database Isolation | [DbIsolation][] | Enables or disables database isolation. Disabled by default, unless you are using `DataFixture()` attribute, in which case it is enabled by default. All data, required for a test, live during transaction only. Any test results won't be written in a database. | -| Data Fixture | [DataFixture][] | Points to a class or a method which creates testing entities (fixtures) for test execution. These are applied during the transaction. | -| Data Fixture Before Transaction | [DataFixtureBeforeTransaction][] | Points to a class or a method which creates testing entities (fixtures) for test execution before the transaction has begun. You will need to implement a rollback method changes made here. | +| Application Isolation | [AppIsolation][] | Enables or disables application isolation when you run tests. When enabled, an application state after a test run will be the same as before the test run. For example, you should enable it when you want to create sessions in a test, but you don't want them to affect other tests. | +| Configuration Fixture | [Config][] | Sets up configuration settings for a particular test. The list of settings is stored in the `core_config_data` database table. Multiple configuration parameters can be set with a single command. After test execution, the settings revert to their original state. | +| Database Isolation | [DbIsolation][] | Enables or disables database isolation. Disabled by default, unless you are using the `DataFixture()` attribute, in which case it is enabled by default. All data required for a test live during transaction only. Test results won't be written to the database. | +| Data Fixture | [DataFixture][] | Points to a class or a method that creates testing entities (fixtures) for test execution. These are applied during the transaction. | +| Data Fixture Before Transaction | [DataFixtureBeforeTransaction][] | Points to a class or a method that creates testing entities (fixtures) for test execution before the transaction begins. You must implement a rollback method for changes made here. | | Application Area | [AppArea][] | Configures test environment in the context of specified application area. | -| Enable/Disable Cache | [Cache][] | Enables or disables certain cache segment or all of them to prevent isolation problems. | +| Enable/Disable Cache | [Cache][] | Enables or disables certain cache segment (or all of them) to prevent isolation problems. | | Indexer Dimension Mode | [IndexerDimensionMode][] | Sets the indexer dimension mode for the test run. More information can be found in the [DevBlog](https://community.magento.com/t5/Magento-DevBlog/Indexers-parallelization-and-optimization/ba-p/104922). | -| Register Components | [ComponentsDir][] | Registers fixture components from specified directory (recursively). Unregisters the components after the test is finished. | +| Register Components | [ComponentsDir][] | Registers fixture components from the specified directory (recursively). Unregisters the components after the test is finished. | ## Applying annotations -The Magento-specific annotations for integration tests are applied in the following order: +The application-specific annotations for integration tests are applied in the following order: 1. `AppIsolation` 1. `DbIsolation` diff --git a/src/guides/v2.4/test/integration/attributes/magento-app-area.md b/src/guides/v2.4/test/integration/attributes/magento-app-area.md index 1835e5fe714..c0edd10056e 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-app-area.md +++ b/src/guides/v2.4/test/integration/attributes/magento-app-area.md @@ -36,7 +36,7 @@ Configure a test environment in scope of the particular [application area][] wit A test class attribute enables the specified application area for all tests in the test class. {:.bs-callout-info} -Test class attribute override test method attribute. +Test class attributes override test method attributes. Example: @@ -72,7 +72,7 @@ class ClassToTest extends \PHPUnit\Framework\TestCase ## Test method attribute A test method attribute is used to configure the environment in scope of the specified application area for the test method. -Magento is reinitialized in the corresponding scope each time you specify a different area. +The application is reinitialized in the corresponding scope each time you specify a different area. Example: diff --git a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md index cd8ce145b64..303727dd78a 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md +++ b/src/guides/v2.4/test/integration/attributes/magento-app-isolation.md @@ -67,10 +67,10 @@ Default values for the `AppIsolation` attribute: `AppIsolation` cannot be disabled at the test class level. -You can use non-isolated tests unless they do not modify or utilize the same application areas such as: +You can use non-isolated tests unless they do not modify or utilize the same application areas, such as: -- same attributes of an application object. -- same paths in a current configuration or current scope (for example "store"). +- Same attributes of an application object. +- Same paths in a current configuration or current scope (for example "store"). {:.bs-callout-tip} Set up application isolation if any application objects were intentionally modified within the test class. \ No newline at end of file diff --git a/src/guides/v2.4/test/integration/attributes/magento-cache.md b/src/guides/v2.4/test/integration/attributes/magento-cache.md index 39e39f4b353..c778e7e4838 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-cache.md +++ b/src/guides/v2.4/test/integration/attributes/magento-cache.md @@ -30,11 +30,11 @@ Enable or disable a [cache type][] using the `Cache` attribute. ## Test class attribute -`Cache` attribute at the test case level is applied to all tests. +The `Cache` attribute at the test case level is applied to all tests. ## Test method attribute -`Cache` attribute at a test method level configures the test method only. +The `Cache` attribute at a test method level configures the test method only. It completely overrides the attribute specified for the test class. ## Example @@ -86,7 +86,7 @@ class BarTest extends \PHPUnit\Framework\TestCase - `testOne()` is run with all cache types enabled. - `testTwo()` is run with all cache types disabled. - The `Cache('config', false)` completely overrides the test method attribute. The test method attribute wasn't applied in this case. By default, all cache types are disabled. Thus disabling any attributes does not make much sense here. + The `Cache('config', false)` completely overrides the test method attribute. The test method attribute wasn't applied in this case. By default, all cache types are disabled, so disabling attributes does not make much sense here. - `testThree()` is run with all but `config` cache type enabled. - `testFour()` is run with all the cache types enabled. diff --git a/src/guides/v2.4/test/integration/attributes/magento-components-dir.md b/src/guides/v2.4/test/integration/attributes/magento-components-dir.md index ef9d630a26e..d76c88aa19d 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-components-dir.md +++ b/src/guides/v2.4/test/integration/attributes/magento-components-dir.md @@ -3,7 +3,7 @@ group: testing title: Component registration attribute --- -When your test design requires to register fixture components and unregister them after the test execution, use the `ComponentsDir` attribute. +When your test design requires you to register fixture components and unregister them after the test execution, use the `ComponentsDir` attribute. It enables you to register all the components at a specified directory recursively. ## Format @@ -26,11 +26,11 @@ It enables you to register all the components at a specified directory recursive ## Test method attribute `ComponentsDir` attribute for a test method configures the test to run with registered components located in a specified directory. -If the parent test case also declares a `ComponentsDir`, both attribute are merged. +If the parent test case also declares a `ComponentsDir`, both attributes are merged. ## Example -The following example demonstrates `ComponentsDir` attribute in different scopes. +The following example demonstrates the `ComponentsDir` attribute in different scopes. ```php?start_inline=1 namespace Magento\Foo; @@ -58,7 +58,7 @@ class BarTest extends \PHPUnit\Framework\TestCase } ``` -Each path declared in attribute must contain a registration file in the specified directory or its subdirectories. +Each path declared in an attribute must contain a registration file in the specified directory or its subdirectories. For example, the `MagentoFooTest_MyModule` component at `ComponentsDir('Magento/Foo/_files/code/Magento')` can be registered in `Magento/Foo/_files/code/Magento/MyModule/registration.php`: ```php?start_inline=1 @@ -72,7 +72,7 @@ use Magento\Framework\Component\ComponentRegistrar; ); ``` - {:.bs-callout-info} +{:.bs-callout-info} A theme must be registered in the database. Each time you register a theme, reset the entire application. Use the [`DbIsolation`][] attribute to keep the database integrity safe. diff --git a/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md index 688a8f4b82e..926498d9ec9 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-config-fixture.md @@ -3,7 +3,7 @@ group: testing title: Configuration fixture attribute --- -To set Magento configuration values for individual tests and revert them after the test execution, use the `Config` attribute. +To set configuration values for individual tests and revert them after the test execution, use the `Config` attribute. ## Format @@ -20,9 +20,9 @@ To set Magento configuration values for individual tests and revert them after t - **value** - A fixture value for the configuration option. - **scopeType** - - The scope to use to set config value. Allowed values: default, store, group and website. Default value: default. + - The scope to use to set configuration value. Allowed values: default, store, group and website. Default value: default. - **scopeValue** - - The code of the scope to be configured. If "default" scope is provided, this parameter can be omitted. If the scope type is store, group or website, the default value of this parameter is the current value of the specified scope. + - The code of the scope to be configured. If "default" scope is provided, this parameter can be omitted. If the scope type is store, group, or website, the default value of this parameter is the current value of the specified scope. ## Principles diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md index 6b688197930..c7594088f88 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture-before-transaction.md @@ -5,7 +5,7 @@ title: Data fixture before transaction attribute ## Overview -Data fixture before transaction attribute is an extension of [Data Fixture attribute][] that applies fixtures before the transaction and reverts applied fixtures after the transaction. With disabled Db isolation, this attribute is identical to [Data Fixture attribute][] +The data fixture before transaction attribute is an extension of [Data Fixture attribute][] that applies fixtures before the transaction and reverts applied fixtures after the transaction. With disabled DB isolation, this attribute is identical to the [Data Fixture attribute][] ## Format @@ -26,7 +26,7 @@ Data fixture before transaction attribute is an extension of [Data Fixture attri ### Example -In the following example, we fixtures supplied to `DataFixtureBeforeTransaction` attribute are applied before the transaction whereas fixtures supplied to `DataFixture` attribute are applied within the transaction +In the following example, the fixtures supplied to the `DataFixtureBeforeTransaction` attribute are applied before the transaction, whereas fixtures supplied to the `DataFixture` attribute are applied within the transaction. ```php?start_inline=1 class CategoryTest extends TestCase diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md index cba51a98de3..e283630c102 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md @@ -8,9 +8,9 @@ redirect_from: ## Overview -Data fixture attribute applies fixtures that implement `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. +Data fixture attributes apply fixtures that implement `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface`. It takes two more optional parameters alongside the fixture class name. -The second parameter is the data that is used to customize the fixture and the third parameter is the alias (ID) of the fixture that is used to retrieve the data returned by the fixture and also as a reference in other fixtures parameters. +The second parameter is the data that is used to customize the fixture and the third parameter is the alias (ID) of the fixture that is used to retrieve the data returned by the fixture and also as a reference in other fixture parameters. Use data fixtures to prepare a database for tests. The Integration Testing Framework (ITF) reverts the database to its initial state automatically. To set up a date fixture, use the `DataFixture` attribute. @@ -83,11 +83,11 @@ class QuoteTest extends \PHPUnit\Framework\TestCase ### Test class and test method scopes The `DataFixture` can be specified for a particular test or for an entire test case. -The basic rules for fixture attribute at different levels are: +The basic rules for fixture attributes at different levels are: -- `DataFixture` at a test case level, makes the framework to apply the declared fixtures to each test in the test case. +- `DataFixture` at a test case level makes the framework apply the declared fixtures to each test in the test case. When the final test is complete, all class-level fixtures are reverted. -- `DataFixture` for a particular test, signals the framework to revert the fixtures declared on a test case level and applies the fixtures declared at a test method level instead. +- `DataFixture` for a particular test signals the framework to revert the fixtures declared on a test case level and applies the fixtures declared at a test method level instead. When the test is complete, the ITF reverts the applied fixtures. {:.bs-callout-info} @@ -102,14 +102,14 @@ Data Fixture is a PHP class that implements `Magento\TestFramework\Fixture\DataF 1. Data Fixture class MUST implement `Magento\TestFramework\Fixture\DataFixtureInterface` or `Magento\TestFramework\Fixture\RevertibleDataFixtureInterface` if the data created by the fixture is revertible. For instance, a fixture that creates an entity (for example, product). 1. Data Fixture class MUST be placed in the `/Test/Fixture` folder of the corresponding module with namespace: `\\Test\Fixture` (for example, `Magento\Catalog\Test\Fixture`). 1. Data Fixture class SHOULD follow single responsibility principle. -1. Data Fixture class MUST depend only on services from modules that are declared in the `require` section of its module's composer.json. +1. Data Fixture class MUST depend only on services from modules that are declared in the `require` section of its module's composer.json file. 1. Data Fixture MUST NOT depend on another fixture. 1. Data Fixture SHOULD be implemented using service APIs. 1. Data Fixture SHOULD have dynamic default data to allow generating unique fixtures. ### Dynamic default data -In order to generate multiple fixtures of the same type without having to manually configure unique fields, you can use the placeholder `%uniqid%` in the default value of unique fields and `Magento\TestFramework\Fixture\Data\ProcessorInterface` to substitute the placeholder with unique sequence. +In order to generate multiple fixtures of the same type without having to manually configure unique fields, you can use the placeholder `%uniqid%` in the default value of unique fields and `Magento\TestFramework\Fixture\Data\ProcessorInterface` to substitute the placeholder with a unique sequence. [`Magento\Catalog\Test\Fixture\Product`][] demonstrates the usage of `%uniqid%` (`sku`: `simple-product%uniqid%`) in the fixture default data. @@ -131,22 +131,22 @@ class ProductsListTest extends \PHPUnit\Framework\TestCase ### Decoupling fixtures Fixtures must be written in the way that they only use one API to generate data. For example, the fixture that creates -a product should only invoke "Create Product" API and return the product created. This fixture should not add any extra +a product should only invoke the "Create Product" API and return the product created. This fixture should not add any extra logic beyond the "create product" API capabilities, such logic should be implemented in a separate fixture. ### Fixture rollback -A fixture that contains database transactions only, are reverted automatically. -Otherwise, when a fixture creates files or performs any actions other than database transaction, provide the corresponding rollback logic, +A fixture that contains database transactions only are reverted automatically. +Otherwise, when a fixture creates files or performs any actions other than a database transaction, provide the corresponding rollback logic, in the `revert` method of the revertible data fixture. Rollbacks are run after reverting all the fixtures related to database transactions. {:.bs-callout-info} -Please refer to [`Magento\Catalog\Test\Fixture\Product`][] fixture to see the example. +See the [`Magento\Catalog\Test\Fixture\Product`][] fixture for an example. ### Restrictions -Do not rely on and do not modify an application state from within a fixture, because [application isolation attribute][magentoAppIsolation] can reset the application state at any time. +Do not rely on and do not modify an application state from within a fixture. The [application isolation attribute][magentoAppIsolation] can reset the application state at any time. diff --git a/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md b/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md index 2badb1f5827..fbb6df98e82 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md +++ b/src/guides/v2.4/test/integration/attributes/magento-db-isolation.md @@ -4,11 +4,11 @@ title: Database isolation attribute --- To isolate database changes between tests, the Integration testing framework (ITF) implements the `DbIsolation` attribute. -When the `DbIsolation` is enabled, the ITF: +When the `DbIsolation` attribute is enabled, the ITF: -- starts a database transaction before the test/test case. -- avoids a database commit during the test/test case. -- restores the database after the test/test case. +- Starts a database transaction before the test/test case. +- Avoids a database commit during the test/test case. +- Restores the database after the test/test case. ## Format @@ -74,7 +74,7 @@ class Some\EntityTest extends \PHPUnit\Framework\TestCase ## Test method attribute -To isolate changes made to database by a single test, enable the `DbIsolation` for the test method. +To isolate changes made to the database by a single test, enable the `DbIsolation` attribute for the test method. ```php?start_inline=1 #[ diff --git a/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md b/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md index 54f73568694..bbd25d1f650 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md +++ b/src/guides/v2.4/test/integration/attributes/magento-indexer-dimension-mode.md @@ -31,11 +31,11 @@ Sets the indexer dimension mode for the test run. ## Test class attribute -`IndexerDimensionMode` attribute at the test case level is applied to all tests. +An `IndexerDimensionMode` attribute at the test case level is applied to all tests. ## Test method attribute -`IndexerDimensionMode` attribute at a test method level configures the test method only. +An `IndexerDimensionMode` attribute at the test method level configures the test method only. It completely overrides the attribute specified for the test class. ## Example From 86e8cb36b23098162f980d85123358f94e38f159 Mon Sep 17 00:00:00 2001 From: Kevin Harper Date: Wed, 15 Jun 2022 15:01:17 -0500 Subject: [PATCH 194/776] Editorial updates --- src/guides/v2.4/graphql/authorization-tokens.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/guides/v2.4/graphql/authorization-tokens.md b/src/guides/v2.4/graphql/authorization-tokens.md index 7d9324155ee..fb291064aa4 100644 --- a/src/guides/v2.4/graphql/authorization-tokens.md +++ b/src/guides/v2.4/graphql/authorization-tokens.md @@ -9,7 +9,7 @@ redirect_from: Adobe Commerce and Magento Open Source provide two mechanisms for authorizing GraphQL calls: -* **Authorization tokens**. Commerce generates a JSON Web Token (JWT), a set of cryptographically signed credentials. All calls that perform an action on behalf of a logged-in customer or admin provide an authorization token. Authorization tokens are stateless. Commerce does not need to know the state of a client to execute a request--the token contains all of the information needed for authorization. +* **Authorization tokens**. Commerce generates a JSON Web Token (JWT), a set of cryptographically signed credentials. All calls that perform an action on behalf of a logged-in customer orgi admin provide an authorization token. Authorization tokens are stateless. Commerce does not need to know the state of a client to execute a request--the token contains all of the information needed for authorization. * **Session cookies**. A session cookie is information generated by Commerce that is stored in the client's browser. It contains details about the session, including the time period the user can access resources. Cookies are stateful, thereby increasing complexity and possibly latency. @@ -92,11 +92,11 @@ By default, an admin token is valid for 4 hours. You can change these values fro ## Session cookies -The client's browser will use a session cookie if the server provides one. Prior to version 2.4.5, Commerce automatically provides/generated as session cookie even if an authorization token was specified. +The client's browser will use a session cookie if the server provides one. Prior to version 2.4.5, Commerce automatically generated session cookies even if an authorization token was specified. Browser-based applications that make GraphQL calls can continue implementing these cookies without changing the default setting. If you use cookies, avoid specifying Authorization headers to prevent problems caused by using two different authorization methods. -Adobe recommends that apps should be implemented without cookies. In this case, you should configure GraphQL so that the server doesn't generate them. Disabling cookies also prevents the system file locks and racing conditions on server resources. These problems cause slower HTTP GET requests throughputs under peak traffic conditions. +Adobe recommends that you do not use session cookies when developing a Commerce-based application. If you adhere to this best practice, you should configure GraphQL so that the server doesn't generate them. Disabling cookies also prevents the system file locks and racing conditions on server resources. These problems cause slower HTTP GET request throughputs under peak traffic conditions. Run the following command to disable session cookies for GraphQL: From c34a646979baac5328fe05658ad94636e485a5f7 Mon Sep 17 00:00:00 2001 From: Leslie Tilling Date: Wed, 15 Jun 2022 13:11:16 -0700 Subject: [PATCH 195/776] Redirects for B2B guide topics Install and release notes are moved to the ExL guide --- src/extensions/b2b/index.md | 2 ++ src/guides/v2.4/release-notes/b2b-release-notes.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/extensions/b2b/index.md b/src/extensions/b2b/index.md index 5dfbb1631c0..8f1ee7d2efc 100644 --- a/src/extensions/b2b/index.md +++ b/src/extensions/b2b/index.md @@ -4,6 +4,8 @@ title: Install B2B ee_only: true redirect_from: - guides/v2.3/comp-mgr/install-extensions/b2b-installation.html +migrated_to: https://experienceleague.adobe.com/docs/commerce-admin/b2b/install.html +layout: migrated --- {:.bs-callout-warning} diff --git a/src/guides/v2.4/release-notes/b2b-release-notes.md b/src/guides/v2.4/release-notes/b2b-release-notes.md index 6c786d046c9..6e76a1c5d07 100644 --- a/src/guides/v2.4/release-notes/b2b-release-notes.md +++ b/src/guides/v2.4/release-notes/b2b-release-notes.md @@ -1,6 +1,8 @@ --- group: release-notes title: Commerce B2B Release Notes +migrated_to: https://experienceleague.adobe.com/docs/commerce-admin/b2b/release-notes.html +layout: migrated --- The release notes for the B2B extension captures additions and bug fixes that Magento has added during a release cycle. From 370c9cd082c60cf1048d75c03998d6568e929487 Mon Sep 17 00:00:00 2001 From: gregory-marshall Date: Wed, 15 Jun 2022 16:33:18 -0700 Subject: [PATCH 196/776] Fix hyphen inconsistencies, misc editorial --- src/cloud/cdn/cloud-fastly.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cloud/cdn/cloud-fastly.md b/src/cloud/cdn/cloud-fastly.md index 6286a2ea330..bba630f7f59 100644 --- a/src/cloud/cdn/cloud-fastly.md +++ b/src/cloud/cdn/cloud-fastly.md @@ -32,15 +32,15 @@ Fastly provides the following services to optimize and secure content delivery o - [Web Application Firewall (WAF)]—Managed web application firewall service that provides PCI-compliant protection to block malicious traffic before it can damage your production {{ site.data.var.ece }} sites and network. The WAF service is available on Pro and Starter Production environments only. - - [Distributed Denial of Service (DDoS) protection](#ddos-protection)-Built-in DDoS protection against common attacks like Ping of Death, Smurf attacks, and other ICMP-based flood attacks. + - [Distributed Denial of Service (DDoS) protection](#ddos-protection)—Built-in DDoS protection against common attacks like Ping of Death, Smurf attacks, and other ICMP-based flood attacks. - - [SSL/TLS certificates]–The Fastly service requires an SSL/TLS certificate to serve secure traffic over HTTPS. {{site.data.var.ee}} provides a Domain-validated Let's Encrypt SSL/TLS certificate for each Staging and Production environment. {{site.data.var.ee}} completes domain validation and certificate provisioning during the Fastly set up process. + - [SSL/TLS certificates]—The Fastly service requires an SSL/TLS certificate to serve secure traffic over HTTPS. {{site.data.var.ee}} provides a Domain-validated Let's Encrypt SSL/TLS certificate for each Staging and Production environment. {{site.data.var.ee}} completes domain validation and certificate provisioning during the Fastly set up process. - - **Origin cloaking**–Prevents traffic from bypassing the Fastly WAF and hides the IP addresses of your origin servers to protect them from direct access and DDoS attacks. Origin cloaking is enabled by default on {{ site.data.var.ece }} Pro Production projects. To enable origin cloaking on {{ site.data.var.ece }} Starter Production projects, submit a [{{site.data.var.ee}} support ticket]. If you have traffic that does not require caching, you can customize the Fastly service configuration to allow requests to [bypass the Fastly cache]. + - **Origin cloaking**—Prevents traffic from bypassing the Fastly WAF and hides the IP addresses of your origin servers to protect them from direct access and DDoS attacks. Origin cloaking is enabled by default on {{ site.data.var.ece }} Pro Production projects. To enable origin cloaking on {{ site.data.var.ece }} Starter Production projects, submit a [{{site.data.var.ee}} support ticket]. If you have traffic that does not require caching, you can customize the Fastly service configuration to allow requests to [bypass the Fastly cache]. -- [Image optimization]-Offloads image processing and resizing load to the Fastly service freeing servers to process orders and conversions efficiently. +- [Image optimization]—Offloads image processing and resizing load to the Fastly service freeing servers to process orders and conversions efficiently. -- [Fastly CDN and WAF logs]-For {{ site.data.var.ece }} Pro projects, you can use the New Relic Logs service to review and analyze Fastly CDN and WAF log data. +- [Fastly CDN and WAF logs]—For {{ site.data.var.ece }} Pro projects, you can use the New Relic Logs service to review and analyze Fastly CDN and WAF log data. ## Fastly CDN module for Magento 2 @@ -69,7 +69,7 @@ To change the Fastly API token credential: 1. [Test the new credential]. -1. After you have updated the credentials, submit a support ticket to delete the old API token. +1. After you have updated the credential, submit a [{{site.data.var.ee}} support ticket] to delete the old API token. ### Multiple Fastly accounts and assigned domains {#domain} From 2f0769a62a02ebede1b950b86a5c22bd063227dd Mon Sep 17 00:00:00 2001 From: Kevin Harper Date: Thu, 16 Jun 2022 09:16:08 -0500 Subject: [PATCH 197/776] One more comment --- src/guides/v2.4/graphql/authorization-tokens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/graphql/authorization-tokens.md b/src/guides/v2.4/graphql/authorization-tokens.md index fb291064aa4..d910e3ff24a 100644 --- a/src/guides/v2.4/graphql/authorization-tokens.md +++ b/src/guides/v2.4/graphql/authorization-tokens.md @@ -9,7 +9,7 @@ redirect_from: Adobe Commerce and Magento Open Source provide two mechanisms for authorizing GraphQL calls: -* **Authorization tokens**. Commerce generates a JSON Web Token (JWT), a set of cryptographically signed credentials. All calls that perform an action on behalf of a logged-in customer orgi admin provide an authorization token. Authorization tokens are stateless. Commerce does not need to know the state of a client to execute a request--the token contains all of the information needed for authorization. +* **Authorization tokens**. Commerce generates a JSON Web Token (JWT), a set of cryptographically signed credentials. All calls that perform an action on behalf of a logged-in customer orgi admin provide an authorization token. Authorization tokens are stateless. Commerce does not need to know the state of a client to execute a request--the token contains all of the information needed for authorization and authentication. * **Session cookies**. A session cookie is information generated by Commerce that is stored in the client's browser. It contains details about the session, including the time period the user can access resources. Cookies are stateful, thereby increasing complexity and possibly latency. From 262bcf675019244ca425cd2cbcca0e11bb3f9114 Mon Sep 17 00:00:00 2001 From: hguthrie Date: Thu, 16 Jun 2022 09:23:40 -0500 Subject: [PATCH 198/776] Update src/guides/v2.3/frontend-dev-guide/validations/custom-validation.md Co-authored-by: Barny Shergold --- .../v2.3/frontend-dev-guide/validations/custom-validation.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/guides/v2.3/frontend-dev-guide/validations/custom-validation.md b/src/guides/v2.3/frontend-dev-guide/validations/custom-validation.md index a4942bd4325..5dc0576e377 100644 --- a/src/guides/v2.3/frontend-dev-guide/validations/custom-validation.md +++ b/src/guides/v2.3/frontend-dev-guide/validations/custom-validation.md @@ -47,7 +47,6 @@ define(['jquery'], function($) { }, $.mage.__('Please enter exactly five words') ) - return targetWidget; } }); From fde05c5584d0ee9666bb81166ca5b592f05c27be Mon Sep 17 00:00:00 2001 From: Kevin Harper Date: Thu, 16 Jun 2022 09:34:55 -0500 Subject: [PATCH 199/776] Fix typo --- src/guides/v2.4/graphql/authorization-tokens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/graphql/authorization-tokens.md b/src/guides/v2.4/graphql/authorization-tokens.md index d910e3ff24a..9e9ea448ee5 100644 --- a/src/guides/v2.4/graphql/authorization-tokens.md +++ b/src/guides/v2.4/graphql/authorization-tokens.md @@ -9,7 +9,7 @@ redirect_from: Adobe Commerce and Magento Open Source provide two mechanisms for authorizing GraphQL calls: -* **Authorization tokens**. Commerce generates a JSON Web Token (JWT), a set of cryptographically signed credentials. All calls that perform an action on behalf of a logged-in customer orgi admin provide an authorization token. Authorization tokens are stateless. Commerce does not need to know the state of a client to execute a request--the token contains all of the information needed for authorization and authentication. +* **Authorization tokens**. Commerce generates a JSON Web Token (JWT), a set of cryptographically signed credentials. All calls that perform an action on behalf of a logged-in customer or admin provide an authorization token. Authorization tokens are stateless. Commerce does not need to know the state of a client to execute a request--the token contains all of the information needed for authorization and authentication. * **Session cookies**. A session cookie is information generated by Commerce that is stored in the client's browser. It contains details about the session, including the time period the user can access resources. Cookies are stateful, thereby increasing complexity and possibly latency. From 36cb873154ad6ad91f7a559a3e59aeff0310300f Mon Sep 17 00:00:00 2001 From: Kevin Harper Date: Thu, 16 Jun 2022 10:01:13 -0500 Subject: [PATCH 200/776] Apply suggestions from code review Co-authored-by: Donald Booth --- src/guides/v2.4/graphql/authorization-tokens.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/guides/v2.4/graphql/authorization-tokens.md b/src/guides/v2.4/graphql/authorization-tokens.md index 9e9ea448ee5..949f6722fa0 100644 --- a/src/guides/v2.4/graphql/authorization-tokens.md +++ b/src/guides/v2.4/graphql/authorization-tokens.md @@ -96,7 +96,7 @@ The client's browser will use a session cookie if the server provides one. Prior Browser-based applications that make GraphQL calls can continue implementing these cookies without changing the default setting. If you use cookies, avoid specifying Authorization headers to prevent problems caused by using two different authorization methods. -Adobe recommends that you do not use session cookies when developing a Commerce-based application. If you adhere to this best practice, you should configure GraphQL so that the server doesn't generate them. Disabling cookies also prevents the system file locks and racing conditions on server resources. These problems cause slower HTTP GET request throughputs under peak traffic conditions. +Adobe recommends that you do not use session cookies when developing a Commerce-based application. If you adhere to this best practice, you should configure GraphQL so that the server doesn't generate them. Disabling cookies also prevents system file locks and race conditions on server resources. These problems cause slower HTTP GET request throughputs under peak traffic conditions. Run the following command to disable session cookies for GraphQL: @@ -104,4 +104,4 @@ Run the following command to disable session cookies for GraphQL: To re-enable these cookies, run: -`bin/magento config:set graphql/session/disable 1` +`bin/magento config:set graphql/session/disable 0` From f3da989e1e3bb4ee224a73f5d684bce5aa02837d Mon Sep 17 00:00:00 2001 From: Donald Booth Date: Mon, 20 Jun 2022 08:03:16 -0400 Subject: [PATCH 201/776] Adding missing images --- src/common/images/contribute-prerequisites.png | Bin 0 -> 24120 bytes .../images/contribute-write-submit-pr.png | Bin 0 -> 22343 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/common/images/contribute-prerequisites.png create mode 100644 src/common/images/contribute-write-submit-pr.png diff --git a/src/common/images/contribute-prerequisites.png b/src/common/images/contribute-prerequisites.png new file mode 100644 index 0000000000000000000000000000000000000000..f741de4366155ebbc509a8a377efb00bd4f2e53d GIT binary patch literal 24120 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 P4uGrEG2DYAA?g1G@@HMD literal 0 HcmV?d00001 From 4d704da2d7320de23fda9e0f11759ff7059568e1 Mon Sep 17 00:00:00 2001 From: magedocs Date: Mon, 20 Jun 2022 14:38:48 +0000 Subject: [PATCH 202/776] Update News data --- src/_data/whats-new.yml | 56 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/src/_data/whats-new.yml b/src/_data/whats-new.yml index e4df24b7ca4..184df7c4c25 100644 --- a/src/_data/whats-new.yml +++ b/src/_data/whats-new.yml @@ -4,8 +4,62 @@ description: This page contains recent changes that we think you'd like to know We exclude from this list proofreading, spelling checks, and all minor updates. link: "/whats-new.html" thread: "/whatsnew-feed.xml" -updated: Mon Jun 13 14:38:46 2022 +updated: Mon Jun 20 14:38:46 2022 entries: +- description: The following PHP tutorials moved to the [Adobe Developer documentation](https://developer.adobe.com/commerce/php/best-practices/) + and will be redirected soon:
    - [Custom attributes](https://devdocs.magento.com/guides/v2.4/howdoi/custom-attributes/introduction.html)
    - + [Customize product creation form](https://devdocs.magento.com/guides/v2.4/howdoi/customize_product.html)
    - + [Customize checkout](https://devdocs.magento.com/guides/v2.4/howdoi/checkout/checkout_overview.html)
    - + [Customize the Admin Design](https://devdocs.magento.com/guides/v2.4/howdoi/admin/customize_admin.html)
    - + [Copy fieldsets](https://devdocs.magento.com/guides/v2.4/ext-best-practices/tutorials/copy-fieldsets.html)
    - + [Serialized to JSON data upgrade](https://devdocs.magento.com/guides/v2.4/ext-best-practices/tutorials/serialized-to-json-data-upgrade.html)
    - + [Modify image library folder permissions](https://devdocs.magento.com/guides/v2.4/ext-best-practices/tutorials/modify-image-library-permissions/)
    - + [Creating an Admin page](https://devdocs.magento.com/guides/v2.4/ext-best-practices/extension-coding/example-module-adminpage.html)
    - + [Creating a dynamic row config](https://devdocs.magento.com/guides/v2.4/ext-best-practices/tutorials/dynamic-row-system-config.html)
    - + [Creating a custom import entity](https://devdocs.magento.com/guides/v2.4/ext-best-practices/tutorials/custom-import-entity.html)
    - + [Creating a custom widget](https://devdocs.magento.com/guides/v2.4/ext-best-practices/tutorials/custom-widget.html)
    - + [Creating an access control list (ACL) rule](https://devdocs.magento.com/guides/v2.4/ext-best-practices/tutorials/create-access-control-list-rule.html)
    - + [Creating an integration with an external API](https://devdocs.magento.com/guides/v2.4/ext-best-practices/tutorials/create-integration-with-api.html)
    - + [Create a custom REST API](https://devdocs.magento.com/guides/v2.4/ext-best-practices/tutorials/create-custom-rest-api.html) + versions: 2.4.x + type: Major Update + date: June 20, 2022 + link: https://github.com/magento-commerce/devdocs/pull/3003 + merge_commit: 6e7f71f325d588e046fc8fe07f96d9bf74391e9b + contributor: jeff-matthews + membership: true + labels: + - Major Update + - 2.4.x + - migration +- description: "`
    Added [config import command point](https://devdocs.magento.com/guides/v2.3/config-guide/cli/logging.html#to-enable-database-logging) + to the [Logging](https://devdocs.magento.com/guides/v2.3/config-guide/cli/logging.html) + topic." + versions: 2.x + type: Technical + date: June 15, 2022 + link: https://github.com/magento/devdocs/pull/9467 + merge_commit: cfdd4ea65539ff27d573663b4be5641dcce2c290 + contributor: guentur + membership: false + labels: + - 2.x + - Technical + - 'Progress: done' +- description: The [Get Started with our Web APIs](https://devdocs.magento.com/guides/v2.4/get-started/bk-get-started-api.html) + guide moved to the [Adobe Developer documentation](https://developer.adobe.com/commerce/webapi/get-started/) + and will be redirected soon. + versions: 2.4.x + type: Major Update + date: June 14, 2022 + link: https://github.com/magento-commerce/devdocs/pull/2988 + merge_commit: b9460c32fa7236dd7cb44c5fc5724126fa5a5bb6 + contributor: jhadobe + membership: true + labels: + - Major Update + - 2.4.x + - migration - description: Clarified notes throughout the Cloud guide about updating configurations in Pro projects. See [Configure environments](https://devdocs.magento.com/cloud/env/environments.html) as an example. From 91796371ff4a0ba38e3ac855e6c7b239d62807bd Mon Sep 17 00:00:00 2001 From: Donald Booth Date: Mon, 20 Jun 2022 11:21:24 -0400 Subject: [PATCH 203/776] Removed errant BR tag --- src/_data/whats-new.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_data/whats-new.yml b/src/_data/whats-new.yml index 184df7c4c25..b2e9bf88def 100644 --- a/src/_data/whats-new.yml +++ b/src/_data/whats-new.yml @@ -32,9 +32,9 @@ entries: - Major Update - 2.4.x - migration -- description: "`
    Added [config import command point](https://devdocs.magento.com/guides/v2.3/config-guide/cli/logging.html#to-enable-database-logging) +- description: Added [config import command point](https://devdocs.magento.com/guides/v2.3/config-guide/cli/logging.html#to-enable-database-logging) to the [Logging](https://devdocs.magento.com/guides/v2.3/config-guide/cli/logging.html) - topic." + topic. versions: 2.x type: Technical date: June 15, 2022 From a1c1aac9cdb2647d9f1aad471905eec4733f3a00 Mon Sep 17 00:00:00 2001 From: jfrontain Date: Mon, 20 Jun 2022 12:13:06 -0500 Subject: [PATCH 204/776] added last inventory issues --- .../release-notes/engcomm-2-4-5-issues.md | 25 ++ .../release-notes/engcomm-2-4-5-partner.md | 7 + src/guides/v2.3/inventory/release-notes.md | 4 + src/guides/v2.3/release-notes/2-3-7-p4.md | 2 +- src/guides/v2.4/release-notes/2-4-3-p3.md | 2 +- src/guides/v2.4/release-notes/2-4-4-p1.md | 2 +- .../v2.4/release-notes/commerce-2-4-5.md | 214 +++++++++++++++--- 7 files changed, 223 insertions(+), 33 deletions(-) diff --git a/src/_includes/release-notes/engcomm-2-4-5-issues.md b/src/_includes/release-notes/engcomm-2-4-5-issues.md index e69de29bb2d..8b717f9111d 100644 --- a/src/_includes/release-notes/engcomm-2-4-5-issues.md +++ b/src/_includes/release-notes/engcomm-2-4-5-issues.md @@ -0,0 +1,25 @@ +| Contributing community member | Pull Requests | Related GitHub Issues | +| ------- | ------- | ------- | +| hostep | [magento/magento2#30640](https://github.com/magento/magento2/pull/30640) | [magento/magento2#30607](https://github.com/magento/magento2/issues/30607) | +| nuzil | [magento/magento2#31944](https://github.com/magento/magento2/pull/31944) | [magento/magento2#31947](https://github.com/magento/magento2/issues/31947) | +| kate-kyzyma | [magento/magento2#32293](https://github.com/magento/magento2/pull/32293) | [magento/magento2#32378](https://github.com/magento/magento2/issues/32378) | +| wassuupp | [magento/magento2#32371](https://github.com/magento/magento2/pull/32371) | [magento/magento2#33767](https://github.com/magento/magento2/issues/33767) | +| nuzil | [magento/magento2#32648](https://github.com/magento/magento2/pull/32648) | [magento/magento2#32649](https://github.com/magento/magento2/issues/32649) | +| DmitryTsymbal | [magento/magento2#33342](https://github.com/magento/magento2/pull/33342) | [magento/magento2#33344](https://github.com/magento/magento2/issues/33344) | +| AnnaAPak | [magento/magento2#33557](https://github.com/magento/magento2/pull/33557) | [magento/magento2#33692](https://github.com/magento/magento2/issues/33692) | +| ihor-sviziev | [magento/magento2#33904](https://github.com/magento/magento2/pull/33904) | [magento/magento2#33929](https://github.com/magento/magento2/issues/33929) | +| marvinhinz | [magento/magento2#34388](https://github.com/magento/magento2/pull/34388) | [magento/magento2#35150](https://github.com/magento/magento2/issues/35150) | +| kate-kyzyma | [magento/magento2#34552](https://github.com/magento/magento2/pull/34552) | [magento/magento2#34631](https://github.com/magento/magento2/issues/34631) | +| in-session | [magento/magento2#34558](https://github.com/magento/magento2/pull/34558) | [magento/magento2#34563](https://github.com/magento/magento2/issues/34563) [magento/magento2#34595](https://github.com/magento/magento2/issues/34595) | +| convenient | [magento/magento2#34582](https://github.com/magento/magento2/pull/34582) | [magento/magento2#34988](https://github.com/magento/magento2/issues/34988) | +| ihor-sviziev | [magento/magento2#34943](https://github.com/magento/magento2/pull/34943) | [magento/magento2#34942](https://github.com/magento/magento2/issues/34942) | +| liamjtoohey | [magento/magento2#35050](https://github.com/magento/magento2/pull/35050) | [magento/magento2#35180](https://github.com/magento/magento2/issues/35180) | +| dudzio12 | [magento/magento2#35109](https://github.com/magento/magento2/pull/35109) | [magento/magento2#35108](https://github.com/magento/magento2/issues/35108) [magento/magento2#35128](https://github.com/magento/magento2/issues/35128) | +| shochdoerfer | [magento/magento2#35234](https://github.com/magento/magento2/pull/35234) | [magento/magento2#35315](https://github.com/magento/magento2/issues/35315) | +| tobias-forkel | [magento/magento2#35299](https://github.com/magento/magento2/pull/35299) | [magento/magento2#35458](https://github.com/magento/magento2/issues/35458) | +| Inevix | [magento/magento2#35349](https://github.com/magento/magento2/pull/35349) | [magento/magento2#35480](https://github.com/magento/magento2/issues/35480) | +| fredden | [magento/magento2#35356](https://github.com/magento/magento2/pull/35356) | [magento/magento2#35587](https://github.com/magento/magento2/issues/35587) | +| mahesh-singh-rajawat | [magento/magento2#35376](https://github.com/magento/magento2/pull/35376) | [magento/magento2#35204](https://github.com/magento/magento2/issues/35204) | +| Usik2203 | [magento/magento2#35385](https://github.com/magento/magento2/pull/35385) | [magento/magento2#35386](https://github.com/magento/magento2/issues/35386) | +| arifadobe | [magento/magento2#35439](https://github.com/magento/magento2/pull/35439) | [magento/magento2#35506](https://github.com/magento/magento2/issues/35506) | +| pykettk | [magento/magento2#35504](https://github.com/magento/magento2/pull/35504) | [magento/magento2#35505](https://github.com/magento/magento2/issues/35505) | \ No newline at end of file diff --git a/src/_includes/release-notes/engcomm-2-4-5-partner.md b/src/_includes/release-notes/engcomm-2-4-5-partner.md index e69de29bb2d..7cd865118e3 100644 --- a/src/_includes/release-notes/engcomm-2-4-5-partner.md +++ b/src/_includes/release-notes/engcomm-2-4-5-partner.md @@ -0,0 +1,7 @@ +| Partner | Pull Requests | Related GitHub Issues | +| ------- | ------- | ------- | +| Fisheye | [magento/magento2#35504](https://github.com/magento/magento2/pull/35504) [magento/magento2#35356](https://github.com/magento/magento2/pull/35356) [magento/magento2#35355](https://github.com/magento/magento2/pull/35355) | [magento/magento2#35505](https://github.com/magento/magento2/issues/35505) [magento/magento2#35587](https://github.com/magento/magento2/issues/35587) | +| Atwix | [magento/magento2#35421](https://github.com/magento/magento2/pull/35421) [magento/magento2#35385](https://github.com/magento/magento2/pull/35385) [magento/magento2#35118](https://github.com/magento/magento2/pull/35118) [magento/magento2#35099](https://github.com/magento/magento2/pull/35099) [magento/magento2#35040](https://github.com/magento/magento2/pull/35040) [magento/magento2#34883](https://github.com/magento/magento2/pull/34883) [magento/magento2#34862](https://github.com/magento/magento2/pull/34862) [magento/magento2#34552](https://github.com/magento/magento2/pull/34552) [magento/magento2#33795](https://github.com/magento/magento2/pull/33795) [magento/magento2#33557](https://github.com/magento/magento2/pull/33557) [magento/magento2#33536](https://github.com/magento/magento2/pull/33536) [magento/magento2#33409](https://github.com/magento/magento2/pull/33409) [magento/magento2#33342](https://github.com/magento/magento2/pull/33342) [magento/magento2#32293](https://github.com/magento/magento2/pull/32293) [magento/magento2#28958](https://github.com/magento/magento2/pull/28958) | [magento/magento2#35386](https://github.com/magento/magento2/issues/35386) [magento/magento2#34631](https://github.com/magento/magento2/issues/34631) [magento/magento2#33692](https://github.com/magento/magento2/issues/33692) [magento/magento2#33344](https://github.com/magento/magento2/issues/33344) [magento/magento2#32378](https://github.com/magento/magento2/issues/32378) | +| Ampersand | [magento/magento2#35050](https://github.com/magento/magento2/pull/35050) [magento/magento2#34582](https://github.com/magento/magento2/pull/34582) | [magento/magento2#35180](https://github.com/magento/magento2/issues/35180) [magento/magento2#34988](https://github.com/magento/magento2/issues/34988) | +| EY | [magento/magento2#33898](https://github.com/magento/magento2/pull/33898) | | +| Comwrap | [magento/magento2#32648](https://github.com/magento/magento2/pull/32648) [magento/magento2#32371](https://github.com/magento/magento2/pull/32371) [magento/magento2#31944](https://github.com/magento/magento2/pull/31944) | [magento/magento2#32649](https://github.com/magento/magento2/issues/32649) [magento/magento2#33767](https://github.com/magento/magento2/issues/33767) [magento/magento2#31947](https://github.com/magento/magento2/issues/31947) | \ No newline at end of file diff --git a/src/guides/v2.3/inventory/release-notes.md b/src/guides/v2.3/inventory/release-notes.md index 21e32913992..aa60a4affcd 100644 --- a/src/guides/v2.3/inventory/release-notes.md +++ b/src/guides/v2.3/inventory/release-notes.md @@ -48,6 +48,10 @@ The release notes include: - {:.fix} Compatibility issues with PHP 7.4 have been resolved. +- {:.fix} The performance of save operations that include bundle products that contain many options (several hundred) has been improved. Previously, saving these large bundle products took several minutes and sometimes resulted in timeouts in deployments with Inventory services enabled. [GitHub-34732](https://github.com/magento/magento2/issues/34732) + +- {:.fix} The product bulk action tool (**Catalog** > **Products** > **Select Products** > **Actions** > **Assign Inventory Source**) now works as expected when assigning inventory source to multiple products when SKUs are duplicate with the exception of a leading 0 (for example, 01234 and 1234). Previously, only one product was assigned an Inventory source. [GitHub-35171](https://github.com/magento/magento2/issues/35171) + ### v1.2.4 {{site.data.var.im}} 1.2.4 (module version: `magento/inventory-metapackage = 1.2.4`) is supported with version 2.4.4 and compatible with version 2.4.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. diff --git a/src/guides/v2.3/release-notes/2-3-7-p4.md b/src/guides/v2.3/release-notes/2-3-7-p4.md index fab562e08f2..e7fa0a836c6 100644 --- a/src/guides/v2.3/release-notes/2-3-7-p4.md +++ b/src/guides/v2.3/release-notes/2-3-7-p4.md @@ -3,7 +3,7 @@ group: release-notes title: Adobe Commerce 2.3.7-p4 Release Notes --- -{{ site.data.var.ee }} 2.3.7-p4 is a security release that provides security fixes that enhance your {{ site.data.var.ee }} 2.3.7 or {{ site.data.var.ce }} 2.3.7 deployment. It provides fixes for vulnerabilities that have been identified in the previous release ({{ site.data.var.ee }} 2.3.7-p3). +{{ site.data.var.ee }} 2.3.7-p4 provides 16 security fixes that enhance your {{ site.data.var.ee }} 2.3.7 or {{ site.data.var.ce }} 2.3.7 deployment. It provides fixes for vulnerabilities that have been identified in the previous release ({{ site.data.var.ee }} 2.3.7-p3). {:.bs-callout-info} PHP 7.3 reached end of support in December 2021, and {{ site.data.var.ee }} 2.3.x and {{ site.data.var.ce }} 2.3.x will reach end of support in September 2022. **We strongly recommend planning your upgrade now to {{ site.data.var.ee }} 2.4.x or {{ site.data.var.ce }} 2.4.x deployment to help maintain PCI compliance**. diff --git a/src/guides/v2.4/release-notes/2-4-3-p3.md b/src/guides/v2.4/release-notes/2-4-3-p3.md index 019666a5ae7..6a098979c2e 100644 --- a/src/guides/v2.4/release-notes/2-4-3-p3.md +++ b/src/guides/v2.4/release-notes/2-4-3-p3.md @@ -3,7 +3,7 @@ group: release-notes title: Adobe Commerce 2.4.3-p3 Release Notes --- -{{ site.data.var.ee }} 2.4.3-p3 is a security release that provides two security fixes that enhance your {{ site.data.var.ee }} 2.4.3 or {{ site.data.var.ce }} 2.4.3 deployment. It provides fixes for vulnerabilities that have been identified in the previous release ({{ site.data.var.ee }} 2.4.3 and {{ site.data.var.ce }} 2.4.3). +{{ site.data.var.ee }} 2.4.3-p3 is a security release that provides 18 security fixes that enhance your {{ site.data.var.ee }} 2.4.3 or {{ site.data.var.ce }} 2.4.3 deployment. It provides fixes for vulnerabilities that have been identified in the previous release ({{ site.data.var.ee }} 2.4.3 and {{ site.data.var.ce }} 2.4.3). {:.bs-callout-info} Releases may contain backward-incompatible changes (BIC). To review minor backward-incompatible changes, see [BIC reference]({{page.baseurl}}/release-notes/backward-incompatible-changes/reference.html). (Major backward-incompatible issues are described in [BIC highlights]({{page.baseurl}}/release-notes/backward-incompatible-changes/index.html). Not all releases introduce major BICs.) diff --git a/src/guides/v2.4/release-notes/2-4-4-p1.md b/src/guides/v2.4/release-notes/2-4-4-p1.md index 1c95f6564bd..199eb71360a 100644 --- a/src/guides/v2.4/release-notes/2-4-4-p1.md +++ b/src/guides/v2.4/release-notes/2-4-4-p1.md @@ -3,7 +3,7 @@ group: release-notes title: Adobe Commerce 2.4.4-p1 Release Notes --- -{{ site.data.var.ee }} 2.4.4-p1 is a security release that provides two security fixes that enhance your {{ site.data.var.ee }} 2.4.4 or {{ site.data.var.ce }} 2.4.4 deployment. It provides fixes for vulnerabilities that have been identified in the previous release ({{ site.data.var.ee }} 2.4.4 and {{ site.data.var.ce }} 2.4.4). +{{ site.data.var.ee }} 2.4.4-p1 is a security release that provides 18 security fixes that enhance your {{ site.data.var.ee }} 2.4.4 or {{ site.data.var.ce }} 2.4.4 deployment. It provides fixes for vulnerabilities that have been identified in the previous release ({{ site.data.var.ee }} 2.4.4 and {{ site.data.var.ce }} 2.4.4). {:.bs-callout-info} Releases may contain backward-incompatible changes (BIC). To review minor backward-incompatible changes, see [BIC reference]({{page.baseurl}}/release-notes/backward-incompatible-changes/reference.html). (Major backward-incompatible issues are described in [BIC highlights]({{page.baseurl}}/release-notes/backward-incompatible-changes/index.html). Not all releases introduce major BICs.) diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md index 884b76e6e00..a1bdeffcdcb 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-5.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -24,7 +24,7 @@ Look for the following highlights in this release. ### Security enhancements -This release includes security fix and platform security improvements. This security fix has been backported to {{ site.data.var.ee }} 2.4.3-p3 and {{ site.data.var.ee }} 2.3.7-p4. +This release includes 20 security fix and platform security improvements. This security fix has been backported to {{ site.data.var.ee }} 2.4.3-p3 and {{ site.data.var.ee }} 2.3.7-p4. No confirmed attacks related to these issues have occurred to date. However, certain vulnerabilities can potentially be exploited to access customer information or take over administrator sessions. Most of these issues require that an attacker first obtains access to the Admin. As a result, we remind you to take all necessary steps to protect your Admin, including but not limited to these efforts: @@ -40,13 +40,13 @@ See Adobe Security Bulletin for the latest discussion of these fixed issues. Security improvements for this release improve compliance with the latest security best practices, including: -* reCAPTCHA support has been added to the Wish List Sharing, Create New Customer Account, and Gift Card forms. +* reCAPTCHA support has been added to the Wish List Sharing, Create New Customer Account, and Gift Card forms. -* ACL resources have been added to Inventory. +* ACL resources have been added to Inventory. * Inventory template security has been enhanced. -* The `MaliciousCode` filter has been upgraded to use the `HtmlPurifier` library. +* The `MaliciousCode` filter has been upgraded to use the `HtmlPurifier` library. ### Platform enhancements @@ -56,11 +56,15 @@ Security improvements for this release improve compliance with the latest securi * Elasticsearch (~7.17.0 with constraint) -* TinyMCE (5.10.2) +* TinyMCE (5.10.2). Earlier versions of TinyMCE (v5.9.2 or earlier) allowed arbitrary JavaScript execution when a specially crafted URL or an image with a specially crafted URL was updated. * jQueryUI (1.13.1) -* `PHPStan` (^1.5.7 with constraint) +* `PHPStan` (^1.5.7 with constraint) [GitHub-35315](https://github.com/magento/magento2/issues/35315) + +* DHL Integration schema has been updated from v6.0 to v6.2. DHL is deprecated v6.0 + +Outdated JavaScript libraries have been updated to their latest versions, and outdated dependencies have been removed. These changes are backward compatible. #### Composer dependency updates @@ -68,28 +72,28 @@ Security improvements for this release improve compliance with the latest securi The following Composer dependencies have been updated to the latest versions with constraint: -`colinmollenhour/credis` (1.13.0 or 1.12.2)? -`guzzlehttp/guzzle` (^7.4.2) -`laminas/laminas-captcha` (updated with a constraint ^2.12) -`laminas/laminas-db` (^2.15.0) -`laminas/laminas-di` (^3.4.0) -`laminas/laminas-escaper` (~2.10.0) -`laminas/laminas-eventmanager` (^3.5.0) -`laminas/laminas-feed` (^2.17.0) -`laminas/laminas-mail` (^2.16.0) -`laminas/laminas-mvc` (^3.3.3) -`laminas/laminas-server` (^2.11.1) -`laminas/laminas-servicemanager` (^3.11.0) -`laminas/laminas-session` (^2.12.1) -`laminas/laminas-validator` (^2.17.0) -`league/fly` (2.4.3) -`monolog/monolog` (^2.5) -`phpmd/phpmd` (^2.12.0) -`phpstan/phpstan` (^1.5.7) -`phpunit/phpunit` (~9.5.20) -`phpunit/phpunit` (^9.4) -`php-cs-fixer` (^3.4.0) -`webonyx/graphql-php` (14.11.6) +* `colinmollenhour/credis` (1.13.0 or 1.12.2)? +* `guzzlehttp/guzzle` (^7.4.2) +* `laminas/laminas-captcha` (updated with a constraint ^2.12) +* `laminas/laminas-db` (^2.15.0) +* `laminas/laminas-di` (^3.4.0) +* `laminas/laminas-escaper` (~2.10.0) +* `laminas/laminas-eventmanager` (^3.5.0) +* `laminas/laminas-feed` (^2.17.0) +* `laminas/laminas-mail` (^2.16.0) +* `laminas/laminas-mvc` (^3.3.3) +* `laminas/laminas-server` (^2.11.1) +* `laminas/laminas-servicemanager` (^3.11.0) +* `laminas/laminas-session` (^2.12.1) +* `laminas/laminas-validator` (^2.17.0) +* `league/fly` (2.4.3) +* `monolog/monolog` (^2.5) +* `phpmd/phpmd` (^2.12.0) +* `phpstan/phpstan` (^1.5.7) +* `phpunit/phpunit` (~9.5.20) +* `phpunit/phpunit` (^9.4) +* `php-cs-fixer` (^3.4.0) +* `webonyx/graphql-php` (14.11.6) The `laminas/laminas-session`, `laminas/laminas-text`, and `laminas/laminas-view` dependencies have been removed. @@ -123,6 +127,10 @@ The `laminas/laminas-session`, `laminas/laminas-text`, and `laminas/laminas-view Performance enhancements in this release: +#### Price indexer optimization + +To improve performance of product price indexation, the number of primary indexes has been reduced from 3 to 1 for the `catalog_product_index_price_tmp` table. As a result, the indexation time of the product price index has been significantly reduced. + ### GraphQL This release includes these GraphQL enhancements: @@ -133,24 +141,66 @@ This release includes these GraphQL enhancements: See the [GraphQL Developer Guide]({{page.baseurl}}/graphql/) for details on these enhancements. +### Adobe Sign Extension + +The Adobe Commerce check out workflow now supports the inclusion of an esignature agreement page powered by Adobe Sign. + ### B2B This release includes multiple bug fixes. See [B2B Release Notes]({{page.baseurl}}/release-notes/b2b-release-notes.html) +**Reduced eSKU multiplication with Shared Catalogs (Customer Groups)**. The new **Enabled Shared Catalog direct product price assigning** configuration option improves product price indexer performance when enabled. + +### Channel Manager + +Channel Manager can now trigger refunds from Adobe Commerce. Merchants can now manage the entire order workflow from within Adobe Commerce, including these tasks: + +* Process refunds from Adobe Commerce +* Refund shoppers using the origin form of payment + +Requests are now automatically synced back to the Walmart Marketplace. + ### PWA Studio -PWA Studio v.12.x.x is compatible with {{ site.data.var.ee }} 2.4.5. It includes support for . For information about enhancements and bug fixes, see [PWA Studio releases](https://github.com/magento/pwa-studio/releases). See [Version compatibility](https://developer.adobe.com/commerce/pwa-studio/integrations/adobe-commerce/version-compatibility/) for a list of PWA Studio versions and their compatible {{ site.data.var.ee }} core versions. +PWA Studio v.12.x.x is compatible with {{ site.data.var.ee }} 2.4.5. + +New features for this release include: + +* Shopper behavior data is collected on PWA Studio storefront for web analytics services. Merchants can now subscribe and extend these events as needed. +* Merchants can now select a service to deploy from the Admin (Beacon or Google Tag Manager). + +For information about enhancements and bug fixes, see [PWA Studio releases](https://github.com/magento/pwa-studio/releases). See [Version compatibility](https://developer.adobe.com/commerce/pwa-studio/integrations/adobe-commerce/version-compatibility/) for a list of PWA Studio versions and their compatible {{ site.data.var.ee }} core versions. ### PayPal Payment enhancements +Merchants in Spain and Italy can now offer PayPal Pay Later to shoppers. + +### Braintree + ### Live Search +This release introduces support for B2B customer groups and custom pricing. + ### Accessibility updates -This release brings increased conformance to standard accessibility guidelines. +This release includes enhancements to the Admin UI that improve the experience of users with vision limitations and increase conformance to standard accessibility guidelines. These enhancements include: + +* The screen reader now summarizes search results +* Screen readers are now informed when a new page loads +* Contrast and keyboard accessibility have been improved ### Page Builder +Page Builder column layout includes these enhancements: + +* Columns are now exposed, permitting users to control column settings on the storefront. + +* Column resizing now supports wrapping triggered by user actions. + +### Branding and style changes + +The Admin has been updated to align with Adobe’s branch strategy. Changes affect headers, footers, data grid color updates, and navigation elements. + ## Fixed issues We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. @@ -169,6 +219,12 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * Merchants can now successfully upgrade from an {{ site.data.var.ee }} 2.4.2 deployment with Klarna to {{ site.data.var.ee }} 2.4.3. [GitHub-33760](https://github.com/magento/magento2/issues/33760) + + + + + + ### Accessibility @@ -295,6 +351,10 @@ The **Shopping bag** button now provides a programmatic or textual indication of * Merchants can now create a credit memo in which **Refund Shipping (Incl. Tax)** is set to -0.01 and can now set this amount to 0. Previously, the credit memo could not be created under these conditions. + + + + ### Cart price rule @@ -415,6 +475,14 @@ The **Shopping bag** button now provides a programmatic or textual indication of * The EAV indexer now processes product IDs as type `int` to prevent possible performance issues. + + + + + + + + ### Catalog rule ### CMS content @@ -539,6 +607,32 @@ The **Shopping bag** button now provides a programmatic or textual indication of * Magento no longer triggers a `trim(): Passing null to parameter #1 ($string) of type string is deprecated` error when the AMPQ connection is configured without SSL configuration. + + + + + + + + + + + + + + + + + + + + + + + + + + ### General fixes @@ -609,6 +703,14 @@ The **Shopping bag** button now provides a programmatic or textual indication of * Magento no longer throws the following error during the creation of a catalog rule in the Admin after upgrade: `A technical problem with the server created an error. Try again to continue what you were doing. If the problem persists, try again later`. + + + + + + + + ### Gift cards @@ -817,6 +919,8 @@ The **Shopping bag** button now provides a programmatic or textual indication of * Added validation for category names during import. Previously, {{ site.data.var.ee }} did not validate category names, which lead to errors when category names exceeded 255 characters. + + ### Index ### Infrastructure @@ -833,6 +937,8 @@ The **Shopping bag** button now provides a programmatic or textual indication of * The TinyMCE editor toolbar-related logic in the Page Builder module has been updated as a result of introducing `delayedRender` logic for the toolbar in TinyMCE. + + #### Library removals and deprecations #### Library upgrades @@ -857,10 +963,16 @@ The **Shopping bag** button now provides a programmatic or textual indication of Repetitive actions have been replaced with action groups in these tests: +`AdminConfigurableProductChildrenOutOfStockTest` [GitHub-32378](https://github.com/magento/magento2/issues/32378) +`AdminCreateStoreViewTest` [GitHub-34631](https://github.com/magento/magento2/issues/34631) + #### New tests +`StorefrontNewsletterSubscriptionWithEnabledNeedToConfirmConfigTest` [GitHub-33344](https://github.com/magento/magento2/issues/33344) #### Refactored tests +`AdminCancelTheCreatedOrderWithCashOnDeliveryPaymentMethodTest` [GitHub-33692](https://github.com/magento/magento2/issues/33692) + ### Newsletter @@ -917,6 +1029,10 @@ Repetitive actions have been replaced with action groups in these tests: * Magento now displays correct order status during checkout when customer store credit is used. + + + + ### Payment methods @@ -927,6 +1043,10 @@ Repetitive actions have been replaced with action groups in these tests: * Payment Review page in the checkout workflow now displays the correct payment method name when payment is made with Venmo, PayPal Later, or PayPal. + + + + #### PayPal @@ -947,6 +1067,8 @@ Repetitive actions have been replaced with action groups in these tests: * The new `Grid Filter Condition Type` customer/customer address attribute controls how an attribute filter is matched against the attribute values in the database, Options include `Partial Match`, `Prefix Match`, and `Full Match`. + + ### Pricing @@ -957,6 +1079,12 @@ Repetitive actions have been replaced with action groups in these tests: * The price listed on the product detail page is now the same as the price listed in the checkout workflow for tier prices that differ by quantity selected (for example, a product priced differently based on buying 2 items versus 5 items). Previously, the checkout price reflected the price for the lowest product quantity. +### Product + + + + + ### ProductAlert ### Product video @@ -967,10 +1095,16 @@ Repetitive actions have been replaced with action groups in these tests: * The **Times Used** value for a discount is no longer incremented twice when a guest customer places an order with a discount and subsequently registers an account. + + ### ReCAPTCHA * The **Submit** button on the Login and Create an Account pages is now inactive until ReCaptcha is fully loaded. +### Reports + + + ### Return Merchandise Authorizations (RMA) @@ -1027,6 +1161,8 @@ Repetitive actions have been replaced with action groups in these tests: * Filtering products by color swatch in the layered navigation now displays the correct product images. Previously, the layered navigation `PageCache` key did not include filter parameters for configurable products. + + ### Shipping @@ -1041,6 +1177,8 @@ Repetitive actions have been replaced with action groups in these tests: * Table rate shipping rates with zero price are now displayed correctly in the checkout workflow Order Summary block for orders that have had a discount coupon applied. Previously, the shipping method was not displayed. + + ### Staging @@ -1127,6 +1265,8 @@ Repetitive actions have been replaced with action groups in these tests: * Web API requests for order data (`rest/V1/orders/`) no longer returns negative values for row totals. + + ### Test @@ -1229,6 +1369,14 @@ Repetitive actions have been replaced with action groups in these tests: * You can now switch between store views when website restrictions are enabled. Previously, problems with the store view switcher prevented switching store views. + + + + + + + + ### URL rewrites @@ -1283,6 +1431,12 @@ Repetitive actions have been replaced with action groups in these tests: * The Bulk Rest API now works with the `bySku` option for configurable products. Previously, it returned a 500 error. + + + + + + ### Wish list From cfbbad445b024b62a81cce4d4b1c952c11e7d2e5 Mon Sep 17 00:00:00 2001 From: Leslie Tilling Date: Mon, 20 Jun 2022 13:06:56 -0700 Subject: [PATCH 205/776] Add migration ExL URLs for IM --- src/extensions/inventory-management/index.md | 2 ++ src/guides/v2.3/inventory/release-notes.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/extensions/inventory-management/index.md b/src/extensions/inventory-management/index.md index 1ab5ce3f9e5..1e357becc36 100644 --- a/src/extensions/inventory-management/index.md +++ b/src/extensions/inventory-management/index.md @@ -2,6 +2,8 @@ group: extensions title: Install Inventory Management redirect_from: guides/v2.3/comp-mgr/install-extensions/inventory-management-installation.html +migrated_to: https://experienceleague.adobe.com/docs/commerce-admin/inventory/get-started/install-update.html +layout: migrated --- {{site.data.var.im}} modules provide all inventory features and options for Single and Multi Source merchants to manage product quantities and stock for sales channels. These features are available in 2.3.x {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. diff --git a/src/guides/v2.3/inventory/release-notes.md b/src/guides/v2.3/inventory/release-notes.md index 6b9f7e481c1..e08a1437df9 100644 --- a/src/guides/v2.3/inventory/release-notes.md +++ b/src/guides/v2.3/inventory/release-notes.md @@ -1,6 +1,8 @@ --- group: inventory title: Release Notes +migrated_to: https://experienceleague.adobe.com/docs/commerce-admin/inventory/release-notes.html +layout: migrated --- **{{site.data.var.im}} (provided by the [Magento Inventory (was MSI)](https://github.com/magento/inventory) project)** is available with {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}} 2.3.x. Merchants can use {{site.data.var.im}} to manage inventory for all product types in a single warehouse and across complex shipping networks. Manage these locations as sources, tracking on-hand inventory quantities per product. Stocks connect these sources with sales channels (websites) to provide an accurate salable quantity, calculating available on-hand products, pending orders (reservations), and configured thresholds. {{site.data.var.im}} also updates order and shipment options, giving you full control over your inventory and deductions at the source level. From 3331771feed462a9896204e5b02812d621f9969b Mon Sep 17 00:00:00 2001 From: jfrontain Date: Mon, 20 Jun 2022 15:32:38 -0500 Subject: [PATCH 206/776] added Elasticsearch highlihts --- src/guides/v2.4/release-notes/commerce-2-4-5.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md index a1bdeffcdcb..4d154d7a295 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-5.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -50,12 +50,14 @@ Security improvements for this release improve compliance with the latest securi ### Platform enhancements +* **Adobe Commerce on-premises deployments**: Adobe Commerce 2.4.5 has been tested and confirmed to be compatible with Elasticsearch 7.17 (~7.17.0 with constraint). Merchants hosting Adobe Commerce on-premises can use either Elasticsearch or OpenSearch. + +* **Adobe Commerce cloud-hosted deployments**: ElasticSearch 7.11 or later is not supported on Adobe Commerce 2.4.5 cloud-hosted deployments. OpenSearch is the default search engine for Adobe Commerce 2.4.5 cloud deployments. + {{ site.data.var.ee }} 2.4.5 now supports * Composer 2.2 -* Elasticsearch (~7.17.0 with constraint) - * TinyMCE (5.10.2). Earlier versions of TinyMCE (v5.9.2 or earlier) allowed arbitrary JavaScript execution when a specially crafted URL or an image with a specially crafted URL was updated. * jQueryUI (1.13.1) @@ -99,6 +101,8 @@ The `laminas/laminas-session`, `laminas/laminas-text`, and `laminas/laminas-view #### Other upgrades and replacements +* DHL Integration schema has been updated from v6.0 to v6.2. (DHL is deprecating the v6.0 schema mid-2022.) + * The default Gateway URL for USPS shipping has been updated to use `https` instead of `http`. * The `Froogaloop` library has been replaced with the Vimeo `Player.js` library (2.16.4). @@ -119,7 +123,7 @@ The `laminas/laminas-session`, `laminas/laminas-text`, and `laminas/laminas-view * The library `jquery/jquery-cookie` has been replaced with `js-cookie/js-cookie`. -* The `jarallax.js` and `jaralax-video.js` libraries have been updated to the latest versions (2.0.3). +* The `jarallax.js` and `jaralax-video.js` libraries have been updated to use the latest version of the Vimeo REST API. See [The Basics]( https://developer.vimeo.com/api/guides/start). ### Performance and scalability enhancements @@ -129,7 +133,7 @@ Performance enhancements in this release: #### Price indexer optimization -To improve performance of product price indexation, the number of primary indexes has been reduced from 3 to 1 for the `catalog_product_index_price_tmp` table. As a result, the indexation time of the product price index has been significantly reduced. +Primary index performance has been improved by reducing the number of primary indexes from 3 to 1 for the `catalog_product_index_price_tmp` table. This enhancement reduced the number of records created in the price index by reducing eSKU multiplication that resulted from shared catalogs. Indexing time has been significantly reduced. ### GraphQL From 5a454c3c416d3be70fa477985c530d44df3179f9 Mon Sep 17 00:00:00 2001 From: Erik Marr Date: Tue, 21 Jun 2022 10:51:57 -0500 Subject: [PATCH 207/776] Updating for PREX 4.0.0 --- src/_data/mde.yml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/_data/mde.yml b/src/_data/mde.yml index 7cafda503c5..e964aeedd4e 100644 --- a/src/_data/mde.yml +++ b/src/_data/mde.yml @@ -915,7 +915,7 @@ extensions: name: Product Recommendations versions: - - name: 3.3.7 + name: 4.0.0 support: 2.4.4: supported 2.4.3: supported @@ -930,6 +930,22 @@ extensions: 2.3.2: supported 2.3.1: supported 2.3.0: supported + - + name: 3.3.7 + support: + 2.4.4: compatible + 2.4.3: compatible + 2.4.2: compatible + 2.4.1: compatible + 2.4.0: compatible + 2.3.7: compatible + 2.3.6: compatible + 2.3.5-p1: compatible + 2.3.4: compatible + 2.3.3: compatible + 2.3.2: compatible + 2.3.1: compatible + 2.3.0: compatible - name: 3.3.6 support: From e8719212964bec88467c70abd3c8a2c88d495984 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Tue, 21 Jun 2022 11:37:50 -0500 Subject: [PATCH 208/776] ACP2E-927: Update the documentation with new PHP8 Attributes features in integration tests annotations --- .../attributes/magento-data-fixture.md | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md index e283630c102..14c5e0c2b89 100644 --- a/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md +++ b/src/guides/v2.4/test/integration/attributes/magento-data-fixture.md @@ -134,6 +134,53 @@ Fixtures must be written in the way that they only use one API to generate data. a product should only invoke the "Create Product" API and return the product created. This fixture should not add any extra logic beyond the "create product" API capabilities, such logic should be implemented in a separate fixture. +### Examples + +Example 1: + +```php?start_inline=1 +class QuoteTest extends \PHPUnit\Framework\TestCase +{ + + #[ + DataFixture(ProductFixture::class, as: 'p'), + DataFixture(GuestCartFixture::class, as: 'cart'), + DataFixture(AddProductToCartFixture::class, ['cart_id' => '$cart.id$', 'product_id' => '$p.id$', 'qty' => 2]), + DataFixture(SetBillingAddressFixture::class, ['cart_id' => '$cart.id$']), + DataFixture(SetShippingAddressFixture::class, ['cart_id' => '$cart.id$']), + ] + public function testCollectTotals(): void + { + } +} +``` + +Example 2: + +```php?start_inline=1 +class PriceTest extends \PHPUnit\Framework\TestCase +{ + #[ + DataFixture(ProductFixture::class, ['sku' => 'simple1', 'price' => 10], 'p1'), + DataFixture(ProductFixture::class, ['sku' => 'simple2', 'price' => 20], 'p2'), + DataFixture(ProductFixture::class, ['sku' => 'simple3', 'price' => 30], 'p3'), + DataFixture(BundleSelectionFixture::class, ['sku' => '$p1.sku$', 'price' => 10, 'price_type' => 0], 'link1'), + DataFixture(BundleSelectionFixture::class, ['sku' => '$p2.sku$', 'price' => 25, 'price_type' => 1], 'link2'), + DataFixture(BundleSelectionFixture::class, ['sku' => '$p3.sku$', 'price' => 25, 'price_type' => 0], 'link3'), + DataFixture(BundleOptionFixture::class, ['product_links' => ['$link1$', '$link2$', '$link3$']], 'opt1'), + DataFixture( + BundleProductFixture::class, + ['sku' => 'bundle1','price' => 50,'price_type' => 1,'_options' => ['$opt1$']], + 'bundle1' + ), + ] + public function testBundleWithFixedPrice(): void + { + + } +} +``` + ### Fixture rollback A fixture that contains database transactions only are reverted automatically. From 2d9ce14f98d5ebc03fc008cb5bdb9c7a9834d882 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 21 Jun 2022 15:16:52 -0500 Subject: [PATCH 209/776] Replaced 2.4 symlinks --- .../frontend-dev-guide/cache_for_frontdevs.md | 72 +- .../v2.4/frontend-dev-guide/conventions.md | 34 +- .../css-guide/css_quick_guide_approach.md | 176 +- .../css-guide/css_quick_guide_mode.md | 151 +- .../css-guide/css_quick_guide_overview.md | 63 +- .../css-topics/css-critical-path.md | 63 +- .../css-topics/css-jquery.md | 24 +- .../css-topics/css-overview.md | 92 +- .../css-topics/css-practice.md | 77 +- .../css-topics/css-preprocess.md | 288 ++- .../css-topics/css-themes.md | 117 +- .../css-topics/css_debug.md | 130 +- .../css-topics/custom-preprocess-parent.md | 7 +- .../css-topics/custom_preprocess.md | 92 +- .../css-topics/gulp-sass.md | 111 +- .../css-topics/theme-ui-lib.md | 255 ++- .../layouts/layout-create.md | 70 +- .../layouts/layout-extend.md | 90 +- .../layouts/layout-override.md | 117 +- .../layouts/layout-overview.md | 134 +- .../layouts/layout-practice.md | 295 ++- .../layouts/layout-types.md | 493 ++++- .../layouts/product-layouts.md | 73 +- .../layouts/xml-instructions.md | 458 ++++- .../frontend-dev-guide/layouts/xml-manage.md | 766 +++++++- .../responsive-web-design/rwd-breakpoints.md | 91 +- .../responsive-web-design/rwd_css.md | 145 +- .../responsive-web-design/rwd_mobile.md | 64 +- .../responsive-web-design/rwd_overview.md | 39 +- .../responsive-web-design/rwd_practice.md | 48 +- .../templates/template-email-layout-handle.md | 56 +- .../templates/template-email.md | 418 +++- .../templates/template-override.md | 126 +- .../templates/template-overview.md | 29 +- .../templates/template-sample.md | 33 +- .../templates/template-walkthrough.md | 54 +- .../frontend-dev-guide/theme-best-practice.md | 88 +- .../themes/admin_theme_apply.md | 81 +- .../themes/admin_theme_create.md | 103 +- .../frontend-dev-guide/themes/debug-theme.md | 119 +- .../v2.4/frontend-dev-guide/themes/favicon.md | 64 +- .../frontend-dev-guide/themes/js-bundling.md | 163 +- .../themes/product-video.md | 101 +- .../frontend-dev-guide/themes/theme-apply.md | 92 +- .../frontend-dev-guide/themes/theme-create.md | 283 ++- .../themes/theme-inherit.md | 195 +- .../themes/theme-install.md | 54 +- .../themes/theme-overview.md | 28 +- .../themes/theme-structure.md | 306 ++- .../themes/theme-uninstall.md | 84 +- .../themes/theme-workflow.md | 105 +- .../tools/tools_overview.md | 14 +- .../frontend-dev-guide/tools/using_grunt.md | 139 +- .../translations/theme_dictionary.md | 78 +- .../translations/translate_practice.md | 67 +- .../translations/translate_theory.md | 163 +- .../validations/custom-form-validation.md | 145 +- .../validations/custom-validation.md | 99 +- .../validations/form-validation.md | 31 +- .../validations/rule-list.md | 1677 ++++++++++++++++- 60 files changed, 9570 insertions(+), 60 deletions(-) mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/cache_for_frontdevs.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/conventions.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_approach.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_mode.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_overview.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/css-topics/css-critical-path.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/css-topics/css-jquery.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/css-topics/css-overview.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/css-topics/css-practice.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/css-topics/css-preprocess.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/css-topics/css-themes.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/css-topics/css_debug.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/css-topics/custom-preprocess-parent.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/css-topics/custom_preprocess.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/css-topics/gulp-sass.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/css-topics/theme-ui-lib.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/layouts/layout-create.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/layouts/layout-extend.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/layouts/layout-override.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/layouts/layout-overview.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/layouts/layout-practice.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/layouts/layout-types.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/layouts/product-layouts.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/layouts/xml-instructions.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/layouts/xml-manage.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd-breakpoints.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_css.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_mobile.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_overview.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_practice.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/templates/template-email-layout-handle.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/templates/template-email.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/templates/template-override.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/templates/template-overview.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/templates/template-sample.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/templates/template-walkthrough.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/theme-best-practice.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/themes/admin_theme_apply.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/themes/admin_theme_create.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/themes/debug-theme.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/themes/favicon.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/themes/js-bundling.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/themes/product-video.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/themes/theme-apply.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/themes/theme-create.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/themes/theme-inherit.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/themes/theme-install.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/themes/theme-overview.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/themes/theme-structure.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/themes/theme-uninstall.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/themes/theme-workflow.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/tools/tools_overview.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/tools/using_grunt.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/translations/theme_dictionary.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/translations/translate_practice.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/translations/translate_theory.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/validations/custom-form-validation.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/validations/custom-validation.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/validations/form-validation.md mode change 120000 => 100644 src/guides/v2.4/frontend-dev-guide/validations/rule-list.md diff --git a/src/guides/v2.4/frontend-dev-guide/cache_for_frontdevs.md b/src/guides/v2.4/frontend-dev-guide/cache_for_frontdevs.md deleted file mode 120000 index 0c3c6571d1a..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/cache_for_frontdevs.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/frontend-dev-guide/cache_for_frontdevs.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/cache_for_frontdevs.md b/src/guides/v2.4/frontend-dev-guide/cache_for_frontdevs.md new file mode 100644 index 00000000000..4d4e730d584 --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/cache_for_frontdevs.md @@ -0,0 +1,71 @@ +--- +group: frontend-developer-guide +title: Cache overview +functional_areas: + - Frontend +--- + +{% include cache/page-cache-overview.md%} + +## Cache types + +The following cache types mostly have impact on frontend development process: + +| Cache type "friendly" name | Cache type code name | Description | +|----------------------------|----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Layout | `layout` | Compiled page layouts (that is, the layout components from all components). Clean or flush this cache type after modifying layout files. | +| Block HTML output | `block_html` | HTML page fragments per block. Clean or flush this cache type after modifying the view layer. | +| Page cache | `full_page` | Generated HTML pages. If necessary, Magento cleans up this cache automatically, but third-party developers can put any data in any segment of the cache. Clean or flush this cache type after modifying code level that affects HTML output. It’s recommended to keep this cache enabled because caching HTML improves performance significantly. | +| Translations | `translate` | Merged translations from all modules. | + + {:.bs-callout-info} +The full list of cache types can be found in the [Overview of cache types]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-cache.html#config-cli-subcommands-cache-clean-over) topic. + +## Clean cache {#clean_cache} + +To clean cache, run + +```bash +bin/magento cache:clean ... +``` + +To view the status of the cache, run: + +```bash +bin/magento cache:status +``` + +For more details about working with cache, see [Manage the cache]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-cache.html) + +## Clean static files cache {#clean_static_cache} + +You can clean generated static view files in any of the following ways: + +- In the [Admin](https://glossary.magento.com/magento-admin). Go to **System** > **Tools** > **Cache Management** and click **Flush [Static Files](https://glossary.magento.com/static-files) Cache**. + + {:.bs-callout-info} + This option is only available in `developer` mode. Refer to the [static view files overview]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-static-view.html#config-cli-static-overview) for more information. For more details about the Magento modes, see [Magento Modes]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-mode.html) + +- Manually by clearing the `pub/static` and `var/view_preprocessed` directories and subdirectories _except_ for `pub/static/.htaccess`. + + To clear the `pub/static` directory of all files except `.htaccess` (which is a hidden file), enter the following command: + + ```bash + rm -r pub/static/*/* + ``` + + To clear the `var/view_preprocessed`, enter the following command: + + ```bash + rm -r var/view_preprocessed/* + ``` + +- Several commands support an optional parameter `--clear-static-content`, which cleans generated static view files: + + - [`magento module:enable` and `magento module:disable`]({{ page.baseurl }}/install-gde/install/cli/install-cli-subcommands-enable.html) + - [`magento theme:uninstall`]({{ page.baseurl }}/install-gde/install/cli/install-cli-theme-uninstall.html) + - [`magento module:uninstall`]({{ page.baseurl }}/install-gde/install/cli/install-cli-uninstall-mods.html) + +## Clean static files {#clean_static} + +Besides the cached files, in theme development process developers also deal with other saved files - static view files that are preprocessed and published to the `var/view_preprocessed` and `pub/static` directories correspondingly. In most cases when working on a custom theme, for example, if you are only working on styles, you do not need to clean cache, but need to clean the previously preprocessed and published static view files. To clean them, run `grunt clean ` or manually clear the `pub/static` and `var/view_preprocessed` directories. diff --git a/src/guides/v2.4/frontend-dev-guide/conventions.md b/src/guides/v2.4/frontend-dev-guide/conventions.md deleted file mode 120000 index abcd230eac8..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/conventions.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/frontend-dev-guide/conventions.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/conventions.md b/src/guides/v2.4/frontend-dev-guide/conventions.md new file mode 100644 index 00000000000..c194b8acb9d --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/conventions.md @@ -0,0 +1,33 @@ +--- +group: frontend-developer-guide +title: Conventional notations used in this Guide +functional_areas: + - Frontend +--- + +## Conventional notations for paths to modules and themes + +Magento application components, including modules, themes, and language packages technically can be located anywhere under the Magento root directory. This refers to both, Magento default and custom components. + +The following relative paths are used for modules and themes: + +### `` + +[Theme](https://glossary.magento.com/theme) directory. Usually used when talking about custom themes, or any theme in general. + +For Magento out of the box [frontend](https://glossary.magento.com/frontend) themes, the absolute path usually is one of the following: + +- `app/design/frontend//` +- `vendor/magento/theme-frontend-` + +### `` + +Module directory. When talking about a particular Magento module, the following notation is used: ``, where `X` would indicate the module's name. The directory for module `X` in the Magento installation directory would be one of the following: + +- `app/code/Magento/X` +- `vendor/magento/module-x` + +For example, `` would resolve to one of the following: + +- `app/code/Magento/Checkout` +- `vendor/magento/module-checkout` diff --git a/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_approach.md b/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_approach.md deleted file mode 120000 index c9b014892c2..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_approach.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/css-guide/css_quick_guide_approach.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_approach.md b/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_approach.md new file mode 100644 index 00000000000..c6bedf2ed25 --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_approach.md @@ -0,0 +1,175 @@ +--- +group: frontend-developer-guide +title: Simple ways to customize a theme's styles +functional_areas: + - Frontend +--- +## What's in this topic + +Let's say you created a new [theme](https://glossary.magento.com/theme) inheriting from Magento Blank or Luma, and chose the [Less compilation mode]. What's next? Where to add the style changes? This topic gives quick answers. + +## Simplest way to extend parent styles {#simple_extend} + +To extend the parent theme's styles in your theme: + +1. In your theme directory, create a `web/css/source` sub-directory. +1. Create a `_extend.less` file there. The path to it looks like following: + + ```tree + / + │ ├── web/ + │ │ ├── css/ + │ │ │ ├── source/ + │ │ │ ├──_extend.less + ... + ``` + +1. Add your Less code in this file. + +However, the above only works if the theme's parent is a Blank. Consider a Theme A which is the child of Blank. Theme A has two children, B and C. A global style rule is added to the `_extend.less` file of theme A. This extends its parent Blank. Theme B and C also have their own `_extend.less` files. Theme B and C will override the parent (Theme A), rather than extending it further. Theme B & Theme C are extending their grandparent (Blank) and overriding their parent (Theme A) in this setup. + +In case of subsequent descendants of the child theme, you can avoid this behavior by following these steps: + +1. Create a `_extend-child.less` in both your parent and child themes. +1. Keep `_extend-child.less` empty in your parent theme and add it too your parent theme's `_extend.less` file. +1. Add a `@import '_extend-child.less'` rule to the end of your parent's theme's `_extend.less` file. +1. In your child theme, add `@import` or style rules in `_extend-child.less` to extend parent theme's CSS. + + ```tree + app/design/frontend/Vendor/ + ├── parent + │ └── web + │ └── css + │ └── source + │ ├── _extend-child.less (keep this file empty) + │ └── _extend.less + └── child + └── web + └── css + └── source + └── _extend-child.less + ... + ``` + +Extending a theme using `_extend.less` is the simplest option when you are happy with everything the parent theme has, but want to add more styles. + +{:.bs-callout-info} +The rules and variables declared in `_extend.less` always have precedence over ones declared in `_theme.less`. + +## Simplest way to override parent styles {#simple_override} + +To override parent styles (that is, override default Magento UI [library](https://glossary.magento.com/library) variables): + +1. In your theme directory, create a `web/css/source` sub-directory. +1. Create a `_theme.less` file here. The path to it then looks like following: + + ```tree + / + │ ├── web/ + │ │ ├── css/ + │ │ │ ├── source/ + │ │ │ ├──_theme.less + ... + ``` + + It is important to remember that your `_theme.less` overrides the parent `_theme.less`. + +1. Copy all variables you need from the parent `_theme.less`, including those which will not be changed. For example, if your theme inherits from Blank, the `_theme.less` you should copy from is located at `/web/css/source/_theme.less`. +1. Make the necessary changes. + +The drawback of this approach is that you need to monitor and manually update your files whenever the parent's `_theme.less` is updated. + +## Adding structured changes {#structured_changes} + +To make your changes easier to read and support, structure them by adding a separate overriding or extending `.less` files for each [Magento UI library component] you change. Let's use the `button` component implemented in `_button.less` as an illustration. + +### Extend component's styles {#structured_extend} + +1. In your theme directory, create a `web/css/source` sub-directory. +1. Add `_buttons_extend.less` and `_extend.less` here. The path to the files looks like following: + + ```tree + + │ ├── web/ + │ │ ├── css/ + │ │ │ ├── source/ + │ │ │ ├──_buttons_extend.less + │ │ │ ├──_extend.less + ... + ``` + +1. In `_buttons_extend.less` add your styles for the button component. +1. In `_extend.less` register the `_buttons_extend.less` by adding the following code: `@import '_buttons_extend.less';` + +### Override component's styles {#structured_override} + +To override the parent theme's styles for buttons in your theme: + +1. In your theme directory, create a `web/css/source` sub-directory. +1. Create a `_buttons.less` file here. The path to it looks like following: + + ```tree + / + │ ├── web/ + │ │ ├── css/ + │ │ │ ├── source/ + │ │ │ ├──_buttons.less + ... + ``` + + This file overrides the `_buttons.less` of the parent theme. + +1. Add your styles for the button component. If the file is left blank, then no styles are applied for the component. + +### Extend module styles + +To extend a Module's styles in your theme: + +1. In your theme directory, create a `Module_Name/web/css/source` directory. +1. Create an `_extend.less` file in the theme directory. For example: + + ```tree + / + ├── / + │ ├── web/ + │ │ ├── css/ + │ │ │ ├── source/ + ├──_extend.less + ... + ``` + +1. Add additional styles in the `_extend.less` file. + +For example, to extend the Magento_Review module's style, the directory path should be `/Magento_Review/web/css/source/_extend.less`. + +### Override module styles + +To override module styles in your theme: + +1. In your theme directory, create a `Module_Name/web/css/source` directory. +1. Create a `_module.less` file in the theme directory. For example: + + ```tree + / + ├── / + │ ├── web/ + │ │ ├── css/ + │ │ │ ├── source/ + | | | ├──_module.less + ... + ``` + + This file overrides the `_module.less` file of the specific module. + +1. Add your styles in the `_module.less` file. + +For example, to override the Magento_Review module's style, the directory path should be `/Magento_Review/web/css/source/_module.less`. + +## Recommended reading + +- [Compile Less with Grunt]({{page.baseurl}}/frontend-dev-guide/css-topics/css_debug.html) +- [CSS preprocessing]({{page.baseurl}}/frontend-dev-guide/css-topics/css-preprocess.html) +- [Magento UI library]({{page.baseurl}}/frontend-dev-guide/css-topics/theme-ui-lib.html) + +[Less compilation mode]: {{page.baseurl}}/frontend-dev-guide/css-guide/css_quick_guide_mode.html +[Magento UI library component]: {{page.baseurl}}/frontend-dev-guide/css-topics/theme-ui-lib.html#library_elements diff --git a/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_mode.md b/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_mode.md deleted file mode 120000 index 6018aee14fe..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_mode.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/css-guide/css_quick_guide_mode.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_mode.md b/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_mode.md new file mode 100644 index 00000000000..b709e42a222 --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_mode.md @@ -0,0 +1,150 @@ +--- +group: frontend-developer-guide +title: Simple style changes with client-side LESS compilation vs. server-side +functional_areas: + - Frontend +--- + +After you [create a theme]({{ page.baseurl }}/frontend-dev-guide/themes/theme-create.html), you need to decide which LESS compilation mode to use before changing styles. You can choose between [two modes]({{ page.baseurl }}/frontend-dev-guide/css-topics/css-preprocess.html): + +- **Server-side compilation mode (default):** less file is compiled with PHP less library. In developer mode, PHP will generate the CSS files on the fly provided there is not one already. Running static content deploy will compile the stylesheet. + +- **Client-side compilation mode (recommended for [theme](https://glossary.magento.com/theme) development):** Less file is compiled client-side on every page load, which results in slow response times and "flash of unstyled text" (FOUT) issues. + +The examples in this topic use the [simple approach]({{ page.baseurl }}/frontend-dev-guide/css-guide/css_quick_guide_approach.html#simple_extend) for customizing theme styles. You make changes to the `_extend.less` file. + +In our examples, we will change the color and font of the primary buttons. The default view of the primary buttons can be illustrated by the **Create an Account** button view on the Customer login page: + +![Admin login page with the default view of the primary buttons]({{ site.baseurl }}/common/images/extend_less_screenshot21.png) + +## Before you begin + +1. [Create a theme]({{ page.baseurl }}/frontend-dev-guide/themes/theme-create.html). In your `theme.xml` file, specify Magento Luma or Magento Blank as the parent theme. +1. [Apply your theme]({{ page.baseurl }}/frontend-dev-guide/themes/theme-apply.html#theme-apply-apply) in the [Admin](https://glossary.magento.com/magento-admin). + +## Using server-side compilation mode + +The following is an illustration of how the process of making simple changes looks like with the server-side LESS compilation mode: + +1. Navigate to your theme directory and add the `web/css/source/_extend.less` file. +1. Change the color of the buttons by adding the following code in the `_extend.less` file: + + ```less + .action { + &.primary { + background-color: palevioletred; + border-color: palevioletred; + } + } + ``` + +1. [Clean static files cache]({{ page.baseurl }}/frontend-dev-guide/cache_for_frontdevs.html#clean_static_cache). +1. Refresh the page and verify your changes. + + ![Less code redefining the color of the primary buttons]({{ site.baseurl }}/common/images/extend_less_screenshot121.png) + +1. Change the button font size by adding the following code in the `_extend.less` file: + + ```less + .action { + &.primary { + background-color: palevioletred; + border-color: palevioletred; + font-size: 1.5em; + } + } + ``` + +1. Delete all files in the following directories: + + - `pub/static/frontend//` + - `var/view_preprocessed/pub/static/frontend//` + +1. Refresh the page and verify your changes. + + ![Admin login page where the font of the buttons was changed]({{ site.baseurl }}/common/images/extend_less_screenshot221.png) + +{:.bs-callout-info} +If you are using server-side compilation mode, you must [clean generated static view files]({{ page.baseurl }}/frontend-dev-guide/cache_for_frontdevs.html#clean_static_cache). Continue to the next section to learn how to use Grunt to automate this process. + +## Using server-side compilation mode with Grunt + +1. Navigate to your theme directory and create a `web/css/source/_extend.less` file. +1. Install Grunt and register your theme as described in [Installing and configuring Grunt]({{ page.baseurl }}/frontend-dev-guide/tools/using_grunt.html#grunt_prereq). +1. From your Magento installation directory, run the following commands: + + - `grunt exec:` + - `grunt less:` + - `grunt watch` + +1. Change the color of the buttons by adding the following code in the `_extend.less` file: + + ```less + .action { + &.primary { + background-color: palevioletred; + border-color: palevioletred; + } + } + ``` + +1. Refresh the page and verify your changes. + + ![Admin login page where the color of the button was changed]({{ site.baseurl }}/common/images/extend_less_screenshot121.png) + +1. Change the button font size by adding the following code in the `_extend.less` file: + + ```less + .action { + &.primary { + background-color: palevioletred; + border-color: palevioletred; + font-size: 1.5em; + } + } + ``` + +1. Refresh the page and verify your changes. + + ![Admin login page where the font of the buttons was changed]({{ site.baseurl }}/common/images/extend_less_screenshot221.png) + +## Using client-side compilation mode + +1. Navigate to your theme directory and create a `web/css/source/_extend.less` file. +1. Log in to the Admin. +1. Click **STORES** > **Settings** > **Configuration** > **ADVANCED** > **Developer** > **Frontend development workflow** > **Workflow type**. +1. Change the LESS compilation mode to client-side. +1. [Clean static view files]({{ page.baseurl }}/frontend-dev-guide/cache_for_frontdevs.html#clean_static_cache). +1. Change the color of the buttons by adding the following code in the `_extend.less` file: + + ```less + .action { + &.primary { + background-color: palevioletred; + border-color: palevioletred; + } + } + ``` + +1. Refresh the page and verify your changes. + + ![Admin login page where the font of the buttons was changed]({{ site.baseurl }}/common/images/extend_less_screenshot121.png) + +1. Change the button font size by adding the following code in the `_extend.less` file: + + ```less + .action { + &.primary { + background-color: palevioletred; + border-color: palevioletred; + font-size: 1.5em; + } + } + ``` + +1. Refresh the page and verify your changes. + + ![Admin login page where the font of the buttons was changed]({{ site.baseurl }}/common/images/extend_less_screenshot221.png) + +{:.bs-callout-info} +When your Magento instance is in client-side Less compilation mode, simple changes are applied after saving or refreshing the page. For more sophisticated changes, you may need to manually clean the theme sub-directory in the `pub/static/frontend` directory and generate a new deployment. See [Styles debugging]({{ page.baseurl }}/frontend-dev-guide/css-topics/css_debug.html). diff --git a/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_overview.md b/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_overview.md deleted file mode 120000 index bdc7c5ea47e..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_overview.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/css-guide/css_quick_guide_overview.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_overview.md b/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_overview.md new file mode 100644 index 00000000000..1fb8f89c971 --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_overview.md @@ -0,0 +1,62 @@ +--- +group: frontend-developer-guide +title: Quick start guide to working with styles for a new theme +functional_areas: + - Frontend +--- + +This chapter combines the topics aiming to help you to quickly start working with styles of your custom theme: + +- [Simple ways to customize a theme's styles] +- [Simple style changes with client-side Less compilation vs. server-side] + +## High-level steps to create a theme and change styles + +1. [Set] your Magento application to the developer [mode]. +1. In the file system, [add a new theme] inheriting from Magento Blank or Luma. +1. [Apply your theme] +1. Decide which CSS compilation mode you will use. Compilation modes are described in the following topics: + - Detailed description: [Styles debugging] + - Practical illustration: [Simple style changes with client-side Less compilation vs. server-side] +1. Customize styles. To learn how, check out the following sources: + - [CSS chapter of this book][css overview] + - [Simple ways to customize a theme's styles] + +## Why do you need to create a custom theme? + +Magento provides two themes out of the box: Blank and Luma. If Magento is installed with sample data, the theme applied after installation is Luma. If no sample data is installed, the Blank theme is installed by default. + +![Storefront with Luma applied] + +Luma inherits from Blank, which contains all the basic functionality and styling required for a theme. + +You can use either Luma or Blank for your storeview, if there is literally nothing you want to change in their design. + +But if there is something you want to improve, the only recommended way is creating a new theme. It can inherit from Blank or Luma so you can preserve all you need, and change or add whatever is required. + +Making changes in the Magento out-of-the-box themes is a bad idea, because can result in your changes being overwritten during upgrade. + +{:.ref-header} +Related topics + +- [CSS in Magento themes][css overview] +- [Simple ways to customize a theme's styles] +- [Simple style changes with client-side Less compilation vs. server-side] + + +[Simple ways to customize a theme's styles]: {{ page.baseurl }}/frontend-dev-guide/css-guide/css_quick_guide_approach.html +[Simple style changes with client-side Less compilation vs. server-side]: {{ page.baseurl }}/frontend-dev-guide/css-guide/css_quick_guide_mode.html +[Set]: {{ page.baseurl }}/config-guide/cli/config-cli-subcommands-mode.html +[mode]: {{ page.baseurl }}/config-guide/bootstrap/magento-modes.html +[add a new theme]: {{ page.baseurl }}/frontend-dev-guide/themes/theme-create.html + +[Apply your theme]: {{ page.baseurl }}/frontend-dev-guide/themes/theme-apply.html + +[Styles debugging]: {{ page.baseurl }}/frontend-dev-guide/css-topics/css_debug.html +[Simple style changes with client-side Less compilation vs. server-side]: {{ page.baseurl }}/frontend-dev-guide/css-guide/css_quick_guide_mode.html +[css overview]: {{ page.baseurl }}/frontend-dev-guide/css-topics/css-overview.html +[Simple ways to customize a theme's styles]: {{ page.baseurl }}/frontend-dev-guide/css-guide/css_quick_guide_approach.html +[Simple style changes with client-side Less compilation vs. server-side]: {{ page.baseurl }}/frontend-dev-guide/css-guide/css_quick_guide_mode.html + + +[Storefront with Luma applied]: {{ site.baseurl }}/common/images/css_guide_luma21.png diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-critical-path.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-critical-path.md deleted file mode 120000 index 19a8c94a928..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/css-critical-path.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/css-topics/css-critical-path.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-critical-path.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-critical-path.md new file mode 100644 index 00000000000..597ecf10d37 --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/css-critical-path.md @@ -0,0 +1,62 @@ +--- +group: frontend-developer-guide +title: CSS critical path +functional_areas: + - Frontend +--- + +All CSS styles loaded from external files are considered as render-blocking. This means that a web page will not be displayed until these files are loaded. +By using 'CSS critical path', we deliver minified critical CSS inline in `` and defer all non-critical styles that are loaded asynchronously. +Thus we can significantly improve the time to first render of our pages. + +## Enable CSS critical path + + {:.bs-callout-info} +CSS critical path configuration is located on the **Stores** > Settings > **Configuration** > **ADVANCED** > **Developer** tab. However, the **Developer** tab is hidden in [production mode]({{page.baseurl}}/config-guide/bootstrap/magento-modes.html). Once in production mode, CSS critical path can only be enabled using the CLI. + +To enable the CSS critical path: + +```bash +bin/magento config:set dev/css/use_css_critical_path 1 +``` + +Make sure that there is a `critical.css` file for your theme. Other non-critical CSS files will be loaded asynchronously. + +## Overview of Magento's critical CSS + +The 'critical' CSS file should be located in `app/design/frontend///web/css/critical.css` +The default Luma theme critical CSS file is located in `app/design/frontend/Magento/luma/web/css/critical.css` +If there is not a `critical.css` file for the custom theme, but there is one for the Luma theme, Luma's `critical.css` will be used. +The critical css file path can also be configured in `di.xml` as a constructor `filePath` argument in the `Magento\Theme\Block\Html\Header\CriticalCss` block. + +To generate a critical CSS for your theme, critical path CSS generators like [Penthouse](https://www.npmjs.com/package/penthouse) or [Critical](https://www.npmjs.com/package/critical) can be used, or you can create it yourself. While creating critical CSS, adhere to the following principles: + +- Minify your `critical.css` to reduce its size. +- Do not duplicate styles in `critical.css` and non-critical style sheets. +- Do not introduce new styles in `critical.css` that are not present in non-critical style sheets. CSS rules from non-critical style sheets should overwrite critical CSS rules. Otherwise your styles can be broken. + +### Critical CSS loader + +If 'CSS critical path' is enabled in the configuration, a preloading spinner will be used. It is added in `Magento/Theme/view/frontend/layout/default.xml`. +After non-critical CSS is loaded and applied, the spinner disappears. The spinner will disappear automatically only if you have CSS styles from the 'Blank' theme CSS. If you have your own CSS rules, you should hide the preloader by using the `data-role='main-css-loader'` attribute. + +## Critical CSS performance improvements + +Introducing a critical path CSS to Magento leads to performance improvements: + +- Eliminated render-blocking CSS resources. As a result, the time for loading render-blocking resources decreases substantially. + + ![CSS resources eliminated as render-blocking]({{ site.baseurl }}/common/images/critical_css_improvements1.png) + +- The first meaningful paint time improved from 3.5 seconds to 2.3 seconds. + + ![First meaningful paint time improved]({{ site.baseurl }}/common/images/critical_css_improvements2.png) + +- The speed index increased by 0.8 seconds. + + ![Speed index increased]({{ site.baseurl }}/common/images/critical_css_improvements3.png) + +As a result, the Google PageSpeed Insights score improved by **5** points. + + {:.bs-callout-info} +These are results for mobile devices with slow connection from [Google PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights/). diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-jquery.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-jquery.md deleted file mode 120000 index 69342a62fdc..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/css-jquery.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/css-topics/css-jquery.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-jquery.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-jquery.md new file mode 100644 index 00000000000..de2d5dae2bd --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/css-jquery.md @@ -0,0 +1,23 @@ +--- +group: frontend-developer-guide +title: Using jQuery UI styles +functional_areas: + - Frontend +--- + +## What's in this topic + +This topic provides an overview of how jQuery UI styles are used in Magento out of the box, and how you can use them in a custom [theme](https://glossary.magento.com/theme). + +## jQuery UI styles used on the storefront + +In Magento out of the box certain [storefront](https://glossary.magento.com/storefront) elements are implemented using jQuery UI widgets (like navigation menu, mini [shopping cart](https://glossary.magento.com/shopping-cart) and so on), with the default jQuery classes assigned. But Magento does not contain jQuery UI styles in the code base. Styles for the certain default jQuery UI classes are defined in Magento by default (in the default Magento storefront and [Admin](https://glossary.magento.com/admin) themes). For other jQuery UI classes styles are not defined. + +We do not recommend downloading the jQuery UI styles as is, because they will override the default Magento themes definitions and break the default Magento design. + +To use the jQuery styles, you need to define those which you need in your custom stylesheets in the `/web/css` directory. + +## Recommended reading + +- [Define what styles you need to change]({{ page.baseurl }}/frontend-dev-guide/themes/debug-theme.html#debug-theme-style) +- [Quick start guide to working with styles for a new theme]({{ page.baseurl }}/frontend-dev-guide/css-guide/css_quick_guide_overview.html) diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-overview.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-overview.md deleted file mode 120000 index f284a5f72ba..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/css-overview.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/css-topics/css-overview.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-overview.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-overview.md new file mode 100644 index 00000000000..a79ee2df52f --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/css-overview.md @@ -0,0 +1,91 @@ +--- +group: frontend-developer-guide +title: Cascading style sheets (CSS) +functional_areas: + - Frontend +--- + +## Overview + +Magento 2 incorporates [Less](http://lesscss.org/), a CSS pre-processor that simplifies the management of complex CSS files. +To define styles of a Magento store, you can use both - CSS and Less stylesheets. + +Magento application provides a built-in Less UI library, which you can optionally extend. + +To customize [storefront](https://glossary.magento.com/storefront) styles, you need to [create a custom design theme]({{ page.baseurl }}/frontend-dev-guide/themes/theme-create.html). Then you can use one of the following approaches: + +* If your theme [inherits]({{ page.baseurl }}/frontend-dev-guide/themes/theme-inherit.html) from the Magento out-of-the-box Blank or Luma theme, you can override the default Less files. For example, to [change the values of the variables]({{ page.baseurl }}/frontend-dev-guide/css-topics/theme-ui-lib.html#fedg_using-ui-lib_predef-vars) used in the default files. +* Create your own Less files using the built-in Less preprocessor. +* Create your own CSS files, optionally having compiled them using third-party CSS preprocessor. + +## Things to remember when working with styles + +* Make sure that you [set]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-mode.html) your Magento application to the developer or default [mode]({{ page.baseurl }}/config-guide/bootstrap/magento-modes.html). + +* If your style changes do not apply after refreshing the page, cleaning the static files cache might help. See the [Clean static files cache topic]({{ page.baseurl }}/frontend-dev-guide/cache_for_frontdevs.html#clean_static_cache) for instructions how to do this. + +### CSS merging, minification and performance + +There are a couple options to help with CSS and site performance. + +* Merge CSS files to decrease the number of HTTP requests required to load the page. + +* Minification of CSS files reduces the file size being sent. It does this by stripping white space within the file. + +* Use CSS critical path to eliminate render-blocking CSS resources. + +To enable / disable these settings, go into Admin > **Stores** > Setting > **Configuration** > **Advanced** > **Developer** > **CSS Settings**. + +## Change styles: walkthrough {#css_walk} + +Here is a simple illustration of changing styles using the first approach: changing the color of the buttons of a certain class. +In the Blank theme, the buttons of the `.action.primary` class, so called *primary* buttons, are blue. The following image illustrates this: + +![The default view of a product page, with the orange Add to Cart button] + +ExampleCorp wants to change the color of the primary buttons to orange. To achieve this, they do the following: + +1. Create a new Orange theme, which inherits from the Blank [theme](https://glossary.magento.com/theme). +1. In the Orange theme directory add the overriding `app/design/frontend/ExampleCorp/orange/web/css/source/_theme.less` file with the following code: + + ```less + // Primary button + @button-primary__color: @color-white; + @button-primary__hover__color: @color-white; + @button-primary__background: @color-orange-red1; + @button-primary__hover__background: @color-orange-red4; + @button-primary__border: 1px solid @color-orange-red2; + @button-primary__hover__border: 1px solid @color-orange-red2; + ``` + +ExampleCorp wants to change the color of the primary buttons to a custom color. In the orange theme directory add the overriding `app/design/frontend/ExampleCorp/orange/web/css/source/_theme.less` file with the following code: + + ```less + // Primary button + @btn-color-text: #2e3138; + @btn-color-background: #d5d7dd; + @btn-color-background-hover: #d9dbe0; + @button-primary__color: @btn-color-text; + @button-primary__hover__color: @btn-color-text; + @button-primary__background: @btn-color-background; + @button-primary__hover__background: @btn-color-background-hover; + @button-primary__border: 1px solid @btn-color-background; + ``` + +When ExampleCorp [applies their theme]({{ page.baseurl }}/frontend-dev-guide/themes/theme-apply.html), the primary buttons will look like on the following image: + +![The customized view of a product page, with the grey Add to Cart button] + +## In this chapter {#css_topics} + +Other topics of this chapter describe the following: + +* [Including CSS]({{ page.baseurl }}/frontend-dev-guide/css-topics/css-themes.html): how stylesheets are organized and included to be used for store pages in the Magento application. +* [CSS Preprocessing]({{ page.baseurl }}/frontend-dev-guide/css-topics/css-preprocess.html): how stylesheets are preprocessed and compiled. +* [Magento UI Library]({{ page.baseurl }}/frontend-dev-guide/css-topics/theme-ui-lib.html): how to use the Magento styles [library](https://glossary.magento.com/library) in your custom themes. +* [Using Custom Fonts]({{ page.baseurl }}/frontend-dev-guide/css-topics/using-fonts.html): how to add custom fonts. +* [CSS critical path]({{ page.baseurl }}/frontend-dev-guide/css-topics/css-critical-path.html): how to use CSS critical path. +* [Customizing styles illustration]({{ page.baseurl }}/frontend-dev-guide/css-topics/css-practice.html): how to change a theme's color scheme using Magento UI library. + +[The default view of a product page, with the orange Add to Cart button]: {{site.baseurl}}/common/images/css_over1.png +[The customized view of a product page, with the grey Add to Cart button]: {{site.baseurl}}/common/images/css_over2.png diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-practice.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-practice.md deleted file mode 120000 index 446ef862ad8..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/css-practice.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/css-topics/css-practice.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-practice.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-practice.md new file mode 100644 index 00000000000..69f710fd0d2 --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/css-practice.md @@ -0,0 +1,76 @@ +--- +group: frontend-developer-guide +title: Customizing styles illustration +functional_areas: + - Frontend +--- + +## What is in this topic {#practice_over} + +This topic features a step-by-step illustration of how to change a theme's color scheme using Magento UI library. + +## Changing theme color scheme + +ExampleCorp created a custom theme that inherits from the Magento basic Blank theme. +The following image illustrates how store pages look when the Blank theme is applied: + +![product page when Blank applied] + +In their Grey theme, ExampleCorp wants to change the color scheme from white to grey. + +The Grey theme directory is `app/design/frontend/ExampleCorp/grey`. + +ExampleCorp decided to use the Magento UI library, so to change the color scheme, they need to define new values for certain default Less variables. +To do this, they added an overriding `_theme.less` file in the `app/design/frontend/ExampleCorp/grey/web/css/source` directory, with the following content: + +```less +// Color nesting +@page__background-color: @color-gray20; +@sidebar__background-color: @color-gray40; +@primary__color: @color-gray80; +@border-color__base: @color-gray76; + +@link__color: @color-gray56; +@link__hover__color: @color-gray60; + +// Buttons +@button__color: @color-gray20; +@button__background: @color-gray80; +@button__border: 1px solid @border-color__base; + +// Primary button +@button-primary__background: @color-orange-red1; +@button-primary__border: 1px solid @color-orange-red2; +@button-primary__color: @color-white; +@button-primary__hover__background: darken(@color-orange-red1, 5%); +@button-primary__hover__border: 1px solid @color-orange-red2; +@button-primary__hover__color: @color-white; + +// Navigation +@navigation-level0-item__color: @color-gray80; +@submenu-item__color: @color-gray80; + +@navigation__background: @color-gray40; +@navigation-desktop-level0-item__color: @color-gray80; +@navigation-desktop-level0-item__hover__color: @color-gray34; +@navigation-desktop-level0-item__active__color: @navigation-desktop-level0-item__color; + +// Tabs +@tab-control__background-color: @page__background-color; + +// Forms +@form-element-input__background: @color-gray89; +@form-element-input-placeholder__color: @color-gray60; + +// Header icons +@header-icons-color: @color-gray89; +@header-icons-color-hover: @color-gray60; +``` + +After the Grey theme is applied (and [static files cache cleared]), store pages will look like following: + +![product page when Grey applied] + +[product page when Blank applied]: {{site.baseurl}}/common/images/practice_blank.png +[product page when Grey applied]: {{site.baseurl}}/common/images/css_practice.png +[static files cache cleared]: {{page.baseurl}}/frontend-dev-guide/cache_for_frontdevs.html#clean_static_cache diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-preprocess.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-preprocess.md deleted file mode 120000 index 4d5f2ea2f52..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/css-preprocess.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/css-topics/css-preprocess.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-preprocess.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-preprocess.md new file mode 100644 index 00000000000..473061f5d8b --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/css-preprocess.md @@ -0,0 +1,287 @@ +--- +group: frontend-developer-guide +title: How CSS and Less files are preprocessed and how to debug them +functional_areas: + - Frontend +--- + +## What's in this topic {#preproc_over} + +The topic describes how stylesheets are preprocessed and compiled to [CSS](https://glossary.magento.com/css) in the Magento application. It provides the theoretical background a [frontend](https://glossary.magento.com/frontend) developer needs to debug stylesheets effectively. + +## Terms used {#css_preprocess_terms} + + + + + + + + + + +
    + Term + + Description +
    +

    Root source files

    +
    + The .less files from which the .css files included in layout are compiled. For example, in one of the layout files of the Magento Blank theme, the following .css files are included in the head: +
    +<head>
    +    <css src="css/styles-m.css"/>
    +    <css src="css/styles-l.css" media="screen and (min-width: 768px)"/>
    +    <css src="css/print.css" media="print"/>
    +</head>
    +
    + The root source files for the Blank theme: + +
    + +## Less compilation modes {#less_modes} + +In the Magento application, the following modes of compiling `.less` files to CSS are implemented: + +1. Server-side Less compilation. + + This is the default compilation mode, and is the only option in [production application mode]. In this case the compilation is performed on the server, using the [Less PHP library]. + +1. Client-side Less compilation. + + When your application is not in the production mode, you can set Magento to compile `.less` files in a browser, using the [native `less.js` library] + +To set the compilation mode, do the following: + +1. In the Admin, navigate to **Stores** > **Settings** > **Configuration** > ADVANCED > **Developer**. +1. In the **Store View** drop-down field, select **Default Config**. +1. Under **Frontend development workflow**, in the **Workflow type** field, select the compilation mode. +1. To save the settings, click **Save Config**. + +### Server-side Less compilation {#server-side} + +The following paragraph describes how the Less preprocessor works in server-side compilation mode. +For each CSS file included in the layouts, Less preprocessor does the following: + +1. Checks if the requested `.css` file is found. If it is found, the preprocessor stops its execution. Otherwise, it proceeds to the next step. +1. Changes the extension of the requested file to `.less` and tries to find the file using the [Magento fallback mechanism]. If the `.less` file is not found, Less preprocessor stops its execution. Otherwise, it proceeds to the next step. +1. Reads `.less` file contents and resolves [`@magento_import`](#fedg_css-magento-import) and default Less `@import` directives. + +1. Resolves all paths in `.less` files to relative paths in the system using the Magento fallback mechanism. All files resolved by the Less preprocessor are copied to `var/view_preprocessed/less`. Imported files are processed recursively. + +1. All source files are passed to the PHP Less compiler. The resulting compiled `.css` files are published to `pub/static/frontend///`. + +#### Styles debugging in server-side compilation mode {#css_debug_server} + +In server-side Less compilation mode, to have your changes applied, you need to do the following: + +1. Clear `pub/static/frontend///` by deleting the directory in the file system (excluding .htaccess). +1. Clear the `var/cache` and `var/view_preprocessed` directories by deleting the directory in the file system. (if they already existed there). +1. Trigger [static files](https://glossary.magento.com/static-files) compilation and publication. This can be done in one of the following ways: + + - Reloading the page where the modified styles are applied. + - Running the [static files deployment tool]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-static-view.html). + +Reloading the page only triggers compilation and publication of the styles used on this very page, and does not give you the information about the errors if any. So if you made changes in `.less` files used on many pages, and want to debug them, using the deployment tool is the better option. + +##### Debugging using the static view files deployment tool + +Once you save your changes, run the following command from your `` directory: + +```bash +bin/magento setup:static-content:deploy +``` + +To generate frontend static view files in all languages: + +```bash +bin/magento setup:static-content:deploy --area frontend +``` + +To generates backend static view files: + +```bash +bin/magento setup:static-content:deploy --area adminhtml +``` + +The tool pre-processes (including compilation) and publishes the static view files. + +{:.bs-callout-info} +Manual static content deployment is not required in "default" and "developer" modes. If you still want to deploy in these modes, use the -f option: `bin/magento setup:static-content:deploy -f`. Read more about the command in the [Deploy static view files]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-static-view.html) section. + +All errors occurring during `.less` files compilation are handled by the [LESS PHP library][] third party library. + +{:.bs-callout-info} +Since Magento 2.3.3, `oyegorge/less.php` has been replaced by `wikimedia/less.php` + +Errors are caught as exceptions and written to the system log (by default it is `var/log/system.log`) and displayed on the screen. For each error, the following information is written: + +- The path to the processed file in the `var/view_preprocessed` directory. +- The error description, including the path to file where the actual error occurred. It might be either the processed file, or the imported file. +- The error line and the column number. +- The content of the `.less` code in the previous and following lines. + +Example of an error message: + +```terminal +Compilation from source: /var/www/magento2/app/design/adminhtml/Magento/backend/web/css/styles.less +variable @variable-x is undefined in file /var/www/magento2/var/view_preprocessed/css/adminhtml/Magento/backend/en_US/css/styles.less in styles.less on line 56, column 17 + margin-left: 0; + width: 100%; + height: @variable-x; + } + .menu-wrapper, +``` + +##### Debugging using Grunt + +Alternatively, to streamline the process of applying and debugging styles customizations, in server-side compilation mode, you can + +See the [Compile LESS with Grunt]({{ page.baseurl }}/frontend-dev-guide/css-topics/css_debug.html) topic for details how to install, configure and use Grunt. + +### Client-side LESS compilation {#client-side} + +The client-side compilation flow is similar to [server-side](#server-side). The difference is in the set of files, published to `pub/static` on the last step. In the client-side mode, the following files are published to the `pub/static/frontend///` directory: + +- root source (.less) files with resolved `@magento_import` directive +- [symlinks](http://en.wikipedia.org/wiki/Symbolic_link) to the root source file that do not contain `@magento_import` +- symlinks to all other `.less` files imported recursively by the `@magento_import` and `@import` directives + +{:.bs-callout-info} +Symlink is not created, and a copy of the processed file is published to `pub/static` instead, if the source file differs from the processed one. One of the reasons of this difference might be the usage of the `@import` directive without file extension in the source file. See [The @import directive usage](#fedg_css-import) for more details. + +#### Styles debugging in client-side compilation mode {#css_debug_client} + +Client-side LESS compilation is implemented using the native `less.js` library. The default configuration is set in `lib/web/less/config.less.js`; you can change it as needed. + +You can find the detailed information about the configuration and other options of the `less.js` used in a browser at [http://lesscss.org/usage/#using-less-in-the-browser](http://lesscss.org/usage/#using-less-in-the-browser). + +In client-side compilation mode, most of the stylesheet customizations display immediately after you reload a page in a browser. + +With client-side compilation mode enabled, LESS files are compiled on every page load. This reduces page-loading performance. + +##### When you need to clean static view files {#css_exception} + +There are certain types of changes, that require you to clear the `pub/static/frontend///` directory and trigger the compilation and [publication] processes anew. + +This is required in the following cases: + +- If you change the [root source files] that contain the `@magento_import` directive, or the `@import` directive where the imported file is specified without extension. +- If you rename, remove, or add a `.less` file imported with a `@magento_import` or `@import` directive but you did not correct the directives accordingly. + +To clear the `pub/static/frontend///` directory, delete the directory in the file system, and reload the store pages in a browser to trigger compilation and publication. + +## The `@import` directive rules of usage {#fedg_css-import} + +You can import local and remote `.less` and `.css` files in your `.less` Magento stylesheets by using the standard LESS [`@import` directive](http://lesscss.org/features/#import-directives-feature). +According to the `@import` syntax, specifying the file extension for the imported file is not mandatory. For example, the following notation is allowed: + +```less +@import 'source/lib/_lib'; +@import (css) 'styles'; +``` + +But in process of resolving the file path, Magento adds the `.less` extension for the imported files in all `@import` entrees. So in the processed files, the statements from the previous example will look like following: + +```less +@import 'source/lib/_lib.less'; +@import (css) 'styles.less'; +``` + +As a result, the processed files are different from the source files. So in the [client-side compilation mode](#client-side) or when using [grunt commands]({{ page.baseurl }}/frontend-dev-guide/css-topics/css_debug.html), Magento cannot use symlinks to the source files. Instead it uses the copies of processed files, and they are published to the `pub/static` directory. In case of importing CSS resources, this also results in not finding and not importing the required files. + +### Importing remote CSS files + +If you need to import a remote CSS file in your `.less` source, use `url()` notation. For example, to import a Google font, use the following notation: + +```less +@import url('//fonts.googleapis.com/css?family=Titillium+Web:400,300,200,600.css'); +``` + +To [include the font]({{ page.baseurl }}/frontend-dev-guide/css-topics/using-fonts.html) in your theme's CSS files, use the `@font-face` CSS rule for the fastest loading time. + +This way Magento will skip the `@import` directive while resolving paths to the local resources. + +## The @magento_import directive {#fedg_css-magento-import} + +`@magento_import` is a Magento-specific LESS directive that allows including multiple files by a name pattern. It is used to include files with the same name from the different locations, for example, different modules. +The standard `@import` directive includes a single file, which is found according to the [static files fallback]. + +`@magento_import` can be used in the root source files of a theme only. + +### @magento_import rules of usage {#magento-import-usage} + +To include a `.less` file using the `@magento_import` directive: + +1. To avoid any conflicts with the original LESS syntax, `@magento_import` must be commented out with two slashes. Otherwise, the LESS preprocessor ignores it. + + **Example:** + + ```less + // Comment in a LESS document + + // Standard LESS import directive + // --------------------------------------------- + + @import 'source/_reset'; + @import '_styles'; + + // + // Custom Magento LESS import directives + // --------------------------------------------- + + //@magento_import 'source/_module.less'; // Theme modules + //@magento_import 'source/_widgets.less'; // Theme widgets + //@magento_import 'source/_extend.less'; // Extend for minor customization + ``` + +1. `@magento_import` must contain the file path. The path is specified relatively to the file, where the directive is called and put in either single ('') or double quotes (""). The best practice is to specify the file extension in the path, though technically you can omit this. + +### @magento_import processing {#magento_import_example} + +In the scope of static resources preprocessing, the built-in LESS preprocessor does the following: + +1. Searches for all `@magento_import` directives. +1. Replaces the original `@magento_import` directives with the standard `@import` directives. The latter specify the paths to the particular files that correspond to the pattern specified in `@magento_import`. + +Example of how `@magento_import` is used and processed in `/web/css/styles-l.less`: + + + + + + + + + + + + +
    BeforeAfter
    In there's a following directive: +
    +..
    + //@magento_import 'source/_widgets.less'; // Theme widgets
    +..
    +
    +
    In the processed file, this results in the following: +
    +@import '../Magento_Catalog/css/source/_widgets.less';
    +@import '../Magento_Cms/css/source/_widgets.less';
    +@import '../Magento_Reports/css/source/_widgets.less';
    +@import '../Magento_Sales/css/source/_widgets.less';
    + // Theme widgets
    +
    +
    + + +[production application mode]: {{page.baseurl}}/config-guide/bootstrap/magento-modes.html#production-mode +[LESS PHP library]: https://github.com/wikimedia/less.php +[native `less.js` library]: http://lesscss.org/usage/#using-less-in-the-browser +[Magento fallback mechanism]: {{page.baseurl}}/frontend-dev-guide/themes/theme-inherit.html#theme-inherit-static +[publication]: {{page.baseurl}}/config-guide/cli/config-cli-subcommands-static-view.html#config-cli-static-overview +[root source files]: {{page.baseurl}}/frontend-dev-guide/css-topics/css-preprocess.html#css_preprocess_terms +[static files fallback]: {{page.baseurl}}/frontend-dev-guide/themes/theme-inherit.html#theme-inherit-static diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-themes.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-themes.md deleted file mode 120000 index 54ed71e79c1..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/css-themes.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/css-topics/css-themes.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-themes.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-themes.md new file mode 100644 index 00000000000..7c26777b3c9 --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/css-themes.md @@ -0,0 +1,116 @@ +--- +group: frontend-developer-guide +title: Include CSS +functional_areas: + - Frontend + - Theme +--- + +## In this topic {#fedg_css-in-themes_overview} + +In the Magento application, CSS files are included in [layout files]. + +Technically there is an option to include them in template files, but we strongly recommend avoiding this. + +{:.bs-callout-info} +The CSS class names can be assigned in both templates and layouts. + +This topic describes how stylesheets are located by default in the Magento application file system, and the recommended way to include CSS files in layouts. + +## How Magento stylesheet files are organized + +Conventionally, CSS and Less files are stored only in themes. [Module](https://glossary.magento.com/module) directories do not contain any default styles. + +In a [theme directory][], stylesheets are stored in the following locations: + + + + + + + + + + + + + + + +
    Directory, relative to <theme_dir>Description
    /<Namespace>_<Module>/web/css + Module-specific styles. +
    /web/css + +Contains the following: +
      +
    • +print.less: used to generate styles for the printed version of store pages. +
    • +
    • _styles.less - a composite file, which includes all Less files used in the theme. The underscore sign ("_") in a file name conventionally means that a file is not used independently, but is included in other files. +
    • +
    • styles-m.less: used to generate mobile-specific styles, includes _styles.less. +
    • +
    • styles-l.less: used to generate desktop-specific styles, includes _styles.less. +
    • +
    • /source: this subdirectory contains Less configuration files that invoke mixins from the Magento UI library. +
    • +
    • +/source/_theme.less: overrides the default Magento UI library variables values. +
    • + +
    +
    + +## Include CSS {#fedg_css-in-themes_xml} + +In the Magento application, the recommended way to include stylesheets is to specify them in [layout](https://glossary.magento.com/layout) files. + +Usually, the stylesheets you include should be available for all store pages. To achieve this, include your CSS in `default_head_blocks.xml` of the `Magento_Theme` module, which defines the default `` page section for all Magento pages. +The recommended way to do this is adding an [extending]({{ page.baseurl }}/frontend-dev-guide/layouts/layout-extend.html) `default_head_blocks.xml` in your theme, and including the required stylesheets in this file. + +Your custom `default_head_blocks.xml` should be located as follows: + +`/Magento_Theme/layout/default_head_blocks.xml`. + +To include a CSS file, add the `` block in `` section in a layout file. `` is specified relative to the theme web directory (`/web`) + +For example, to include `/web/css/custom.css`: + +```xml + + + + + +``` + +The following illustrates how stylesheets are included in the default Blank theme: + +[`/Magento_Theme/layout/default_head_blocks.xml`] + +```xml + + + + + + + +``` + +To include an external CSS file, add ``. + +```xml + + + + + +``` + +{:.bs-callout-info} +If the system does not find the included CSS files, it searches for the same file names with a `.less` extension. This is part of the built-in preprocessing mechanism. You can find more information about it in the [CSS Preprocessing] topic. + +[layout files]: {{page.baseurl}}/frontend-dev-guide/layouts/layout-overview.html +[theme directory]: {{page.baseurl}}/frontend-dev-guide/themes/theme-structure.html +[CSS Preprocessing]: {{page.baseurl}}/frontend-dev-guide/css-topics/css-preprocess.html diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css_debug.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css_debug.md deleted file mode 120000 index 966be15081a..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/css_debug.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/css-topics/css_debug.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css_debug.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css_debug.md new file mode 100644 index 00000000000..cad4ce6ae60 --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/css_debug.md @@ -0,0 +1,129 @@ +--- +group: frontend-developer-guide +title: Compile LESS using Grunt +functional_areas: + - Frontend +--- + +The topic describes how to install, configure, and use [Grunt JavaScript task runner](http://gruntjs.com/) to compile `.less` files in Magento 2. + +## Prerequisites + +- Make sure that you [set]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-mode.html) your Magento application to the developer or default [mode]({{ page.baseurl }}/config-guide/bootstrap/magento-modes.html). The default mode sets the Less compilation mode to Server-side Less compilation. +- Install and configure Grunt as described in [Using Grunt for Magento tasks]({{ page.baseurl }}/frontend-dev-guide/tools/using_grunt.html) + +## Adding themes to Grunt configuration {#add_theme} + +To compile `.less` files, add your theme to `module.exports` in the Grunt configuration, either in the default `dev/tools/grunt/configs/themes.js` or in the [custom configuration file]({{ page.baseurl }}/frontend-dev-guide/tools/using_grunt.html#grunt_config). For example: + +1. Install [node.js] to any location on your machine. + +1. Install the Grunt CLI globally. To do this, run the following command in a command prompt: + + ```bash + npm install -g grunt-cli + ``` + +1. From the `` directory, copy and paste the contents of the following files: + + - `package.json.sample` to `package.json` + - `Gruntfile.js.sample` to `Gruntfile.js` + - `grunt-config.json.sample` into `grunt-config.json` + +1. Install (or refresh) the `node.js` project dependency, including Grunt, for your Magento instance. To do this, run the following commands in a command prompt: + + ```bash + cd + ``` + + ```bash + npm install + ``` + + ```bash + npm update + ``` + +1. Add your [theme](https://glossary.magento.com/theme) to Grunt configuration. To do this, in the `dev/tools/grunt/configs/themes.js` file, add your theme to `module.exports` like following: + + ```javascript + : { + area: '', + name: '/', + locale: '', + files: [ + '', //path to root source file + '' + ], + dsl: 'less' + } + ``` + + Where the following notation is used: + + - ``: vendor name. + - ``: your theme code, conventionally should correspond to the theme directory name. + - ``: specified in the `code_subtag` format, for example `en_US`. Only one locale can be specified here. To debug the theme with another locale, create one more theme declaration, having specified another value for `language`. + - ``: area code, can be either `frontend` or `adminhtml`. + - ``: path to the root source file, relative to the `app/design/frontend///web` directory. You need to specify all [root source files of the theme]({{ page.baseurl }}/frontend-dev-guide/css-topics/css-preprocess.html#css_preprocess_terms). If your theme [inherits] from a certain theme, and does not contain its own root source files, specify the root source files of the parent theme. + + **IMPORTANT NOTE** : If grunt gives the error "Error: Cannot find module ....", check the path in your `grunt-config.json` file and correct as necessary. + +1. (Optional) If you want to use Grunt for "watching" changes automatically, without reloading pages in a browser each time, install the [LiveReload extension] in your browser. + +## Grunt commands {#grunt_commands} + +The following table describes the grunt commands you can use to perform different customization tasks. Run all commands from your Magento installation directory. + +Grunt task | Action +---------- | ------- +grunt clean | Removes the theme related static files in the `pub/static` and `var` directories. +grunt exec | Republishes symlinks to the source files to the `pub/static/frontend/` directory. Use `grunt exec:` to republish symlinks for a specific theme. +grunt less | Compiles CSS files using the symlinks published in the `pub/static/frontend/` directory. Use `grunt less:` to use the symlinks published for a specific theme. +grunt watch | Tracks the changes in the source files, recompiles `.css` files, and reloads the page in the browser. + +## Use cases of tracking changes using Grunt {#use_cases} + +The following shows which Grunt tasks to use for debugging: + +- After you switch the compilation mode from client-side to server-side, run the `exec` command. +- After you customize the content of any `.less` file, except the root source files, run the `less` task and reload the page. +- After you [customize the root source files or move the files included to the root files]({{ page.baseurl }}/frontend-dev-guide/css-topics/css-preprocess.html#css_exception), run the `exec` command and reload the page. +- After you run `php bin/magento setup:upgrade`, run `exec` command. +- After you run the `exec` command, run the `clear` command to `clear` the Magento cache, then run the `watch` command. Running the commands in this order will ensure that any custom jQuery attributes like product sliders, banners, etc are loaded correctly. + +If you have LiveReload installed, run the `grunt watch` command, and the flow is even simpler: + +- After you customize the content of any `.less` file, changes are applied and the page reloads automatically. No additional changes +- After you [customize the root source files or move the files included to the root files]({{ page.baseurl }}/frontend-dev-guide/css-topics/css-preprocess.html#css_exception), run the `clean` and `exec` commands, which reloads the page in the browser. + +## CSS source maps {#source_maps} + +When using Grunt for styles preprocessing, you can enable the CSS source maps generation in your browser. It will make the theme styles debugging easier. + +For each theme, Magento compiles all theme `.less` files into two CSS files: `styles-m.css` and `styles-l.css`. So when you debug a theme, your browser only sees `styles-m.css` and it might be difficult to define which `.css` or `.less` file requires corrections. For example: + +![node declaration autocomplete]({{ site.baseurl }}/common/images/fdg/no-map.png){:width="610px"} + +CSS source maps solve this issue. They help to find the `.less` file, where the style is specified. For example: + +![node declaration autocomplete]({{ site.baseurl }}/common/images/fdg/with-map.png){:width="610px"} + +CSS source maps are generated automatically when you compile CSS for your theme using the `grunt less: ` command. To use them, you need to enable the display of source maps in your browser. For example, in Chrome, you would open the Developer Tools, go to the **Settings** panel, select **Preferences**, then check the **Enable CSS source maps** checkbox. + +Magento has a base set of variables that define commonly used aspects of a theme; such as colors, fonts, style of page titles, and so on. + +The `/lib/web/css/source/lib/variables` directory contains LESS files that define values assigned to variables for many of the common elements in Magento. + +To change or override any of these variables, simply create a file in `/web/css/source/_theme.less` For example: + +![node declaration autocomplete]({{ site.baseurl }}/common/images/fdg/lib-map.png){:width="610px"} + +```css +@navigation__background: @secondary__color__light; +@font-family__sans-serif: 'Helvetica Neue', Helvetica, Arial, sans-serif; +``` + +[inherits]: {{page.baseurl}}/frontend-dev-guide/themes/theme-inherit.html +[LiveReload extension]: http://livereload.com/extensions/ +[node.js]: https://nodejs.org/en/download/package-manager/ diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/custom-preprocess-parent.md b/src/guides/v2.4/frontend-dev-guide/css-topics/custom-preprocess-parent.md deleted file mode 120000 index 18ec98fa723..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/custom-preprocess-parent.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/css-topics/custom-preprocess-parent.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/custom-preprocess-parent.md b/src/guides/v2.4/frontend-dev-guide/css-topics/custom-preprocess-parent.md new file mode 100644 index 00000000000..f0a855686ef --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/custom-preprocess-parent.md @@ -0,0 +1,6 @@ +--- +group: frontend-developer-guide +title: Using custom CSS preprocessor +functional_areas: + - Frontend +--- diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/custom_preprocess.md b/src/guides/v2.4/frontend-dev-guide/css-topics/custom_preprocess.md deleted file mode 120000 index 1805ad5fd4f..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/custom_preprocess.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/css-topics/custom_preprocess.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/custom_preprocess.md b/src/guides/v2.4/frontend-dev-guide/css-topics/custom_preprocess.md new file mode 100644 index 00000000000..d5dfbb2968e --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/custom_preprocess.md @@ -0,0 +1,91 @@ +--- +group: frontend-developer-guide +title: Add custom CSS preprocessor +functional_areas: + - Frontend +--- + +## What's in this topic + +This topic describes how to add a custom [CSS](https://glossary.magento.com/css) preprocessor. Adding [Sass](http://sass-lang.com/) support is used as an example. + +## Sample Sass module + +Magento has a sample [module-sample-scss](https://github.com/magento/magento2-samples/tree/master/module-sample-scss) [module](https://glossary.magento.com/module) implementing the [Sass](https://glossary.magento.com/sass) preprocessor. + +You can view it as example when adding your custom preprocessor. Or install the module as is if you need to add Sass preprocessing. Installing a module is described in the [repository's Readme file](https://github.com/magento/magento2-samples/blob/master/README.md). + +## Adding a custom preprocessor + +### Prerequisites + +For the sake of compatibility, upgradability and easy maintenance, do not edit the default Magento code. Create a new custom module for your customizations. + +For details about creating a module refer to the [Magento PHP Developer Guide]({{ page.baseurl }}/extension-dev-guide/bk-extension-dev-guide.html). + +### Step by step instruction + +To add a custom preprocessor, take the following steps: + +1. In your module directory, add the [adapter](https://glossary.magento.com/adapter) [PHP](https://glossary.magento.com/php) class. It must implement the `Magento\Framework\View\Asset\ContentProcessorInterface` interface. For illustration, see the adapter for Sass in the sample module: [module-sample-scss/Preprocessor/Adapter/Scss/Processor.php](https://github.com/magento/magento2-samples/blob/master/module-sample-scss/Preprocessor/Adapter/Scss/Processor.php) + +1. If the browser compilation is possible for your file types, that is, if the corresponding [JavaScript](https://glossary.magento.com/javascript) [library](https://glossary.magento.com/library) exists, create the custom renderer for the client-side compilation. This will allow the default [client-side compilation functionality]({{ page.baseurl }}/frontend-dev-guide/css-topics/css-preprocess.html#client-side) to be applied for your files type as well. You can use the default Magento renderer for reference: [app/code/Magento/Developer/Model/View/Page/Config/ClientSideLessCompilation/Renderer.php]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Developer/Model/View/Page/Config/ClientSideLessCompilation/Renderer.php) + +1. If in your custom preprocessor, the syntax of the importing directives is different from `@import` and `@magento_import`, you must implement custom processor classes. You can view the default Magento processors for reference: [lib/internal/Magento/Framework/Css/PreProcessor/Instruction]({{ site.mage2bloburl }}/{{ page.guide_version }}/lib/internal/Magento/Framework/Css/PreProcessor/Instruction). + +1. In `/etc/di.xml`, declare the following: + + * your custom adapter + * your processor (if relevant) + * the renderer for the client-side compilation (if relevant) + +The content of your `di.xml` will be similar to the following: + +**`/etc/di.xml`** + +```xml + + + + + + + %Your\Adapter\Class% + + + + scss + + + + + + + + + + + %Your\Import\Processor% + + + magento_import + %Your\Magento_import\Processor% + + + + + + + + + + %Your\Client\Side\Renderer% + + + + +``` + +## Related reading + +* [Magento PHP Developer Guide]({{ page.baseurl }}/extension-dev-guide/bk-extension-dev-guide.html) diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/gulp-sass.md b/src/guides/v2.4/frontend-dev-guide/css-topics/gulp-sass.md deleted file mode 120000 index fadc7c3e072..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/gulp-sass.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/css-topics/gulp-sass.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/gulp-sass.md b/src/guides/v2.4/frontend-dev-guide/css-topics/gulp-sass.md new file mode 100644 index 00000000000..d663f2de282 --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/gulp-sass.md @@ -0,0 +1,110 @@ +--- +group: frontend-developer-guide +title: Use Sass preprocessor and Gulp task runner +functional_areas: + - Frontend + - Tools +--- + +By default, Magento uses [Less](http://lesscss.org/) for themes styling. But you can use other stylesheet languages that can be compiled (processed) to CSS. For example, Sass is a popular alternative. + +If you decide not to use Less and the default [Magento UI library]({{ page.baseurl }}/frontend-dev-guide/css-topics/theme-ui-lib.html), you need to create your own theme from scratch and use an alternative preprocessor. This topic describes how to configure and use the [Gulp](http://gulpjs.com/) task runner and the gulp-sass package for the Sass preprocessor. + +For details about adding a custom preprocessor, see [Add custom CSS preprocessor]({{ page.baseurl }}/frontend-dev-guide/css-topics/custom_preprocess.html). + +## Install Gulp and its Sass preprocessor + +1. In the root of the theme directory, create an empty `package.json` and copy-paste the following code: + + ```json + { + "author": "Magento Commerce Inc.", + "description": "Magento node modules dependencies for local development", + "version": "1.0.0", + "main": "gulpfile.js", + "dependencies": { + "path": "^0.12.7" + }, + "devDependencies": { + "gulp": "^3.9.1", + "gulp-notify": "^3.0.0", + "gulp-plumber": "^1.1.0", + "gulp-sass": "^3.1.0" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + } + } + ``` + +1. Install Gulp by running the following command in a command prompt: + + `npm install --save gulp-install` + +1. Add the gulp-sass package for the Sass preprocessor by running the following command: + + `npm install gulp-sass` + +## Create a theme and add Sass styles + +1. Create a theme, as described in [Create a new storefront theme]({{ page.baseurl }}/frontend-dev-guide/themes/theme-create.html). + +1. Set up a Gulp task for Sass compilation by placing the file with the task code in the root of your theme directory (`app/design/frontend//`). Create an empty `app/design/frontend///gulpfile.js` file and copy-paste this code into it (no changes needed): + + ```js + var gulp = require('gulp'), + sass = require('gulp-sass'), + plumber = require('gulp-plumber'), + notify = require('gulp-notify'); + + var config = { + src : './web/css/*.scss', + dest : './web/css/' + }; + + // Error message + var onError = function (err) { + notify.onError({ + title : 'Gulp', + subtitle: 'Failure!', + message : 'Error: <%= error.message %>', + sound : 'Beep' + })(err); + + this.emit('end'); + }; + + // Compile CSS + gulp.task('styles', function () { + var stream = gulp + .src([config.src]) + .pipe(plumber({errorHandler: onError})) + .pipe(sass().on('error', sass.logError)); + + return stream + .pipe(gulp.dest('./web/css/')); + }); + ``` + + This task uses `styles.scss`, stored in the `app/design/frontend///web/css/` directory, as the source of Sass. It stores the generated CSS in `styles.css` in the `app/design/frontend//` directory. + +1. Put the source `styles.scss` file in the `app/design/frontend///web/css/` directory. + +1. Declare the resulting CSS file in the `default_head_blocks.xml` file in the `app/design/frontend// + + + + + ``` +1. To generate CSS, run + `gulp styles`. + +## Using the @import directive in Sass + +In the source .`scss` files you can use the `@import` directive, to import other `.scss` files. You can put the module-related stylesheets in the module directories in the theme, and then include them in the main `.scss` file. For example, if you create a `_catalogstls.scss` file for styles of the `Magento_Catalog` module and put it in `app/design/frontend///Magento_Catalog/styles`, you can import it using the following notation: +```css +@import '../Magento_Theme/styles/module` +``` diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/theme-ui-lib.md b/src/guides/v2.4/frontend-dev-guide/css-topics/theme-ui-lib.md deleted file mode 120000 index fc195cbf7d0..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/theme-ui-lib.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/css-topics/theme-ui-lib.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/theme-ui-lib.md b/src/guides/v2.4/frontend-dev-guide/css-topics/theme-ui-lib.md new file mode 100644 index 00000000000..7b3b96209b1 --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/theme-ui-lib.md @@ -0,0 +1,254 @@ +--- +group: frontend-developer-guide +title: UI library +functional_areas: + - Frontend + - Theme +--- + +The Magento UI [library](https://glossary.magento.com/library) is a flexible [Less]-based [frontend](https://glossary.magento.com/frontend) library designed to assist Magento [theme](https://glossary.magento.com/theme) developers. +It employs a set of mixins for base elements to ease frontend theme development and customization. + +This topic describes how the library is organized, and how to use it. For more information, see the [Magento UI library documentation] that reflects the latest [embedded documentation]. + +## Components provided by the UI library {#library_elements} + +The Magento UI library provides the ability to customize and reuse the following user interface elements and properties: + +* actions-toolbar +* breadcrumbs +* buttons +* drop-downs +* forms +* icons +* [layout](https://glossary.magento.com/layout) +* loaders +* messages +* pagination +* popups +* ratings +* sections - tabs and accordions +* tables +* [tooltips](#tooltip-element) +* typography +* list of theme variables + +The following illustration shows a [storefront](https://glossary.magento.com/storefront) product page containing some of the preceding elements: + +![*A product page with user interface elements specified*][ui_lib1.png] + +## Mixin location {#fedg_using-ui-lib_mixins} + +You can find the Magento UI library under [`lib/web/css`][]. +Library source `.less` files are stored under the `source` directory, each file contains mixins for configuring a certain element, and in most cases the element coincides with the file name: + +```tree +lib/web + ├── css/ + │ ├── docs/ (Library documentation) + │ ├── source/ + │ │ ├── lib/ (Library source files) + | | | ├── variables/ (Predefined variables for each mixin) + │ │ │ ├── _actions-toolbar.less + │ │ │ ├── _breadcrumbs.less + │ │ │ ├── _buttons.less + │ │ │ ├── _dropdowns.less + │ │ │ ├── _forms.less + | | | ├── _grids.less + │ │ │ ├── _icons.less + │ │ │ ├── _layout.less + │ │ │ ├── _lib.less + │ │ │ ├── _loaders.less + │ │ │ ├── _messages.less + │ │ │ ├── _navigation.less + │ │ │ ├── _pages.less + │ │ │ ├── _popups.less + │ │ │ ├── _rating.less + │ │ │ ├── _resets.less + │ │ │ ├── _responsive.less + │ │ │ ├── _sections.less + │ │ │ ├── _tables.less + │ │ │ ├── _tooltips.less + │ │ │ ├── _typography.less + │ │ │ ├── _utilities.less + │ │ │ └── _variables.less + │ │ └── _email-variables.less + │ │ └── _extend.less + │ │ └── _theme.less + │ │ └── _variables.less + │ │ └── _widgets.less + │ └── styles.less + ├── fonts/ + │ └── Blank-Theme-Icons/ (Library custom icons font) + ├── images/ + │ └── blank-theme-icons.png (Library icons sprite) + └── jquery/ (Library javascript files) +``` + +## Predefined variables {#fedg_using-ui-lib_predef-vars} + +If your theme [inherits][] from any Magento out-of-the-box theme, for example Blank, you can easily customize any element of a store page without changing any [CSS](https://glossary.magento.com/css) code or templates. +Customization can be performed by simply changing in your theme the values of the predefined variables used in the UI library or parent theme mixins. + +The complete list of these variables and their default values are stored in [`lib/web/css/source/lib/variables`][]. +This directory contains a set of files, corresponding to the set of UI library elements, and each of the files lists element-specific variables. +For example, [`lib/web/css/source/lib/variables/_breadcrumbs.less`][] contains variables used in the `breadcrumbs()` [mixin](https://glossary.magento.com/mixin). + +To change the default library variables values, specify the new values for the required variables in the `/web/css/source/_theme.less` file. + +{:.bs-callout-info} +Please mind, that your `/web/css/source/_theme.less` file overrides `_theme.less` of the parent theme (if your theme has a parent). +So if you want to inherit the parent theme's variable values additionally to your changes, add the content of parent’s `_theme.less` to your file as well. + +The following figure shows the product page shown earlier in this topic, after a custom theme was applied. +The theme customized Blank by redefining variables only. + +![*Changing design by redefining variables*][ui_lib2.png] + +## Your custom variables {#fedg_using-ui-lib_vars} + +When naming custom variables, please follow the [Magento naming convention for the Less variables]. + +## Using mixins {#fedg_using-ui-lib_customize} + +You can use a mixin with default variables values, or you can redefine them when calling a mixin. +The following paragraphs describe both ways to call a mixin. + +To use a mixin with default values, call the mixin without specifying any parameters. +For example: + +```css +.breadcrumbs { + .lib-breadcrumbs(); +} +``` + +To call a mixin with parameter values different from default, set these values when calling the mixin, like in the following example: + +```css +.example-button { + .lib-button( + @_button-padding: @button-padding, + @_button-color: #fff, + @_button-color-hover: #ccc + ); +} +``` + +Variables starting with `@_` are private mixin variables used only in this mixin. +Variables starting with `@` (without the underscore) are global, and are listed in [`lib/web/css/source/lib/variables`]. + +## Tabs and accordions set with CSS + +Use the accordion style for mobile and tab style for desktop. + +To set tabs and accordions using breakpoints, see the following example: + +```css +// +// Mobile + Desktop +// _____________________________________________ + +& when (@media-common = true) { + .product.data.items { + .lib-data-accordion(); + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .product.data.items { + .lib-data-tabs(); + } +} +``` + +## Navigation set with CSS + +Use the Navigation style for mobile and tab style for desktop. + +To set navigation using breakpoints, see the following example: + +```css +// +// Mobile +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { + .lib-main-navigation(); +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .lib-main-navigation-desktop(); +} +``` + +## Tooltip element + +To create a tooltip element, use the `.lib-tooltip()` mixin. + +| Option | Default | +| --- | --- | +| `position` | `top` | +| `selector-toggle` | `.tooltip-toggle` | +| `selector-content` | `.tooltip-content` | + +```html + + Hover me + Details here + +``` + +```css +.my-tooltip { + .lib-tooltip(right); +} +``` + +### Result + +As result, the tooltip placed on the right side. + +![Tooltip element]({{ site.baseurl }}/common/images/fdg/tooltip-element-result.png) + +## Embedded documentation {#docs} + +The detailed information about the Magento UI library is embedded in the code repository: + +* [`lib/web/css/docs/source/README.md`] describes the Magento UI library structure, naming conventions, and code style. +* [`lib/web/css/docs`] contains a set of `.html` files with detailed information about the library mixins. + +Each file is named after the mixin it describes, and contains detailed mixin description and navigation controls to access documentation for other mixins. +The generated Magento UI library documentation is provided in a convenient [HTML](https://glossary.magento.com/html) view. It is available in the following location in your Magento installation: `/pub/static/frontend/Magento/blank/en_US/css/docs/index.html` (view in a browser). + + + +[`lib/web/css/docs/source/README.md`]: {{ site.mage2bloburl }}/{{ page.guide_version }}/lib/web/css/docs/source/README.md + +[`lib/web/css/docs`]: {{ site.mage2bloburl }}/{{ page.guide_version }}/lib/web/css/docs + +[`lib/web/css/source/lib/variables/_breadcrumbs.less`]: {{ site.mage2bloburl }}/{{ page.guide_version }}/lib/web/css/source/lib/variables/_breadcrumbs.less + +[`lib/web/css/source/lib/variables`]: {{ site.mage2bloburl }}/{{ page.guide_version }}/lib/web/css/source/lib/variables + +[`lib/web/css`]: {{ site.mage2bloburl }}/{{ page.guide_version }}/lib/web/css + +[embedded documentation]: #docs +[inherits]: {{ page.baseurl }}/frontend-dev-guide/themes/theme-inherit.html + +[Less]: http://lesscss.org/ + +[Magento naming convention for the Less variables]: {{ page.baseurl }}/coding-standards/code-standard-less.html#naming + +[Magento UI library documentation]: {{ page.baseurl }}/frontend-dev-guide/css-topics/theme-ui-lib.html + +[ui_lib1.png]: {{ site.baseurl }}/common/images/ui_lib1.png +[ui_lib2.png]: {{ site.baseurl }}/common/images/ui_lib2.png diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-create.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-create.md deleted file mode 120000 index 6357e5a14c4..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/layouts/layout-create.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/layouts/layout-create.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-create.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-create.md new file mode 100644 index 00000000000..8c069db9290 --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/layouts/layout-create.md @@ -0,0 +1,69 @@ +--- +group: frontend-developer-guide +title: Create a new layout +functional_areas: + - Frontend +--- + +## Create a new page layout in custom theme + +When an existing page layout does not meet your requirements, create a new page layout in Magento. + +If the new page has a `3-columns-double-footer` layout, create a custom page-layout XML file: `app/design/frontend///Magento_Theme/page_layout/3-columns-double-footer.xml`. + +```xml + + + + + + + + + +``` + +To add a block to the container, create the layout: + +`app/design/frontend///Magento_Theme/layout/default.xml` + +```xml + + + + + + +``` + +## Add the new layout to the layouts.xml file + +Add the newly created page layout to the `layouts.xml` file of the theme directory: `app/design/frontend///Magento_Theme/layouts.xml`. + +```xml + + + + + + +``` + +{:.bs-callout-info} +Note that the value of the new layout `id` attribute should match the name of the newly created page-layout XML file. + +Clean the cache by going to **System** > **Cache Management** > **Flush Magento Cache** or by entering the following command: + +```bash +bin/magento cache:clean +``` + +## Result + +The new page layout displays in all `Layout` dropdowns. + +![Custom page layout]({{ site.baseurl }}/common/images/fdg/custom_layout_admin_backend.png) + +On the storefront, there is a new footer for those pages that use the `3 Columns Double Footer` layout. + +![Storefront two footers layout]({{ site.baseurl }}/common/images/fdg/custom_layout_footer_bottom.png) diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-extend.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-extend.md deleted file mode 120000 index 42e7b7600f0..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/layouts/layout-extend.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/layouts/layout-extend.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-extend.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-extend.md new file mode 100644 index 00000000000..7e6461e759b --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/layouts/layout-extend.md @@ -0,0 +1,89 @@ +--- +group: frontend-developer-guide +title: Extend a layout +functional_areas: + - Frontend +--- + +## Create a theme extending file {#fedg_layout_extend_merge} + +Rather than copy extensive page layout or page configuration code and then modify what you want to change, in the Magento system, you only need to create an *extending layout file* that contains the changes you want. + +To add an extending [page configuration]({{ page.baseurl }}/frontend-dev-guide/layouts/layout-types.html#layout-types-conf) or [generic layout]({{ page.baseurl }}/frontend-dev-guide/layouts/layout-types.html#layout-types-gen) file: + +1. Put the layout file in the following location: + ```tree + + |__/_ + |__/layout + |--.xml + |--.xml + ``` + +For example, to customize the layout defined in `/view/frontend/layout/catalog_product_view.xml`, you need to add a layout file with the same name in your custom theme, such as: `/Magento_Catalog/layout/catalog_product_view.xml`. Then do your customizations on the layout xml. + +**Example:** + +```xml + + + + + +``` + +To add an extending [page layout]({{ page.baseurl }}/frontend-dev-guide/layouts/layout-types.html#layout-types-page) file: + +1. Put the file in the following location: + ```tree + + |__/_ + |__/page_layout + |--.xml + |--.xml + ``` + +For example, to customize the page layout defined in `/view/frontend/page_layout/1column.xml`, you need to add a page layout file with the same name in your custom theme, such as: `/Magento_Theme/page_layout/1column.xml`. Then do your customizations on the page layout xml. + +**Example:** + +```xml + + + + + + +``` + +## Processing extending layouts + +Magento merges layout files as follows: + +1. For each layout file in the list: + 1. Loads layout handle declaration and layout instructions. + 1. Appends to the result in the following format: + +```xml + + + + + + + + + +``` + +Where a `handle ID` is defined by the name of the corresponding layout file, and handle attributes are defined by the attributes of the root layout node of this layout file. + +1. Replaces the base URL placeholders in the result. + +{:.ref-header} +Related topics + +* [Override a layout]({{ page.baseurl }}/frontend-dev-guide/layouts/layout-override.html) +* [XML instructions]({{ page.baseurl }}/frontend-dev-guide/layouts/xml-instructions.html) +* [Create a theme]({{ page.baseurl }}/frontend-dev-guide/themes/theme-create.html) +* [Magento UI library]({{ page.baseurl }}/frontend-dev-guide/css-topics/theme-ui-lib.html) diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-override.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-override.md deleted file mode 120000 index 7c6b19b1325..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/layouts/layout-override.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/layouts/layout-override.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-override.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-override.md new file mode 100644 index 00000000000..63d4851df0b --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/layouts/layout-override.md @@ -0,0 +1,116 @@ +--- +group: frontend-developer-guide +title: Override a layout +functional_areas: + - Frontend +--- + +## What's in this topic {#fedg_layout_override_overview} + +Not all layout customizations can be performed by [extending layouts]. If the amount of customizations is large, you can use the overriding function for the needed layout file. This means that the new file that you place in the theme will be used instead of the parent [theme] layout file or [base] layout file. + +In this article, [page layouts], [page configurations], and [generic layouts] are referred to as *layout files*, as the mechanism of overriding is similar for all of them. + +Layout files with instructions that override the default or parent theme files are referred to as *overriding layout files*. + +## Examples of customizations that involve overriding layouts + +Examples of customizations that involve overriding layouts: + +* Suppressing method invocation. + + {:.bs-callout-info} + Overriding is not necessary if a block has a method that cancels the effect of the originally invoked method. In this case, you can customize the layout by adding a layout file where the canceling method is invoked. + +* Modifying method arguments. +* Canceling block/container removal using the `remove` attribute. +* Setting XML attributes of blocks and containers. + + {:.bs-callout-info} +Certain attributes, like `htmlClass`, `htmlId`, `label` attributes can be changed in [extending layouts]. + +* Removing block arguments. +* Modifying and suppressing [handles] inclusion. +* Removing all handle instructions by declaring an overriding layout file with an empty handle. + +## How to override a layout {#fedg_layout_override_howto} + +This section discusses how to override: + +* [Base layout] +* [Theme layout] + +### Override base layouts {#fedg_layout_override_default} + +To add an overriding base layout file (to override a base layout provided by the module): + +1. Put a layout file with the same name in the following location: + + ```tree + + |__/ + |__/layout + |__/override + |__/base + |--.xml + |--.xml + ``` + +These files override the following layouts: + +* `/view/frontend/layout/.xml` +* `/view/frontend/layout/.xml` + +For example, `/Magento_Checkout/layout/override/base/checkout_cart_index.xml` will override `Magento_Checkout/view/frontend/layout/checkout_cart_index.xml`. + +### Override theme layouts {#fedg_layout_override_theme} + +To add an overriding theme file (to override a parent theme layout): + +1. Put a layout file with the same name in the following location: + +```tree + + |__/ + |__/layout + |__/override + |__/theme + |__/ + |__/ + |--.xml + |--.xml +``` + +These files override the following layouts: + +* `/_/layout/.xml` +* `/_/layout/.xml` + +For example, `/Magento_Checkout/layout/override/theme/Magento/luma/checkout_cart_index.xml` will override `app/design/frontend/Magento/luma/Magento_Checkout/layout/checkout_cart_index.xml`. + +{:.bs-callout-info} +To override page layout files, use the `page_layout` directory name instead of `layout`. + +## Customization mistakes {#override-mistake} + +Although the layout overriding mechanism provides great customization flexibility, it's possible to use it to add logically irrelevant changes. We strongly recommend you not make the following changes: + +* Changing block name or alias. The name of a block should not be changed, and neither should the alias of a block remaining in the same parent element. +* Changing handle inheritance. For example, you should not change the page type parent handle. + +{:.ref-header} +Related topics + +* [Extend a layout]({{ page.baseurl }}/frontend-dev-guide/layouts/layout-extend.html) +* [Create a theme]({{ page.baseurl }}/frontend-dev-guide/themes/theme-create.html) +* [Layout instructions]({{ page.baseurl }}/frontend-dev-guide/layouts/xml-instructions.html) + +[extending layouts]: {{page.baseurl}}/frontend-dev-guide/layouts/layout-extend.html +[theme]: {{page.baseurl}}/frontend-dev-guide/layouts/layout-overview.html#layout-loc +[base]: {{page.baseurl}}/frontend-dev-guide/layouts/layout-overview.html#layout-loc +[page layouts]: {{page.baseurl}}/frontend-dev-guide/layouts/layout-types.html#layout-types-page +[page configurations]: {{page.baseurl}}/frontend-dev-guide/layouts/layout-types.html#layout-types-conf +[generic layouts]: {{page.baseurl}}/frontend-dev-guide/layouts/layout-types.html#layout-types-gen +[handles]: {{page.baseurl}}/frontend-dev-guide/layouts/layout-overview.html#layout-over-terms +[Base layout]: {{page.baseurl}}/frontend-dev-guide/layouts/layout-overview.html#layout-loc +[Theme layout]: {{page.baseurl}}/frontend-dev-guide/layouts/layout-overview.html#layout-loc diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-overview.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-overview.md deleted file mode 120000 index c5d21bfe8ec..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/layouts/layout-overview.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/layouts/layout-overview.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-overview.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-overview.md new file mode 100644 index 00000000000..045f8d14fdb --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/layouts/layout-overview.md @@ -0,0 +1,133 @@ +--- +group: frontend-developer-guide +title: Layout overview +functional_areas: + - Frontend +--- +## What's in this topic + +This article describes the basic concepts you need to know to create layouts for your custom [theme](https://glossary.magento.com/theme). + +## Introduction + +In Magento, the basic components of page design are layouts, containers, and blocks. A *layout* represents the structure of a web page (1). *Containers* represent the placeholders within that web page structure (2). And *blocks* represent the UI controls or components within the container placeholders (3). These terms are illustrated and defined below. + +The objective is to create a structured, common set of layout instructions to render pages. Most pages on a website can be categorized as a 1 column, 2 column, or 3 column layout. These page layouts can be applied to a page from within the admin panel. + +![web page sample layout][layout] + +(1) *Layouts* provide the structures for web pages using an XML file that identifies all the containers and blocks composing the page. The details of layout XML files are described later in this section. + +(2) *Containers* assign content structure to a page using container tags within a layout XML file. A container has no additional content except the content of included elements. Examples of containers include the header, left column, main column, and footer. + +(3) *Blocks* render the UI elements on a page using block tags within a layout XML file. Blocks use templates to generate the [HTML](https://glossary.magento.com/html) to insert into its parent structural block. Examples of blocks include a [category](https://glossary.magento.com/category) list, a mini cart, product tags, and product listing. + +## Purpose of page layouts + +The purpose of page layouts is to create a structured, common set of layout instructions to render pages. Most pages on a website can be categorized as fitting into a 1, 2, or 3-column container system. These page layouts can be selected in the admin panel to provide a specific layout per page. + +## Basic layouts + +The basic view of all Magento [storefront](https://glossary.magento.com/storefront) pages is defined in two page configuration layout files located in the Magento_Theme module: + +* `/view/frontend/layout/default.xml`: defines the page layout. +* `/view/frontend/layout/default_head_blocks.xml`: defines the scripts, images, and meta data included in pages' `` section. + +These basic page configuration layouts are extended in other Magento modules and in Magento themes. + +You can also [extend] or [override] these files in your custom theme. + +## Layout handles {#layout-over-terms} + +A *layout handle* is a uniquely identified set of [layout instructions](https://glossary.magento.com/layout-instructions) that serves as a name of a layout file. + +There are three kinds of layout handles: + +* **page-type layout handles** – Synonyms of the page type identifiers. Correspond to "full action names" of controller actions, for example, catalog_product_view. +* **page layout handles** – Identifiers of specific pages. Correspond to controller actions with parameters that identify specific pages, for example, catalog_product_view_type_simple_id_128 or for a CMS page, cms_page_view_id_home.xml. +* **arbitrary handles** - Do not correspond to any page type, but other handles use them by including. + +## Layout files types and conventions + +### Layout file types: by role + +For a particular page, its layout is defined by two major layout components: *page layout* file and *page configuration* file (or *generic layout* for pages returned in AJAX requests, emails, and so on). + +Following are the definitions of each layout file type: + +* *Page layout*: an XML file declaring a page wireframe inside the `` section of the HTML page markup, for example, two-column page layout. +* *Page configuration*: an XML file declaring detailed structure, contents and meta-information of a page (includes the ``, ``, and `` sections of the HTML page markup). +* *Generic layout*: an XML file declaring page detailed structure and contents inside the `body` section of the HTML page markup. Used for pages returned by AJAX requests, emails, HTML snippets, and so on. + +For details, refer to [Layout file types]. + +In this guide we use *layout files* when talking about concepts which are similarly applied to all of these types of layout files. + +### Module and theme layout files {#layout-loc} + +The following terms are used to distinguish layouts provided by different application components: + +* *Base layouts*: Layout files provided by modules. Conventional location: + * Page configuration and generic layout files: `/view/frontend/layout` + * Page layout files: `/view/frontend/page_layout` +* *Theme layouts*: Layout files provided by themes. Conventional location: + * Page configuration and generic layout files: `/_/layout` + * Page layout files: `/_/page_layout` + +## Customize layout {#layout-custom} + +To ensure stability and secure your customizations from being deleted during upgrade, do not change out-of-the-box Magento [module](https://glossary.magento.com/module) and theme layouts. +To make the necessary changes, create [extending][extend] and [overriding][override] layout files in your custom theme. + +## Layout files processing {#layout_processing} + +The Magento application processes layout files in the following order: + +1. Module base files loaded. +1. Module area files loaded. +1. Collects all layout files from modules. The order is determined by the modules order in the module list from the `app/etc/config.php` file. (If their priorities are equal, they are sorted according to their alphabetical priority.) +1. Determines the sequence of [inherited] themes `[, ..., ] ` +1. Iterates the sequence of themes from last ancestor to current: + + a. Adds all extending theme layout files to the list. + + b. Replaces overridden layout files in the list. + +1. Merges all layout files from the list. + +Layout files that belong to inactive modules or modules with disabled output are ignored. + {:.bs-callout-info} + +## Layout files validation + +After layouts are merged, Magento validates them. + +Layout validations and error handling depends on the [application mode] in which your Magento instance runs: + +* developer mode: syntax is validated in `.xml` and `.xsd` files, and `.xml` files are validated according to the xsd schema. If any validation fails, the hard failure with process halt occurs. + +* production or default modes: syntax is validated in `.xml` and `.xsd` files. If validation fails, errors are logged to the `var/log` directory without throwing an exception. The validation according to the xsd schema is not performed. + +## Guide contents + +* [Layout instructions][] +* [Layout file types][] +* [Product layouts][] +* [Extend a layout][extend] +* [Override a layout][override] +* [Common layout customization tasks][] +* [Customizing layout - step-by-step illustration][] + + +[extend]: {{ page.baseurl }}/frontend-dev-guide/layouts/layout-extend.html +[override]: {{ page.baseurl }}/frontend-dev-guide/layouts/layout-override.html +[Layout file types]: {{ page.baseurl }}/frontend-dev-guide/layouts/layout-types.html +[inherited]: {{ page.baseurl }}/frontend-dev-guide/themes/theme-inherit.html +[application mode]: {{ page.baseurl }}/config-guide/bootstrap/magento-modes.html +[Layout instructions]: {{ page.baseurl }}/frontend-dev-guide/layouts/xml-instructions.html +[Product layouts]: {{ page.baseurl }}/frontend-dev-guide/layouts/product-layouts.html +[Common layout customization tasks]: {{ page.baseurl }}/frontend-dev-guide/layouts/xml-manage.html +[Customizing layout - step-by-step illustration]: {{ page.baseurl }}/frontend-dev-guide/layouts/layout-practice.html + + +[layout]: {{ site.baseurl }}/common/images/layouts_block_containers_defn21.png diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-practice.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-practice.md deleted file mode 120000 index c57fdccd3f4..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/layouts/layout-practice.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/layouts/layout-practice.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-practice.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-practice.md new file mode 100644 index 00000000000..86b5ebe46fa --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/layouts/layout-practice.md @@ -0,0 +1,294 @@ +--- +group: frontend-developer-guide +title: Customizing layout illustration +functional_areas: + - Frontend +--- + +## What's in this topic + +This article features a step-by-step illustration of how a real-life layout customization task is performed. Namely, it illustrates how to change the layout of customer account links in a Magento store page header. + +## Moving customer account links + +In their Orange theme, ExampleCorp wants to transform the header links block to a drop-down, the way it is done in the Magento Luma theme: + +![layout transform] + +To do this, they need to wrap the list of header links with a container and add a greeting with a drop-down arrow before the list. + +The Orange theme [inherits]({{ page.baseurl }}/frontend-dev-guide/themes/theme-inherit.html) from Blank, so by default the rendered header links look like following: + +```html +
    + ... + + ... +
    +``` + +The markup required for the drop-down is the following: + +```html +
    + ... + + .... +
    +``` + +### Step 1: Define the layout blocks + +ExampleCorp [applies the Luma theme]({{ page.baseurl }}/frontend-dev-guide/themes/theme-apply.html). Using the approach described in [Locate templates, layouts, and styles]({{ page.baseurl }}/frontend-dev-guide/themes/debug-theme.html) they find out that the original block responsible for displaying the header links is defined in + +`/view/frontend/layout/default.xml`: + +```xml + + ... + + + header links + + + +``` + +(See [app/code/Magento/Theme/view/frontend/layout/default.xml]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Theme/view/frontend/layout/default.xml#L43-L47) on GitHub). + +Other modules use this block to add their specific links to the header using the [referenceBlock]({{ page.baseurl }}/frontend-dev-guide/layouts/xml-instructions.html#fedg_layout_xml-instruc_ex_ref) instruction. For example, see how links are added in the Customer module: [app/code/Magento/Customer/view/frontend/layout/default.xml#L10-L23]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Customer/view/frontend/layout/default.xml#L10-L23) + +The Luma theme [moves]({{ page.baseurl }}/frontend-dev-guide/layouts/xml-instructions.html#fedg_layout_xml-instruc_ex_mv) the `top.links` block to the new `customer` block in the extending layout file. + +`/Magento_Customer/layout/default.xml` + +```xml + + + ... + +... + +... +``` + +The links that should be in header, but outside the drop-down menu are added in the new `header.links` block (`/Magento_Theme/layout/default.xml`): + +```xml + + + + header links + + + +``` + +### Step 2: Define the templates + +Similar to the way they defined the layout on the previous step, ExampleCorp +defines the template which is used as the drop-down container : `/view/frontend/templates/account/customer.phtml`. + +```php +customerLoggedIn()): ?> +
  • + + + + + + getChildHtml()):?> +
    + getChildHtml();?> +
    + +
  • + +``` + +See [app/code/Magento/Customer/view/frontend/templates/account/customer.phtml]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Customer/view/frontend/templates/account/customer.phtml). + +### Step 3: Extend the base layout to add a block + +ExampleCorp needs to create a new block, say, `header.links`, in the `header.panel` container, to move the links there. As the links can be added to this list by different modules, it is better to add this block to the `default.xml` page configuration of the `Magento_Theme` module. + +So the following [extending]({{ page.baseurl }}/frontend-dev-guide/layouts/layout-extend.html) layout is added in the Orange theme: + +`app/design/frontend/ExampleCorp/orange/Magento_Theme/layout/default.xml` + +```xml + + + + + + + header links + + + + + +``` + +### Step 4: Move links + +To move the links to the `header.links` block, ExampleCorp adds an extending layout: + +`app/design/frontend/ExampleCorp/orange/Magento_Customer/layout/default.xml` + +```xml + + + + + + + + + + + + +``` + +Now the customer links look like following: + +![layout screen1] + +Clicking the **Change** button toggles the `active` CSS class: + +To add quick basic styling and visual behavior to the "dropdown" menu, ExampleCorp added [_extend.less]({{ page.baseurl }}/frontend-dev-guide/css-guide/css_quick_guide_approach.html#simple_extend) to their theme with the following customizations: + +* Redundant elements are hidden with CSS. +* The `.lib-dropdown()` mixin from [Magento UI library]({{ page.baseurl }}/frontend-dev-guide/css-topics/theme-ui-lib.html) was applied to the corresponding element. + +`app/design/frontend/ExampleCorp/orange/web/css/source/_extend.less` + +```css +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + .header.panel .header.links { + .customer-welcome + .authorization-link { + display: none; + } + } +} + +// +// Mobile +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { + .customer-name, + .customer-welcome + .authorization-link { + display: none; + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .customer-welcome { + .lib-dropdown( + @_toggle-selector: ~'.action.switch', + @_options-selector: ~'.customer-menu .header.links', + @_dropdown-actions-padding: 0, + @_icon-font-text-hide: true, + @_icon-font-size: 22px, + @_icon-font-line-height: 22px, + @_dropdown-list-min-width: 160px, + @_dropdown-list-item-hover: transparent, + @_dropdown-list-pointer-position: right, + @_dropdown-list-position-right: 0 + ); + + li { + a { + .lib-link( + @_link-color: #333, + @_link-text-decoration: none, + @_link-color-visited: #333, + @_link-text-decoration-visited: none, + @_link-color-hover: #333, + @_link-text-decoration-hover: none, + @_link-color-active: #333, + @_link-text-decoration-active: none + ); + display: block; + line-height: 1.4; + padding: 8px; + } + } + } +} +``` + +As a result, the customer links look like following: + +![layout screen2] + +[layout transform]: {{site.baseurl}}/common/images/layout_transform21.png +[layout screen1]: {{site.baseurl}}/common/images/layout_screen221.png +[layout screen2]: {{site.baseurl}}/common/images/layout_screen321.png \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-types.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-types.md deleted file mode 120000 index 96b43bf1b62..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/layouts/layout-types.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/layouts/layout-types.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-types.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-types.md new file mode 100644 index 00000000000..46cd81f5557 --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/layouts/layout-types.md @@ -0,0 +1,492 @@ +--- +group: frontend-developer-guide +title: Layout file types +functional_areas: + - Frontend +--- + +## What's in this topic + +For a particular page, its layout is defined by two major layout components: *page layout* file and *page configuration* file. + +A page layout file defines the page wireframe, for example, one-column layout. Technically page layout is an .xml file defining the structure inside the `` section of the HTML page markup. Page layouts feature only [containers]({{ page.baseurl }}/frontend-dev-guide/layouts/xml-instructions.html#fedg_layout_xml-instruc_ex_cont). +All page layouts used for page rendering should be declared in the page layout declaration file. + +Page configuration is also an .xml file. It defines the detailed structure (page header, footer, etc.), contents and page meta information, including the page layout used. Page configuration features both main elements, [blocks]({{ page.baseurl }}/frontend-dev-guide/layouts/xml-instructions.html#fedg_layout_xml-instruc_ex_block) and [containers]({{ page.baseurl }}/frontend-dev-guide/layouts/xml-instructions.html#fedg_layout_xml-instruc_ex_cont). + +We also distinguish the third type of layout files, *generic layouts*. They are .xml files which define the contents and detailed structure inside the `` section of the HTML page markup. These files are used for pages returned by AJAX requests, emails, HTML snippets and so on. + +This article gives a comprehensive description of each layout file type. + +## Page layout {#layout-types-page} + +Page layout declares the wireframe of a page inside the `` section. For example, one-column layout or two-column layout. + +Allowed layout instructions: + +* `` +* `` +* [``]({{ page.baseurl }}/frontend-dev-guide/layouts/xml-instructions.html#fedg_layout_xml-instruc_ex_cont) +* [``]({{ page.baseurl }}/frontend-dev-guide/layouts/xml-instructions.html#fedg_layout_xml-instruc_ex_ref) +* [``]({{ page.baseurl }}/frontend-dev-guide/layouts/xml-instructions.html#fedg_layout_xml-instruc_ex_mv) +* [``]({{ page.baseurl }}/frontend-dev-guide/layouts/xml-instructions.html#fedg_layout_xml-instruc_ex_upd) + +Sample page layout: + +`/view/frontend/page_layout/2columns-left.xml` + +```xml + + + + + + + + + + + +``` + +### Page layout files conventional location {#layout-types-page-conv} + +Conventionally page layouts must be located as follows: + +* Module page layouts: `/view/frontend/page_layout` +* Theme page layouts: `/_/page_layout` + +### Page layouts declaration {#layout-types-page-dec} + +To be able to use a layout for actual page rendering, you need to declare it in `layouts.xml`. + +Conventionally layout declaration file can be located in one of the following locations: + +* Module layout declarations: `/view/frontend/layouts.xml` +* Theme layout declaration: `/_/layouts.xml` + +Declare a layout file using the `` instruction, for which specify the following: + +* ``. For example, the `2columns-left.xml` page layout is declared like following: `` +* `` + +Sample page layout declaration file: `/view/frontend/layouts.xml` + +```xml + + + + + + + + + + + + + + +``` + +Use the `layout` attribute in the `page` node of a page configuration file to define a layout type for the page. The following example shows how to use the `3 columns` page layout type for the [Wish List Sharing]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_share.xml#L8) page: + +Override the default `wishlist_index_share.xml` in any one of the following paths and add the `layout="3columns"` in the `page` node. + +* Override the layout in a custom `theme` (_in the case where a custom-built theme is applied on the storefront_): `/Magento_Wishlist/layout/wishlist_index_share.xml` +* Override the layout in custom `module` (_in case the when building third-party extensions and you need to make changes to the existing layout_): `/view/frontend/layout/wishlist_index_share.xml` + +```xml + + + + + + + + + + +``` + +![Wish List Sharing. 3 columns layout page type]({{ page.baseurl }}/frontend-dev-guide/images/wish-list-sharing.png) + +{:.bs-callout-info} +By default, Magento provides 5 page layout types for the frontend (`empty`, `1column`, `2columns-left`, `2columns-right`, and `3columns`) and 3 page layout types for the backend (`admin-empty`, `admin-1column`, and `admin-2columns-left`). + +## Page configuration {#layout-types-conf} + +The page configuration adds content to the wireframe defined in a page layout file. A page configuration also contains page meta-information, and contents of the `` section. + +### Page configuration file conventional location {#layout-type-conf-loc} + +Conventionally page configuration files must be located as follows: + +* Module page configurations: `/view/frontend/layout` +* Theme page configurations: `/_/layout` + +### Page configuration structure and allowed layout instructions + +The following table describes the instructions specific for page configuration files. For the descriptions of common layout instructions see the [Layout instructions]({{ page.baseurl }}/frontend-dev-guide/layouts/xml-instructions.html) article. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ElementAttributesParent ofDescription
    + <page></page> + +
      +
    • + layout = {layout} +
    • +
    • + xsi:noNamespaceSchemaLocation ="{path_to_schema}" +
    • +
    +
    +
      +
    • <html>
    • +
    • <head>
    • +
    • <body>
    • +
    • <update>
    • +
    +
    Mandatory root element.
    <html></html> +

    none

    +
    +
      +
    • <attribute>
    • +
    +
    <head></head>none +
      +
    • <title>
    • +
    • <meta>
    • +
    • <link>
    • +
    • <css>
    • +
    • <font>
    • +
    • <script>
    • +
    • <remove>
    • +
    • <attribute>
    • +
    +
    <body></body>none +
      +
    • <block>
    • +
    • <container>
    • +
    • <move>
    • +
    • <attribute>
    • +
    • <referenceBlock>
    • +
    • <referenceContainer>
    • +
    • <action>
    • +
    +
    <attribute> +
      +
    • name = {arbitrary_name} +
    • +
    • value = {arbitrary_value} +
    • +
    +
    +

    Specified for <html>, rendered like following:

    +

    <html name="value'>

    +
    +

    <title>

    +
    nonenonePage title
    +

    <meta>

    +
    +
      +
    • + content +
    • +
    • + charset +
    • +
    • + http-equiv +
    • +
    • + name +
    • +
    • + scheme +
    • +
    +
    + none +
    +

    <link>

    +
    +
      +
    • + defer +
    • +
    • + ie_condition +
    • +
    • + charset +
    • +
    • + hreflang +
    • +
    • + media +
    • +
    • + rel +
    • +
    • + rev +
    • +
    • + sizes +
    • +
    • + src +
    • +
    • + src_type +
    • +
    • + target +
    • +
    • + type +
    • +
    +
    + none +  
    + <css> + +
      +
    • + defer +
    • +
    • + ie_condition +
    • +
    • + charset +
    • +
    • + hreflang +
    • +
    • + media +
    • +
    • + rel +
    • +
    • + rev +
    • +
    • + sizes +
    • +
    • + src +
    • +
    • + src_type +
    • +
    • + target +
    • +
    • + type +
    • +
    +
    + none +
    +

    <script>

    +
    +
      +
    • + defer +
    • +
    • + ie_condition +
    • +
    • + async +
    • +
    • + charset +
    • +
    • + src +
    • +
    • + src_type +
    • +
    • + type +
    • +
    +
    + none +
    + +## Generic layout {#layout-types-gen} + +Generic layouts define the contents and detailed structure inside the `` section of the HTML page markup. + +### Generic layout file conventional location {#layout-type-gen-loc} + +Conventionally generic layout files must be located as follows: + +* Module generic layouts: `/view/frontend/layout` +* Theme generic layouts: `/_/layout` + +### Generic layout structure and allowed layout instructions + +The following table describes the instructions specific for generic layout files. For the descriptions of common layout instructions see the [Layout instructions]({{ page.baseurl }}/frontend-dev-guide/layouts/xml-instructions.html) article. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ElementAttributesParent ofDescription
    + <layout></layout> + +
      +
    • + + xsi:noNamespaceSchemaLocation="{path_to_schema}" + +
    • +
    +
    +
      +
    • <container>
    • +
    • <update>
    • +
    +
    Mandatory root element.
    + <update> + +
      +
    • + handle="{name_of_handle_to_include}" +
    • +
    +
    +none +
    <container> + + +
      +
    • <block>
    • +
    • <container>
    • +
    • <referenceBlock>
    • +
    • <referenceContainer>
    • +
    +
    Mandatory element
    + +Sample generic layout: + +```xml + + + + + + + +``` diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/product-layouts.md b/src/guides/v2.4/frontend-dev-guide/layouts/product-layouts.md deleted file mode 120000 index 1d9453aca06..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/layouts/product-layouts.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/layouts/product-layouts.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/product-layouts.md b/src/guides/v2.4/frontend-dev-guide/layouts/product-layouts.md new file mode 100644 index 00000000000..698dc24c57f --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/layouts/product-layouts.md @@ -0,0 +1,72 @@ +--- +group: frontend-developer-guide +title: Product layouts +functional_areas: + - Frontend +contributor_name: Atwix +contributor_link: https://www.atwix.com/ +--- + +This topic provides information about product layouts files. Magento allows you to customize view pages for all product types in the common layout files. It is also possible to perform the customization for a particular product type or even for a concrete product page by Product Entity ID or SKU. + +## Product view page + +Layout file | Description +--- | --- +`catalog_product_view.xml` | Common layout. Affects all product types +`catalog_product_view_type_bundle.xml` | Layout from this file is applied to `bundle` product only +`catalog_product_view_type_configurable.xml` | Layout from this file is applied to `configurable` product only +`catalog_product_view_type_downloadable.xml` | Layout from this file is applied to `downloadable` product only +`catalog_product_view_type_grouped.xml` | Layout from this file is applied to `grouped` product only +`catalog_product_view_type_simple.xml` | Layout from this file is applied to `simple` product only +`catalog_product_view_type_virtual.xml` | Layout from this file is applied to `virtual` product only +`catalog_product_view_id_{id}.xml` | Layout from this file is applied to the specific product by `Entity ID` value. E.g. `catalog_product_view_id_45.xml` +`catalog_product_view_sku_{sku}.xml` | Layout from this file is applied to the specific product by `SKU` value. E.g. `catalog_product_view_sku_24-WG080.xml` + +## Customize product view pages + +Use containers on the product page to structure content in the layout. You can reference the container and add blocks to it. + +Containers assign content structure to a page using container tags within a layout XML file. A container has no additional content except the content of included elements. Examples of containers include: + +* `product.info.main` +* `product.info.price` +* `product.info.stock.sku` +* `product.info.form.content` +* `product.info.extrahint` +* `product.info.social` +* `product.info.media` + +### Example + +```xml + +``` + +## Checkout cart configure page + +Layout file | Description +--- | --- +`checkout_cart_configure.xml` | Common layout. Affects all product types +`checkout_cart_configure_type_bundle.xml` | Layout from this file is applied to `bundle` product only +`checkout_cart_configure_type_configurable.xml` | Layout from this file is applied to `configurable` product only +`checkout_cart_configure_type_downloadable.xml` | Layout from this file is applied to `downloadable` product only +`checkout_cart_configure_type_simple.xml` | Layout from this file is applied to `simple` product only +`checkout_cart_configure_id_{id}.xml` | Layout from this file is applied to the specific product by `Entity ID` value. E.g. `checkout_cart_configure_id_45.xml` +`checkout_cart_configure_sku_{sku}.xml` | Layout from this file is applied to the specific product by `SKU` value. E.g. `checkout_cart_configure_sku_24-WG080.xml` +`checkout_cart_item_renderers.xml` | Layout from this file is applied to renderer's cart page items + +## Wishlist item configure page + +Layout file | Description +--- | --- +`wishlist_index_configure.xml` | Common layout. Affects all product types +`wishlist_index_configure_type_bundle.xml` | Layout from this file is applied to `bundle` product only +`wishlist_index_configure_type_configurable.xml` | Layout from this file is applied to `configurable` product only +`wishlist_index_configure_type_downloadable.xml` | Layout from this file is applied to `downloadable` product only +`wishlist_index_configure_type_grouped.xml` | Layout from this file is applied to `grouped` product only +`wishlist_index_configure_type_simple.xml` | Layout from this file is applied to `simple` product only +`wishlist_index_configure_id_{id}.xml` | Layout from this file is applied to the specific product by `Entity ID` value. E.g. `wishlist_index_configure_id_45.xml` +`wishlist_index_configure_sku_{sku}.xml` | Layout from this file is applied to the specific product by `SKU` value. E.g. `wishlist_index_configure_sku_24-WG080.xml` + +For setting a custom layout on specific category, product, and CMS pages, see [Common layout customization tasks]({{ page.baseurl }}/frontend-dev-guide/layouts/xml-manage.html#create-cms-pageproductcategory-specific-selectable-layouts). diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/xml-instructions.md b/src/guides/v2.4/frontend-dev-guide/layouts/xml-instructions.md deleted file mode 120000 index f93aa8a4806..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/layouts/xml-instructions.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/layouts/xml-instructions.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/xml-instructions.md b/src/guides/v2.4/frontend-dev-guide/layouts/xml-instructions.md new file mode 100644 index 00000000000..a45861e11ea --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/layouts/xml-instructions.md @@ -0,0 +1,457 @@ +--- +group: frontend-developer-guide +title: Layout instructions +functional_areas: + - Frontend +--- + +## What's in this topic {#fedg_layout_xml-instruc_overview} + +There are two possible ways to customize page layout in Magento: + +- Changing [layout](https://glossary.magento.com/layout) files. +- Altering templates. + +To change the page wireframe, modify the [page layout] files; all other customizations are performed in the [page configuration] or [generic layout] files. + +## Manage layouts + +To make layout changes available on every page, modify the `default.xml` file. +For example, layout changes added to `app/code/Vendor/Module/view/frontend/layout/default.xml` are loaded on all pages. +To add layout changes to a specific page, use a layout file that corresponds to the page's path. +For example, changes to the `app/code/Vendor/Module/view/frontend/layout/catalog_product_view.xml` page are loaded on the product details page. + +Use these [layout instructions](https://glossary.magento.com/layout-instructions) to: + +- Move a page element to another parent element. +- Add content. +- Remove a page element. +- Arrange the element position. + +The basic set of instructions is the same for all types of layout files. This topic describes these basic instructions. For details about how they are used in a particular layout file type, please refer to the [Layout file types] topic. + +## Common layout instructions {#fedg_layout_xml-instruc_ex} + +Use the following layout instructions to customize your layout: + +- [``](#fedg_layout_xml-instruc_ex_block) +- [``](#fedg_layout_xml-instruc_ex_cont) +- [`before` and `after` attributes](#fedg_xml-instrux_before-after) +- [``](#fedg_layout_xml-instruc_ex_act) +- [`` and ``](#fedg_layout_xml-instruc_ex_ref) +- [``](#fedg_layout_xml-instruc_ex_mv) +- [``](#fedg_layout_xml-instruc_ex_rmv) +- [``](#fedg_layout_xml-instruc_ex_upd) +- [``](#argument) +- [` vs `](#block_vs_container) + +### block {#fedg_layout_xml-instruc_ex_block} + +Defines a block. + +**Details:** A block is a unit of page output that renders some distinctive content (anything visually tangible for the end-user), such as a piece of information or a user interface element. + +Blocks are a foundational building unit for layouts in Magento. They are the link between a PHP block class (which contains logic) and a template (which renders content). Blocks can have children and grandchildren (and so on). Information can be passed from layout XML files to blocks using the `` child node. + +Blocks employ templates to generate HTML. Examples of blocks include a [category](https://glossary.magento.com/category) list, a mini cart, product tags, and product listing. + +{:.bs-callout-info} +We recommend always adding a `name` to blocks. Otherwise, it is given a random name. + +| Attribute | Description | Values | Required? | +|:------- |:------ |:------ |:------ | +| `class` | Name of a class that implements rendering of a particular block. An object of this class is responsible for actual rendering of block output. | A fully-qualified class name, such as `Vendor\Module\Block\Class`. Defaults to `Magento\Framework\View\Element\Template`. | no | +| `display` | Prevents a block from displaying (the associated PHP classes are still loaded). | `true` or `false`. Defaults to `true`. | no | +| `name` | Name that can be used to address the block to which this attribute is assigned. The name must be unique per generated page. If not specified, an automatic name will be assigned in the format ANONYMOUS_n | 0-9, A-Z, a-z, underscore (_), period (.), dash (-). Should start with a letter. Case-sensitive. | no | +| `before` | Used to position the block before an element under the same parent. The element name or alias name is specified in the value. Use dash (-) to position the block before all other elements of its level of nesting. See [before and after attributes](#fedg_xml-instrux_before-after) for details. | Element name or dash (-) | no | +| `after` | Used to position the block after an element under the same parent. The element name or alias name is specified in the value. Use dash (-) to position the block after all other elements of its level of nesting. See [before and after attributes](#fedg_xml-instrux_before-after) for details. | Element name or dash (-) | no | +| `template` | A template that represents the functionality of the block to which this attribute is assigned. If the attribute is omitted, the block will not render any output unless the block class (or a parent class) has the `$_template` property defined correctly. | `Vendor_Module::path/to/template.phtml` (Scope is already in the `templates` directory of the module) | no | +| `as` | An alias name that serves as identifier in the scope of the parent element. | 0-9, A-Z, a-z, underscore (_), period (.), dash (-). Case-sensitive. | no | +| `cacheable` | Defines whether a block element is cacheable. This can be used for development purposes and to make needed elements of the page dynamic. | `true` or `false`. Defaults to `true`. | no | +| `ifconfig` | Makes the block's visibility dependent on a system configuration field. | XPath to the system configuration field. E.g. `contact/contact/enabled` | no | + +To pass parameters use the [``](#argument) instruction. + +Sample of usage in the product listing page layout: + +```xml + +``` + +### container {#fedg_layout_xml-instruc_ex_cont} + +A structure without content that holds other layout elements such as blocks and containers. + +**Details:** +A container renders child elements during view output generation. It can be empty or it can contain an arbitrary set of `` and `` elements. If the `` is empty, and there is no child `` available, it will not be displayed in the frontend source code. + +{:.bs-callout-info} +We recommend always adding a `name` to containers. Otherwise, it is given a random name. + +| Attribute | Description | Values | Required? | +|:------- |:------ |:------ |:------ | +| `name` | A name that can be used to address the container in which this attribute is assigned. The name must be unique per generated page. If not specified, it will be auto-generated. | A-Z, a-z, 0-9, underscore (_), period (.), dash (-). Should start with a letter. Case-sensitive. | No | +| `label` | Describes the purpose of the container. | Any | No | +| `before` | Used to position the container before an element under the same parent. The element name or alias name is specified in the value. Use dash (-) to position the block before all other elements of its level of nesting. See [before and after attributes](#fedg_xml-instrux_before-after) for details. | Element name or dash (`-`) | No | +| `after` | Used to position the container after an element under the same parent. The element name or alias name is specified in the value. Use dash (-) to position the block after all other elements of its level of nesting. See [before and after attributes](#fedg_xml-instrux_before-after) for details. | Element name or dash (-). | No | +| `as` | An alias name that serves as identifier in the scope of the parent element. | 0-9, A-Z, a-z, underscore (_), period (.), dash (-). Case-sensitive. | No | +| `output` | Defines whether to output the root element. If specified, the element will be added to output list. (If not specified, the parent element is responsible for rendering its children.) | Any value except the obsolete `toHtml`. Recommended value is `1`. | No | +| `htmlTag` | Output parameter. If specified, the output is wrapped into specified HTML tag. | Any of the following: `aside`, `dd`, `div`, `dl`, `fieldset`, `main`, `nav`, `header`, `footer`, `ol`, `p`, `section`, `table`, `tfoot`, `ul` | No, Yes - if `htmlClass` or `htmlId` is specified | +| `htmlId` | Output parameter. If specified, the value is added to the wrapper element. If there is no wrapper element, this attribute has no effect. | Any valid HTML 5 `id` value. | No | +| `htmlClass` | Output parameter. If specified, the value is added to the wrapper element. If there is no wrapper element, this attribute has no effect. | Any valid HTML 5 `class` value. | No | + +Sample of usage in layout: + +```xml + + + +``` + +This would add a new column to the page layout. + +#### Controlling children visibility + +The `output` attribute controls the visibility of the container's children elements. +Set this value to `1` to render children content or `0` to disable the output of the entire container. + +Use this feature to make temporary changes to a store, such as disabling a section of the page for a sales event and re-enabling it after the event ends. + +### block vs. container {#block_vs_container} + +- Blocks represents the end of the chain in rendering HTML for Magento. +- Containers contain blocks and can wrap them in an HTML tag. +- Containers do not render any output if there are no children assigned to them. + +### before and after attributes {#fedg_xml-instrux_before-after} + +To help you to position elements in a specific order suitable for design, SEO, usability, or other requirements, Magento software provides the `before` and `after` layout attributes. +These optional attributes can be used in layout XML files to control the order of elements in their common parent. + +The following tables give a detailed description of the results you can get using the `before` and `after` attributes. The first table uses a block a as positioned element. + +| Attribute | Value | Description | +|:------- |:------ |:------ | +| `before` | Dash (-) | The block displays before all other elements in its parent node. | +| `before` | [element name] | The block displays before the named element. | +| `before` | Empty value or [element name] is absent | Use the value of `after`. If that value is empty or absent as well, the element is considered as non-positioned. | +| `after` | Dash (-) | The block displays after all other elements in its parent node. | +| `after` | [element name] | The block displays after the named element. | +| `after` | Empty value or [element name] is absent | Use the value of `before`. If that value is empty or absent as well, the block is considered as non-positioned. | + +#### Examples {#examples} + +| Situation | Result | +|:------- |:------ | +| Both `before` and `after` attributes are present | `after` takes precedence. | +| Both `before` and `after` attributes are absent or empty | The element is considered as non-positioned. All other elements are positioned at their specified locations. The non-positioned element displays at a random position that doesn't violate requirements for the positioned elements. | +| Several elements have `before` or `after` set to dash (-) | All elements display at the top (or bottom, in case of the after attribute), but the ordering of group of these elements is undefined. | +| The `before` or `after` attribute's value refers to an element that is not located in the parent node of the element being defined. | The element displays at a random location that doesn't violate requirements for the correctly positioned elements. | + +Sample usage in a layout: + +```xml + + + + + +``` + +### action {#fedg_layout_xml-instruc_ex_act} + +{:.bs-callout-warning} +The `` instruction is deprecated. If the method implementation allows, use the [``](#argument) for [``](#fedg_layout_xml-instruc_ex_block) or [``](#fedg_layout_xml-instruc_ex_ref) to access the block public API. + +Calls public methods on the block API. + +**Details:** Used to set up the execution of a certain method of the block during block generation; the `` node must be located in the scope of the `` node. + +```xml + + + Text + + + true + + +``` + +`` child nodes are translated into block method arguments. Child nodes names are arbitrary. If there are two or more nodes with the same name under ``, they are passed as one array. + +| Attribute | Description | Values | Required? | +|:------- |:------ |:------ |:------ | +| `method` | The public method that is called during block generation. | The method name in the block | yes | + +To pass parameters, use the [``](#argument) instruction. + +### referenceBlock and referenceContainer {#fedg_layout_xml-instruc_ex_ref} + +Updates in `` and `` are applied to the corresponding `` or ``. + +For example, if you make a reference by ``, you are targeting the block ``. + +To pass parameters to a block use the [``](#argument) instruction. + +| Attribute | Description | Values | Required? | +|:------- |:------ |:------ |:------ | +| `remove` | Allows to remove or cancel the removal of the element. When a container is removed, its child elements are removed as well. | `true` or `false` | no | +| `display` | Allows you to disable rendering of specific block or container with all its children (both set directly and by reference). The PHP objects of the block or container and its children are still generated and available for manipulation. | `true` or `false` | no | + +- The `remove` attribute is optional and its default value is `false`. + + This implementation allows you to remove a block or container in your layout by setting the remove attribute value to `true`, or to cancel the removal of a block or container by setting the value to `false`. + + ```xml + + ``` + +- The `display` attribute is optional and its default value is true. + + You are always able to overwrite this value in your layout. + In situation when remove value is true, the display attribute is ignored. + + ```xml + + ``` + +### move {#fedg_layout_xml-instruc_ex_mv} + +Sets the declared block or container element as a child of another element in the specified order. + +```xml + +``` + +- `` is skipped if the element to be moved is not defined. +- If the `as` attribute is not defined, the current value of the element alias is used. If that is not possible, the value of the `name` attribute is used instead. +- During layout generation, the `` instruction is processed before the removal (set using the `remove` attribute). This means if any elements are moved to the element scheduled for removal, they will be removed as well. + +| Attribute | Description | Values | Required? | +|:------- |:------ |:------ |:------ | +| `element` | Name of the element to move. | Element name | yes | +| `destination` | Name of the target parent element. | Element name | yes | +| `as` | Alias name for the element in the new location. | 0-9, A-Z, a-z, underscore (_), period (.), dash (-). Case-sensitive. | no | +| `after` or `before` | Specifies the element's position relative to siblings. Use dash (-) to position the block before or after all other siblings of its level of nesting. If the attribute is omitted, the element is placed after all siblings. | Element name | no | + +Sample of usage in the page layout: + +```xml + +``` + +### remove {#fedg_layout_xml-instruc_ex_rmv} + +`` is used only to remove the static resources linked in a page `` section. +For removing blocks or containers, use the `remove` attribute for [`` and ``](#fedg_layout_xml-instruc_ex_ref). + +```xml + + + + + + + + + + + + + +``` + +### update {#fedg_layout_xml-instruc_ex_upd} + +Includes a certain layout file. + +```xml + +``` + +The specified [handle] is "included" and executed recursively. + +Sample of usage in the page layout: + +```xml + +``` + +### argument {#argument} + + {:.bs-callout-info} +Magento 2.3.2 added the `shared` attribute. Now, instances of the view models are shared by default. If a view model is required to be a new instance each time, you must add the attribute `shared="false"` on the argument node in the layout xml file. + +Used to pass an argument. Must be always enclosed in [``](#arguments). + +| Attribute | Description | Values | Required? | +|:------- |:------ |:------ |:------ | +| `name` | Argument name. | unique | yes | +| `shared` | If false, creates a new instance of the block. | `false` | no | +| `translate` | Specify whether the string is translatable or not | `true` or `false` | no | +| `xsi:type` | Argument type. | `string`, `boolean`, `object`, `number`, `null`, `array`, `options`, `url`, `helper` | yes | + +To pass multiple arguments use the following construction: + +```xml + + Custom string + true + ... + +``` + +Arguments values set in a layout file can be accessed in [templates] using the `getData('{ArgumentName}')` and `hasData('{ArgumentName}')` methods. The latter returns a boolean defining whether there's any value set. +`{ArgumentName}` is obtained from the `name` attribute the following way: for getting the value of `` the method name is `getData('some_string')`. + +**Example:** + +Setting a value of `css_class` in the `[app/code/Magento/Theme/view/frontend/layout/default.xml]` layout file: + +```xml + + header links + +``` + +Using the value of `css_class` in `[app/code/Magento/Theme/view/frontend/templates/html/title.phtml]`: + +```php +$cssClass = $this->hasCssClass() ? ' ' . $this->getCssClass() : ''; +``` + +#### Argument types examples + +As was described above the argument attribute can be added with different types. +There are examples of all argument types. + +- The *string* type: + +```xml +Some String +``` + +- The *boolean* type: + +```xml +true +``` + +- The *object* type: + +```xml +Vendor\CustomModule\ViewModel\Class +``` + +The `Vendor\CustomModule\ViewModel\Class` class should implement the `\Magento\Framework\View\Element\Block\ArgumentInterface` interface. + +- The *number* type: + +```xml +100 +``` + +- The *null* type: + +```xml + +``` + +- The *array* type: + +```xml + + First Item + Second Item + ... + +``` + +- The *options* type: + +```xml +Vendor\CustomModule\Source\Options\Class +``` + +The `Vendor\CustomModule\Source\Options\Class` class should implement the `\Magento\Framework\Data\OptionSourceInterface` interface. + +- The *url* type: + +```xml + + param1value + param2value + ... + +``` + +The *url* may have parameters, but they are optional. + +- The *helper* type: + +```xml + + firstValue + secondValue + ... + +``` + +The *helper* can use only public methods. In this example the `someMethod()` method should be public. +The argument with *helper* type can contain `param` items which can be passed as a helper method parameters. + +#### Obtain arguments examples in template + +These argument examples can be taken in the template by *getData* method. Another way to take these arguments is using the magic method *get* followed by the name of argument in CamelCase format. Here is an example to retrieve the arguments from above example: + +```php +getData('some_string'); //or $block->getSomeString() + +/** @var bool $isActive */ +$isActive = $block->getData('is_active'); //or $block->getIsActive() + +/** @var Vendor\CustomModule\ViewModel\Class|\Magento\Framework\View\Element\Block\ArgumentInterface $viewModel */ +$viewModel = $block->getData('view_model'); //or $block->getViewModel() + +/** @var string|int|float $someNumber */ +$someNumber = $block->getData('some_number'); //or $block->getSomeNumber() + +/** @var null $nullValue */ +$nullValue = $block->getData('null_value'); //or $block->getNullValue() + +/** @var array $customArray */ +$customArray = $block->getData('custom_array'); //or $block->getCustomArray() + +/** @var array $options */ +$options = $block->getData('options'); //or $block->getoptions() + +/** @var string $shoppingCartUrl */ +$shoppingCartUrl = $block->getData('shopping_cart_url'); //or $block->getShoppingCartUrl() + +/** @var mixed $helperMethodResult */ +$helperMethodResult = $block->getData('helper_method_result'); // or $block->getHelperMethodResult() +``` + +### arguments {#arguments} + +`` is a required container for ``. It does not have its own attributes. + +```xml + + header links + +``` + +[page layout]: {{page.baseurl}}/frontend-dev-guide/layouts/layout-types.html#layout-types-page +[page configuration]: {{page.baseurl}}/frontend-dev-guide/layouts/layout-types.html#layout-types-conf +[generic layout]: {{page.baseurl}}/frontend-dev-guide/layouts/layout-types.html#layout-types-gen +[handle]: {{page.baseurl}}/frontend-dev-guide/layouts/layout-overview.html#layout-over-terms +[templates]: {{page.baseurl}}/frontend-dev-guide/templates/template-overview.html +[app/code/Magento/Theme/view/frontend/layout/default.xml]: {{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Theme/view/frontend/layout/default.xml +[app/code/Magento/Theme/view/frontend/templates/html/title.phtml]: {{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Theme/view/frontend/templates/html/title.phtml +[Layout file types]: {{page.baseurl}}/frontend-dev-guide/layouts/layout-types.html diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/xml-manage.md b/src/guides/v2.4/frontend-dev-guide/layouts/xml-manage.md deleted file mode 120000 index 4f3300a933a..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/layouts/xml-manage.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/layouts/xml-manage.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/xml-manage.md b/src/guides/v2.4/frontend-dev-guide/layouts/xml-manage.md new file mode 100644 index 00000000000..887c07a6778 --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/layouts/xml-manage.md @@ -0,0 +1,765 @@ +--- +group: frontend-developer-guide +title: Common layout customization tasks +functional_areas: + - Frontend +--- + +## In this topic + +This article describes the following typical [layout](https://glossary.magento.com/layout) customization tasks: + +- [Set the page layout](#layout_markup_columns) +- [Include static resources (JavaScript, CSS, fonts) in \](#layout_markup_css) +- [Remove static resources (JavaScript, CSS, fonts) in \](#layout_markup_css_remove) +- [Add meta tags to the head block](#layout_markup_meta) +- [Create a container](#create_cont) +- [Reference a container](#ref_container) +- [Reference a CMS block](#ref_cms_block) +- [Making the block visibility dynamic](#ref_config_block) +- [Create a block](#xml-manage-block) +- [Set body attributes](#layout_body_attributes) +- [Set the template used by a block](#set_template) +- [Modify block arguments](#layout_markup_modify-block) +- [Reference a block](#xml-manage-ref-block) +- [Use block object methods to set block properties](#layout_markup_block-properties) +- [Rearrange elements](#layout_markup_rearrange) +- [Add functionality to existing elements](#layout_markup_add_to_elements) +- [Modify functionality with plugins (interceptors)](#layout_markup_modify_with_plugins) + +{:.bs-callout-info} +To ensure stability and secure your customizations from being deleted during upgrade, do not change out-of-the-box Magento [module](https://glossary.magento.com/module) and [theme](https://glossary.magento.com/theme) layouts. To customize your layout, create extending and overriding layout files in your custom theme. + +## Set the page layout {#layout_markup_columns} + +The type of page layout to be used for a certain page is defined in the page configuration file, in the `layout` attribute of the root `` node. + +Example: +Change the layout of Advanced Search page from default "1-column" to "2-column with left bar". To do this, extend `catalogsearch_advanced_index.xml` in your theme by adding the following layout: + +```xml + +... + +``` + +## Include static resources (JavaScript, CSS, fonts) {#layout_markup_css} + +JavaScript, CSS, and other static assets are added in the `` section of a [page configuration] file. The default look of a Magento store page `` is defined by `app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml`. The recommended way to add CSS and JavaScript is to extend this file in your custom theme, and add the assets there. +The following file is a sample of a file you must add: + +```xml + + + + + + + + +``` + +## Form validation rules + +All available Magento validation rules may be found in [validation/rules.js]({{ site.mage2bloburl }}/{{page.guide_version}}/app/code/Magento/Ui/view/base/web/js/lib/validation/rules.js). + +Additionally, you may also use any available [jQuery validation rules](https://jqueryvalidation.org/documentation/#link-list-of-built-in-validation-methods). + +## Defining validation rules + +There are couple of ways to define validation rules for a form field. + +### As a `data-validate` attribute + +```html + +``` + +### As a `data-validate` attribute with arguments + +```html + +``` + +### As an attribute + +```html + +``` + +### As an attribute with arguments + +```html + +``` + +### As a class name + +```html + +``` + +### As a class name with arguments + +```html + +``` + +### Using `data-mage-init` + +```html +
    + ... +
    +``` +### Using `data-mage-init` with arguments + +```html +
    + ... +
    +``` + +## Examples + +### Adding the validation for a form + +Here are examples of all available ways of validating the form fields. + +```html +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +``` + +### Result + +As a result, the form gets validated before sending data to the server for processing. + +![Validated Form Example]({{ site.baseurl }}/common/images/form-validation-result.png) diff --git a/src/guides/v2.4/frontend-dev-guide/validations/custom-validation.md b/src/guides/v2.4/frontend-dev-guide/validations/custom-validation.md deleted file mode 120000 index 6b835106688..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/validations/custom-validation.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/validations/custom-validation.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/validations/custom-validation.md b/src/guides/v2.4/frontend-dev-guide/validations/custom-validation.md new file mode 100644 index 00000000000..312b5960f7a --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/validations/custom-validation.md @@ -0,0 +1,98 @@ +--- +group: frontend-developer-guide +title: Custom validation rules +contributor_name: Adarsh Manickam +contributor_link: https://github.com/drpayyne +--- + +Custom validation rules can be added by creating a Javascript mixin for the `mage/validation` module and calling the `$.validator.addMethod` function with the custom validation rule parameters as described below: + +```javascript +$.validator.addMethod( + 'rule-name', + function(value, element) { + // Return true or false after validation rule check + }, + $.mage.__('Error message to display if validation fails') +) +``` + +This code snippet adds a simple new validation rule to the mixin to validate if an input field has only five words. + +`Vendor/Module/view/frontend/requirejs-config.js` + +```javascript +var config = { + config: { + mixins: { + 'mage/validation': { + 'Vendor_Module/js/validation-mixin': true + } + } + } +} +``` + +`Vendor/Module/view/frontend/web/js/validation-mixin.js` + +```javascript +define(['jquery'], function($) { + 'use strict'; + + return function() { + $.validator.addMethod( + 'validate-five-words', + function(value, element) { + return value.split(' ').length == 5; + }, + $.mage.__('Please enter exactly five words') + ) + } +}); +``` + +## Modify an existing validation message + +It is possible to adjust the existing error message for form fields. +This is implemented in the core codebase in scope of the [`Magento_CatalogSearch` module]({{ site.mage2bloburl }}/{{page.guide_version}}/app/code/Magento/CatalogSearch/view/frontend/templates/advanced/form.phtml). + +```html + +``` + +The `messages` object is the one that does the job - they key is the input name and the value is a list of validation rules that should be modified for the specified input field. +Here the rule name is the key and the validation message is the value. + +```js +$('#form-to-validate').mage('validation', { + messages: { + 'input-name': { + 'validation-rule-1': 'Validation message 1', + 'validation-rule-2': 'Validation message 2', + }, + } +}); +``` + +This comes in handy when the error message needs to be specific but the rule does not change. diff --git a/src/guides/v2.4/frontend-dev-guide/validations/form-validation.md b/src/guides/v2.4/frontend-dev-guide/validations/form-validation.md deleted file mode 120000 index 4db9dcc8999..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/validations/form-validation.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/validations/form-validation.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/validations/form-validation.md b/src/guides/v2.4/frontend-dev-guide/validations/form-validation.md new file mode 100644 index 00000000000..bc592d4c65e --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/validations/form-validation.md @@ -0,0 +1,30 @@ +--- +group: frontend-developer-guide +title: Form validation +contributor_name: Adarsh Manickam +contributor_link: https://github.com/drpayyne +functional_areas: + - Frontend +--- + +The Magento application provides various ways to validate your form inputs. This implementation is based, and extends, [jQuery Validation](https://jqueryvalidation.org/documentation). + +## Validation Module Structure + +There are three main validation modules present in Magento: `jquery/validate`, `mage/validation`, and `mage/validation/validation`. + +### `jquery/validate` + +This is an alias for [`lib/web/jquery/jquery.validate`]({{ site.mage2bloburl }}/{{ page.guide_version }}/lib/web/jquery/jquery.validate.js). This is the base validation JavaScript file provided by jQuery that Magento extends. + +### `mage/validation` + +This module is present at [`lib/web/mage/validation.js`]({{ site.mage2bloburl }}/{{ page.guide_version }}/lib/web/mage/validation.js). This module includes `jquery/validate` and adds various functions, such as `$.validator.addMethod`, which can be used by mixins to add custom validation rules, a base set of rules to validate, the `mage.validation` widget, and more. + +### `mage/validation/validation` + +This module is present at [`lib/web/mage/validation/validation.js`]({{ site.mage2bloburl }}/{{ page.guide_version }}/lib/web/mage/validation/validation.js). This is considered the entry point for the form validator in Magento and is aliased as `validation` at [`Magento_Theme/view/frontend/requirejs-config.js`]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Theme/view/frontend/requirejs-config.js#L29). This includes `mage/validation` (which in turn includes `jquery/validate`), and adds a few more rules to the validator. + +## See also + +* [Validate a custom form]({{ page.baseurl }}/frontend-dev-guide/validations/custom-form-validation.html) diff --git a/src/guides/v2.4/frontend-dev-guide/validations/rule-list.md b/src/guides/v2.4/frontend-dev-guide/validations/rule-list.md deleted file mode 120000 index 5cd38661eed..00000000000 --- a/src/guides/v2.4/frontend-dev-guide/validations/rule-list.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/frontend-dev-guide/validations/rule-list.md \ No newline at end of file diff --git a/src/guides/v2.4/frontend-dev-guide/validations/rule-list.md b/src/guides/v2.4/frontend-dev-guide/validations/rule-list.md new file mode 100644 index 00000000000..c49ec9c1036 --- /dev/null +++ b/src/guides/v2.4/frontend-dev-guide/validations/rule-list.md @@ -0,0 +1,1676 @@ +--- +group: frontend-developer-guide +title: Validation Rule List +contributor_name: Goivvy LLC +contributor_link: https://www.goivvy.com/magento-optimization-service +--- + +This is a list of available form validation rules, ordered alphabetically. +Each rule contains a short description and a usage example. + +### alphanumeric + +Check if the value contains only letters, numbers, spaces or underscores. + +#### Example + +```html +
    +... + +... +
    +``` + +### credit-card-types + +A valid credit card number of a certain type(s), that can be specified as parameters. + +#### Example + +```html +
    +... + +... +
    +``` + +Possible values are: amex, mastercard, visa, dinersclub, enroute, discover, jcb, unknown, all. + +### dateITA + +Date in Italy, **\d{1,2}\/\d{1,2}\/\d{4}** format, i.e. **4/4/24** or **24/12/21**. + +#### Example + +```html +
    +... + +... +
    +``` + +* `44/44/40` - false +* `12-12-2021` - false +* `1/1/2022` - true +* `12/10/2022` - true + +There is a sanity check, so dates such as `99/12/2021` will be false. + +### dateNL + +Date in Netherlands, **\d\d?[\.\/-]\d\d?[\.\/-]\d\d\d?\d?** format. + +### Example + +```html +
    +... + +... +
    +``` + +There is no sanity check so dates such as `33-12-12` will be true. + +### datetime-validation + +Checks that the field is not empty. + +### Example + +```html +
    +... + +... +
    +``` + +### email2 + +Checks for a valid email address. + +#### Example + +```html +
    +... + +... +
    +``` + +### greater-than-equals-to + +Checks for a value of one field being greater than or equal to a value of another field + +#### Example + +```html +
    +... + + +... +
    +``` + +It does not check for both values to be numeric, so if `field-3` = 5 and `field-5` = 'a', it will silently accept it + +### integer + +Checks for a field value to be an integer, positive or negative. + +#### Example + +```html +
    +... + +... +
    +``` + +### ipv4 + +Checks for a valid IPv4 address. + +#### Example + +```html +
    +... + +... +
    +``` + +### ipv6 + +Checks for a valid IPv6 address. + +#### Example + +```html +
    +... + +... +
    +``` + +### less-than-equals-to + +Checks for a value of one field being less than or equal to a value of another field. + +#### Example + +```html +
    +... + + +... +
    +``` + +It does not check for both values to be numeric, so if `field-3` = 10 and `field-5` = '3a', it will silently accept it. + +### letters-only + +Checks for Latin A-Z,a-z letters only. + +#### Example + +```html +
    +... + +... +
    +``` + +### letters-with-basic-punc + +Checks for Latin letters and punctuation only, the regex being `a-z\-.,()'\"\s`. + +```html +
    +... + +... +
    +``` + +### max-words + +Checks that there are no more than a predefined number of words. Maximum number of words should be set as a parameter. + +#### Example + +```html +
    +... + +... +
    +``` + +Here, it accepts no more than 4 words. + +### min-words + +Checks that there are not less than a predefined number of words. Minimum number of words should be set as a parameter. + +#### Example + +```html +
    +... + +... +
    +``` + +Here, it accepts at least 4 words. + +### mobileUK + +Checks for a valid UK mobile number. + +#### Example + +```html +
    +... + +... +
    +``` + +* `+447911123456` - true +* `44791112` - false + +### no-marginal-whitespace + +Does not allow whitespaces at the start, or at the end, of an input text. + +#### Example + +```html +
    +... + +... +
    +``` + +### no-whitespace + +Does not allow whitespaces anywhere in an input text. + +#### Example + +```html +
    +... + +... +
    +``` + +### not-negative-amount + +Checks for a non-negative number. + +#### Example + +```html +
    +... + +... +
    +``` + +There is a sanity check, so **0a** will result in a warning. + +* `0` - pass +* `2.4` - pass +* `0a` - fail +* `+2` - fail + +### password-not-equal-to-user-name + +Checks that a password is not the same as a predefined string. + +#### Example + +```html +
    +... + +... +
    +``` + +In the example above, if you enter `username@domain.com` you will get a warning. + +### pattern + +Checks an input against a predefined regex pattern. + +#### Example + +```html +
    +... + +... +
    +``` + +In the example above anything except lowercase letters will trigger a warning. + +### phoneUK + +Checks for a valid UK phone number. + +#### Example + +```html +
    +... + +... +
    +``` + +### phoneUS + +Checks for a valid US phone number. + +#### Example + +```html +
    +... + +... +
    +``` + +### range-words + +Checks for a predefined number of words. + +#### Example + +```html +
    +... + +... +
    +``` + +In the example above, only a 2, 3 or 4 word input string will not trigger a warning: + +* `not used` - pass +* `not` - fail +* `not used before` - pass + +### required-dropdown-attribute-entry + +Checks that all disabled input fields (with a `required-option` class) within a table tag are empty. + +#### Example + +```html +
    + + + + + + +
    +
    +
    + +
    +
    +
    +``` + +In the example above it will trigger a warning as `field-1` is not empty. + +### required-entry + +Checks that a field is not empty. + +#### Example + +```html +
    +... + +... +
    +``` + +### required-file + +Checks for a file field to be populated. + +#### Example + +```html +
    +... + +... +
    +``` + +### required-if-all-sku-empty-and-file-not-loaded + +Makes the field required if specified fields and a specified file input are empty. + +#### Example + +```html +
    +... + + + +... +
    +``` + +In the example above, a warning is only displayed if all fields are empty. + +### required-if-not-specified + +Makes a field required if the dependent field is filled. + +#### Example + +```html +
    +... + + +... +
    +``` + +If `field-5` is not empty, then `field-3` is not required. + +### required-if-specified + +Makes a field required if the dependent field is filled. + +#### Example + +```html +
    +... + + +... +
    +``` + +If `field-5` is not empty, then `field-3` is required. + +### required-number + +Requires a number to be entered. + +```html +
    +... + +... +
    +``` + +Warning : This tag has bugs and will accept any non-empty input. + +### required-number-if-specified + +Makes a field number required if the dependent field is filled. + +#### Example + +```html +
    +... + + +... +
    +``` + +If `field-5` is not empty, then `field-3` is required, although any input will work, not just numbers. + +### required-text-swatch-entry + +Checks that all disabled input fields (with a `required-option` class) within a table tag to be empty. + +#### Example + +```html +
    + + + + + + +
    +
    +
    + +
    +
    +
    +``` + +In the example above, it will trigger a warning as `field-1` is not empty. + +### required-visual-swatch-entry + +Checks that all disabled input fields (with a `required-option` class) within a table tag are empty. + +#### Example + +```html +
    + + + + + + +
    +
    +
    + +
    +
    +
    +``` + +In the example above it will trigger a warning as `field-1` is not empty. + +### stripped-min-length + +Checks that there are at least a predefined number of characters in the input. + +#### Example + +```html +
    +... + +... +
    +``` + +In the example above, any input less than 4 characters will trigger a warning. + +### time + +Checks for a valid time between 00:00 and 23:59:59. + +#### Example + +```html +
    +... + +... +
    +``` + +### time12h + +Checks for a valid time between 00:00 am and 12:00 pm. `12:01 pm` and `11:59 pm` values are also valid. + +#### Example + +```html +
    +... + +... +
    +``` + +Warning : The implementation has bugs, for example a valid time `00:31 am` triggers a warning. + +### url2 + +Checks for a valid URL link. + +#### Example + +```html +
    +... + +... +
    +``` + +* `http://www.m2.com` - true +* `magento.com` - false + +### validate-admin-password + +Checks for a valid admin password. It must be 7 or more characters long and it has to have letters and numbers only. + +#### Example + +```html +
    +... + +... +
    +``` + +* `admindsdsdsd` - false +* `minsdsdss8` - true + +### validate-ajax-error + +Checks for an AJAX error. + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-alpha + +Checks for letters (a-z or A-Z) only. + +#### Example + +```html +
    +... + +... +
    +``` + +* `jkjkjk` - true +* `dfdfdf1` - false + +### validate-alphanum + +Checks for letters (a-z or A-Z) or numbers (0-9) only. + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-alphanum-with-spaces + +Checks for letters (a-z or A-Z) or numbers (0-9) or spaces only. + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-cc-cvn + +Checks for a valid credit card identification number. + +#### Example + +```html +
    +... + + +... +
    +``` + +### validate-cc-exp + +Checks for a valid credit card expiration month. + +#### Example + +```html +
    +... + + +... +
    +``` + +It interprets input as a month number with year set in a predefined field. Sanity check is limited. + +* `40` - true +* `G` - false + +### validate-cc-number + +Checks for a valid credit card number based on mod 10. + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-cc-type + +Checks for a credit card number to match a predefined credit card type. + +#### Example + +```html +
    +... + + +... +
    +``` + +Field `field-5` holds a credit card type, possible values are: + +* `SO` - Solo +* `SM` - Switch/Maestro +* `VI` - Visa +* `MC` - MasterCard +* `AE` - American Express +* `DI` - Discover +* `JCB` - JCB (Japan Credit Bureau) +* `DN` - Diners +* `UN` - UN +* `MI` - Maestro International +* `MD` - Maestro Domestic + +### validate-cc-type-select + +Checks for a credit card type to match a predefined credit card number. + +#### Example + +```html +
    +... + + +... +
    +``` + +### validate-cc-ukss + +Checks that the Switch/Solo/Maestro issue number and start date are filled. + +#### Example + +```html +
    +... + +... +
    +``` + +It does not do any sanity check except that a field is not empty. + +### validate-clean-url + +Checks for a valid URL. Protocol type is not necessary. + +#### Example + +```html +
    +... + +... +
    +``` + +* `fsdsd` - false +* `https://www.domain.com` - true +* `http://domain.com` - false +* `www.domain.com` - true +* `domain.com` - false + +### validate-code + +Checks for an input that has only letters (a-z or A-Z), numbers (0-9) or underscore (\_), and the first character should be a letter. + +#### Example + +```html +
    +... + +... +
    +``` + +* `1ddf` - false +* `Ad` - true + +### validate-cpassword + +Checks for a confirmation password to be the same as the password. + +#### Example + +```html +
    +... + + +... +
    +``` + +It is important to have `password` and `confirmation` IDs for the fields above. + +### validate-css-length + +Checks for a valid CSS length (Ex: 100px, 77pt, 20em, .5ex or 50%). + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-currency-dollar + +Checks for a valid US dollar amount, for example $100. + +#### Example + +```html +
    +... + +... +
    +``` + +* `$100` - true +* `200` - true +* `$ 100` - false + +### validate-customer-password + +Checks for a password to be greater or equal to a predefined number of characters and predefined number of character classes. Classes of characters: Lowercase, Uppercase, Digits, Special Characters. + +#### Example + +```html +
    +... + +... +
    +``` + +In the example above the password must be 10 or more characters long and have two or more different character classes: + +* `dfdfdfdfdfdfdfdfdfdfdfdf` - false +* `dfdfdfdfdfdfdfdfdfdfdfdf1` - true +* `d1$` - false + +### validate-data + +Checks for an input to have only letters (a-z or A-Z), numbers (0-9) or underscore (\_), and the first character should be a letter. + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-date + +Checks for a valid date against a predefined format. + +#### Example + +```html +
    +... + +... +
    +``` + +In the example above: + +* `09 09` - true +* `dfdf` - false +* `98-98` - false + +### validate-date-au + +Checks for a valid date in the format: dd/mm/yyyy. + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-date-range + +Checks for `From`-`To` date range. + +#### Example + +```html +
    +... + + +... +
    +``` + +### validate-digits + +Checks for a digits only input. + +#### Example + +```html +
    +... + +... +
    +``` + +* `sdsd` - false +* `34` - true + +### validate-digits-range + +Checks for a digits only input within a specified range. There are two ways to specify a range. You can specify a negative number as a range limit. + +#### Example + +```html +
    +... + + +... +
    +``` + +In the example above, the first range is from `-10` to `-9` and the second range is from `10` to `34`. + +### validate-email + +Checks for a valid email address. + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-emails + +Checks for a valid email(s) separated (if several) by a comma, newline or a space. + +#### Example + +```html +
    +... + +... +
    +``` + +* `test@test.com` - true +* `test@test.com,test@test2.com` - true +* `test@test.com - test@test2.com` - false + +### validate-emailSender + +Checks for a valid email address although no sanity check is performed, i.e. any input is valid. Regex is `^[\S ]+$`. + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-fax + +Checks for a valid fax number. + +#### Example + +```html +
    +... + +... +
    +``` + +* `044-434-3434` - true +* `111 222-2323` - true +* `111-12-2323` - false + +### validate-forbidden-extensions + +Checks that an input (comma separated file extensions) does not have an extension from a predefined list. + +### Example + +```html +
    +... + +... +
    +``` + +* `ddff` - true +* `jpg,png` - false +* `ddf` - false + +### validate-greater-than-zero + +Checks for a number greater than zero. There is a sanity check so `dfdf` input will trigger a warning. + +#### Example + +```html +
    +... + +... +
    +``` + +* `r4` - false +* `3.4` - true +* `+1.3` - true +* `0` - false + +### validate-identifier + +Checks for a valid URL key. + +#### Example + +```html +
    +... + +... +
    +``` + +* `dfdfdf` - true +* `hepee.html` - true +* `fdf$%.html` - false + +### validate-item-quantity + +Checks for a quantity number to be within `minAllowed` and `maxAllowed` and to be in `qtyIncremenets`. + +#### Example + +```html +
    +... + +... +
    +``` + +* `9` - false +* `28` - true +* `29` - false +* `300` - false + +### validate-length + +Checks for input length to be within specified limits. + +#### Example + +```html +
    +... + +... +
    +``` + +In the example above: + +* `f` - false +* `fa` - true +* `dfdfdf` - false + +### validate-new-password + +Checks for input to be 6 or more characters. Leading and trailing spaces are ignored. + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-no-empty + +Checks that an input is not empty. + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-no-html-tags + +Checks that an input does not have HTML tags. + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-no-utf8mb4-characters + +Checks that an input does not have characters that would require more than 3 bytes. + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-not-negative-number + +Checks for non-negative number input. + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-not-number-first + +Checks that an input does not start with a number. + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-number + +Checks for a valid number. + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-number-range + +Checks for a number to be within a specified range. + +#### Example + +```html +
    +... + +... +
    +``` + +### validate-one-required + +It is supposed to check for radio buttons selection but it always returns true. There is possibly a bug in JS files. + +#### Example + +```html +
    +... +
    + + + +
    +... +
    +``` + +### validate-one-required-by-name + +Checks for a radio button selection. + +#### Example + +```html +
    +... +
    + + + +
    +... +
    +``` + +### validate-optional-datetime + +Validates an optional datetime field. + +#### Example + +```html +
    +... +
    + + + + +
    +... +
    +``` + +### validate-password + +Checks for an input to be 6 or more characters long. Leading and trailing spaces are ignored. + +#### Example + +```html +
    +... +
    + +
    +... +
    +``` + +### validate-per-page-value + +Checks for an input to be a specified value from a comma separated field. + +#### Example + +```html +
    +... +
    + + +
    +... +
    +``` + +* `44` - false +* `8` - true + +### validate-per-page-value-list + +Checks for comma separated numbers. + +#### Example + +```html +
    +... +
    + +
    +... +
    +``` + +* `kjkjdf,dfdf` - false +* `1` - true +* `1,3,4,5` - true + +### validate-phoneLax + +Checks for a valid phone number. Formatting may be lax. + +#### Example + +```html +
    +... +
    + +
    +... +
    +``` + +### validate-phoneStrict + +Checks for a valid phone number with strict formatting. + +#### Example + +```html +
    +... +
    + +
    +... +
    +``` + +### validate-range + +Checks for an input to be within a specified range. + +#### Example + +```html +
    +... +
    + +
    +... +
    +``` + +* `100` - false +* `9` - true + +### validate-required-datetime + +Validates a required datetime field. + +#### Example + +```html +
    +... +
    + + + + +
    +... +
    +``` + +### validate-select + +Checks for a select field to be selected. + +#### Example + +```html +
    +... +
    + +
    +... +
    +``` + +### validate-ssn + +Checks for a valid Social Security number. + +#### Example + +```html +
    +... +
    + +
    +... +
    +``` + +### validate-state + +Checks for a valid State/Province. + +#### Example + +```html +
    +... +
    + +
    +... +
    +``` + +### validate-street + +Checks for a valid street address. It allows only letters (a-z or A-Z), numbers (0-9), spaces and `#`. + +#### Example + +```html +
    +... +
    + +
    +... +
    +``` + +### validate-url + +Checks for a valid URL. + +#### Example + +```html +
    +... +
    + +
    +... +
    +``` + +### validate-xml-identifier + +Checks for a valid XML-identifier (Ex: something\_1, block5, id-4). + +#### Example + +```html +
    +... +
    + +
    +... +
    +``` + +### validate-zero-or-greater + +Checks that a number is zero or greater in this field. + +#### Example + +```html +
    +... +
    + +
    +... +
    +``` + +### validate-zip-international + +Checks for a valid international zip code. + +#### Example + +```html +
    +... +
    + +
    +... +
    +``` + +### validate-zip-us + +Checks for a valid US zip code (Ex: 90602 or 90602-1234). + +#### Example + +```html +
    +... +
    + +
    +... +
    +``` + +### vinUS + +Checks for a valid vehicle identification number (VIN). + +#### Example + +```html +
    +... +
    + +
    +... +
    +``` + +### zip-range + +Checks for a zip code to be in the range 902xx-xxxx to 905-xx-xxxx. + +#### Example + +```html +
    +... +
    + +
    +... +
    +``` From 65287aeb63a8e566ed99e3d71bff57ad331e63f4 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 21 Jun 2022 16:18:52 -0500 Subject: [PATCH 210/776] Added migration metadata --- src/guides/v2.4/frontend-dev-guide/bk-frontend-dev-guide.md | 2 ++ src/guides/v2.4/frontend-dev-guide/cache_for_frontdevs.md | 2 ++ src/guides/v2.4/frontend-dev-guide/conventions.md | 2 ++ .../frontend-dev-guide/css-guide/css_quick_guide_approach.md | 2 ++ .../v2.4/frontend-dev-guide/css-guide/css_quick_guide_mode.md | 2 ++ .../frontend-dev-guide/css-guide/css_quick_guide_overview.md | 2 ++ .../v2.4/frontend-dev-guide/css-topics/css-critical-path.md | 2 ++ src/guides/v2.4/frontend-dev-guide/css-topics/css-jquery.md | 2 ++ src/guides/v2.4/frontend-dev-guide/css-topics/css-overview.md | 2 ++ src/guides/v2.4/frontend-dev-guide/css-topics/css-practice.md | 2 ++ .../v2.4/frontend-dev-guide/css-topics/css-preprocess.md | 2 ++ src/guides/v2.4/frontend-dev-guide/css-topics/css-themes.md | 2 ++ src/guides/v2.4/frontend-dev-guide/css-topics/css_debug.md | 2 ++ .../frontend-dev-guide/css-topics/custom-preprocess-parent.md | 2 ++ .../v2.4/frontend-dev-guide/css-topics/custom_preprocess.md | 2 ++ src/guides/v2.4/frontend-dev-guide/css-topics/gulp-sass.md | 2 ++ src/guides/v2.4/frontend-dev-guide/css-topics/theme-ui-lib.md | 2 ++ src/guides/v2.4/frontend-dev-guide/css-topics/using-fonts.md | 2 ++ src/guides/v2.4/frontend-dev-guide/layouts/layout-create.md | 2 ++ src/guides/v2.4/frontend-dev-guide/layouts/layout-extend.md | 2 ++ src/guides/v2.4/frontend-dev-guide/layouts/layout-override.md | 2 ++ src/guides/v2.4/frontend-dev-guide/layouts/layout-overview.md | 3 +++ src/guides/v2.4/frontend-dev-guide/layouts/layout-practice.md | 2 ++ src/guides/v2.4/frontend-dev-guide/layouts/layout-types.md | 2 ++ src/guides/v2.4/frontend-dev-guide/layouts/product-layouts.md | 2 ++ src/guides/v2.4/frontend-dev-guide/layouts/xml-instructions.md | 2 ++ src/guides/v2.4/frontend-dev-guide/layouts/xml-manage.md | 2 ++ .../responsive-web-design/rwd-breakpoints.md | 2 ++ .../v2.4/frontend-dev-guide/responsive-web-design/rwd_css.md | 2 ++ .../v2.4/frontend-dev-guide/responsive-web-design/rwd_js.md | 2 ++ .../frontend-dev-guide/responsive-web-design/rwd_mobile.md | 2 ++ .../frontend-dev-guide/responsive-web-design/rwd_overview.md | 2 ++ .../frontend-dev-guide/responsive-web-design/rwd_practice.md | 2 ++ .../templates/template-email-layout-handle.md | 2 ++ .../frontend-dev-guide/templates/template-email-migration.md | 2 ++ src/guides/v2.4/frontend-dev-guide/templates/template-email.md | 2 ++ .../v2.4/frontend-dev-guide/templates/template-override.md | 2 ++ .../v2.4/frontend-dev-guide/templates/template-overview.md | 2 ++ .../v2.4/frontend-dev-guide/templates/template-sample.md | 2 ++ .../v2.4/frontend-dev-guide/templates/template-walkthrough.md | 2 ++ src/guides/v2.4/frontend-dev-guide/theme-best-practice.md | 2 ++ src/guides/v2.4/frontend-dev-guide/themes/admin_theme_apply.md | 2 ++ .../v2.4/frontend-dev-guide/themes/admin_theme_create.md | 2 ++ src/guides/v2.4/frontend-dev-guide/themes/debug-theme.md | 2 ++ src/guides/v2.4/frontend-dev-guide/themes/favicon.md | 2 ++ src/guides/v2.4/frontend-dev-guide/themes/js-bundling.md | 2 ++ src/guides/v2.4/frontend-dev-guide/themes/product-video.md | 2 ++ src/guides/v2.4/frontend-dev-guide/themes/theme-apply.md | 2 ++ src/guides/v2.4/frontend-dev-guide/themes/theme-create.md | 2 ++ src/guides/v2.4/frontend-dev-guide/themes/theme-images.md | 2 ++ src/guides/v2.4/frontend-dev-guide/themes/theme-inherit.md | 2 ++ src/guides/v2.4/frontend-dev-guide/themes/theme-install.md | 2 ++ src/guides/v2.4/frontend-dev-guide/themes/theme-overview.md | 2 ++ src/guides/v2.4/frontend-dev-guide/themes/theme-structure.md | 2 ++ src/guides/v2.4/frontend-dev-guide/themes/theme-uninstall.md | 2 ++ src/guides/v2.4/frontend-dev-guide/themes/theme-workflow.md | 2 ++ src/guides/v2.4/frontend-dev-guide/tools/tools_overview.md | 2 ++ src/guides/v2.4/frontend-dev-guide/tools/using_grunt.md | 2 ++ .../v2.4/frontend-dev-guide/translations/theme_dictionary.md | 2 ++ .../v2.4/frontend-dev-guide/translations/translate_practice.md | 2 ++ .../v2.4/frontend-dev-guide/translations/translate_theory.md | 2 ++ src/guides/v2.4/frontend-dev-guide/translations/xlate.md | 2 ++ .../frontend-dev-guide/validations/custom-form-validation.md | 2 ++ .../v2.4/frontend-dev-guide/validations/custom-validation.md | 2 ++ .../v2.4/frontend-dev-guide/validations/form-validation.md | 2 ++ src/guides/v2.4/frontend-dev-guide/validations/rule-list.md | 2 ++ 66 files changed, 133 insertions(+) diff --git a/src/guides/v2.4/frontend-dev-guide/bk-frontend-dev-guide.md b/src/guides/v2.4/frontend-dev-guide/bk-frontend-dev-guide.md index d3d4f08c181..798c5fe5182 100644 --- a/src/guides/v2.4/frontend-dev-guide/bk-frontend-dev-guide.md +++ b/src/guides/v2.4/frontend-dev-guide/bk-frontend-dev-guide.md @@ -4,6 +4,8 @@ title: Frontend Developer Guide landing-page: Frontend Developer Guide functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/ +layout: migrated --- ## Introduction {#overview-introduction} diff --git a/src/guides/v2.4/frontend-dev-guide/cache_for_frontdevs.md b/src/guides/v2.4/frontend-dev-guide/cache_for_frontdevs.md index 4d4e730d584..928dd8edc31 100644 --- a/src/guides/v2.4/frontend-dev-guide/cache_for_frontdevs.md +++ b/src/guides/v2.4/frontend-dev-guide/cache_for_frontdevs.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Cache overview functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/caching/ +layout: migrated --- {% include cache/page-cache-overview.md%} diff --git a/src/guides/v2.4/frontend-dev-guide/conventions.md b/src/guides/v2.4/frontend-dev-guide/conventions.md index c194b8acb9d..7d8b543ee2f 100644 --- a/src/guides/v2.4/frontend-dev-guide/conventions.md +++ b/src/guides/v2.4/frontend-dev-guide/conventions.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Conventional notations used in this Guide functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/conventions/ +layout: migrated --- ## Conventional notations for paths to modules and themes diff --git a/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_approach.md b/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_approach.md index c6bedf2ed25..6b9ae3c6cad 100644 --- a/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_approach.md +++ b/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_approach.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Simple ways to customize a theme's styles functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/css/quickstart/customize-styles/ +layout: migrated --- ## What's in this topic diff --git a/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_mode.md b/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_mode.md index b709e42a222..108a9e7251c 100644 --- a/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_mode.md +++ b/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_mode.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Simple style changes with client-side LESS compilation vs. server-side functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/css/quickstart/compilation-mode/ +layout: migrated --- After you [create a theme]({{ page.baseurl }}/frontend-dev-guide/themes/theme-create.html), you need to decide which LESS compilation mode to use before changing styles. You can choose between [two modes]({{ page.baseurl }}/frontend-dev-guide/css-topics/css-preprocess.html): diff --git a/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_overview.md b/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_overview.md index 1fb8f89c971..c87f07b4bfd 100644 --- a/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_overview.md +++ b/src/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_overview.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Quick start guide to working with styles for a new theme functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/css/quickstart/ +layout: migrated --- This chapter combines the topics aiming to help you to quickly start working with styles of your custom theme: diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-critical-path.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-critical-path.md index 597ecf10d37..18d94dc008c 100644 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/css-critical-path.md +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/css-critical-path.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: CSS critical path functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/css/critical-path/ +layout: migrated --- All CSS styles loaded from external files are considered as render-blocking. This means that a web page will not be displayed until these files are loaded. diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-jquery.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-jquery.md index de2d5dae2bd..da946384743 100644 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/css-jquery.md +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/css-jquery.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Using jQuery UI styles functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/css/jquery/ +layout: migrated --- ## What's in this topic diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-overview.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-overview.md index a79ee2df52f..52abc0e0ff0 100644 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/css-overview.md +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/css-overview.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Cascading style sheets (CSS) functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/css/ +layout: migrated --- ## Overview diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-practice.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-practice.md index 69f710fd0d2..5c45a417b82 100644 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/css-practice.md +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/css-practice.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Customizing styles illustration functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/css/practice/ +layout: migrated --- ## What is in this topic {#practice_over} diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-preprocess.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-preprocess.md index 473061f5d8b..4b8a3716a95 100644 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/css-preprocess.md +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/css-preprocess.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: How CSS and Less files are preprocessed and how to debug them functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/css/preprocess/ +layout: migrated --- ## What's in this topic {#preproc_over} diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css-themes.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css-themes.md index 7c26777b3c9..a78c83785b5 100644 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/css-themes.md +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/css-themes.md @@ -4,6 +4,8 @@ title: Include CSS functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/css/themes/ +layout: migrated --- ## In this topic {#fedg_css-in-themes_overview} diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/css_debug.md b/src/guides/v2.4/frontend-dev-guide/css-topics/css_debug.md index cad4ce6ae60..b9e9753ab60 100644 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/css_debug.md +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/css_debug.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Compile LESS using Grunt functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/css/debug/ +layout: migrated --- The topic describes how to install, configure, and use [Grunt JavaScript task runner](http://gruntjs.com/) to compile `.less` files in Magento 2. diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/custom-preprocess-parent.md b/src/guides/v2.4/frontend-dev-guide/css-topics/custom-preprocess-parent.md index f0a855686ef..ab0ccc04ea4 100644 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/custom-preprocess-parent.md +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/custom-preprocess-parent.md @@ -3,4 +3,6 @@ group: frontend-developer-guide title: Using custom CSS preprocessor functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/css/custom-preprocessor/gulp-sass/ +layout: migrated --- diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/custom_preprocess.md b/src/guides/v2.4/frontend-dev-guide/css-topics/custom_preprocess.md index d5dfbb2968e..3eb7dfb77ae 100644 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/custom_preprocess.md +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/custom_preprocess.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Add custom CSS preprocessor functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/css/custom-preprocessor/add/ +layout: migrated --- ## What's in this topic diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/gulp-sass.md b/src/guides/v2.4/frontend-dev-guide/css-topics/gulp-sass.md index d663f2de282..40ed6d0794b 100644 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/gulp-sass.md +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/gulp-sass.md @@ -4,6 +4,8 @@ title: Use Sass preprocessor and Gulp task runner functional_areas: - Frontend - Tools +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/css/custom-preprocessor/gulp-sass/ +layout: migrated --- By default, Magento uses [Less](http://lesscss.org/) for themes styling. But you can use other stylesheet languages that can be compiled (processed) to CSS. For example, Sass is a popular alternative. diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/theme-ui-lib.md b/src/guides/v2.4/frontend-dev-guide/css-topics/theme-ui-lib.md index 7b3b96209b1..543789741a5 100644 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/theme-ui-lib.md +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/theme-ui-lib.md @@ -4,6 +4,8 @@ title: UI library functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/css/ui-library/ +layout: migrated --- The Magento UI [library](https://glossary.magento.com/library) is a flexible [Less]-based [frontend](https://glossary.magento.com/frontend) library designed to assist Magento [theme](https://glossary.magento.com/theme) developers. diff --git a/src/guides/v2.4/frontend-dev-guide/css-topics/using-fonts.md b/src/guides/v2.4/frontend-dev-guide/css-topics/using-fonts.md index 3d5a4393682..ea3ad01f0eb 100644 --- a/src/guides/v2.4/frontend-dev-guide/css-topics/using-fonts.md +++ b/src/guides/v2.4/frontend-dev-guide/css-topics/using-fonts.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Using custom fonts functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/css/fonts/ +layout: migrated --- The Magento application contains a set of built-in fonts, but you can easily include custom fonts. This topic describes how to include a locally stored custom font in your Magento [theme](https://glossary.magento.com/theme). diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-create.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-create.md index 8c069db9290..6b600a32042 100644 --- a/src/guides/v2.4/frontend-dev-guide/layouts/layout-create.md +++ b/src/guides/v2.4/frontend-dev-guide/layouts/layout-create.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Create a new layout functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/layouts/create/ +layout: migrated --- ## Create a new page layout in custom theme diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-extend.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-extend.md index 7e6461e759b..c44dfab81bc 100644 --- a/src/guides/v2.4/frontend-dev-guide/layouts/layout-extend.md +++ b/src/guides/v2.4/frontend-dev-guide/layouts/layout-extend.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Extend a layout functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/layouts/extend/ +layout: migrated --- ## Create a theme extending file {#fedg_layout_extend_merge} diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-override.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-override.md index 63d4851df0b..919a5062967 100644 --- a/src/guides/v2.4/frontend-dev-guide/layouts/layout-override.md +++ b/src/guides/v2.4/frontend-dev-guide/layouts/layout-override.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Override a layout functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/layouts/override/ +layout: migrated --- ## What's in this topic {#fedg_layout_override_overview} diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-overview.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-overview.md index 045f8d14fdb..171f3d3d15b 100644 --- a/src/guides/v2.4/frontend-dev-guide/layouts/layout-overview.md +++ b/src/guides/v2.4/frontend-dev-guide/layouts/layout-overview.md @@ -3,7 +3,10 @@ group: frontend-developer-guide title: Layout overview functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/layouts/ +layout: migrated --- + ## What's in this topic This article describes the basic concepts you need to know to create layouts for your custom [theme](https://glossary.magento.com/theme). diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-practice.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-practice.md index 86b5ebe46fa..5f47e04024e 100644 --- a/src/guides/v2.4/frontend-dev-guide/layouts/layout-practice.md +++ b/src/guides/v2.4/frontend-dev-guide/layouts/layout-practice.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Customizing layout illustration functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/layouts/practice/ +layout: migrated --- ## What's in this topic diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/layout-types.md b/src/guides/v2.4/frontend-dev-guide/layouts/layout-types.md index 46cd81f5557..55d9ef56618 100644 --- a/src/guides/v2.4/frontend-dev-guide/layouts/layout-types.md +++ b/src/guides/v2.4/frontend-dev-guide/layouts/layout-types.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Layout file types functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/layouts/types/ +layout: migrated --- ## What's in this topic diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/product-layouts.md b/src/guides/v2.4/frontend-dev-guide/layouts/product-layouts.md index 698dc24c57f..b5a5c068082 100644 --- a/src/guides/v2.4/frontend-dev-guide/layouts/product-layouts.md +++ b/src/guides/v2.4/frontend-dev-guide/layouts/product-layouts.md @@ -5,6 +5,8 @@ functional_areas: - Frontend contributor_name: Atwix contributor_link: https://www.atwix.com/ +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/layouts/product-layouts/ +layout: migrated --- This topic provides information about product layouts files. Magento allows you to customize view pages for all product types in the common layout files. It is also possible to perform the customization for a particular product type or even for a concrete product page by Product Entity ID or SKU. diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/xml-instructions.md b/src/guides/v2.4/frontend-dev-guide/layouts/xml-instructions.md index a45861e11ea..c86632a4564 100644 --- a/src/guides/v2.4/frontend-dev-guide/layouts/xml-instructions.md +++ b/src/guides/v2.4/frontend-dev-guide/layouts/xml-instructions.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Layout instructions functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/layouts/xml-instructions/ +layout: migrated --- ## What's in this topic {#fedg_layout_xml-instruc_overview} diff --git a/src/guides/v2.4/frontend-dev-guide/layouts/xml-manage.md b/src/guides/v2.4/frontend-dev-guide/layouts/xml-manage.md index 887c07a6778..b434d8fd71c 100644 --- a/src/guides/v2.4/frontend-dev-guide/layouts/xml-manage.md +++ b/src/guides/v2.4/frontend-dev-guide/layouts/xml-manage.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Common layout customization tasks functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/layouts/xml-manage/ +layout: migrated --- ## In this topic diff --git a/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd-breakpoints.md b/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd-breakpoints.md index 71384b4952b..091c8ed68d8 100644 --- a/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd-breakpoints.md +++ b/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd-breakpoints.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Add a custom breakpoint functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/responsive-design/breakpoints/ +layout: migrated --- ## What's in this topic diff --git a/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_css.md b/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_css.md index 87ef6f3fa96..047e2e9ab63 100644 --- a/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_css.md +++ b/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_css.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: CSS in responsive design functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/responsive-design/css/ +layout: migrated --- ## In this topic diff --git a/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_js.md b/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_js.md index 5c25b803c1a..daf5db9d8fd 100644 --- a/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_js.md +++ b/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_js.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: JavaScript in responsive design functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/responsive-design/js/ +layout: migrated --- ## What's in this topic diff --git a/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_mobile.md b/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_mobile.md index 09e2975333f..e7fca8661cd 100644 --- a/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_mobile.md +++ b/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_mobile.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Create a responsive mobile theme based on a default theme functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/responsive-design/mobile/ +layout: migrated --- ## What's in this topic diff --git a/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_overview.md b/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_overview.md index 873be2d1f0e..332a6bafeee 100644 --- a/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_overview.md +++ b/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_overview.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Overview of responsive web design in Magento functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/responsive-design/ +layout: migrated --- Responsive web design (RWD, also referred as *responsive design*) crafts websites to provide an optimal viewing experience across a wide range of devices (from large, high-resolution desktop computer monitors to mobile phones). diff --git a/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_practice.md b/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_practice.md index ccf1fae1a5b..2eb9860b374 100644 --- a/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_practice.md +++ b/src/guides/v2.4/frontend-dev-guide/responsive-web-design/rwd_practice.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Customizing RWD illustration functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/responsive-design/practice/ +layout: migrated --- ## What's in this topic diff --git a/src/guides/v2.4/frontend-dev-guide/templates/template-email-layout-handle.md b/src/guides/v2.4/frontend-dev-guide/templates/template-email-layout-handle.md index f176efeff7e..886b2e450cb 100644 --- a/src/guides/v2.4/frontend-dev-guide/templates/template-email-layout-handle.md +++ b/src/guides/v2.4/frontend-dev-guide/templates/template-email-layout-handle.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Email templates layout handle functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/templates/email-migration/ +layout: migrated --- {:.bs-callout-warning} diff --git a/src/guides/v2.4/frontend-dev-guide/templates/template-email-migration.md b/src/guides/v2.4/frontend-dev-guide/templates/template-email-migration.md index 4e5bed5aedf..7204690c835 100644 --- a/src/guides/v2.4/frontend-dev-guide/templates/template-email-migration.md +++ b/src/guides/v2.4/frontend-dev-guide/templates/template-email-migration.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Migrating custom email templates functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/templates/email-migration/ +layout: migrated --- {% raw %} diff --git a/src/guides/v2.4/frontend-dev-guide/templates/template-email.md b/src/guides/v2.4/frontend-dev-guide/templates/template-email.md index 6619737d46d..b0ec32d04f3 100644 --- a/src/guides/v2.4/frontend-dev-guide/templates/template-email.md +++ b/src/guides/v2.4/frontend-dev-guide/templates/template-email.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Email templates functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/templates/email/ +layout: migrated --- {:.bs-callout-warning} diff --git a/src/guides/v2.4/frontend-dev-guide/templates/template-override.md b/src/guides/v2.4/frontend-dev-guide/templates/template-override.md index 1dcdd65be5d..4b2f707cdbf 100644 --- a/src/guides/v2.4/frontend-dev-guide/templates/template-override.md +++ b/src/guides/v2.4/frontend-dev-guide/templates/template-override.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Templates basic concepts functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/templates/override/ +layout: migrated --- ## What's in this topic diff --git a/src/guides/v2.4/frontend-dev-guide/templates/template-overview.md b/src/guides/v2.4/frontend-dev-guide/templates/template-overview.md index 143c4039a75..1d4604df010 100644 --- a/src/guides/v2.4/frontend-dev-guide/templates/template-overview.md +++ b/src/guides/v2.4/frontend-dev-guide/templates/template-overview.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Templates overview functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/templates/ +layout: migrated --- ## Introduction to customizing a theme using templates diff --git a/src/guides/v2.4/frontend-dev-guide/templates/template-sample.md b/src/guides/v2.4/frontend-dev-guide/templates/template-sample.md index 0e9ddf41e25..07189b4e8e0 100644 --- a/src/guides/v2.4/frontend-dev-guide/templates/template-sample.md +++ b/src/guides/v2.4/frontend-dev-guide/templates/template-sample.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Templates customization sample functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/templates/sample/ +layout: migrated --- This topic contains a step-by-step guide to solving a typical design customization task using templates. diff --git a/src/guides/v2.4/frontend-dev-guide/templates/template-walkthrough.md b/src/guides/v2.4/frontend-dev-guide/templates/template-walkthrough.md index ee5c153e36f..d2ddd5fb167 100644 --- a/src/guides/v2.4/frontend-dev-guide/templates/template-walkthrough.md +++ b/src/guides/v2.4/frontend-dev-guide/templates/template-walkthrough.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Templates customization walkthrough functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/templates/walkthrough/ +layout: migrated --- ## What's in this topic diff --git a/src/guides/v2.4/frontend-dev-guide/theme-best-practice.md b/src/guides/v2.4/frontend-dev-guide/theme-best-practice.md index f6178fba1cc..9f3947563dc 100644 --- a/src/guides/v2.4/frontend-dev-guide/theme-best-practice.md +++ b/src/guides/v2.4/frontend-dev-guide/theme-best-practice.md @@ -5,6 +5,8 @@ functional_areas: - Frontend - Theme - Standards +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/best-practices/ +layout: migrated --- Utilizing best practices for theme development give you a better chance of avoiding conflicts and issues with your theme after you update or upgrade your Magento instance or install a custom extension. diff --git a/src/guides/v2.4/frontend-dev-guide/themes/admin_theme_apply.md b/src/guides/v2.4/frontend-dev-guide/themes/admin_theme_apply.md index 01a46dad9e2..16777493a7d 100644 --- a/src/guides/v2.4/frontend-dev-guide/themes/admin_theme_apply.md +++ b/src/guides/v2.4/frontend-dev-guide/themes/admin_theme_apply.md @@ -4,6 +4,8 @@ title: Apply an Admin theme functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/themes/apply-admin/ +layout: migrated --- ## What's in this topic {#favicon-intro} diff --git a/src/guides/v2.4/frontend-dev-guide/themes/admin_theme_create.md b/src/guides/v2.4/frontend-dev-guide/themes/admin_theme_create.md index e548755cc75..2db91cb7211 100644 --- a/src/guides/v2.4/frontend-dev-guide/themes/admin_theme_create.md +++ b/src/guides/v2.4/frontend-dev-guide/themes/admin_theme_create.md @@ -4,6 +4,8 @@ title: Create an Admin theme functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/themes/create-admin/ +layout: migrated --- ## What's in this topic {#favicon-intro} diff --git a/src/guides/v2.4/frontend-dev-guide/themes/debug-theme.md b/src/guides/v2.4/frontend-dev-guide/themes/debug-theme.md index c5329737704..52d5ed7cb1c 100644 --- a/src/guides/v2.4/frontend-dev-guide/themes/debug-theme.md +++ b/src/guides/v2.4/frontend-dev-guide/themes/debug-theme.md @@ -4,6 +4,8 @@ title: Locate templates, layouts, and styles functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/themes/debug/ +layout: migrated --- ## What's in this topic {#debug-theme-intro} diff --git a/src/guides/v2.4/frontend-dev-guide/themes/favicon.md b/src/guides/v2.4/frontend-dev-guide/themes/favicon.md index f6d2b355b8e..0ccc19b480c 100644 --- a/src/guides/v2.4/frontend-dev-guide/themes/favicon.md +++ b/src/guides/v2.4/frontend-dev-guide/themes/favicon.md @@ -4,6 +4,8 @@ title: Adding custom favicons functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/themes/favicon/ +layout: migrated --- ## What's in this topic {#favicon-intro} diff --git a/src/guides/v2.4/frontend-dev-guide/themes/js-bundling.md b/src/guides/v2.4/frontend-dev-guide/themes/js-bundling.md index 7f2c188a22e..577dcbf1d0c 100644 --- a/src/guides/v2.4/frontend-dev-guide/themes/js-bundling.md +++ b/src/guides/v2.4/frontend-dev-guide/themes/js-bundling.md @@ -4,6 +4,8 @@ title: JavaScript Bundling functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/themes/js-bundling/ +layout: migrated --- JavaScript bundling is an optimization technique you can use to reduce the number of server requests for JavaScript files. Bundling accomplishes this by merging multiple JavaScript files together into one file to reduce the number of page requests. diff --git a/src/guides/v2.4/frontend-dev-guide/themes/product-video.md b/src/guides/v2.4/frontend-dev-guide/themes/product-video.md index ce2b6106a3d..371bf19864f 100644 --- a/src/guides/v2.4/frontend-dev-guide/themes/product-video.md +++ b/src/guides/v2.4/frontend-dev-guide/themes/product-video.md @@ -4,6 +4,8 @@ title: Configure product video functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/themes/product-video/ +layout: migrated --- ## What's in this topic diff --git a/src/guides/v2.4/frontend-dev-guide/themes/theme-apply.md b/src/guides/v2.4/frontend-dev-guide/themes/theme-apply.md index 35a85fe7bde..f354e400b84 100644 --- a/src/guides/v2.4/frontend-dev-guide/themes/theme-apply.md +++ b/src/guides/v2.4/frontend-dev-guide/themes/theme-apply.md @@ -4,6 +4,8 @@ title: Apply and configure a storefront theme functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/themes/apply-storefront/ +layout: migrated --- ## What's in this topic {#theme-apply-overview} diff --git a/src/guides/v2.4/frontend-dev-guide/themes/theme-create.md b/src/guides/v2.4/frontend-dev-guide/themes/theme-create.md index f371dfc14bc..66ea46e3269 100644 --- a/src/guides/v2.4/frontend-dev-guide/themes/theme-create.md +++ b/src/guides/v2.4/frontend-dev-guide/themes/theme-create.md @@ -4,6 +4,8 @@ title: Create a new storefront theme functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/themes/create-storefront/ +layout: migrated --- This topic discusses how to create the files that make up a theme, how to add a logo to a theme, and how to size images. diff --git a/src/guides/v2.4/frontend-dev-guide/themes/theme-images.md b/src/guides/v2.4/frontend-dev-guide/themes/theme-images.md index 593c77c7ed0..2fce5246883 100644 --- a/src/guides/v2.4/frontend-dev-guide/themes/theme-images.md +++ b/src/guides/v2.4/frontend-dev-guide/themes/theme-images.md @@ -4,6 +4,8 @@ title: Configure theme properties functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/themes/configure/ +layout: migrated --- ## What's in this topic diff --git a/src/guides/v2.4/frontend-dev-guide/themes/theme-inherit.md b/src/guides/v2.4/frontend-dev-guide/themes/theme-inherit.md index ac72d9d3bc2..1f6b9b20899 100644 --- a/src/guides/v2.4/frontend-dev-guide/themes/theme-inherit.md +++ b/src/guides/v2.4/frontend-dev-guide/themes/theme-inherit.md @@ -4,6 +4,8 @@ title: Theme inheritance functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/themes/inheritance/ +layout: migrated --- ## What's in this topic {#theme-inherit-over} diff --git a/src/guides/v2.4/frontend-dev-guide/themes/theme-install.md b/src/guides/v2.4/frontend-dev-guide/themes/theme-install.md index b202b77c9fc..88867fa2cc9 100644 --- a/src/guides/v2.4/frontend-dev-guide/themes/theme-install.md +++ b/src/guides/v2.4/frontend-dev-guide/themes/theme-install.md @@ -4,6 +4,8 @@ title: Install a third-party storefront theme functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/themes/install/ +layout: migrated --- ## What's in this topic diff --git a/src/guides/v2.4/frontend-dev-guide/themes/theme-overview.md b/src/guides/v2.4/frontend-dev-guide/themes/theme-overview.md index 97327d56504..875f0d0d35b 100644 --- a/src/guides/v2.4/frontend-dev-guide/themes/theme-overview.md +++ b/src/guides/v2.4/frontend-dev-guide/themes/theme-overview.md @@ -4,6 +4,8 @@ title: Themes overview functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/themes/ +layout: migrated --- ## Themes overview diff --git a/src/guides/v2.4/frontend-dev-guide/themes/theme-structure.md b/src/guides/v2.4/frontend-dev-guide/themes/theme-structure.md index 649925efcd7..351f721054e 100644 --- a/src/guides/v2.4/frontend-dev-guide/themes/theme-structure.md +++ b/src/guides/v2.4/frontend-dev-guide/themes/theme-structure.md @@ -4,6 +4,8 @@ title: Theme structure functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/themes/structure/ +layout: migrated --- ## What's in this topic {#theme-structure-intro} diff --git a/src/guides/v2.4/frontend-dev-guide/themes/theme-uninstall.md b/src/guides/v2.4/frontend-dev-guide/themes/theme-uninstall.md index 198bfd4685a..cc30bd6984e 100644 --- a/src/guides/v2.4/frontend-dev-guide/themes/theme-uninstall.md +++ b/src/guides/v2.4/frontend-dev-guide/themes/theme-uninstall.md @@ -4,6 +4,8 @@ title: Uninstall a storefront theme functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/themes/uninstall/ +layout: migrated --- ## What's in this topic diff --git a/src/guides/v2.4/frontend-dev-guide/themes/theme-workflow.md b/src/guides/v2.4/frontend-dev-guide/themes/theme-workflow.md index 3dd5e786d8e..eef99075aa2 100644 --- a/src/guides/v2.4/frontend-dev-guide/themes/theme-workflow.md +++ b/src/guides/v2.4/frontend-dev-guide/themes/theme-workflow.md @@ -4,6 +4,8 @@ title: Theme development workflow functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/themes/workflow/ +layout: migrated --- Continue From: diff --git a/src/guides/v2.4/frontend-dev-guide/tools/tools_overview.md b/src/guides/v2.4/frontend-dev-guide/tools/tools_overview.md index 6443141e900..60c65fcc768 100644 --- a/src/guides/v2.4/frontend-dev-guide/tools/tools_overview.md +++ b/src/guides/v2.4/frontend-dev-guide/tools/tools_overview.md @@ -4,6 +4,8 @@ title: Additional tools for frontend developers functional_areas: - Frontend - Tools +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/tools/ +layout: migrated --- This chapter describes how to install and use additional tools that can make your Magento frontend development tasks easier. diff --git a/src/guides/v2.4/frontend-dev-guide/tools/using_grunt.md b/src/guides/v2.4/frontend-dev-guide/tools/using_grunt.md index 3b78063c5c4..a391da1defc 100644 --- a/src/guides/v2.4/frontend-dev-guide/tools/using_grunt.md +++ b/src/guides/v2.4/frontend-dev-guide/tools/using_grunt.md @@ -4,6 +4,8 @@ title: Using Grunt functional_areas: - Frontend - Tools +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/tools/grunt/ +layout: migrated --- The topic describes how to install and configure [Grunt JavaScript task runner](http://gruntjs.com/). diff --git a/src/guides/v2.4/frontend-dev-guide/translations/theme_dictionary.md b/src/guides/v2.4/frontend-dev-guide/translations/theme_dictionary.md index fe9cb03e6dd..e8060fef245 100644 --- a/src/guides/v2.4/frontend-dev-guide/translations/theme_dictionary.md +++ b/src/guides/v2.4/frontend-dev-guide/translations/theme_dictionary.md @@ -4,6 +4,8 @@ title: Use translation dictionary to customize strings functional_areas: - Frontend - Theme +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/translations/dictionary/ +layout: migrated --- Modify default strings in your custom [theme](https://glossary.magento.com/theme) to load and use [translation dictionaries]. Learn more about locales, modifying strings, and how Magento searches and applies translations. diff --git a/src/guides/v2.4/frontend-dev-guide/translations/translate_practice.md b/src/guides/v2.4/frontend-dev-guide/translations/translate_practice.md index 7afcc616965..2bda4ede90e 100644 --- a/src/guides/v2.4/frontend-dev-guide/translations/translate_practice.md +++ b/src/guides/v2.4/frontend-dev-guide/translations/translate_practice.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Example theme translation dictionary functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/translations/practice/ +layout: migrated --- This topic is a step-by-step tutorial to create a default en_US [locale](https://glossary.magento.com/locale) [dictionary] for a custom [theme](https://glossary.magento.com/theme). diff --git a/src/guides/v2.4/frontend-dev-guide/translations/translate_theory.md b/src/guides/v2.4/frontend-dev-guide/translations/translate_theory.md index ac4f51a20df..9fdd57fdb31 100644 --- a/src/guides/v2.4/frontend-dev-guide/translations/translate_theory.md +++ b/src/guides/v2.4/frontend-dev-guide/translations/translate_theory.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Translate theme strings functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/translations/theory/ +layout: migrated --- This topic describes how to add theme strings so that the i18n tool can collect and add the strings to the dictionary. diff --git a/src/guides/v2.4/frontend-dev-guide/translations/xlate.md b/src/guides/v2.4/frontend-dev-guide/translations/xlate.md index 124f4fa61b6..4081c1f366e 100644 --- a/src/guides/v2.4/frontend-dev-guide/translations/xlate.md +++ b/src/guides/v2.4/frontend-dev-guide/translations/xlate.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Translations overview functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/translations/ +layout: migrated --- The Magento application enables you to localize your store for multiple regions and markets. We improved the localization and customization of Magento instances by making translation dictionaries easier to update and by maintaining a reduced amount of code coupling and duplication. diff --git a/src/guides/v2.4/frontend-dev-guide/validations/custom-form-validation.md b/src/guides/v2.4/frontend-dev-guide/validations/custom-form-validation.md index c5b473468ee..b48320b91b4 100644 --- a/src/guides/v2.4/frontend-dev-guide/validations/custom-form-validation.md +++ b/src/guides/v2.4/frontend-dev-guide/validations/custom-form-validation.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Custom form validation contributor_name: Atwix contributor_link: https://www.atwix.com/ +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/validations/custom-form/ +layout: migrated --- This tutorial shows you how to create custom form validations, using the `mage/validation` library, before submitting it to the server. diff --git a/src/guides/v2.4/frontend-dev-guide/validations/custom-validation.md b/src/guides/v2.4/frontend-dev-guide/validations/custom-validation.md index 312b5960f7a..d1f4cdd9f9b 100644 --- a/src/guides/v2.4/frontend-dev-guide/validations/custom-validation.md +++ b/src/guides/v2.4/frontend-dev-guide/validations/custom-validation.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Custom validation rules contributor_name: Adarsh Manickam contributor_link: https://github.com/drpayyne +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/validations/custom-rules/ +layout: migrated --- Custom validation rules can be added by creating a Javascript mixin for the `mage/validation` module and calling the `$.validator.addMethod` function with the custom validation rule parameters as described below: diff --git a/src/guides/v2.4/frontend-dev-guide/validations/form-validation.md b/src/guides/v2.4/frontend-dev-guide/validations/form-validation.md index bc592d4c65e..f44ae3e56ce 100644 --- a/src/guides/v2.4/frontend-dev-guide/validations/form-validation.md +++ b/src/guides/v2.4/frontend-dev-guide/validations/form-validation.md @@ -5,6 +5,8 @@ contributor_name: Adarsh Manickam contributor_link: https://github.com/drpayyne functional_areas: - Frontend +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/validations/ +layout: migrated --- The Magento application provides various ways to validate your form inputs. This implementation is based, and extends, [jQuery Validation](https://jqueryvalidation.org/documentation). diff --git a/src/guides/v2.4/frontend-dev-guide/validations/rule-list.md b/src/guides/v2.4/frontend-dev-guide/validations/rule-list.md index c49ec9c1036..5aeb374a11d 100644 --- a/src/guides/v2.4/frontend-dev-guide/validations/rule-list.md +++ b/src/guides/v2.4/frontend-dev-guide/validations/rule-list.md @@ -3,6 +3,8 @@ group: frontend-developer-guide title: Validation Rule List contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/validations/rule-list/ +layout: migrated --- This is a list of available form validation rules, ordered alphabetically. From 4ed608783ae1699b8728777a222032441934a769 Mon Sep 17 00:00:00 2001 From: Donald Booth Date: Wed, 22 Jun 2022 13:55:57 -0400 Subject: [PATCH 211/776] Removed ref to EOL IE --- src/_includes/browsers/supported-browsers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_includes/browsers/supported-browsers.md b/src/_includes/browsers/supported-browsers.md index dab3451f284..4661b3f9b99 100644 --- a/src/_includes/browsers/supported-browsers.md +++ b/src/_includes/browsers/supported-browsers.md @@ -1,6 +1,6 @@ Storefront and Admin: -* Internet Explorer 11 or later, Microsoft Edge, latest and previous major version +* Microsoft Edge, latest and previous major version * Firefox latest, latest and previous major version (any operating system) * Chrome latest, latest and previous major version (any operating system) * Safari latest, latest and previous major version (Mac OS only) From 793c0134e6b4aea58a91ed86994d07e22622d580 Mon Sep 17 00:00:00 2001 From: jfrontain Date: Wed, 22 Jun 2022 15:06:21 -0500 Subject: [PATCH 212/776] added known issue for 2.4.4-p1 --- src/guides/v2.4/release-notes/2-4-4-p1.md | 4 ++++ src/guides/v2.4/release-notes/commerce-2-4-5.md | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/guides/v2.4/release-notes/2-4-4-p1.md b/src/guides/v2.4/release-notes/2-4-4-p1.md index 199eb71360a..6b290f514e5 100644 --- a/src/guides/v2.4/release-notes/2-4-4-p1.md +++ b/src/guides/v2.4/release-notes/2-4-4-p1.md @@ -26,6 +26,10 @@ Security improvements for this release improve compliance with the latest securi For instructions on downloading and applying security patches (including patch 2.4.4-p1), see [Quick start install]({{site.baseurl}}/guides/v2.4/install-gde/composer.html). +## Known issue + +**Issue**: Web API and integration tests display this error when run on the 2.4.4-p1 package: `[2022-06-14T16:58:23.694Z] PHP Fatal error: Declaration of Magento\TestFramework\ErrorLog\Logger::addRecord(int $level, string $message, array $context = []): bool must be compatible with Monolog\Logger::addRecord(int $level, string $message, array $context = [], ?Monolog\DateTimeImmutable $datetime = null): bool in /var/www/html/dev/tests/integration/framework/Magento/TestFramework/ErrorLog/Logger.php on line 69`. **Workaround**: Install the previous version of Monolog by running the `require monolog/monolog:2.6.0` command. + ## More information? For general information about security patches, see [Introducing the New Security Patch Release](https://community.magento.com/t5/Magento-DevBlog/Introducing-the-New-Security-Patch-Release/ba-p/141287). diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md index 4d154d7a295..1a6c6ebca21 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-5.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -50,7 +50,7 @@ Security improvements for this release improve compliance with the latest securi ### Platform enhancements -* **Adobe Commerce on-premises deployments**: Adobe Commerce 2.4.5 has been tested and confirmed to be compatible with Elasticsearch 7.17 (~7.17.0 with constraint). Merchants hosting Adobe Commerce on-premises can use either Elasticsearch or OpenSearch. +* **Adobe Commerce on-premises deployments**: Adobe Commerce 2.4.5 has been tested and confirmed to be compatible with Elasticsearch 7.17 (~7.17.0 with constraint). Merchants hosting Adobe Commerce on-premises can use either Elasticsearch or OpenSearch 1.2. * **Adobe Commerce cloud-hosted deployments**: ElasticSearch 7.11 or later is not supported on Adobe Commerce 2.4.5 cloud-hosted deployments. OpenSearch is the default search engine for Adobe Commerce 2.4.5 cloud deployments. @@ -233,7 +233,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -The **Shopping bag** button now provides a programmatic or textual indication of its state. Screen reader users are informed that clicking this button will expand other content, or that the associated content is expanded or collapsed. Previously, this button did not provide a programmatic or textual indication of its state. +* The **Shopping bag** button now provides a programmatic or textual indication of its state. Screen reader users are informed that clicking this button will expand other content, or that the associated content is expanded or collapsed. Previously, this button did not provide a programmatic or textual indication of its state. From 3b2440dfa580903bcc78c3931c77facbde02c962 Mon Sep 17 00:00:00 2001 From: jhadobe Date: Wed, 22 Jun 2022 15:24:17 -0500 Subject: [PATCH 213/776] Adding migrated_to and updating links to dev site --- src/guides/v2.3/b2b/company-object.md | 2 +- src/guides/v2.3/b2b/company-structures.md | 2 +- src/guides/v2.3/b2b/company-users.md | 2 +- src/guides/v2.3/b2b/credit-manage.md | 4 ++-- src/guides/v2.3/b2b/shared-cat-manage.md | 2 +- src/guides/v2.3/b2b/shared-catalog.md | 2 +- src/guides/v2.3/graphql/tutorials/checkout/index.md | 4 ++-- src/guides/v2.3/inventory/release-notes.md | 2 +- src/guides/v2.3/rest/anonymous-api-security.md | 1 + src/guides/v2.3/rest/asynchronous-web-endpoints.md | 5 +++-- src/guides/v2.3/rest/bulk-endpoints.md | 1 + src/guides/v2.3/rest/modules/catalog-pricing.md | 1 + src/guides/v2.3/rest/modules/catalog.md | 1 + .../v2.3/rest/modules/inventory/bulk-inventory.md | 3 ++- .../rest/modules/inventory/link-stocks-sources.md | 5 +++-- .../rest/modules/inventory/manage-low-quantity.md | 1 + .../modules/inventory/manage-source-selection.md | 1 + .../v2.3/rest/modules/inventory/manage-stocks.md | 3 ++- src/guides/v2.3/rest/modules/sales/refunds.md | 1 + src/guides/v2.3/rest/notes.md | 3 ++- src/guides/v2.3/rest/operation-status-endpoints.md | 9 +++++---- src/guides/v2.3/rest/operation-status-search.md | 5 +++-- src/guides/v2.3/rest/performing-searches.md | 1 + src/guides/v2.3/rest/retrieve-filtered-responses.md | 5 +++-- src/guides/v2.3/rest/search-endpoint.md | 5 +++-- .../config-product-intro.md | 9 +++++---- .../create-configurable-simple-products.md | 7 ++++--- .../create-personalization-option.md | 7 ++++--- .../define-config-product-options.md | 9 +++++---- .../bulk-configurable-product/plan-product.md | 1 + .../bundle-product/bundle-product-intro.md | 1 + .../bundle-product/create-bundle-product.md | 7 ++++--- .../bundle-product/create-simple-products.md | 5 +++-- .../rest/tutorials/bundle-product/plan-product.md | 1 + .../configurable-product/config-product-intro.md | 5 +++-- .../create-configurable-product.md | 5 +++-- .../create-personalization-option.md | 7 ++++--- .../configurable-product/create-simple-products.md | 5 +++-- .../define-config-product-options.md | 5 +++-- .../tutorials/configurable-product/plan-product.md | 1 + .../create-and-manage-grouped-products.md | 9 +++++---- .../v2.3/rest/tutorials/orders/order-add-items.md | 1 + .../rest/tutorials/orders/order-create-customer.md | 1 + .../rest/tutorials/orders/order-create-invoice.md | 1 + .../rest/tutorials/orders/order-create-order.md | 1 + .../rest/tutorials/orders/order-create-quote.md | 1 + .../rest/tutorials/orders/order-create-shipment.md | 1 + .../rest/tutorials/orders/order-prepare-checkout.md | 1 + src/guides/v2.4/b2b/negotiable-order-workflow.md | 6 +++--- src/guides/v2.4/b2b/roles.md | 2 +- .../tutorials/create-custom-rest-api.md | 4 ++-- .../searching-with-repositories.md | 2 +- src/guides/v2.4/extension-dev-guide/security/dos.md | 2 +- .../authentication/gs-authentication-token.md | 4 ++-- src/guides/v2.4/get-started/bk-get-started-api.md | 2 +- src/guides/v2.4/get-started/gs-web-api-request.md | 2 +- src/guides/v2.4/graphql/authorization-tokens.md | 2 +- .../v2.4/inventory/inventory-api-reference.md | 4 ++-- src/guides/v2.4/mrg/intro.md | 2 +- src/guides/v2.4/rest/bk-rest.md | 1 + src/guides/v2.4/rest/generate-local.md | 3 ++- .../modules/inventory/check-salable-quantity.md | 1 + .../v2.4/rest/modules/inventory/in-store-pickup.md | 3 ++- .../rest/modules/inventory/manage-source-items.md | 3 ++- .../v2.4/rest/modules/inventory/manage-sources.md | 3 ++- src/guides/v2.4/rest/protected-endpoints.md | 1 + src/guides/v2.4/rest/tutorials/index.md | 13 +++++++------ .../tutorials/inventory/assign-source-to-stock.md | 3 ++- .../tutorials/inventory/bulk-transfer-products.md | 1 + .../tutorials/inventory/configure-environment.md | 1 + .../tutorials/inventory/create-cart-add-products.md | 1 + .../rest/tutorials/inventory/create-customer.md | 1 + .../v2.4/rest/tutorials/inventory/create-invoice.md | 3 ++- .../v2.4/rest/tutorials/inventory/create-order.md | 1 + .../rest/tutorials/inventory/create-shipment.md | 1 + .../v2.4/rest/tutorials/inventory/create-sources.md | 3 ++- .../v2.4/rest/tutorials/inventory/create-stock.md | 1 + .../rest/tutorials/inventory/in-store-pickup.md | 7 ++++--- src/guides/v2.4/rest/tutorials/inventory/index.md | 7 ++++--- .../tutorials/inventory/prepare-for-checkout.md | 1 + .../reassign-products-to-another-source.md | 1 + src/guides/v2.4/rest/tutorials/inventory/run-ssa.md | 7 ++++--- .../v2.4/rest/tutorials/orders/order-admin-token.md | 1 + .../rest/tutorials/orders/order-config-store.md | 1 + .../v2.4/rest/tutorials/orders/order-intro.md | 5 +++-- .../rest/tutorials/orders/order-issue-refund.md | 5 +++-- .../prerequisite-tasks/create-admin-token.md | 1 + 87 files changed, 171 insertions(+), 103 deletions(-) diff --git a/src/guides/v2.3/b2b/company-object.md b/src/guides/v2.3/b2b/company-object.md index ac8c7389f1d..174ed3f82a5 100644 --- a/src/guides/v2.3/b2b/company-object.md +++ b/src/guides/v2.3/b2b/company-object.md @@ -242,7 +242,7 @@ None The following call returns all companies that are located in California (`region_id` = `12`) -See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/b2b/company-structures.md b/src/guides/v2.3/b2b/company-structures.md index 99c7bfb6fe2..81e76c5939b 100644 --- a/src/guides/v2.3/b2b/company-structures.md +++ b/src/guides/v2.3/b2b/company-structures.md @@ -123,7 +123,7 @@ An empty array The following query returns information about all teams (`team_id` ≥ `0`) -See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/b2b/company-users.md b/src/guides/v2.3/b2b/company-users.md index 7b4af08d349..4bfd801ba06 100644 --- a/src/guides/v2.3/b2b/company-users.md +++ b/src/guides/v2.3/b2b/company-users.md @@ -10,7 +10,7 @@ functional_areas: A company user is a customer (buyer) that is assigned extended attributes that identify the company the user belongs to. Use the `POST /V1/customers` call, which is included with {{site.data.var.ce}} and {{site.data.var.ee}}, to create the user. After the user is created, you can use the `PUT /V1/customers/:customer_id` call to set their company data with the `company_attributes` extended attributes. {:.bs-callout-info} -This topic discusses only the features of the `customerCustomerRepositoryV1` service that are specific to B2B. See [Create a customer]({{ page.baseurl }}/rest/tutorials/orders/order-create-customer.html) for an example of creating a standard customer. +This topic discusses only the features of the `customerCustomerRepositoryV1` service that are specific to B2B. See [Create a customer](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-customer.html) for an example of creating a standard customer. ## Manage company users diff --git a/src/guides/v2.3/b2b/credit-manage.md b/src/guides/v2.3/b2b/credit-manage.md index 8af2bbc11c2..28bd610477f 100644 --- a/src/guides/v2.3/b2b/credit-manage.md +++ b/src/guides/v2.3/b2b/credit-manage.md @@ -144,7 +144,7 @@ Not applicable The following call returns information for all companies whose credit balance is 0. -See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** @@ -326,7 +326,7 @@ This call updates the credit history to specify a purchase order number. The following call returns a list instances in which the credit limit was set to a value higher than $500. -See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/b2b/shared-cat-manage.md b/src/guides/v2.3/b2b/shared-cat-manage.md index 0c72f1a1011..0c4a2929b7b 100644 --- a/src/guides/v2.3/b2b/shared-cat-manage.md +++ b/src/guides/v2.3/b2b/shared-cat-manage.md @@ -137,7 +137,7 @@ Not applicable The following search returns all the custom shared catalogs (`type = 0`) in the system. -See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/b2b/shared-catalog.md b/src/guides/v2.3/b2b/shared-catalog.md index c18d542fa7a..3bec0d294f8 100644 --- a/src/guides/v2.3/b2b/shared-catalog.md +++ b/src/guides/v2.3/b2b/shared-catalog.md @@ -26,4 +26,4 @@ Custom shared catalogs can be assigned to companies only. They cannot be set for * [Manage shared catalogs]({{ page.baseurl }}/b2b/shared-cat-manage.html) * [Assign categories and products]({{ page.baseurl }}/b2b/shared-cat-product-assign.html) * [Assign companies]({{ page.baseurl }}/b2b/shared-cat-company.html) -* [Manage prices for multiple products]({{ page.baseurl }}/rest/modules/catalog-pricing.html) +* [Manage prices for multiple products](https://developer.adobe.com/commerce/webapi/rest/modules/catalog-pricing.html) diff --git a/src/guides/v2.3/graphql/tutorials/checkout/index.md b/src/guides/v2.3/graphql/tutorials/checkout/index.md index 8556e41646c..01c4ca7844f 100644 --- a/src/guides/v2.3/graphql/tutorials/checkout/index.md +++ b/src/guides/v2.3/graphql/tutorials/checkout/index.md @@ -40,6 +40,6 @@ Complete the following prerequisites: ### Other resources -- [Order processing tutorial]({{ page.baseurl }}/rest/tutorials/orders/order-intro.html) shows a system integrator how REST APIs are used in the lifecycle of an order, including configuring a store and creating a customer; creating quotes, orders, invoices, and shipments; preparing for checkout; and more order-related tasks. +- [Order processing tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-intro.html) shows a system integrator how REST APIs are used in the lifecycle of an order, including configuring a store and creating a customer; creating quotes, orders, invoices, and shipments; preparing for checkout; and more order-related tasks. -- [REST Tutorials]({{ page.baseurl }}/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. +- [REST Tutorials](https://developer.adobe.com/commerce/webapi/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. diff --git a/src/guides/v2.3/inventory/release-notes.md b/src/guides/v2.3/inventory/release-notes.md index e08a1437df9..c41fe6a51f7 100644 --- a/src/guides/v2.3/inventory/release-notes.md +++ b/src/guides/v2.3/inventory/release-notes.md @@ -186,7 +186,7 @@ New modules for Inventory Management 1.1.2 Beta include: 'Magento_InventoryExportStockApi' => 0, ``` -- {:.new} **Added a Bulk Partial Stock Transfer Endpoint** - Current bulk transfer endpoints move all assigned quantity from an origin to a destination source. The new `/rest/V1/inventory/bulk-partial-source-transfer` endpoint allows merchants to transfer partial stock from source-to-source as a bulk operation. Enter a request to the endpoint with the `sku`, `qty`, `origin_source_code`, and `destination_source_code` to transfer a specific amount of quantity. Transfers verify the source is assigned to the `sku`, enough quantity exists to transfer, etc. See [Inventory Bulk Actions]({{ page.baseurl }}/rest/modules/inventory/bulk-inventory.html). +- {:.new} **Added a Bulk Partial Stock Transfer Endpoint** - Current bulk transfer endpoints move all assigned quantity from an origin to a destination source. The new `/rest/V1/inventory/bulk-partial-source-transfer` endpoint allows merchants to transfer partial stock from source-to-source as a bulk operation. Enter a request to the endpoint with the `sku`, `qty`, `origin_source_code`, and `destination_source_code` to transfer a specific amount of quantity. Transfers verify the source is assigned to the `sku`, enough quantity exists to transfer, etc. See [Inventory Bulk Actions](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/bulk-inventory.html). - {:.new} **Added Reservation CLI** - New commands give you options to detect and resolve reservation inconsistencies. As orders submit and change status, {{site.data.var.im}} generates initial reservations and updates through compensation reservations. These commands return a list of detected inconsistencies by Order ID, SKU, and Stock ID and create reservations to resolve. See [Inventory CLI reference]({{ page.baseurl }}/inventory/inventory-cli-reference.html). diff --git a/src/guides/v2.3/rest/anonymous-api-security.md b/src/guides/v2.3/rest/anonymous-api-security.md index 8e4c2f2df2b..6453787c759 100644 --- a/src/guides/v2.3/rest/anonymous-api-security.md +++ b/src/guides/v2.3/rest/anonymous-api-security.md @@ -1,6 +1,7 @@ --- group: rest-api title: Restricting access to anonymous web APIs +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/anonymous-api-security/ --- Magento 2 allows some web APIs to be accessed by unauthenticated (anonymous) users. Many of these APIs allow a customer to have a robust shopping experience on the [website](https://glossary.magento.com/website) without having to log in. diff --git a/src/guides/v2.3/rest/asynchronous-web-endpoints.md b/src/guides/v2.3/rest/asynchronous-web-endpoints.md index bff4533f8fe..3606bf1a631 100644 --- a/src/guides/v2.3/rest/asynchronous-web-endpoints.md +++ b/src/guides/v2.3/rest/asynchronous-web-endpoints.md @@ -1,6 +1,7 @@ --- group: rest-api title: Asynchronous web endpoints +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/asynchronous-web-endpoints/ contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ functional_areas: @@ -31,7 +32,7 @@ PUT /async/V1/products/:sku {{site.data.var.ce}} and {{site.data.var.ee}} installations support asynchronous web endpoints. -The [REST API documentation]({{page.baseurl}}/rest/bk-rest.html) provides a list of all current synchronous Magento API routes. +The [REST API documentation](https://developer.adobe.com/commerce/webapi/rest/bk-rest.html) provides a list of all current synchronous Magento API routes. The response of an asynchronous request contains the following fields: @@ -64,7 +65,7 @@ PUT /rest//async/V1/products/24-MB01 ## Response -Magento generates a `bulk_uuid` for each asynchronous request. Use the `bulk_uuid` to determine the [operation status]({{ page.baseurl }}/rest/operation-status-endpoints.html) of your request. +Magento generates a `bulk_uuid` for each asynchronous request. Use the `bulk_uuid` to determine the [operation status](https://developer.adobe.com/commerce/webapi/rest/operation-status-endpoints.html) of your request. ```json { diff --git a/src/guides/v2.3/rest/bulk-endpoints.md b/src/guides/v2.3/rest/bulk-endpoints.md index bc0194ca324..2130b887430 100644 --- a/src/guides/v2.3/rest/bulk-endpoints.md +++ b/src/guides/v2.3/rest/bulk-endpoints.md @@ -1,6 +1,7 @@ --- group: rest-api title: Bulk endpoints +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/bulk-endpoints/ contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ functional_areas: diff --git a/src/guides/v2.3/rest/modules/catalog-pricing.md b/src/guides/v2.3/rest/modules/catalog-pricing.md index f1e125f69b1..8550a39d779 100644 --- a/src/guides/v2.3/rest/modules/catalog-pricing.md +++ b/src/guides/v2.3/rest/modules/catalog-pricing.md @@ -1,6 +1,7 @@ --- group: rest-api title: Manage prices for multiple products +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/catalog-pricing/ functional_areas: - Integration --- diff --git a/src/guides/v2.3/rest/modules/catalog.md b/src/guides/v2.3/rest/modules/catalog.md index da62103b7c5..de3721410ce 100644 --- a/src/guides/v2.3/rest/modules/catalog.md +++ b/src/guides/v2.3/rest/modules/catalog.md @@ -1,6 +1,7 @@ --- group: rest-api title: Catalog module +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/catalog/ functional_areas: - Integration - Catalog diff --git a/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md b/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md index e5ca4b58c0d..c0bca8582f6 100644 --- a/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md +++ b/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md @@ -1,6 +1,7 @@ --- group: rest-api title: Inventory mass actions +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/bulk-inventory/ --- Magento provides several endpoints that allow Multi Source merchants to make quick updates across multiple products. This is helpful for transferring inventory between sources and removing a source without editing each product individually. @@ -111,7 +112,7 @@ An empty array Use the `POST /V1/inventory/bulk-product-source-assign` endpoint to add one or more sources to your products. This endpoint helps when creating and assigning custom sources to your default or custom stocks and preparing new locations and inventory. -After adding new custom sources, you can add inventory quantities per product or for multiple products using the `POST V1/inventory/source-items` endpoint. [Assign products to a source]({{ page.baseurl }}/rest/modules/inventory/manage-source-items.html#assign) describes this endpoint. +After adding new custom sources, you can add inventory quantities per product or for multiple products using the `POST V1/inventory/source-items` endpoint. [Assign products to a source](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-source-items.html#assign) describes this endpoint. The sources are added to the products with an inventory quantity of 0. You can add inventory amounts as available per source. diff --git a/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md b/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md index 136040f8fab..105b2d5e569 100644 --- a/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md +++ b/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md @@ -1,6 +1,7 @@ --- group: rest-api title: Link and unlink stocks and sources +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/link-stocks-sources/ --- @@ -97,7 +98,7 @@ Magento returns empty array. The following call returns the link information for `stock_id = 4`. -See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** @@ -146,7 +147,7 @@ None ## Get sources assigned to a stock -The `GET /V1/inventory/get-sources-assigned-to-stock-ordered-by-priority/:stock_id` endpoint returns details about each source that is assigned to the specified stock. [Manage sources]({{ page.baseurl }}/rest/modules/inventory/manage-sources.html) provides definitions for each attribute returned. +The `GET /V1/inventory/get-sources-assigned-to-stock-ordered-by-priority/:stock_id` endpoint returns details about each source that is assigned to the specified stock. [Manage sources](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-sources.html) provides definitions for each attribute returned. **Sample Usage:** diff --git a/src/guides/v2.3/rest/modules/inventory/manage-low-quantity.md b/src/guides/v2.3/rest/modules/inventory/manage-low-quantity.md index a6f8b4d56b2..57ac314bd82 100644 --- a/src/guides/v2.3/rest/modules/inventory/manage-low-quantity.md +++ b/src/guides/v2.3/rest/modules/inventory/manage-low-quantity.md @@ -1,6 +1,7 @@ --- group: rest-api title: Manage low-quantity notifications +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/manage-low-quantity/ --- Low stock notification alert the merchant that the salable quantity of a stock has reached a critical threshold. The Admin allows the merchant to configure low-quantity notifications from several locations: diff --git a/src/guides/v2.3/rest/modules/inventory/manage-source-selection.md b/src/guides/v2.3/rest/modules/inventory/manage-source-selection.md index 69932af7f02..37979f5117f 100644 --- a/src/guides/v2.3/rest/modules/inventory/manage-source-selection.md +++ b/src/guides/v2.3/rest/modules/inventory/manage-source-selection.md @@ -1,6 +1,7 @@ --- group: rest-api title: Manage source selection algorithms +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/manage-source-selection/ --- Inventory Management uses the Source Selection Algorithm (SSA) to track the salable quantities of product inventory across all sources and make recommendations for partial and full shipments. diff --git a/src/guides/v2.3/rest/modules/inventory/manage-stocks.md b/src/guides/v2.3/rest/modules/inventory/manage-stocks.md index 64f659bae8e..c84a13a348e 100644 --- a/src/guides/v2.3/rest/modules/inventory/manage-stocks.md +++ b/src/guides/v2.3/rest/modules/inventory/manage-stocks.md @@ -1,6 +1,7 @@ --- group: rest-api title: Manage stocks +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/manage-stocks/ --- Stocks map your sources to sales channels, providing a direct link to salable quantities and inventories. @@ -149,7 +150,7 @@ Magento returns an empty array. The following call returns all stocks whose name contains the string `Stock`. -See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/rest/modules/sales/refunds.md b/src/guides/v2.3/rest/modules/sales/refunds.md index bc7cd67f522..f91167ffff4 100644 --- a/src/guides/v2.3/rest/modules/sales/refunds.md +++ b/src/guides/v2.3/rest/modules/sales/refunds.md @@ -1,6 +1,7 @@ --- group: rest-api title: Refunds +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/refunds/ functional_areas: - Integration - Catalog diff --git a/src/guides/v2.3/rest/notes.md b/src/guides/v2.3/rest/notes.md index c324e11d9f3..7cbdece72b5 100644 --- a/src/guides/v2.3/rest/notes.md +++ b/src/guides/v2.3/rest/notes.md @@ -1,6 +1,7 @@ --- group: rest-api title: REST usage notes +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/notes/ functional_areas: - Integration --- @@ -160,4 +161,4 @@ The following sample code creates a bundle product. The `price_type` attribute c {:.ref-header} Related topics -[Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) +[Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) diff --git a/src/guides/v2.3/rest/operation-status-endpoints.md b/src/guides/v2.3/rest/operation-status-endpoints.md index b9f7a54de90..78ea103fec6 100644 --- a/src/guides/v2.3/rest/operation-status-endpoints.md +++ b/src/guides/v2.3/rest/operation-status-endpoints.md @@ -1,13 +1,14 @@ --- group: rest-api title: Bulk operation status endpoints +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/operation-status-endpoints/ contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com/ functional_areas: - Integration --- -Magento generates a `bulk_uuid` each time it executes an [asynchronous API request]({{ page.baseurl }}/rest/asynchronous-web-endpoints.html). You can track the status of an asynchronous operation with the following endpoints: +Magento generates a `bulk_uuid` each time it executes an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html). You can track the status of an asynchronous operation with the following endpoints: * `GET /V1/bulk/:bulkUuid/status` * `GET /V1/bulk/:bulkUuid/operation-status/:status` @@ -25,7 +26,7 @@ Field name | Data type | Description `result_message` | String | Describes the result of the operation. If successful, the value contains the string `Service execution success` as well as the method that executed the operation. `error_code` | Integer | If applicable, an error code associated with the operation. `user_type` | Integer | Type of user who made this request. Possible values are:
    \* `1` = Integration
    \* `2` = Administrator
    \* `3` = Customer
    \* `4` = Guest User -`bulk_id` | String | UUID generated by an [asynchronous API request]({{ page.baseurl }}/rest/asynchronous-web-endpoints.html) or [Bulk API request]({{ page.baseurl }}/rest/bulk-endpoints.html). +`bulk_id` | String | UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html). `description` | String | Contains the message queue topic. `start_time` | String | The time that a bulk or asynchronous operation started. `user_id` | Integer | The user ID that executed the request. @@ -82,7 +83,7 @@ Field name | Data type | Description --- | --- | --- `operations_list` | Object | An array containing information about each operation in a bulk or asynchronous request. `id` | Integer | Identifies the bulk or asynchronous request. -`bulk_uuid` | String | UUID generated by an [asynchronous API request]({{ page.baseurl }}/rest/asynchronous-web-endpoints.html) or [Bulk API request]({{ page.baseurl }}/rest/bulk-endpoints.html). +`bulk_uuid` | String | UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html). `topic_name` | String | The name of the message queue topic, in the format `async..`. The service contract path is lowercase, and the method is either `post`, `put`, or `delete`. `serialized_data` | String | An array of serialized input data. It contains serialized JSON with the following keys: `entity_id` - `null`, `entity_link` - an empty string, `meta_info` - the body of the API request that was executed. `result_serialized_data` | String | Contains serialized output of the corresponding synchronous API call. For example, if you call `POST /async/V1/products`, this field contains serialized response from `POST /V1/products`. @@ -90,7 +91,7 @@ Field name | Data type | Description `result_message` | String | Describes the result of the operation. If successful, the value contains the string `Service execution success` as well as the method that executed the operation. `error_code` | Integer | If applicable, an error code associated with the operation. `user_type` | Integer | Type of user who made this request. Possible values are:
    \* `1` = Integration
    \* `2` = Administrator
    \* `3` = Customer
    \* `4` = Guest User -`bulk_id` | String | UUID generated by an [asynchronous API request]({{ page.baseurl }}/rest/asynchronous-web-endpoints.html) or [Bulk API request]({{ page.baseurl }}/rest/bulk-endpoints.html). +`bulk_id` | String | UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html). `description` | String | Contains the message queue topic name. `start_time` | String | The time that a bulk or asynchronous operation started. `user_id` | Integer | The user ID that executed the request. diff --git a/src/guides/v2.3/rest/operation-status-search.md b/src/guides/v2.3/rest/operation-status-search.md index 63241cbcb47..b45ad971dc3 100644 --- a/src/guides/v2.3/rest/operation-status-search.md +++ b/src/guides/v2.3/rest/operation-status-search.md @@ -1,6 +1,7 @@ --- group: rest-api title: Search for the status of a bulk operation +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/operation-status-search/ contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com functional_areas: @@ -18,7 +19,7 @@ You can specify any of the following fields to filter on operation statuses: * `3` = The operation failed. You must change something to retry it. * `4` = Open * `5` = Rejected -* `bulk_uuid` - UUID generated by an [asynchronous API request]({{ page.baseurl }}/rest/asynchronous-web-endpoints.html) or [Bulk API request]({{ page.baseurl }}/rest/bulk-endpoints.html). +* `bulk_uuid` - UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html). * `topic_name` - Queue topic name **Sample usage:** @@ -32,7 +33,7 @@ searchCriteria[filter_groups][0][filters][0][value]=3& searchCriteria[filter_groups][0][filters][0][condition_type]=eq ``` -See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for more information about the syntax of search requests. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for more information about the syntax of search requests. **Response:** diff --git a/src/guides/v2.3/rest/performing-searches.md b/src/guides/v2.3/rest/performing-searches.md index edc38fdc694..8f3868f1149 100644 --- a/src/guides/v2.3/rest/performing-searches.md +++ b/src/guides/v2.3/rest/performing-searches.md @@ -1,6 +1,7 @@ --- group: rest-api title: Search using REST endpoints +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/performing-searches/ --- POST, PUT, and DELETE requests to the REST Web [API](https://glossary.magento.com/api) require the service method parameters to be in the body of the request. For example, to create a Customer, you would specify a JSON array (or [XML](https://glossary.magento.com/xml) structure) in the body of the message. diff --git a/src/guides/v2.3/rest/retrieve-filtered-responses.md b/src/guides/v2.3/rest/retrieve-filtered-responses.md index 87325dfbd4b..64b81341609 100644 --- a/src/guides/v2.3/rest/retrieve-filtered-responses.md +++ b/src/guides/v2.3/rest/retrieve-filtered-responses.md @@ -1,6 +1,7 @@ --- group: rest-api title: Retrieve filtered responses for REST endpoints +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/retrieve-filtered-responses/ --- Some REST calls return dozens or even hundreds of parameters, and parsing through all this data can be unwieldy. In addition, mobile app developers might find the bandwidth needed to process a request to be excessive. To resolve these problems, Magento provides a query parameter-based syntax for REST requests that return partial responses. @@ -140,7 +141,7 @@ The following POST operation and payload creates a [catalog](https://glossary.ma ## Using with searchCriteria -The [`searchCriteria` query parameter]({{ page.baseurl }}/rest/performing-searches.html) allows you to search across multiple objects in a collection. You can use the `fields` query parameter in conjunction with `searchCriteria` to limit the output. The question mark (?) that precedes `fields` in all the other examples in this document is replaced with an ampersand (&). +The [`searchCriteria` query parameter](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) allows you to search across multiple objects in a collection. You can use the `fields` query parameter in conjunction with `searchCriteria` to limit the output. The question mark (?) that precedes `fields` in all the other examples in this document is replaced with an ampersand (&). The following query returns only the `sku` and `name` parameters for product items whose `category_gear` attribute includes the value `86`. @@ -191,4 +192,4 @@ The following query returns only the `sku` and `name` parameters for product ite {:.ref-header} Related topics -* [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) +* [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) diff --git a/src/guides/v2.3/rest/search-endpoint.md b/src/guides/v2.3/rest/search-endpoint.md index a478d79ce4c..451151df2de 100644 --- a/src/guides/v2.3/rest/search-endpoint.md +++ b/src/guides/v2.3/rest/search-endpoint.md @@ -1,6 +1,7 @@ --- group: rest-api title: Search for products with the /search endpoint +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/search-endpoint/ contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com/ --- @@ -90,7 +91,7 @@ The default filters for advanced searches can use the following [field] value: The filter can also be any searchable attribute. To make an attribute searchable, set **Stores** > Attributes > **Product** > > **Storefront Properties** > **Use in Search** to **Yes**. The search query can include attributes such as the product name, SKU, or any other custom attribute. -Advanced searches can use any condition type to make comparisions, such as `like`, `eq`, or `finset`. See [Search using REST]({{page.baseurl}}/rest/performing-searches.html) describes condition types. +Advanced searches can use any condition type to make comparisions, such as `like`, `eq`, or `finset`. See [Search using REST](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) describes condition types. Advanced searches do not return aggregation data. @@ -139,4 +140,4 @@ searchCriteria[filter_groups][0][filters][0][condition_type]=eq ## Build queries for V1/products -[Search using REST]({{page.baseurl}}/rest/performing-searches.html) provides examples that can be used to search for products. +[Search using REST](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) provides examples that can be used to search for products. diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md index 0895efec3ae..df0722956e3 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Create a configurable product using bulk APIs +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/config-product-intro/ menu_title: Initial tasks menu_order: 0 level3_subgroup: bulk-configurable-product-tutorial @@ -26,11 +27,11 @@ A system integrator can use Magento REST bulk APIs to perform actions on a large * Install a Magento 2.3 (or later) instance with sample data. The sample data defines a functional store, called Luma, that sells fitness clothing and accessories. * Install a REST client. You can use any REST client to send calls to Magento. [Postman](https://www.getpostman.com/) is recommended. -* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token]({{ page.baseurl }}/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. * Use the `bin/magento queue:consumers:start async.operations.all` command to enable bulk endpoint processing. ### Other resources -* [REST Tutorials]({{ page.baseurl }}/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. -* [Asynchronous web endpoints]({{ page.baseurl }}/rest/asynchronous-web-endpoints.html) provides information about how to use Magento Asynchronous API -* [Bulk endpoints]({{ page.baseurl }}/rest/bulk-endpoints.html) provides information about how to use Magento Bulk API \ No newline at end of file +* [REST Tutorials](https://developer.adobe.com/commerce/webapi/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. +* [Asynchronous web endpoints](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) provides information about how to use Magento Asynchronous API +* [Bulk endpoints](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html) provides information about how to use Magento Bulk API \ No newline at end of file diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md index 5c8e627d5e7..43a2968c6cd 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 2. Create the configurable and simple products +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-configurable-simple-products/ subtitle: Create a configurable product using bulk APIs menu_title: Step 2. Create the configurable and simple products menu_order: 20 @@ -38,7 +39,7 @@ Some notes about the configurable product payload example: Although it's not required, the simple product payload also includes `stock_item` information. By default, the Luma store hides out-of-stock items, so adding stock will make the Champ Tee visible on the website. {:.bs-callout-info} -Before you use this code sample, verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute searchCriteria]({{ page.baseurl }}/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. +Before you use this code sample, verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute searchCriteria](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. {:.bs-callout-info} The payload contains both the configurable product and the simple products. @@ -307,12 +308,12 @@ The payload contains both the configurable product and the simple products. ``` {:.bs-callout-info} -For information about response fields, see the [Bulk API]({{ page.baseurl }}/rest/bulk-endpoints.html) section. To check the status of operations, see the API for [Bulk operation status endpoints]({{ page.baseurl }}/rest/operation-status-endpoints.html). +For information about response fields, see the [Bulk API](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html) section. To check the status of operations, see the API for [Bulk operation status endpoints](https://developer.adobe.com/commerce/webapi/rest/operation-status-endpoints.html). ## Verify this step * Log in to the Luma website and select **Catalog > Products**. The product appears in the grid. - ![Product page with configurable product]({{ page.baseurl }}/rest/images/products-page.png) + ![Product page with configurable product](https://developer.adobe.com/commerce/webapi/rest/images/products-page.png) * On the Luma storefront page, search for `Champ`. No results are returned. diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md index 5f0d4e6cae2..15721c6d0fe 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 4. Create the personalization option +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-personalization-option/ subtitle: Create a configurable product using bulk APIs menu_title: Step 4. Create the personalization option menu_order: 40 @@ -61,11 +62,11 @@ The `product_sku` is the `sku` of the configurable product. The `sku` specified * Log in to the Luma website and select **Catalog > Products**. Click on the **Champ Tee** configurable product and expand the **Customizable Options** section. - ![Product page with configurable and simple products]({{ page.baseurl }}/rest/images/options-section.png) + ![Product page with configurable and simple products](https://developer.adobe.com/commerce/webapi/rest/images/options-section.png) * On the Luma storefront page, search for `Champ`. Then click on the Champ Tee product. - ![Search results]({{ page.baseurl }}/rest/images/add-your-name.png) + ![Search results](https://developer.adobe.com/commerce/webapi/rest/images/add-your-name.png) {:.bs-callout-info} If the personalization option is not displayed, go to the **Champ Tee** configuration product page in Admin and set **Stock Status** to **In Stock**. @@ -76,4 +77,4 @@ The `product_sku` is the `sku` of the configurable product. The `sku` specified {:.ref-header} Related topic -[Order Processing with REST APIs Tutorial]({{ page.baseurl }}/rest/tutorials/orders/order-intro.html) +[Order Processing with REST APIs Tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-intro.html) diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md index b0a16c57244..30f1873d3fb 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 3. Define configurable product options +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/define-config-product-options/ subtitle: Create a configurable product using bulk APIs menu_title: Step 3. Define configurable product options menu_order: 30 @@ -22,7 +23,7 @@ contributor_link: http://comwrap.com/ The `POST async/bulk/V1/configurable-products/bySku/options` call assigns the specified `attribute_id` to be the configurable attribute. {:.bs-callout-warning} - The `attribute_id` and its value may be different on your installation. Check the values carefully before using them in your calls. To get the correct `attribute_id`, see [Get the list of attributes defined in an attribute searchCriteria]({{ page.baseurl }}/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. + The `attribute_id` and its value may be different on your installation. Check the values carefully before using them in your calls. To get the correct `attribute_id`, see [Get the list of attributes defined in an attribute searchCriteria](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. The value assigned to the `value_index` must be unique within the system. @@ -72,7 +73,7 @@ Now that you have set the configurable attribute to be `sku`, you can link all s **Endpoint:** {:.bs-callout-info} -Bulk endpoint routes cannot contain input parameters, such as a `sku` value. You must replace input parameters with a string that begins with `by` and ends with the input parameter name, such as `bySku`. See [`bulk endpoints`]({{ page.baseurl }}/rest/bulk-endpoints.html) for more information. +Bulk endpoint routes cannot contain input parameters, such as a `sku` value. You must replace input parameters with a string that begins with `by` and ends with the input parameter name, such as `bySku`. See [`bulk endpoints`](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html) for more information. `POST /rest/default/async/bulk/V1/configurable-products/bySku/child` @@ -126,11 +127,11 @@ Bulk endpoint routes cannot contain input parameters, such as a `sku` value. Yo * Log in to the Luma website and select **Catalog > Products**. Click on the **Champ Tee** configurable product and expand the **Configurations** section. - ![Product page with configurable and simple products]({{ page.baseurl }}/rest/images/configurations-section.png) + ![Product page with configurable and simple products](https://developer.adobe.com/commerce/webapi/rest/images/configurations-section.png) * On the Luma storefront page, search for `Champ`. - ![Search results]({{ page.baseurl }}/rest/images/search-results.png) + ![Search results](https://developer.adobe.com/commerce/webapi/rest/images/search-results.png) * Call `GET /rest/default/V1/products/MS-Champ`. The response includes the `configurable_product_options` and `configurable_product_links` arrays. diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/plan-product.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/plan-product.md index 5eef0a030fc..0c4359ff208 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/plan-product.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/plan-product.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 1. Plan the product +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/plan-product/ subtitle: Create a configurable product using bulk APIs menu_title: Step 1. Plan the product menu_order: 10 diff --git a/src/guides/v2.3/rest/tutorials/bundle-product/bundle-product-intro.md b/src/guides/v2.3/rest/tutorials/bundle-product/bundle-product-intro.md index 49f48c491b1..8fe307d7ac8 100644 --- a/src/guides/v2.3/rest/tutorials/bundle-product/bundle-product-intro.md +++ b/src/guides/v2.3/rest/tutorials/bundle-product/bundle-product-intro.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Create a bundle product tutorial +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product-intro/ contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.3/rest/tutorials/bundle-product/create-bundle-product.md b/src/guides/v2.3/rest/tutorials/bundle-product/create-bundle-product.md index 60508e3cc9f..7acdd741438 100644 --- a/src/guides/v2.3/rest/tutorials/bundle-product/create-bundle-product.md +++ b/src/guides/v2.3/rest/tutorials/bundle-product/create-bundle-product.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 3. Create the bundle product +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-bundle-product/ contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- @@ -296,15 +297,15 @@ POST http://domain.com/rest/default/V1/products 1. On the Luma storefront page, search for `Desktop Computer`. There should be one result. - ![Search]({{ page.baseurl }}/rest/tutorials/bundle-product/images/search-desktop-computer.png) + ![Search](https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/images/search-desktop-computer.png) 1. Click on the Desktop Computer product. - ![Product]({{ page.baseurl }}/rest/tutorials/bundle-product/images/site-desktop-computer.png) + ![Product](https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/images/site-desktop-computer.png) 1. Customize Desktop Computer and add it to the shopping cart. - ![Shopping Cart]({{ page.baseurl }}/rest/tutorials/bundle-product/images/shopping-cart-desktop-computer.png) + ![Shopping Cart](https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/images/shopping-cart-desktop-computer.png) {:.bs-callout-info} If you do not see the bundle product on the frontend, you can try reindexing and clearing the cache. diff --git a/src/guides/v2.3/rest/tutorials/bundle-product/create-simple-products.md b/src/guides/v2.3/rest/tutorials/bundle-product/create-simple-products.md index 1a7b9f570ed..3e8a014c941 100644 --- a/src/guides/v2.3/rest/tutorials/bundle-product/create-simple-products.md +++ b/src/guides/v2.3/rest/tutorials/bundle-product/create-simple-products.md @@ -2,12 +2,13 @@ layout: tutorial group: rest-api title: Step 2. Create the simple products +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-simple-products/ contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- {:.bs-callout-info} -Before you run the code, please verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute set]({{ page.baseurl }}/rest/tutorials/bundle-product/plan-product.html#get-attributes) for more information. +Before you run the code, please verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute set](https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/plan-product.html#get-attributes) for more information. We will create four simple products: `RAM 12GB`, `RAM 24GB`, `Monitor 15"` and `Monitor 17"`. @@ -569,7 +570,7 @@ POST http://domain.com/rest/default/V1/products * Log in to the Adobe Commerce Admin Panel and select Catalog > Products and confirm that your products appear in the grid. - ![Simple products]({{ page.baseurl }}/rest/tutorials/bundle-product/images/simple-products-admin-grid.png) + ![Simple products](https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/images/simple-products-admin-grid.png) {:.bs-callout-info} If you do not see your products in the catalog, you can try reindexing and clearing the cache. diff --git a/src/guides/v2.3/rest/tutorials/bundle-product/plan-product.md b/src/guides/v2.3/rest/tutorials/bundle-product/plan-product.md index 140f21cc671..570f4ebe953 100644 --- a/src/guides/v2.3/rest/tutorials/bundle-product/plan-product.md +++ b/src/guides/v2.3/rest/tutorials/bundle-product/plan-product.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 1. Plan the product +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/plan-product/ contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md b/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md index 0a357acf0cb..7e4dbc2f9b4 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Create a configurable product tutorial +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/config-product-intro/ menu_title: Initial tasks menu_order: 0 level3_subgroup: configurable-product-tutorial @@ -26,8 +27,8 @@ This **5-step tutorial** generally takes **45 minutes**. * [Install and configure RabbitMQ]({{ page.baseurl }}/install-gde/prereq/install-rabbitmq.html), which is the default message broker for bulk API endpoints. -* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token]({{ page.baseurl }}/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. ### Other resources -* [REST Tutorials]({{ page.baseurl }}/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. +* [REST Tutorials](https://developer.adobe.com/commerce/webapi/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/create-configurable-product.md b/src/guides/v2.3/rest/tutorials/configurable-product/create-configurable-product.md index c4de68d6be5..9a6eead6df3 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/create-configurable-product.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/create-configurable-product.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 2. Create the configurable product +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-configurable-product/ subtitle: Create a configurable product tutorial menu_title: Step 2. Create the configurable product menu_order: 20 @@ -29,7 +30,7 @@ Visibility | Code `Catalog, Search` | 4 {:.bs-callout-info} -Before you using this code sample, verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute searchCriteria]({{ page.baseurl }}/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. +Before you using this code sample, verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute searchCriteria](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. **Endpoint:** @@ -216,6 +217,6 @@ Before you using this code sample, verify that the attribute values are the same * Log in to the Luma website and select **Catalog > Products**. The product appears in the grid. - ![Product page with configurable product]({{ page.baseurl }}/rest/images/products-page.png) + ![Product page with configurable product](https://developer.adobe.com/commerce/webapi/rest/images/products-page.png) * On the Luma storefront page, search for `Champ`. No results are returned. diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md b/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md index 512c6ec6a5c..12975629f2e 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 5. Create the personalization option +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-personalization-option/ subtitle: Create a configurable product tutorial menu_title: Step 5. Create the personalization option menu_order: 50 @@ -60,11 +61,11 @@ The `product_sku` is the `sku` of the configurable product. The `sku` specified * Log in to the Luma website and select **Catalog > Products**. Click on the **Champ Tee** configurable product and expand the **Customizable Options** section. - ![Product page with configurable and simple products]({{ page.baseurl }}/rest/images/options-section.png) + ![Product page with configurable and simple products](https://developer.adobe.com/commerce/webapi/rest/images/options-section.png) * On the Luma storefront page, search for `Champ`. Then click on the Champ Tee product. - ![Search results]({{ page.baseurl }}/rest/images/add-your-name.png) + ![Search results](https://developer.adobe.com/commerce/webapi/rest/images/add-your-name.png) {:.bs-callout-info} If the personalization option is not displayed, go to the **Champ Tee** configuration product page in Admin and set **Stock Status** to **In Stock**. @@ -75,4 +76,4 @@ The `product_sku` is the `sku` of the configurable product. The `sku` specified {:.ref-header} Related topic -[Order Processing with REST APIs Tutorial]({{ page.baseurl }}/rest/tutorials/orders/order-intro.html) +[Order Processing with REST APIs Tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-intro.html) diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/create-simple-products.md b/src/guides/v2.3/rest/tutorials/configurable-product/create-simple-products.md index 7438ac46489..a4623dfc79e 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/create-simple-products.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/create-simple-products.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 3. Create the simple products +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-simple-products/ subtitle: Create a configurable product tutorial menu_title: Step 3. Create the simple products menu_order: 30 @@ -26,7 +27,7 @@ Although it's not required, the simple product payload also includes `stock_item ## Create the first simple product {:.bs-callout-info} -Before you using this code sample, verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute searchCriteria]({{ page.baseurl }}/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. +Before you using this code sample, verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute searchCriteria](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. **Endpoint:** @@ -232,6 +233,6 @@ Attribute | Medium Value | Large Value * Log in to the Luma website and select Catalog > Products. The product appears in the grid. - ![Product page with configurable and simple products]({{ page.baseurl }}/rest/images/products-page-all.png) + ![Product page with configurable and simple products](https://developer.adobe.com/commerce/webapi/rest/images/products-page-all.png) * On the Luma storefront page, search for `Champ`. No results are returned. diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/define-config-product-options.md b/src/guides/v2.3/rest/tutorials/configurable-product/define-config-product-options.md index 94eb8d22324..ce853abfa70 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/define-config-product-options.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/define-config-product-options.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 4. Define configurable product options +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/define-config-product-options/ subtitle: Create a configurable product tutorial menu_title: Step 4. Define configurable product options menu_order: 40 @@ -71,11 +72,11 @@ The call to link a simple (child) product to the configurable product accepts on * Log in to the Luma website and select **Catalog > Products**. Click on the **Champ Tee** configurable product and expand the **Configurations** section. -![Product page with configurable and simple products]({{ page.baseurl }}/rest/images/configurations-section.png) +![Product page with configurable and simple products](https://developer.adobe.com/commerce/webapi/rest/images/configurations-section.png) * On the Luma storefront page, search for `Champ`. -![Search results]({{ page.baseurl }}/rest/images/search-results.png) +![Search results](https://developer.adobe.com/commerce/webapi/rest/images/search-results.png) * Call `GET /V1/products/MS-Champ`. The response includes the `configurable_product_options` and `configurable_product_links` arrays. diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/plan-product.md b/src/guides/v2.3/rest/tutorials/configurable-product/plan-product.md index d6cd8912193..d2a77741f11 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/plan-product.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/plan-product.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 1. Plan the product +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/plan-product/ subtitle: Create a configurable product tutorial menu_title: Step 1. Plan the product menu_order: 10 diff --git a/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md b/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md index 6ae331597db..cad411a2b72 100644 --- a/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md +++ b/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md @@ -1,6 +1,7 @@ --- group: rest-api title: Create and manage grouped products tutorial +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-and-manage-grouped-products/ functional_areas: - Integration --- @@ -15,11 +16,11 @@ This tutorial describes how you can use the Magento REST API to create and manag * Install a REST client. You can use any REST client to send calls to Magento. [Postman](https://www.getpostman.com/) is recommended. -* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token]({{ page.baseurl }}/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. ### Other resources -* [REST Tutorials]({{ page.baseurl }}/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. +* [REST Tutorials](https://developer.adobe.com/commerce/webapi/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. ## 1. Create an empty grouped product @@ -210,13 +211,13 @@ You also can use the `DELETE` endpoint to delete a simple product from the group 1. Select **Catalog > Products**. 1. Click on the **New Grouped Product** grouped product and expand the **Grouped Products** section. - ![New grouped product]({{ page.baseurl }}/rest/images/new-grouped-product.png) + ![New grouped product](https://developer.adobe.com/commerce/webapi/rest/images/new-grouped-product.png) ## Add a grouped product to a cart Customers can now add this grouped products to their carts, as shown below. -Refer to the [Order processing tutorial]({{ page.baseurl }}/rest/tutorials/orders/order-intro.html) for more information about how to add items to a cart with REST. +Refer to the [Order processing tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-intro.html) for more information about how to add items to a cart with REST. ### Endpoint diff --git a/src/guides/v2.3/rest/tutorials/orders/order-add-items.md b/src/guides/v2.3/rest/tutorials/orders/order-add-items.md index d83e091c944..10268d78ec6 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-add-items.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-add-items.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 5. Add items to the cart +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-add-items/ subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-create-customer.md b/src/guides/v2.3/rest/tutorials/orders/order-create-customer.md index faa64e1c0af..19d8dfd3467 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-create-customer.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-create-customer.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 3. Create a customer +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-create-customer/ subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-create-invoice.md b/src/guides/v2.3/rest/tutorials/orders/order-create-invoice.md index 1e3f480a65d..5251618d133 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-create-invoice.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-create-invoice.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 8. Create an invoice +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-create-invoice/ subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-create-order.md b/src/guides/v2.3/rest/tutorials/orders/order-create-order.md index 8e647b2f576..b63f57675fe 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-create-order.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-create-order.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 7. Create an order +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-create-order/ subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-create-quote.md b/src/guides/v2.3/rest/tutorials/orders/order-create-quote.md index e74079e53b4..05b7cbe3b8a 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-create-quote.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-create-quote.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 4. Create a quote +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-create-quote/ subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-create-shipment.md b/src/guides/v2.3/rest/tutorials/orders/order-create-shipment.md index babdcc78778..89d89a04c5b 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-create-shipment.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-create-shipment.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 9. Create a shipment +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-create-shipment/ subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-prepare-checkout.md b/src/guides/v2.3/rest/tutorials/orders/order-prepare-checkout.md index 74a9580d712..bee30db3984 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-prepare-checkout.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-prepare-checkout.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api subgroup: title: Step 6. Prepare for checkout +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-prepare-checkout/ subtitle: Order Processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/b2b/negotiable-order-workflow.md b/src/guides/v2.4/b2b/negotiable-order-workflow.md index 8f0e490b93c..b53dc2e6787 100644 --- a/src/guides/v2.4/b2b/negotiable-order-workflow.md +++ b/src/guides/v2.4/b2b/negotiable-order-workflow.md @@ -10,11 +10,11 @@ This topic describes how REST calls can be used to place items in a shopping car * You have [installed and enabled]({{ site.baseurl }}/extensions/b2b/) {{site.data.var.b2b}}. * You have [created a company]({{ page.baseurl }}/b2b/company-object.html) and a [company user]({{ page.baseurl }}/b2b/company-object.html). -* You have an integration or [admin authorization token]({{ page.baseurl }}/rest/tutorials/orders/order-admin-token.html) to make calls on behalf of seller, and a [customer token]({{ page.baseurl }}/rest/tutorials/orders/order-create-customer.html#get-token) to make calls on behalf of the company user. +* You have an integration or [admin authorization token](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-admin-token.html) to make calls on behalf of seller, and a [customer token](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-customer.html#get-token) to make calls on behalf of the company user. ## Prepare the order -The steps in this section are similar to those in the [Order processing tutorial]({{ page.baseurl }}/rest/tutorials/orders/order-intro.html), except that different products are added to the cart. +The steps in this section are similar to those in the [Order processing tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-intro.html), except that different products are added to the cart. ### Create a shopping cart @@ -1000,7 +1000,7 @@ Authorization Bearer ## Related information -* [Order processing tutorial]({{ page.baseurl }}/rest/tutorials/orders/order-intro.html) +* [Order processing tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-intro.html) * [Integrate with the NegotiableQuote module]({{ page.baseurl }}/b2b/negotiable-quote.html) * [Manage negotiable quotes]({{ page.baseurl }}/b2b/negotiable-manage.html) * [Update a negotiable quote]({{ page.baseurl }}/b2b/negotiable-update.html) diff --git a/src/guides/v2.4/b2b/roles.md b/src/guides/v2.4/b2b/roles.md index 8fe5a1ae846..2c20d8b979f 100644 --- a/src/guides/v2.4/b2b/roles.md +++ b/src/guides/v2.4/b2b/roles.md @@ -650,7 +650,7 @@ None The following call returns all roles that have been created for a company (`company_id` = `2`). -See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.4/ext-best-practices/tutorials/create-custom-rest-api.md b/src/guides/v2.4/ext-best-practices/tutorials/create-custom-rest-api.md index ff2b91bc3e6..72b163dca78 100644 --- a/src/guides/v2.4/ext-best-practices/tutorials/create-custom-rest-api.md +++ b/src/guides/v2.4/ext-best-practices/tutorials/create-custom-rest-api.md @@ -513,7 +513,7 @@ class ProductRepository implements ProductRepositoryInterface ## Step 6. Test your custom endpoint * You can use any REST client to send calls. [Postman](https://www.getpostman.com/) is recommended. -* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token]({{ page.baseurl }}/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. ### Test the GET endpoint @@ -558,6 +558,6 @@ The example uses Magento sample data for `product_id: 1` and the endpoint ```htt ### Related Topic -* [REST Tutorials]({{ page.baseurl }}/rest/tutorials/index.html) +* [REST Tutorials](https://developer.adobe.com/commerce/webapi/rest/tutorials/index.html) * [Configure a web API]({{ page.baseurl }}/extension-dev-guide/service-contracts/service-to-web-service.html) * [Access Control List (ACL)]({{ page.baseurl }}/ext-best-practices/tutorials/create-access-control-list-rule.html) diff --git a/src/guides/v2.4/extension-dev-guide/searching-with-repositories.md b/src/guides/v2.4/extension-dev-guide/searching-with-repositories.md index 97683f2bc46..68642a37033 100644 --- a/src/guides/v2.4/extension-dev-guide/searching-with-repositories.md +++ b/src/guides/v2.4/extension-dev-guide/searching-with-repositories.md @@ -44,7 +44,7 @@ $filter This filter will find all urls with the suffix of "magento.com". {:.bs-callout-info} -A full list of condition types can be found in the [Rest API Reference]({{ page.baseurl }}/rest/performing-searches.html). +A full list of condition types can be found in the [Rest API Reference](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html). ### Filter Group diff --git a/src/guides/v2.4/extension-dev-guide/security/dos.md b/src/guides/v2.4/extension-dev-guide/security/dos.md index a9d4f51aed4..84f9b3a7ce7 100644 --- a/src/guides/v2.4/extension-dev-guide/security/dos.md +++ b/src/guides/v2.4/extension-dev-guide/security/dos.md @@ -57,7 +57,7 @@ shopping. [Google ReCaptcha]({{ site.user_guide_url }}/stores/security-google-recaptcha.html) is an example of a challenge provider. One of the biggest advantages of ReCaptcha is that it avoids actually presenting -a user with a challenge, unless it detects suspicious behavior. [Protected endpoints]({{page.baseurl}}/rest/protected-endpoints.html) +a user with a challenge, unless it detects suspicious behavior. [Protected endpoints](https://developer.adobe.com/commerce/webapi/rest/protected-endpoints.html) contains a list of forms/endpoints can be enabled for ReCaptcha out-of-the-box. You can extend the list by following the example on how to add coverage can be found in the [SecurityPackage](https://github.com/magento/security-package/tree/develop/ReCaptchaCustomer) repo. diff --git a/src/guides/v2.4/get-started/authentication/gs-authentication-token.md b/src/guides/v2.4/get-started/authentication/gs-authentication-token.md index 94ceff95c94..9a1cbb66948 100644 --- a/src/guides/v2.4/get-started/authentication/gs-authentication-token.md +++ b/src/guides/v2.4/get-started/authentication/gs-authentication-token.md @@ -159,7 +159,7 @@ echo send($request); Magento provides a separate token service for administrators and customers. When you request a token from one of these services, the service returns a unique access token in exchange for the username and password for a Magento account. -The Magento web API framework allows *guest users* to access resources that are configured with the permission level of anonymous. Guest users are users who the framework cannot authenticate through existing authentication mechanisms. As a guest user, you do not need to, but you can, specify a token in a web API call for a resource with anonymous permission. [Restricting access to anonymous web APIs]({{ page.baseurl }}/rest/anonymous-api-security.html) contains a list of APIs that do not require a token. +The Magento web API framework allows *guest users* to access resources that are configured with the permission level of anonymous. Guest users are users who the framework cannot authenticate through existing authentication mechanisms. As a guest user, you do not need to, but you can, specify a token in a web API call for a resource with anonymous permission. [Restricting access to anonymous web APIs](https://developer.adobe.com/commerce/webapi/rest/anonymous-api-security.html) contains a list of APIs that do not require a token. The following table lists endpoints and services that can be used to get an authentication token. Admin accounts must be authenticated with a [two factor authentication]({{page.baseurl}}/security/two-factor-authentication.html) provider. Some providers may require multiple calls. @@ -243,4 +243,4 @@ Related topics [Configure services as web APIs]({{ page.baseurl }}/extension-dev-guide/service-contracts/service-to-web-service.html) -[Restricting access to anonymous web APIs]({{ page.baseurl }}/rest/anonymous-api-security.html) +[Restricting access to anonymous web APIs](https://developer.adobe.com/commerce/webapi/rest/anonymous-api-security.html) diff --git a/src/guides/v2.4/get-started/bk-get-started-api.md b/src/guides/v2.4/get-started/bk-get-started-api.md index 0198aba818c..92a058700a5 100644 --- a/src/guides/v2.4/get-started/bk-get-started-api.md +++ b/src/guides/v2.4/get-started/bk-get-started-api.md @@ -16,7 +16,7 @@ layout: migrated The Magento web [API](https://glossary.magento.com/api) framework provides integrators and developers the means to use web services that communicate with the Magento system. Key features include: -* Support for [GraphQL]({{page.baseurl}}/graphql/index.html), [REST]({{ page.baseurl }}/rest/bk-rest.html) (Representational State Transfer) and [SOAP]({{ page.baseurl }}/soap/bk-soap.html) (Simple Object Access Protocol). In Magento 2, the [web API](https://glossary.magento.com/web-api) coverage is the same for both REST and SOAP. +* Support for [GraphQL]({{page.baseurl}}/graphql/index.html), [REST](https://developer.adobe.com/commerce/webapi/rest/bk-rest.html) (Representational State Transfer) and [SOAP]({{ page.baseurl }}/soap/bk-soap.html) (Simple Object Access Protocol). In Magento 2, the [web API](https://glossary.magento.com/web-api) coverage is the same for both REST and SOAP. * Three types of [authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication.html): * Third-party applications authenticate with [OAuth 1.0a]({{ page.baseurl }}/get-started/authentication/gs-authentication-oauth.html). diff --git a/src/guides/v2.4/get-started/gs-web-api-request.md b/src/guides/v2.4/get-started/gs-web-api-request.md index e03b32da787..c01cf39c905 100644 --- a/src/guides/v2.4/get-started/gs-web-api-request.md +++ b/src/guides/v2.4/get-started/gs-web-api-request.md @@ -145,7 +145,7 @@ The following example builds a Customers Search request based on search criteria 1. Open the [Magento/Customer/etc/webapi.xml]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Customer/etc/webapi.xml) configuration file and find the [CustomerRepositoryInterface]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Customer/Api/CustomerRepositoryInterface.php) interface with the `getList` method. -1. Set the headers, URI and method to a request object. Use URI `/V1/customers/search` and method `GET` values. Use the `searchCriteria` parameter to complete the Customer Search query. See [searchCriteria usage]({{ page.baseurl }}/rest/performing-searches.html). +1. Set the headers, URI and method to a request object. Use URI `/V1/customers/search` and method `GET` values. Use the `searchCriteria` parameter to complete the Customer Search query. See [searchCriteria usage](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html). The following example finds customers whose first name contains "ver" or whose last name contains "Costello". diff --git a/src/guides/v2.4/graphql/authorization-tokens.md b/src/guides/v2.4/graphql/authorization-tokens.md index 3ce58c4f040..f1e275c19c5 100644 --- a/src/guides/v2.4/graphql/authorization-tokens.md +++ b/src/guides/v2.4/graphql/authorization-tokens.md @@ -76,6 +76,6 @@ mutation{ In Magento GraphQL, you specify an admin token only if you need to query products, categories, price rules, or other entities that are scheduled to be in a campaign (staged content). Staging is supported in {{site.data.var.ee}} only. See [Staging queries]({{page.baseurl}}/graphql/queries/index.html#staging) for more information. -Magento does not provide a GraphQL mutation that generates an admin token. You must use a REST endpoint such as `POST /V1/tfa/provider/google/authenticate` instead. [Generate the admin token]({{page.baseurl}}/rest/tutorials/prerequisite-tasks/create-admin-token.html) shows how to use this endpoint. +Magento does not provide a GraphQL mutation that generates an admin token. You must use a REST endpoint such as `POST /V1/tfa/provider/google/authenticate` instead. [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/create-admin-token.html) shows how to use this endpoint. By default, an admin token is valid for 4 hours. You can change these values from Admin by selecting **Stores** > **Settings** > **Configuration** > **Services** > **OAuth** > **Access Token Expiration** > **Admin Token Lifetime**. diff --git a/src/guides/v2.4/inventory/inventory-api-reference.md b/src/guides/v2.4/inventory/inventory-api-reference.md index fb5f4d4e0f7..3422735c581 100644 --- a/src/guides/v2.4/inventory/inventory-api-reference.md +++ b/src/guides/v2.4/inventory/inventory-api-reference.md @@ -88,8 +88,8 @@ Service | Description --- | --- [``DefaultSourceProviderInterface``]({{ msi_blob_url }}/InventoryCatalogApi/Api/DefaultSourceProviderInterface.php) | Retrieves Default Source code [`DefaultStockProviderInterface`]({{ msi_blob_url }}/InventoryCatalogApi/Api/DefaultStockProviderInterface.php) | Retrieves Default Stock id -[`BulkInventoryTransferInterface`]({{ msi_blob_url }}/InventoryCatalogApi/Api/BulkInventoryTransferInterface.php) | [Bulk transfers]({{page.baseurl}}/rest/modules/inventory/bulk-inventory.html) the whole quantity of products from origin to destination source -[`BulkPartialInventoryTransferInterface`]({{ msi_blob_url }}/InventoryCatalogApi/Api/BulkPartialInventoryTransferInterface.php) | Runs [bulk partial inventory transfer]({{page.baseurl}}/rest/modules/inventory/bulk-inventory.html#bulk-partial-transfer) for specified items +[`BulkInventoryTransferInterface`]({{ msi_blob_url }}/InventoryCatalogApi/Api/BulkInventoryTransferInterface.php) | [Bulk transfers](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/bulk-inventory.html) the whole quantity of products from origin to destination source +[`BulkPartialInventoryTransferInterface`]({{ msi_blob_url }}/InventoryCatalogApi/Api/BulkPartialInventoryTransferInterface.php) | Runs [bulk partial inventory transfer](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/bulk-inventory.html#bulk-partial-transfer) for specified items ## Inventory Sales API diff --git a/src/guides/v2.4/mrg/intro.md b/src/guides/v2.4/mrg/intro.md index 235fef24f0e..41eae8ab2f8 100644 --- a/src/guides/v2.4/mrg/intro.md +++ b/src/guides/v2.4/mrg/intro.md @@ -11,4 +11,4 @@ Related topics - [Building a new Magento module]({{ page.baseurl }}/extension-dev-guide/bk-extension-dev-guide.html) - [How to enable/disable a Magento module]({{ page.baseurl }}/install-gde/install/cli/install-cli-subcommands-enable.html) - [SOAP Reference]({{ page.baseurl }}/soap/bk-soap.html) -- [REST Reference]({{ page.baseurl }}/rest/bk-rest.html) \ No newline at end of file +- [REST Reference](https://developer.adobe.com/commerce/webapi/rest/bk-rest.html) \ No newline at end of file diff --git a/src/guides/v2.4/rest/bk-rest.md b/src/guides/v2.4/rest/bk-rest.md index 93be8a695bb..398e66ad2f7 100644 --- a/src/guides/v2.4/rest/bk-rest.md +++ b/src/guides/v2.4/rest/bk-rest.md @@ -1,6 +1,7 @@ --- group: rest-api title: REST API Overview +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/bk-rest/ functional_areas: - Integration --- diff --git a/src/guides/v2.4/rest/generate-local.md b/src/guides/v2.4/rest/generate-local.md index e6446fedaf6..1eea68b3470 100644 --- a/src/guides/v2.4/rest/generate-local.md +++ b/src/guides/v2.4/rest/generate-local.md @@ -1,6 +1,7 @@ --- group: rest-api title: Generate a local REST reference +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/generate-local/ functional_areas: - Integration --- @@ -84,5 +85,5 @@ You may also use web server rewrite rules to redirect users trying to access the {:.ref-header} Related topics -[Restricting access to anonymous web APIs]({{ page.baseurl }}/rest/anonymous-api-security.html) +[Restricting access to anonymous web APIs](https://developer.adobe.com/commerce/webapi/rest/anonymous-api-security.html) [Token-based authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-token.html) diff --git a/src/guides/v2.4/rest/modules/inventory/check-salable-quantity.md b/src/guides/v2.4/rest/modules/inventory/check-salable-quantity.md index c433915ae55..eb2eac9633b 100644 --- a/src/guides/v2.4/rest/modules/inventory/check-salable-quantity.md +++ b/src/guides/v2.4/rest/modules/inventory/check-salable-quantity.md @@ -1,6 +1,7 @@ --- group: rest-api title: Check salable quantities +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/check-salable-quantity/ --- Magento provides several endpoints that allow you to check whether a product from a specified stock is salable and the available quantity. diff --git a/src/guides/v2.4/rest/modules/inventory/in-store-pickup.md b/src/guides/v2.4/rest/modules/inventory/in-store-pickup.md index 9238eb7ecc0..9ac12df4928 100644 --- a/src/guides/v2.4/rest/modules/inventory/in-store-pickup.md +++ b/src/guides/v2.4/rest/modules/inventory/in-store-pickup.md @@ -1,6 +1,7 @@ --- group: rest-api title: In-Store Pickup +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/in-store-pickup/ contributor_name: Oleksandr Kravchuk contributor_link: https://github.com/swnsma --- @@ -54,7 +55,7 @@ Name | Type | Description `[sort][0][field]=` | String | Specifies the field to sort on. `[sort][0][direction]=` | String | Specifies whether to return results in ascending (`ASC`) or descending (`DESC`) order. The default is `DESC`. -[Search using REST endpoints]({{page.baseurl}}/rest/performing-searches.html) provides a full list of supported condition types. +[Search using REST endpoints](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) provides a full list of supported condition types. **Sample Usage:** diff --git a/src/guides/v2.4/rest/modules/inventory/manage-source-items.md b/src/guides/v2.4/rest/modules/inventory/manage-source-items.md index d23c3dede37..5495a22e179 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-source-items.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-source-items.md @@ -1,6 +1,7 @@ --- group: rest-api title: Manage source items +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/manage-source-items/ --- If Magento is configured to manage inventory, Magento assigns all existing products to the default source. Currently, Magento also assigns newly-created products to the default source. Single Source merchants do not need to manage source items, but Multi Source merchants may need to move products from the default source to a custom source, or move products from one custom source to another. @@ -116,7 +117,7 @@ Magento returns an empty array. The following call returns all source items for `sku` = `new_product2`. -See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.4/rest/modules/inventory/manage-sources.md b/src/guides/v2.4/rest/modules/inventory/manage-sources.md index b75a9de8661..e5502f18d80 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-sources.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-sources.md @@ -1,6 +1,7 @@ --- group: rest-api title: Manage sources +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/manage-sources/ --- Sources represent locations storing and shipping available product stock. Any location with available stock and capable of order fulfillment can be added as a source. These locations can include warehouses, brick-and-mortar stores, distribution centers, and drop shippers. @@ -174,7 +175,7 @@ None The following call returns all sources that are located in the United States (`country_id` = `US`) -See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.4/rest/protected-endpoints.md b/src/guides/v2.4/rest/protected-endpoints.md index c958af15382..58fded971ae 100644 --- a/src/guides/v2.4/rest/protected-endpoints.md +++ b/src/guides/v2.4/rest/protected-endpoints.md @@ -1,6 +1,7 @@ --- group: rest-api title: Protected endpoints +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/protected-endpoints/ functional_areas: - Integration --- diff --git a/src/guides/v2.4/rest/tutorials/index.md b/src/guides/v2.4/rest/tutorials/index.md index 1f0a4ecc97a..aca24272705 100644 --- a/src/guides/v2.4/rest/tutorials/index.md +++ b/src/guides/v2.4/rest/tutorials/index.md @@ -1,6 +1,7 @@ --- group: rest-api title: REST tutorials +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/index/ functional_areas: - Integration - Orders @@ -9,15 +10,15 @@ functional_areas: The REST tutorials provide an introduction to Magento web APIs. In general, the tutorials guide you through commonly-performed complex tasks: -* The [**order processing** tutorial]({{ page.baseurl }}/rest/tutorials/orders/order-intro.html) demonstrates the lifecycle of an order. Major steps include creating a quote, converting it to an order, issuing an invoice, and shipping the order. +* The [**order processing** tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-intro.html) demonstrates the lifecycle of an order. Major steps include creating a quote, converting it to an order, issuing an invoice, and shipping the order. -* The [**order processing with Inventory Management**]({{ page.baseurl }}/rest/tutorials/inventory/index.html) tutorial builds upon the original order processing tutorial. It also configures sources and stocks and other Inventory Management features. +* The [**order processing with Inventory Management**](https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/index.html) tutorial builds upon the original order processing tutorial. It also configures sources and stocks and other Inventory Management features. -* The [**configurable product** tutorial]({{ page.baseurl }}/rest/tutorials/configurable-product/config-product-intro.html) helps you plan then create a configurable product and its component simple products. +* The [**configurable product** tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/config-product-intro.html) helps you plan then create a configurable product and its component simple products. -* The [**bulk API configurable product** tutorial]({{ page.baseurl }}/rest/tutorials/bulk-configurable-product/config-product-intro.html) demonstrates how to create configurable products using bulk APIs. +* The [**bulk API configurable product** tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/bulk-configurable-product/config-product-intro.html) demonstrates how to create configurable products using bulk APIs. -* The [**grouped products** tutorial]({{ page.baseurl }}/rest/tutorials/grouped-product/create-and-manage-grouped-products.html) demonstrates how to create and manage grouped products. +* The [**grouped products** tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/grouped-product/create-and-manage-grouped-products.html) demonstrates how to create and manage grouped products. ## Complete these prerequisites @@ -31,7 +32,7 @@ Before you begin any tutorial, make sure you know the basics about {{site.data.v * Know how to construct a REST call in Magento. See [Construct a request](https://developer.adobe.com/commerce/webapi/get-started/gs-web-api-request.html) for details. -* Find the Magento REST API documentation. You can view the [static REST API documentation on devdocs]({{site.baseurl}}/redoc/{{page.guide_version}}/) or [generate a local API reference]({{ page.baseurl }}/rest/generate-local.html). +* Find the Magento REST API documentation. You can view the [static REST API documentation on devdocs]({{site.baseurl}}/redoc/{{page.guide_version}}/) or [generate a local API reference](https://developer.adobe.com/commerce/webapi/rest/generate-local.html). * Find the Magento Merchant documentation. Refer to [Getting Started with {{site.data.var.ce}}]({{ site.user_guide_url }}/getting-started.html) for information about the Luma store that is created when you install Magento with the sample data. diff --git a/src/guides/v2.4/rest/tutorials/inventory/assign-source-to-stock.md b/src/guides/v2.4/rest/tutorials/inventory/assign-source-to-stock.md index d50ef44a0a6..dce256503c0 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/assign-source-to-stock.md +++ b/src/guides/v2.4/rest/tutorials/inventory/assign-source-to-stock.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 4. Link stocks and sources +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/assign-source-to-stock/ subtitle: Order processing with Inventory Management menu_title: Step 4. Link stocks and sources menu_order: 40 @@ -13,7 +14,7 @@ functional_areas: - Integration --- -This step links the sources we created in [Step 2. Create sources]({{page.baseurl}}/rest/tutorials/inventory/create-sources.html) with the stocks we created in [Step 3. Create stocks]({{page.baseurl}}/rest/tutorials/inventory/create-stock.html). +This step links the sources we created in [Step 2. Create sources](https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-sources.html) with the stocks we created in [Step 3. Create stocks](https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-stock.html). Each stock can be assigned one or more sources. Magento uses these associations to calculate the virtual aggregated inventory per product. diff --git a/src/guides/v2.4/rest/tutorials/inventory/bulk-transfer-products.md b/src/guides/v2.4/rest/tutorials/inventory/bulk-transfer-products.md index 02277b28bb8..c3bf0d549af 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/bulk-transfer-products.md +++ b/src/guides/v2.4/rest/tutorials/inventory/bulk-transfer-products.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 13. Bulk transfer products +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bulk-transfer-products/ subtitle: Order processing with Inventory Management menu_title: Step 13. Bulk transfer products menu_order: 130 diff --git a/src/guides/v2.4/rest/tutorials/inventory/configure-environment.md b/src/guides/v2.4/rest/tutorials/inventory/configure-environment.md index 200ebd94f84..000ef76c7fc 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/configure-environment.md +++ b/src/guides/v2.4/rest/tutorials/inventory/configure-environment.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 1. Configure your environment +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configure-environment/ subtitle: Order processing with Inventory Management menu_title: Step 1. Configure your environment menu_order: 10 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-cart-add-products.md b/src/guides/v2.4/rest/tutorials/inventory/create-cart-add-products.md index ef593652aa0..3ca23ee923a 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-cart-add-products.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-cart-add-products.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 7. Create a cart and add products to it +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-cart-add-products/ subtitle: Order processing with Inventory Management menu_title: Step 7. Create a cart and add products to it menu_order: 70 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-customer.md b/src/guides/v2.4/rest/tutorials/inventory/create-customer.md index f336969315f..60a96cab560 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-customer.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-customer.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 6. Create a customer and generate a customer token +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-customer/ subtitle: Order processing with Inventory Management menu_title: Step 6. Create a customer and generate a customer token menu_order: 60 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-invoice.md b/src/guides/v2.4/rest/tutorials/inventory/create-invoice.md index 05a2cf98963..2ea7143818c 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-invoice.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-invoice.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 10. Create an invoice +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-invoice/ subtitle: Order processing with Inventory Management menu_title: Step 10. Create an invoice menu_order: 100 @@ -52,7 +53,7 @@ An invoice `id`, such as `3`. ## Retrieve the order item IDs -When you create an order, Magento generates an `order_item_id` for each product. These values will be used in [Step 12. Create a shipment]({{page.baseurl}}/rest/tutorials/inventory/create-shipment.html). +When you create an order, Magento generates an `order_item_id` for each product. These values will be used in [Step 12. Create a shipment](https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-shipment.html). **Endpoint:** diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-order.md b/src/guides/v2.4/rest/tutorials/inventory/create-order.md index ba98e0e481c..1b209940357 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-order.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-order.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 9. Create an order +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-order/ subtitle: Order processing with Inventory Management menu_title: Step 9. Create an order menu_order: 90 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-shipment.md b/src/guides/v2.4/rest/tutorials/inventory/create-shipment.md index b1db5f1f915..cd1d162697f 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-shipment.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-shipment.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 12. Create a shipment +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-shipment/ menu_title: Step 12. Create a shipment subtitle: Order processing with Inventory Management menu_order: 120 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-sources.md b/src/guides/v2.4/rest/tutorials/inventory/create-sources.md index 64beb15f73c..5915934583b 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-sources.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-sources.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 2. Create sources +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-sources/ subtitle: Order processing with Inventory Management menu_title: Step 2. Create sources menu_order: 20 @@ -22,7 +23,7 @@ This step guides you through the process of creating sources for your inventory, For more information about sources, see [Inventory Management overview]({{ page.baseurl }}/inventory/index.html). {:.bs-callout-info} -This step requires an admin token. See [Generate the admin token]({{ page.baseurl }}/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. +This step requires an admin token. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. ## Create the first source diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-stock.md b/src/guides/v2.4/rest/tutorials/inventory/create-stock.md index c611173f340..916dc69217e 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-stock.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-stock.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 3. Create stocks +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-stock/ subtitle: Order processing with Inventory Management menu_title: Step 3. Create stocks menu_order: 30 diff --git a/src/guides/v2.4/rest/tutorials/inventory/in-store-pickup.md b/src/guides/v2.4/rest/tutorials/inventory/in-store-pickup.md index c53c02231e8..712b4e9593e 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/in-store-pickup.md +++ b/src/guides/v2.4/rest/tutorials/inventory/in-store-pickup.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 14. Create an order for in-store pickup (optional) +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/in-store-pickup/ subtitle: Order processing with Inventory Management menu_title: Step 14. Bulk transfer products menu_order: 140 @@ -20,7 +21,7 @@ An order must meet the following requirements to be eligible for in-store pickup * All physical products must be assigned to the source that serves as the in-store pickup location. * All items must be in stock. -In this step, we will create a second order from the same customer. In [Step 2. Create sources]({{page.baseurl}}/rest/tutorials/inventory/create-sources.html), we created three stores in the New York City area. The customer will be able to choose from these stores when she selects a pickup location. We will skip some of the steps we performed earlier that provides information we already know. +In this step, we will create a second order from the same customer. In [Step 2. Create sources](https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-sources.html), we created three stores in the New York City area. The customer will be able to choose from these stores when she selects a pickup location. We will skip some of the steps we performed earlier that provides information we already know. ## Create a new cart @@ -94,7 +95,7 @@ This time, we will add two Voyage Yoga Bags (`24-WB01`). ## Search for pickup locations -The `GET /V1/inventory/in-store-pickup/pickup-locations` endpoint searches for locations, given a city name or postal code and a radius, in kilometers. You must also specify the sales channel code to search in the `scopeCode` parameter. The endpoint is described in detail in the [In-Store Pickup]({{page.baseurl}}/rest/modules/inventory/in-store-pickup.html) reference topic. +The `GET /V1/inventory/in-store-pickup/pickup-locations` endpoint searches for locations, given a city name or postal code and a radius, in kilometers. You must also specify the sales channel code to search in the `scopeCode` parameter. The endpoint is described in detail in the [In-Store Pickup](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/in-store-pickup.html) reference topic. In this example, we will search for locations within 50 km of New York, New York that are pickup locations for product `24-WB01`. @@ -199,7 +200,7 @@ The customer has chosen to pick up the order at the Brooklyn store. Once again, * The shipping address is that of the Brooklyn store but includes the customer's first and last name to help the store personnel identify who placed the order. The shipping address also includes the `pickup_location_code` extension attribute. -* The billing address includes the customer's billing address ID. In [Step 6. Create a customer and generate a customer token]({{page.baseurl}}/rest/tutorials/inventory/create-customer.html), the `POST /V1/customers` endpoint returned an address ID of `2`. +* The billing address includes the customer's billing address ID. In [Step 6. Create a customer and generate a customer token](https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-customer.html), the `POST /V1/customers` endpoint returned an address ID of `2`. * The `shipping_method_code` and `shipping_carrier_code` attributes are set to `pickup` and `instore`, respectively. diff --git a/src/guides/v2.4/rest/tutorials/inventory/index.md b/src/guides/v2.4/rest/tutorials/inventory/index.md index 33f70691e77..925c63ebfd2 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/index.md +++ b/src/guides/v2.4/rest/tutorials/inventory/index.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Order Processing with Inventory Management +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/index/ menu_title: Initial tasks menu_order: 0 level3_subgroup: msi-tutorial @@ -14,7 +15,7 @@ functional_areas: ### Before you begin -This tutorial builds upon the workflow described in the [Order Processing with REST APIs tutorial]({{ page.baseurl }}/rest/tutorials/orders/order-intro.html). The Order Processing with Inventory Management tutorial provides additional steps that detail how to create stocks and sources, assign products to a custom source, and run the Source Selection Algorithms to recommend shipping options. +This tutorial builds upon the workflow described in the [Order Processing with REST APIs tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-intro.html). The Order Processing with Inventory Management tutorial provides additional steps that detail how to create stocks and sources, assign products to a custom source, and run the Source Selection Algorithms to recommend shipping options. For more information about key inventory features, see [Inventory Management overview]({{ page.baseurl }}/inventory/index.html). @@ -28,8 +29,8 @@ This **14-step tutorial** generally takes **1 hour**. * Know how to construct a REST call in Magento. See [Construct a request](https://developer.adobe.com/commerce/webapi/get-started/gs-web-api-request.html) for details. -* Obtain an admin authorization token. Multiple calls in this tutorial require administrator privileges. See [Generate the admin token]({{ page.baseurl }}/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. +* Obtain an admin authorization token. Multiple calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. ### Other resources -* Magento uses [Swagger](https://swagger.io) to provide REST API documentation on local instances of Magento. See [Generate a local API reference]({{ page.baseurl }}/rest/generate-local.html) for more information. You can view the [static REST API documentation]({{site.baseurl}}/redoc/{{page.guide_version}}/), which displays reference information using ReDoc. +* Magento uses [Swagger](https://swagger.io) to provide REST API documentation on local instances of Magento. See [Generate a local API reference](https://developer.adobe.com/commerce/webapi/rest/generate-local.html) for more information. You can view the [static REST API documentation]({{site.baseurl}}/redoc/{{page.guide_version}}/), which displays reference information using ReDoc. diff --git a/src/guides/v2.4/rest/tutorials/inventory/prepare-for-checkout.md b/src/guides/v2.4/rest/tutorials/inventory/prepare-for-checkout.md index ff18db7f748..7852d392ce6 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/prepare-for-checkout.md +++ b/src/guides/v2.4/rest/tutorials/inventory/prepare-for-checkout.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 8. Prepare for checkout +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/prepare-for-checkout/ subtitle: Order processing with Inventory Management menu_title: Step 8. Prepare for checkout menu_order: 80 diff --git a/src/guides/v2.4/rest/tutorials/inventory/reassign-products-to-another-source.md b/src/guides/v2.4/rest/tutorials/inventory/reassign-products-to-another-source.md index 85fe76ca8ea..7f53b58b677 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/reassign-products-to-another-source.md +++ b/src/guides/v2.4/rest/tutorials/inventory/reassign-products-to-another-source.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 5. Reassign products to custom sources +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/reassign-products-to-another-source/ subtitle: Order processing with Inventory Management menu_title: Step 5. Reassign products to custom sources menu_order: 50 diff --git a/src/guides/v2.4/rest/tutorials/inventory/run-ssa.md b/src/guides/v2.4/rest/tutorials/inventory/run-ssa.md index 45552a9db43..91aab43717e 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/run-ssa.md +++ b/src/guides/v2.4/rest/tutorials/inventory/run-ssa.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 11. Run the Source Selection Algorithms +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/run-ssa/ subtitle: Order processing with Inventory Management menu_title: Step 11. Run the Source Selection Algorithms menu_order: 110 @@ -14,7 +15,7 @@ functional_areas: --- One of the most significant parts of Inventory Management is the Source Selection Algorithm (SSA). The Source Priority SSA analyzes and determines the best match for sources and shipping based on the priorities you specified in [Step 4. Link stocks and sources -]({{ page.baseurl }}/rest/tutorials/inventory/assign-source-to-stock.html). The Distance Priority SSA calculates the distance between the sources and the shipping address. Both algorithms also provide a list of source items with quantities to deduct per each source item. +](https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/assign-source-to-stock.html). The Distance Priority SSA calculates the distance between the sources and the shipping address. Both algorithms also provide a list of source items with quantities to deduct per each source item. For more information about shipping and SSAs, see [About Source Selection Algorithm and Reservations](https://docs.magento.com/m2/ce/user_guide/catalog/inventory-about-ssa.html) in the _Magento User Guide_. @@ -59,11 +60,11 @@ Not applicable ## Run an SSA -The `POST V1/inventory/source-selection-algorithm-result` endpoint uses the algorithm defined by the `algorithmCode` attribute to calculate the recommended sources and quantities for each item defined in the `items` array. In this example, we'll select the `priority` SSA. [Manage source selection algorithms]({{ page.baseurl }}/rest/modules/inventory/manage-source-selection.html) includes an example using the `distance` priority. +The `POST V1/inventory/source-selection-algorithm-result` endpoint uses the algorithm defined by the `algorithmCode` attribute to calculate the recommended sources and quantities for each item defined in the `items` array. In this example, we'll select the `priority` SSA. [Manage source selection algorithms](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-source-selection.html) includes an example using the `distance` priority. This tutorial does not consider complications, such as selling out of products or back ordering. We can ask the SSA to determine the best way to immediately ship all the items ordered (40 items of product `24-WB01` and 20 items of product `24-WB03`). If the `shippable` attribute in the response is `false`, there are not enough salable items to complete a full shipment, but the merchant can still perform a partial shipment. -In [Step 4. Link stocks and sources]({{page.baseurl}}/rest/tutorials/inventory/assign-source-to-stock.html), we assigned the `priority` value of the Northeast warehouse and West warehouse to be `1` and `2`, respectively. Thus, the `priority` SSA attempts to fulfill the order from the Northeast warehouse first. If the primary source does not have enough of a product in stock, the SSA goes down the prioritized list of sources until the ordered quantity can be found. +In [Step 4. Link stocks and sources](https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/assign-source-to-stock.html), we assigned the `priority` value of the Northeast warehouse and West warehouse to be `1` and `2`, respectively. Thus, the `priority` SSA attempts to fulfill the order from the Northeast warehouse first. If the primary source does not have enough of a product in stock, the SSA goes down the prioritized list of sources until the ordered quantity can be found. **Endpoint:** diff --git a/src/guides/v2.4/rest/tutorials/orders/order-admin-token.md b/src/guides/v2.4/rest/tutorials/orders/order-admin-token.md index 3302c31bf0b..e9f29ed8e77 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-admin-token.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-admin-token.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 2. Get the admin token +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-admin-token/ subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-config-store.md b/src/guides/v2.4/rest/tutorials/orders/order-config-store.md index fa0e599dd97..0d7cb1c817c 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-config-store.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-config-store.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 1. Configure the store +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-config-store/ subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-intro.md b/src/guides/v2.4/rest/tutorials/orders/order-intro.md index a9d40b3af87..f533cd21220 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-intro.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-intro.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Order processing tutorial +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-intro/ menu_title: Initial tasks return_to: title: REST tutorials @@ -32,10 +33,10 @@ Complete the following prerequisites: * Know how to construct a REST call in Magento. See [Construct a request](https://developer.adobe.com/commerce/webapi/get-started/gs-web-api-request.html) for details. -* Find the Magento REST API documentation. You can view the [static REST API documentation on devdocs]({{ site.baseurl }}/redoc/{{page.guide_version}}/) or [generate a local API reference]({{ page.baseurl }}/rest/generate-local.html). +* Find the Magento REST API documentation. You can view the [static REST API documentation on devdocs]({{ site.baseurl }}/redoc/{{page.guide_version}}/) or [generate a local API reference](https://developer.adobe.com/commerce/webapi/rest/generate-local.html). * Find the Magento Merchant documentation. Refer to [Getting Started with {{site.data.var.ce}} 2.1]({{ site.user_guide_url }}/getting-started.html) for information about the Luma store that is created when you install Magento with the sample data. ### Other resources -* [REST Tutorials]({{ page.baseurl }}/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. +* [REST Tutorials](https://developer.adobe.com/commerce/webapi/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. diff --git a/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md b/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md index 7903ae264ba..0247e8caaec 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 10. Issue a partial refund +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-issue-refund/ subtitle: Order processing tutorial return_to: title: REST tutorials @@ -82,6 +83,6 @@ Log in to [Admin](https://glossary.magento.com/admin). Click **Sales** > **Credi Related topics * [Getting Started with Magento Web APIs](https://developer.adobe.com/commerce/webapi/get-started/bk-get-started-api.html) -* [Create a configurable product Tutorial]({{ page.baseurl }}/rest/tutorials/configurable-product/config-product-intro.html) -* [REST API Reference Overview]({{ page.baseurl }}/rest/bk-rest.html) +* [Create a configurable product Tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/config-product-intro.html) +* [REST API Reference Overview](https://developer.adobe.com/commerce/webapi/rest/bk-rest.html) * [REST API documentation]({{site.baseurl}}/redoc/{{page.guide_version}}/) diff --git a/src/guides/v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md b/src/guides/v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md index cf37e7d9e38..623da8b78ba 100644 --- a/src/guides/v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md +++ b/src/guides/v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md @@ -1,6 +1,7 @@ --- group: rest-api title: Generate the admin token +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-admin-token/ functional_areas: - Integration - Orders From ccd203600b97933129d34133611a36715aaea49c Mon Sep 17 00:00:00 2001 From: jhadobe Date: Wed, 22 Jun 2022 17:27:51 -0500 Subject: [PATCH 214/776] fixing links and migrated_to --- src/guides/v2.3/b2b/shared-catalog.md | 2 +- src/guides/v2.3/graphql/tutorials/checkout/index.md | 2 +- src/guides/v2.3/rest/anonymous-api-security.md | 2 +- src/guides/v2.3/rest/asynchronous-web-endpoints.md | 4 ++-- src/guides/v2.3/rest/bulk-endpoints.md | 2 +- src/guides/v2.3/rest/modules/catalog-pricing.md | 2 +- src/guides/v2.3/rest/modules/catalog.md | 2 +- .../v2.3/rest/modules/inventory/bulk-inventory.md | 4 ++-- .../v2.3/rest/modules/inventory/link-stocks-sources.md | 4 ++-- .../v2.3/rest/modules/inventory/manage-low-quantity.md | 2 +- .../rest/modules/inventory/manage-source-selection.md | 2 +- .../v2.3/rest/modules/inventory/manage-stocks.md | 2 +- src/guides/v2.3/rest/modules/sales/refunds.md | 2 +- src/guides/v2.3/rest/notes.md | 2 +- src/guides/v2.3/rest/operation-status-endpoints.md | 2 +- src/guides/v2.3/rest/operation-status-search.md | 2 +- src/guides/v2.3/rest/performing-searches.md | 2 +- src/guides/v2.3/rest/retrieve-filtered-responses.md | 2 +- src/guides/v2.3/rest/search-endpoint.md | 2 +- .../bulk-configurable-product/config-product-intro.md | 4 ++-- .../create-configurable-simple-products.md | 2 +- .../create-personalization-option.md | 4 ++-- .../define-config-product-options.md | 2 +- .../bulk-configurable-product/plan-product.md | 2 +- .../tutorials/bundle-product/bundle-product-intro.md | 2 +- .../tutorials/bundle-product/create-bundle-product.md | 2 +- .../tutorials/bundle-product/create-simple-products.md | 2 +- .../v2.3/rest/tutorials/bundle-product/plan-product.md | 2 +- .../configurable-product/config-product-intro.md | 4 ++-- .../create-configurable-product.md | 2 +- .../create-personalization-option.md | 4 ++-- .../configurable-product/create-simple-products.md | 2 +- .../define-config-product-options.md | 2 +- .../tutorials/configurable-product/plan-product.md | 2 +- .../create-and-manage-grouped-products.md | 6 +++--- .../v2.3/rest/tutorials/orders/order-add-items.md | 2 +- .../rest/tutorials/orders/order-create-customer.md | 2 +- .../v2.3/rest/tutorials/orders/order-create-invoice.md | 2 +- .../v2.3/rest/tutorials/orders/order-create-order.md | 2 +- .../v2.3/rest/tutorials/orders/order-create-quote.md | 2 +- .../rest/tutorials/orders/order-create-shipment.md | 2 +- .../rest/tutorials/orders/order-prepare-checkout.md | 2 +- src/guides/v2.4/b2b/negotiable-order-workflow.md | 4 ++-- .../tutorials/create-custom-rest-api.md | 2 +- src/guides/v2.4/get-started/bk-get-started-api.md | 2 +- src/guides/v2.4/graphql/authorization-tokens.md | 2 +- src/guides/v2.4/mrg/intro.md | 2 +- src/guides/v2.4/rest/bk-rest.md | 2 +- src/guides/v2.4/rest/generate-local.md | 2 +- .../rest/modules/inventory/check-salable-quantity.md | 2 +- .../v2.4/rest/modules/inventory/in-store-pickup.md | 2 +- .../v2.4/rest/modules/inventory/manage-source-items.md | 2 +- .../v2.4/rest/modules/inventory/manage-sources.md | 2 +- src/guides/v2.4/rest/protected-endpoints.md | 2 +- src/guides/v2.4/rest/tutorials/index.md | 10 +++++----- .../rest/tutorials/inventory/assign-source-to-stock.md | 2 +- .../rest/tutorials/inventory/bulk-transfer-products.md | 2 +- .../rest/tutorials/inventory/configure-environment.md | 2 +- .../tutorials/inventory/create-cart-add-products.md | 2 +- .../v2.4/rest/tutorials/inventory/create-customer.md | 2 +- .../v2.4/rest/tutorials/inventory/create-invoice.md | 2 +- .../v2.4/rest/tutorials/inventory/create-order.md | 2 +- .../v2.4/rest/tutorials/inventory/create-shipment.md | 2 +- .../v2.4/rest/tutorials/inventory/create-sources.md | 4 ++-- .../v2.4/rest/tutorials/inventory/create-stock.md | 2 +- .../v2.4/rest/tutorials/inventory/in-store-pickup.md | 2 +- src/guides/v2.4/rest/tutorials/inventory/index.md | 6 +++--- .../rest/tutorials/inventory/prepare-for-checkout.md | 2 +- .../inventory/reassign-products-to-another-source.md | 2 +- src/guides/v2.4/rest/tutorials/inventory/run-ssa.md | 4 ++-- .../v2.4/rest/tutorials/orders/order-admin-token.md | 2 +- .../v2.4/rest/tutorials/orders/order-config-store.md | 2 +- src/guides/v2.4/rest/tutorials/orders/order-intro.md | 2 +- .../v2.4/rest/tutorials/orders/order-issue-refund.md | 6 +++--- .../tutorials/prerequisite-tasks/create-admin-token.md | 2 +- 75 files changed, 95 insertions(+), 95 deletions(-) diff --git a/src/guides/v2.3/b2b/shared-catalog.md b/src/guides/v2.3/b2b/shared-catalog.md index 3bec0d294f8..ba46914c0ea 100644 --- a/src/guides/v2.3/b2b/shared-catalog.md +++ b/src/guides/v2.3/b2b/shared-catalog.md @@ -26,4 +26,4 @@ Custom shared catalogs can be assigned to companies only. They cannot be set for * [Manage shared catalogs]({{ page.baseurl }}/b2b/shared-cat-manage.html) * [Assign categories and products]({{ page.baseurl }}/b2b/shared-cat-product-assign.html) * [Assign companies]({{ page.baseurl }}/b2b/shared-cat-company.html) -* [Manage prices for multiple products](https://developer.adobe.com/commerce/webapi/rest/modules/catalog-pricing.html) +* [Manage prices for multiple products](https://developer.adobe.com/commerce/webapi/rest/modules/catalog/catalog-pricing) diff --git a/src/guides/v2.3/graphql/tutorials/checkout/index.md b/src/guides/v2.3/graphql/tutorials/checkout/index.md index 01c4ca7844f..a458935db14 100644 --- a/src/guides/v2.3/graphql/tutorials/checkout/index.md +++ b/src/guides/v2.3/graphql/tutorials/checkout/index.md @@ -40,6 +40,6 @@ Complete the following prerequisites: ### Other resources -- [Order processing tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-intro.html) shows a system integrator how REST APIs are used in the lifecycle of an order, including configuring a store and creating a customer; creating quotes, orders, invoices, and shipments; preparing for checkout; and more order-related tasks. +- [Order processing tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/) shows a system integrator how REST APIs are used in the lifecycle of an order, including configuring a store and creating a customer; creating quotes, orders, invoices, and shipments; preparing for checkout; and more order-related tasks. - [REST Tutorials](https://developer.adobe.com/commerce/webapi/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. diff --git a/src/guides/v2.3/rest/anonymous-api-security.md b/src/guides/v2.3/rest/anonymous-api-security.md index 6453787c759..970ce3a2541 100644 --- a/src/guides/v2.3/rest/anonymous-api-security.md +++ b/src/guides/v2.3/rest/anonymous-api-security.md @@ -1,7 +1,7 @@ --- group: rest-api title: Restricting access to anonymous web APIs -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/anonymous-api-security/ + --- Magento 2 allows some web APIs to be accessed by unauthenticated (anonymous) users. Many of these APIs allow a customer to have a robust shopping experience on the [website](https://glossary.magento.com/website) without having to log in. diff --git a/src/guides/v2.3/rest/asynchronous-web-endpoints.md b/src/guides/v2.3/rest/asynchronous-web-endpoints.md index 3606bf1a631..53e58957b8d 100644 --- a/src/guides/v2.3/rest/asynchronous-web-endpoints.md +++ b/src/guides/v2.3/rest/asynchronous-web-endpoints.md @@ -1,7 +1,7 @@ --- group: rest-api title: Asynchronous web endpoints -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/asynchronous-web-endpoints/ + contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ functional_areas: @@ -32,7 +32,7 @@ PUT /async/V1/products/:sku {{site.data.var.ce}} and {{site.data.var.ee}} installations support asynchronous web endpoints. -The [REST API documentation](https://developer.adobe.com/commerce/webapi/rest/bk-rest.html) provides a list of all current synchronous Magento API routes. +The [REST API documentation](https://developer.adobe.com/commerce/webapi/rest/) provides a list of all current synchronous Magento API routes. The response of an asynchronous request contains the following fields: diff --git a/src/guides/v2.3/rest/bulk-endpoints.md b/src/guides/v2.3/rest/bulk-endpoints.md index 2130b887430..a3cb54768f9 100644 --- a/src/guides/v2.3/rest/bulk-endpoints.md +++ b/src/guides/v2.3/rest/bulk-endpoints.md @@ -1,7 +1,7 @@ --- group: rest-api title: Bulk endpoints -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/bulk-endpoints/ + contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ functional_areas: diff --git a/src/guides/v2.3/rest/modules/catalog-pricing.md b/src/guides/v2.3/rest/modules/catalog-pricing.md index 8550a39d779..876f2047b99 100644 --- a/src/guides/v2.3/rest/modules/catalog-pricing.md +++ b/src/guides/v2.3/rest/modules/catalog-pricing.md @@ -1,7 +1,7 @@ --- group: rest-api title: Manage prices for multiple products -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/catalog-pricing/ + functional_areas: - Integration --- diff --git a/src/guides/v2.3/rest/modules/catalog.md b/src/guides/v2.3/rest/modules/catalog.md index de3721410ce..0835da832c7 100644 --- a/src/guides/v2.3/rest/modules/catalog.md +++ b/src/guides/v2.3/rest/modules/catalog.md @@ -1,7 +1,7 @@ --- group: rest-api title: Catalog module -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/catalog/ + functional_areas: - Integration - Catalog diff --git a/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md b/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md index c0bca8582f6..c6e38818c18 100644 --- a/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md +++ b/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md @@ -1,7 +1,7 @@ --- group: rest-api title: Inventory mass actions -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/bulk-inventory/ + --- Magento provides several endpoints that allow Multi Source merchants to make quick updates across multiple products. This is helpful for transferring inventory between sources and removing a source without editing each product individually. @@ -112,7 +112,7 @@ An empty array Use the `POST /V1/inventory/bulk-product-source-assign` endpoint to add one or more sources to your products. This endpoint helps when creating and assigning custom sources to your default or custom stocks and preparing new locations and inventory. -After adding new custom sources, you can add inventory quantities per product or for multiple products using the `POST V1/inventory/source-items` endpoint. [Assign products to a source](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-source-items.html#assign) describes this endpoint. +After adding new custom sources, you can add inventory quantities per product or for multiple products using the `POST V1/inventory/source-items` endpoint. [Assign products to a source](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-source-items) describes this endpoint. The sources are added to the products with an inventory quantity of 0. You can add inventory amounts as available per source. diff --git a/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md b/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md index 105b2d5e569..996c25f6e12 100644 --- a/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md +++ b/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md @@ -1,7 +1,7 @@ --- group: rest-api title: Link and unlink stocks and sources -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/link-stocks-sources/ + --- @@ -147,7 +147,7 @@ None ## Get sources assigned to a stock -The `GET /V1/inventory/get-sources-assigned-to-stock-ordered-by-priority/:stock_id` endpoint returns details about each source that is assigned to the specified stock. [Manage sources](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-sources.html) provides definitions for each attribute returned. +The `GET /V1/inventory/get-sources-assigned-to-stock-ordered-by-priority/:stock_id` endpoint returns details about each source that is assigned to the specified stock. [Manage sources](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/) provides definitions for each attribute returned. **Sample Usage:** diff --git a/src/guides/v2.3/rest/modules/inventory/manage-low-quantity.md b/src/guides/v2.3/rest/modules/inventory/manage-low-quantity.md index 57ac314bd82..582c561fea2 100644 --- a/src/guides/v2.3/rest/modules/inventory/manage-low-quantity.md +++ b/src/guides/v2.3/rest/modules/inventory/manage-low-quantity.md @@ -1,7 +1,7 @@ --- group: rest-api title: Manage low-quantity notifications -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/manage-low-quantity/ + --- Low stock notification alert the merchant that the salable quantity of a stock has reached a critical threshold. The Admin allows the merchant to configure low-quantity notifications from several locations: diff --git a/src/guides/v2.3/rest/modules/inventory/manage-source-selection.md b/src/guides/v2.3/rest/modules/inventory/manage-source-selection.md index 37979f5117f..001e6e00819 100644 --- a/src/guides/v2.3/rest/modules/inventory/manage-source-selection.md +++ b/src/guides/v2.3/rest/modules/inventory/manage-source-selection.md @@ -1,7 +1,7 @@ --- group: rest-api title: Manage source selection algorithms -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/manage-source-selection/ + --- Inventory Management uses the Source Selection Algorithm (SSA) to track the salable quantities of product inventory across all sources and make recommendations for partial and full shipments. diff --git a/src/guides/v2.3/rest/modules/inventory/manage-stocks.md b/src/guides/v2.3/rest/modules/inventory/manage-stocks.md index c84a13a348e..fc5ded47f9f 100644 --- a/src/guides/v2.3/rest/modules/inventory/manage-stocks.md +++ b/src/guides/v2.3/rest/modules/inventory/manage-stocks.md @@ -1,7 +1,7 @@ --- group: rest-api title: Manage stocks -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/manage-stocks/ + --- Stocks map your sources to sales channels, providing a direct link to salable quantities and inventories. diff --git a/src/guides/v2.3/rest/modules/sales/refunds.md b/src/guides/v2.3/rest/modules/sales/refunds.md index f91167ffff4..44ee0d81952 100644 --- a/src/guides/v2.3/rest/modules/sales/refunds.md +++ b/src/guides/v2.3/rest/modules/sales/refunds.md @@ -1,7 +1,7 @@ --- group: rest-api title: Refunds -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/refunds/ + functional_areas: - Integration - Catalog diff --git a/src/guides/v2.3/rest/notes.md b/src/guides/v2.3/rest/notes.md index 7cbdece72b5..c83785dc329 100644 --- a/src/guides/v2.3/rest/notes.md +++ b/src/guides/v2.3/rest/notes.md @@ -1,7 +1,7 @@ --- group: rest-api title: REST usage notes -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/notes/ + functional_areas: - Integration --- diff --git a/src/guides/v2.3/rest/operation-status-endpoints.md b/src/guides/v2.3/rest/operation-status-endpoints.md index 78ea103fec6..837e0797016 100644 --- a/src/guides/v2.3/rest/operation-status-endpoints.md +++ b/src/guides/v2.3/rest/operation-status-endpoints.md @@ -1,7 +1,7 @@ --- group: rest-api title: Bulk operation status endpoints -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/operation-status-endpoints/ + contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com/ functional_areas: diff --git a/src/guides/v2.3/rest/operation-status-search.md b/src/guides/v2.3/rest/operation-status-search.md index b45ad971dc3..c7c02a32fd9 100644 --- a/src/guides/v2.3/rest/operation-status-search.md +++ b/src/guides/v2.3/rest/operation-status-search.md @@ -1,7 +1,7 @@ --- group: rest-api title: Search for the status of a bulk operation -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/operation-status-search/ + contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com functional_areas: diff --git a/src/guides/v2.3/rest/performing-searches.md b/src/guides/v2.3/rest/performing-searches.md index 8f3868f1149..b8ef346f6dc 100644 --- a/src/guides/v2.3/rest/performing-searches.md +++ b/src/guides/v2.3/rest/performing-searches.md @@ -1,7 +1,7 @@ --- group: rest-api title: Search using REST endpoints -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/performing-searches/ + --- POST, PUT, and DELETE requests to the REST Web [API](https://glossary.magento.com/api) require the service method parameters to be in the body of the request. For example, to create a Customer, you would specify a JSON array (or [XML](https://glossary.magento.com/xml) structure) in the body of the message. diff --git a/src/guides/v2.3/rest/retrieve-filtered-responses.md b/src/guides/v2.3/rest/retrieve-filtered-responses.md index 64b81341609..fe142e676a7 100644 --- a/src/guides/v2.3/rest/retrieve-filtered-responses.md +++ b/src/guides/v2.3/rest/retrieve-filtered-responses.md @@ -1,7 +1,7 @@ --- group: rest-api title: Retrieve filtered responses for REST endpoints -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/retrieve-filtered-responses/ + --- Some REST calls return dozens or even hundreds of parameters, and parsing through all this data can be unwieldy. In addition, mobile app developers might find the bandwidth needed to process a request to be excessive. To resolve these problems, Magento provides a query parameter-based syntax for REST requests that return partial responses. diff --git a/src/guides/v2.3/rest/search-endpoint.md b/src/guides/v2.3/rest/search-endpoint.md index 451151df2de..4e754ec95cc 100644 --- a/src/guides/v2.3/rest/search-endpoint.md +++ b/src/guides/v2.3/rest/search-endpoint.md @@ -1,7 +1,7 @@ --- group: rest-api title: Search for products with the /search endpoint -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/search-endpoint/ + contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com/ --- diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md index df0722956e3..fb98e68dbdc 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Create a configurable product using bulk APIs -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/config-product-intro/ + menu_title: Initial tasks menu_order: 0 level3_subgroup: bulk-configurable-product-tutorial @@ -27,7 +27,7 @@ A system integrator can use Magento REST bulk APIs to perform actions on a large * Install a Magento 2.3 (or later) instance with sample data. The sample data defines a functional store, called Luma, that sells fitness clothing and accessories. * Install a REST client. You can use any REST client to send calls to Magento. [Postman](https://www.getpostman.com/) is recommended. -* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/) for more information. * Use the `bin/magento queue:consumers:start async.operations.all` command to enable bulk endpoint processing. ### Other resources diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md index 43a2968c6cd..094da2885a5 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 2. Create the configurable and simple products -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-configurable-simple-products/ + subtitle: Create a configurable product using bulk APIs menu_title: Step 2. Create the configurable and simple products menu_order: 20 diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md index 15721c6d0fe..5863f5f53ac 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 4. Create the personalization option -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-personalization-option/ + subtitle: Create a configurable product using bulk APIs menu_title: Step 4. Create the personalization option menu_order: 40 @@ -77,4 +77,4 @@ The `product_sku` is the `sku` of the configurable product. The `sku` specified {:.ref-header} Related topic -[Order Processing with REST APIs Tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-intro.html) +[Order Processing with REST APIs Tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/) diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md index 30f1873d3fb..2a8b31a4f86 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 3. Define configurable product options -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/define-config-product-options/ + subtitle: Create a configurable product using bulk APIs menu_title: Step 3. Define configurable product options menu_order: 30 diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/plan-product.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/plan-product.md index 0c4359ff208..14ddbd0d58f 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/plan-product.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/plan-product.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 1. Plan the product -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/plan-product/ + subtitle: Create a configurable product using bulk APIs menu_title: Step 1. Plan the product menu_order: 10 diff --git a/src/guides/v2.3/rest/tutorials/bundle-product/bundle-product-intro.md b/src/guides/v2.3/rest/tutorials/bundle-product/bundle-product-intro.md index 8fe307d7ac8..2645b7ccba3 100644 --- a/src/guides/v2.3/rest/tutorials/bundle-product/bundle-product-intro.md +++ b/src/guides/v2.3/rest/tutorials/bundle-product/bundle-product-intro.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Create a bundle product tutorial -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product-intro/ + contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.3/rest/tutorials/bundle-product/create-bundle-product.md b/src/guides/v2.3/rest/tutorials/bundle-product/create-bundle-product.md index 7acdd741438..c7054060f71 100644 --- a/src/guides/v2.3/rest/tutorials/bundle-product/create-bundle-product.md +++ b/src/guides/v2.3/rest/tutorials/bundle-product/create-bundle-product.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 3. Create the bundle product -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-bundle-product/ + contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.3/rest/tutorials/bundle-product/create-simple-products.md b/src/guides/v2.3/rest/tutorials/bundle-product/create-simple-products.md index 3e8a014c941..57585c31d7b 100644 --- a/src/guides/v2.3/rest/tutorials/bundle-product/create-simple-products.md +++ b/src/guides/v2.3/rest/tutorials/bundle-product/create-simple-products.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 2. Create the simple products -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-simple-products/ + contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.3/rest/tutorials/bundle-product/plan-product.md b/src/guides/v2.3/rest/tutorials/bundle-product/plan-product.md index 570f4ebe953..acd185007c9 100644 --- a/src/guides/v2.3/rest/tutorials/bundle-product/plan-product.md +++ b/src/guides/v2.3/rest/tutorials/bundle-product/plan-product.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 1. Plan the product -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/plan-product/ + contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md b/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md index 7e4dbc2f9b4..5f7a510e070 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Create a configurable product tutorial -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/config-product-intro/ + menu_title: Initial tasks menu_order: 0 level3_subgroup: configurable-product-tutorial @@ -27,7 +27,7 @@ This **5-step tutorial** generally takes **45 minutes**. * [Install and configure RabbitMQ]({{ page.baseurl }}/install-gde/prereq/install-rabbitmq.html), which is the default message broker for bulk API endpoints. -* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/) for more information. ### Other resources diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/create-configurable-product.md b/src/guides/v2.3/rest/tutorials/configurable-product/create-configurable-product.md index 9a6eead6df3..068b4521c21 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/create-configurable-product.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/create-configurable-product.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 2. Create the configurable product -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-configurable-product/ + subtitle: Create a configurable product tutorial menu_title: Step 2. Create the configurable product menu_order: 20 diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md b/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md index 12975629f2e..e8d2c6a29e0 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 5. Create the personalization option -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-personalization-option/ + subtitle: Create a configurable product tutorial menu_title: Step 5. Create the personalization option menu_order: 50 @@ -76,4 +76,4 @@ The `product_sku` is the `sku` of the configurable product. The `sku` specified {:.ref-header} Related topic -[Order Processing with REST APIs Tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-intro.html) +[Order Processing with REST APIs Tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/) diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/create-simple-products.md b/src/guides/v2.3/rest/tutorials/configurable-product/create-simple-products.md index a4623dfc79e..646d83bbe6f 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/create-simple-products.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/create-simple-products.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 3. Create the simple products -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-simple-products/ + subtitle: Create a configurable product tutorial menu_title: Step 3. Create the simple products menu_order: 30 diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/define-config-product-options.md b/src/guides/v2.3/rest/tutorials/configurable-product/define-config-product-options.md index ce853abfa70..b35c2e2575f 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/define-config-product-options.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/define-config-product-options.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 4. Define configurable product options -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/define-config-product-options/ + subtitle: Create a configurable product tutorial menu_title: Step 4. Define configurable product options menu_order: 40 diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/plan-product.md b/src/guides/v2.3/rest/tutorials/configurable-product/plan-product.md index d2a77741f11..b978d0d21e3 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/plan-product.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/plan-product.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 1. Plan the product -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/plan-product/ + subtitle: Create a configurable product tutorial menu_title: Step 1. Plan the product menu_order: 10 diff --git a/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md b/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md index cad411a2b72..4d47f31c975 100644 --- a/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md +++ b/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md @@ -1,7 +1,7 @@ --- group: rest-api title: Create and manage grouped products tutorial -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-and-manage-grouped-products/ + functional_areas: - Integration --- @@ -16,7 +16,7 @@ This tutorial describes how you can use the Magento REST API to create and manag * Install a REST client. You can use any REST client to send calls to Magento. [Postman](https://www.getpostman.com/) is recommended. -* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/) for more information. ### Other resources @@ -217,7 +217,7 @@ You also can use the `DELETE` endpoint to delete a simple product from the group Customers can now add this grouped products to their carts, as shown below. -Refer to the [Order processing tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-intro.html) for more information about how to add items to a cart with REST. +Refer to the [Order processing tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/) for more information about how to add items to a cart with REST. ### Endpoint diff --git a/src/guides/v2.3/rest/tutorials/orders/order-add-items.md b/src/guides/v2.3/rest/tutorials/orders/order-add-items.md index 10268d78ec6..d23ac7267c7 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-add-items.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-add-items.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 5. Add items to the cart -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-add-items/ + subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-create-customer.md b/src/guides/v2.3/rest/tutorials/orders/order-create-customer.md index 19d8dfd3467..68d02a66f8a 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-create-customer.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-create-customer.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 3. Create a customer -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-create-customer/ + subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-create-invoice.md b/src/guides/v2.3/rest/tutorials/orders/order-create-invoice.md index 5251618d133..a686f5ebe83 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-create-invoice.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-create-invoice.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 8. Create an invoice -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-create-invoice/ + subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-create-order.md b/src/guides/v2.3/rest/tutorials/orders/order-create-order.md index b63f57675fe..069aa167524 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-create-order.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-create-order.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 7. Create an order -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-create-order/ + subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-create-quote.md b/src/guides/v2.3/rest/tutorials/orders/order-create-quote.md index 05b7cbe3b8a..fc397b4d38c 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-create-quote.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-create-quote.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 4. Create a quote -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-create-quote/ + subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-create-shipment.md b/src/guides/v2.3/rest/tutorials/orders/order-create-shipment.md index 89d89a04c5b..66e28902fc4 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-create-shipment.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-create-shipment.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 9. Create a shipment -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-create-shipment/ + subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-prepare-checkout.md b/src/guides/v2.3/rest/tutorials/orders/order-prepare-checkout.md index bee30db3984..a48253a582c 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-prepare-checkout.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-prepare-checkout.md @@ -3,7 +3,7 @@ layout: tutorial group: rest-api subgroup: title: Step 6. Prepare for checkout -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-prepare-checkout/ + subtitle: Order Processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/b2b/negotiable-order-workflow.md b/src/guides/v2.4/b2b/negotiable-order-workflow.md index b53dc2e6787..fde89724ec7 100644 --- a/src/guides/v2.4/b2b/negotiable-order-workflow.md +++ b/src/guides/v2.4/b2b/negotiable-order-workflow.md @@ -14,7 +14,7 @@ This topic describes how REST calls can be used to place items in a shopping car ## Prepare the order -The steps in this section are similar to those in the [Order processing tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-intro.html), except that different products are added to the cart. +The steps in this section are similar to those in the [Order processing tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/), except that different products are added to the cart. ### Create a shopping cart @@ -1000,7 +1000,7 @@ Authorization Bearer ## Related information -* [Order processing tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-intro.html) +* [Order processing tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/) * [Integrate with the NegotiableQuote module]({{ page.baseurl }}/b2b/negotiable-quote.html) * [Manage negotiable quotes]({{ page.baseurl }}/b2b/negotiable-manage.html) * [Update a negotiable quote]({{ page.baseurl }}/b2b/negotiable-update.html) diff --git a/src/guides/v2.4/ext-best-practices/tutorials/create-custom-rest-api.md b/src/guides/v2.4/ext-best-practices/tutorials/create-custom-rest-api.md index 72b163dca78..e14b39ffa5e 100644 --- a/src/guides/v2.4/ext-best-practices/tutorials/create-custom-rest-api.md +++ b/src/guides/v2.4/ext-best-practices/tutorials/create-custom-rest-api.md @@ -513,7 +513,7 @@ class ProductRepository implements ProductRepositoryInterface ## Step 6. Test your custom endpoint * You can use any REST client to send calls. [Postman](https://www.getpostman.com/) is recommended. -* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/) for more information. ### Test the GET endpoint diff --git a/src/guides/v2.4/get-started/bk-get-started-api.md b/src/guides/v2.4/get-started/bk-get-started-api.md index 92a058700a5..03ba2ac2a90 100644 --- a/src/guides/v2.4/get-started/bk-get-started-api.md +++ b/src/guides/v2.4/get-started/bk-get-started-api.md @@ -16,7 +16,7 @@ layout: migrated The Magento web [API](https://glossary.magento.com/api) framework provides integrators and developers the means to use web services that communicate with the Magento system. Key features include: -* Support for [GraphQL]({{page.baseurl}}/graphql/index.html), [REST](https://developer.adobe.com/commerce/webapi/rest/bk-rest.html) (Representational State Transfer) and [SOAP]({{ page.baseurl }}/soap/bk-soap.html) (Simple Object Access Protocol). In Magento 2, the [web API](https://glossary.magento.com/web-api) coverage is the same for both REST and SOAP. +* Support for [GraphQL]({{page.baseurl}}/graphql/index.html), [REST](https://developer.adobe.com/commerce/webapi/rest/) (Representational State Transfer) and [SOAP]({{ page.baseurl }}/soap/bk-soap.html) (Simple Object Access Protocol). In Magento 2, the [web API](https://glossary.magento.com/web-api) coverage is the same for both REST and SOAP. * Three types of [authentication]({{ page.baseurl }}/get-started/authentication/gs-authentication.html): * Third-party applications authenticate with [OAuth 1.0a]({{ page.baseurl }}/get-started/authentication/gs-authentication-oauth.html). diff --git a/src/guides/v2.4/graphql/authorization-tokens.md b/src/guides/v2.4/graphql/authorization-tokens.md index f1e275c19c5..1dbf5a5552f 100644 --- a/src/guides/v2.4/graphql/authorization-tokens.md +++ b/src/guides/v2.4/graphql/authorization-tokens.md @@ -76,6 +76,6 @@ mutation{ In Magento GraphQL, you specify an admin token only if you need to query products, categories, price rules, or other entities that are scheduled to be in a campaign (staged content). Staging is supported in {{site.data.var.ee}} only. See [Staging queries]({{page.baseurl}}/graphql/queries/index.html#staging) for more information. -Magento does not provide a GraphQL mutation that generates an admin token. You must use a REST endpoint such as `POST /V1/tfa/provider/google/authenticate` instead. [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/create-admin-token.html) shows how to use this endpoint. +Magento does not provide a GraphQL mutation that generates an admin token. You must use a REST endpoint such as `POST /V1/tfa/provider/google/authenticate` instead. [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/) shows how to use this endpoint. By default, an admin token is valid for 4 hours. You can change these values from Admin by selecting **Stores** > **Settings** > **Configuration** > **Services** > **OAuth** > **Access Token Expiration** > **Admin Token Lifetime**. diff --git a/src/guides/v2.4/mrg/intro.md b/src/guides/v2.4/mrg/intro.md index 41eae8ab2f8..5cc1fa939eb 100644 --- a/src/guides/v2.4/mrg/intro.md +++ b/src/guides/v2.4/mrg/intro.md @@ -11,4 +11,4 @@ Related topics - [Building a new Magento module]({{ page.baseurl }}/extension-dev-guide/bk-extension-dev-guide.html) - [How to enable/disable a Magento module]({{ page.baseurl }}/install-gde/install/cli/install-cli-subcommands-enable.html) - [SOAP Reference]({{ page.baseurl }}/soap/bk-soap.html) -- [REST Reference](https://developer.adobe.com/commerce/webapi/rest/bk-rest.html) \ No newline at end of file +- [REST Reference](https://developer.adobe.com/commerce/webapi/rest/) \ No newline at end of file diff --git a/src/guides/v2.4/rest/bk-rest.md b/src/guides/v2.4/rest/bk-rest.md index 398e66ad2f7..ca79c27bd02 100644 --- a/src/guides/v2.4/rest/bk-rest.md +++ b/src/guides/v2.4/rest/bk-rest.md @@ -1,7 +1,7 @@ --- group: rest-api title: REST API Overview -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/bk-rest/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/ functional_areas: - Integration --- diff --git a/src/guides/v2.4/rest/generate-local.md b/src/guides/v2.4/rest/generate-local.md index 1eea68b3470..0fbbef00b6b 100644 --- a/src/guides/v2.4/rest/generate-local.md +++ b/src/guides/v2.4/rest/generate-local.md @@ -1,7 +1,7 @@ --- group: rest-api title: Generate a local REST reference -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/generate-local/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/generate-local/ functional_areas: - Integration --- diff --git a/src/guides/v2.4/rest/modules/inventory/check-salable-quantity.md b/src/guides/v2.4/rest/modules/inventory/check-salable-quantity.md index eb2eac9633b..d6017214c96 100644 --- a/src/guides/v2.4/rest/modules/inventory/check-salable-quantity.md +++ b/src/guides/v2.4/rest/modules/inventory/check-salable-quantity.md @@ -1,7 +1,7 @@ --- group: rest-api title: Check salable quantities -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/check-salable-quantity/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/check-salable-quantity/ --- Magento provides several endpoints that allow you to check whether a product from a specified stock is salable and the available quantity. diff --git a/src/guides/v2.4/rest/modules/inventory/in-store-pickup.md b/src/guides/v2.4/rest/modules/inventory/in-store-pickup.md index 9ac12df4928..172dec5d65d 100644 --- a/src/guides/v2.4/rest/modules/inventory/in-store-pickup.md +++ b/src/guides/v2.4/rest/modules/inventory/in-store-pickup.md @@ -1,7 +1,7 @@ --- group: rest-api title: In-Store Pickup -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/in-store-pickup/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/in-store-pickup/ contributor_name: Oleksandr Kravchuk contributor_link: https://github.com/swnsma --- diff --git a/src/guides/v2.4/rest/modules/inventory/manage-source-items.md b/src/guides/v2.4/rest/modules/inventory/manage-source-items.md index 5495a22e179..a6c8becfc87 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-source-items.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-source-items.md @@ -1,7 +1,7 @@ --- group: rest-api title: Manage source items -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/manage-source-items/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/ --- If Magento is configured to manage inventory, Magento assigns all existing products to the default source. Currently, Magento also assigns newly-created products to the default source. Single Source merchants do not need to manage source items, but Multi Source merchants may need to move products from the default source to a custom source, or move products from one custom source to another. diff --git a/src/guides/v2.4/rest/modules/inventory/manage-sources.md b/src/guides/v2.4/rest/modules/inventory/manage-sources.md index e5502f18d80..0a999d83558 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-sources.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-sources.md @@ -1,7 +1,7 @@ --- group: rest-api title: Manage sources -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/manage-sources/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-sources/ --- Sources represent locations storing and shipping available product stock. Any location with available stock and capable of order fulfillment can be added as a source. These locations can include warehouses, brick-and-mortar stores, distribution centers, and drop shippers. diff --git a/src/guides/v2.4/rest/protected-endpoints.md b/src/guides/v2.4/rest/protected-endpoints.md index 58fded971ae..d5ea62e5437 100644 --- a/src/guides/v2.4/rest/protected-endpoints.md +++ b/src/guides/v2.4/rest/protected-endpoints.md @@ -1,7 +1,7 @@ --- group: rest-api title: Protected endpoints -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/protected-endpoints/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/protected-endpoints/ functional_areas: - Integration --- diff --git a/src/guides/v2.4/rest/tutorials/index.md b/src/guides/v2.4/rest/tutorials/index.md index aca24272705..14c4c88e5a9 100644 --- a/src/guides/v2.4/rest/tutorials/index.md +++ b/src/guides/v2.4/rest/tutorials/index.md @@ -1,7 +1,7 @@ --- group: rest-api title: REST tutorials -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/index/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/ functional_areas: - Integration - Orders @@ -10,15 +10,15 @@ functional_areas: The REST tutorials provide an introduction to Magento web APIs. In general, the tutorials guide you through commonly-performed complex tasks: -* The [**order processing** tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-intro.html) demonstrates the lifecycle of an order. Major steps include creating a quote, converting it to an order, issuing an invoice, and shipping the order. +* The [**order processing** tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/) demonstrates the lifecycle of an order. Major steps include creating a quote, converting it to an order, issuing an invoice, and shipping the order. * The [**order processing with Inventory Management**](https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/index.html) tutorial builds upon the original order processing tutorial. It also configures sources and stocks and other Inventory Management features. -* The [**configurable product** tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/config-product-intro.html) helps you plan then create a configurable product and its component simple products. +* The [**configurable product** tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/.html) helps you plan then create a configurable product and its component simple products. -* The [**bulk API configurable product** tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/bulk-configurable-product/config-product-intro.html) demonstrates how to create configurable products using bulk APIs. +* The [**bulk API configurable product** tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/bulk-configurable-product/.html) demonstrates how to create configurable products using bulk APIs. -* The [**grouped products** tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/grouped-product/create-and-manage-grouped-products.html) demonstrates how to create and manage grouped products. +* The [**grouped products** tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/grouped-product/) demonstrates how to create and manage grouped products. ## Complete these prerequisites diff --git a/src/guides/v2.4/rest/tutorials/inventory/assign-source-to-stock.md b/src/guides/v2.4/rest/tutorials/inventory/assign-source-to-stock.md index dce256503c0..0066124b021 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/assign-source-to-stock.md +++ b/src/guides/v2.4/rest/tutorials/inventory/assign-source-to-stock.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 4. Link stocks and sources -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/assign-source-to-stock/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/assign-source-to-stock/ subtitle: Order processing with Inventory Management menu_title: Step 4. Link stocks and sources menu_order: 40 diff --git a/src/guides/v2.4/rest/tutorials/inventory/bulk-transfer-products.md b/src/guides/v2.4/rest/tutorials/inventory/bulk-transfer-products.md index c3bf0d549af..00abc207499 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/bulk-transfer-products.md +++ b/src/guides/v2.4/rest/tutorials/inventory/bulk-transfer-products.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 13. Bulk transfer products -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bulk-transfer-products/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/bulk-transfer-products/ subtitle: Order processing with Inventory Management menu_title: Step 13. Bulk transfer products menu_order: 130 diff --git a/src/guides/v2.4/rest/tutorials/inventory/configure-environment.md b/src/guides/v2.4/rest/tutorials/inventory/configure-environment.md index 000ef76c7fc..9435f8504a9 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/configure-environment.md +++ b/src/guides/v2.4/rest/tutorials/inventory/configure-environment.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 1. Configure your environment -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configure-environment/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/configure-environment/ subtitle: Order processing with Inventory Management menu_title: Step 1. Configure your environment menu_order: 10 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-cart-add-products.md b/src/guides/v2.4/rest/tutorials/inventory/create-cart-add-products.md index 3ca23ee923a..05abb0a792e 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-cart-add-products.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-cart-add-products.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 7. Create a cart and add products to it -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-cart-add-products/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-cart-add-products/ subtitle: Order processing with Inventory Management menu_title: Step 7. Create a cart and add products to it menu_order: 70 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-customer.md b/src/guides/v2.4/rest/tutorials/inventory/create-customer.md index 60a96cab560..4352be90229 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-customer.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-customer.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 6. Create a customer and generate a customer token -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-customer/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-customer/ subtitle: Order processing with Inventory Management menu_title: Step 6. Create a customer and generate a customer token menu_order: 60 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-invoice.md b/src/guides/v2.4/rest/tutorials/inventory/create-invoice.md index 2ea7143818c..0d700ac7cde 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-invoice.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-invoice.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 10. Create an invoice -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-invoice/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-invoice/ subtitle: Order processing with Inventory Management menu_title: Step 10. Create an invoice menu_order: 100 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-order.md b/src/guides/v2.4/rest/tutorials/inventory/create-order.md index 1b209940357..2da3ced38b3 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-order.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-order.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 9. Create an order -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-order/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-order/ subtitle: Order processing with Inventory Management menu_title: Step 9. Create an order menu_order: 90 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-shipment.md b/src/guides/v2.4/rest/tutorials/inventory/create-shipment.md index cd1d162697f..71ead0971e4 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-shipment.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-shipment.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 12. Create a shipment -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-shipment/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-shipment/ menu_title: Step 12. Create a shipment subtitle: Order processing with Inventory Management menu_order: 120 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-sources.md b/src/guides/v2.4/rest/tutorials/inventory/create-sources.md index 5915934583b..5a12be59239 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-sources.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-sources.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 2. Create sources -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-sources/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-sources/ subtitle: Order processing with Inventory Management menu_title: Step 2. Create sources menu_order: 20 @@ -23,7 +23,7 @@ This step guides you through the process of creating sources for your inventory, For more information about sources, see [Inventory Management overview]({{ page.baseurl }}/inventory/index.html). {:.bs-callout-info} -This step requires an admin token. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. +This step requires an admin token. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/) for more information. ## Create the first source diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-stock.md b/src/guides/v2.4/rest/tutorials/inventory/create-stock.md index 916dc69217e..8dd3399ef24 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-stock.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-stock.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 3. Create stocks -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-stock/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-stock/ subtitle: Order processing with Inventory Management menu_title: Step 3. Create stocks menu_order: 30 diff --git a/src/guides/v2.4/rest/tutorials/inventory/in-store-pickup.md b/src/guides/v2.4/rest/tutorials/inventory/in-store-pickup.md index 712b4e9593e..eeefae79265 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/in-store-pickup.md +++ b/src/guides/v2.4/rest/tutorials/inventory/in-store-pickup.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 14. Create an order for in-store pickup (optional) -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/in-store-pickup/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/in-store-pickup/ subtitle: Order processing with Inventory Management menu_title: Step 14. Bulk transfer products menu_order: 140 diff --git a/src/guides/v2.4/rest/tutorials/inventory/index.md b/src/guides/v2.4/rest/tutorials/inventory/index.md index 925c63ebfd2..8c7743480c9 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/index.md +++ b/src/guides/v2.4/rest/tutorials/inventory/index.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Order Processing with Inventory Management -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/index/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/ menu_title: Initial tasks menu_order: 0 level3_subgroup: msi-tutorial @@ -15,7 +15,7 @@ functional_areas: ### Before you begin -This tutorial builds upon the workflow described in the [Order Processing with REST APIs tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-intro.html). The Order Processing with Inventory Management tutorial provides additional steps that detail how to create stocks and sources, assign products to a custom source, and run the Source Selection Algorithms to recommend shipping options. +This tutorial builds upon the workflow described in the [Order Processing with REST APIs tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/). The Order Processing with Inventory Management tutorial provides additional steps that detail how to create stocks and sources, assign products to a custom source, and run the Source Selection Algorithms to recommend shipping options. For more information about key inventory features, see [Inventory Management overview]({{ page.baseurl }}/inventory/index.html). @@ -29,7 +29,7 @@ This **14-step tutorial** generally takes **1 hour**. * Know how to construct a REST call in Magento. See [Construct a request](https://developer.adobe.com/commerce/webapi/get-started/gs-web-api-request.html) for details. -* Obtain an admin authorization token. Multiple calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. +* Obtain an admin authorization token. Multiple calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/) for more information. ### Other resources diff --git a/src/guides/v2.4/rest/tutorials/inventory/prepare-for-checkout.md b/src/guides/v2.4/rest/tutorials/inventory/prepare-for-checkout.md index 7852d392ce6..6c07fb5b47d 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/prepare-for-checkout.md +++ b/src/guides/v2.4/rest/tutorials/inventory/prepare-for-checkout.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 8. Prepare for checkout -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/prepare-for-checkout/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/prepare-for-checkout/ subtitle: Order processing with Inventory Management menu_title: Step 8. Prepare for checkout menu_order: 80 diff --git a/src/guides/v2.4/rest/tutorials/inventory/reassign-products-to-another-source.md b/src/guides/v2.4/rest/tutorials/inventory/reassign-products-to-another-source.md index 7f53b58b677..e27a06eb9ce 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/reassign-products-to-another-source.md +++ b/src/guides/v2.4/rest/tutorials/inventory/reassign-products-to-another-source.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 5. Reassign products to custom sources -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/reassign-products-to-another-source/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/reassign-products-to-another-source/ subtitle: Order processing with Inventory Management menu_title: Step 5. Reassign products to custom sources menu_order: 50 diff --git a/src/guides/v2.4/rest/tutorials/inventory/run-ssa.md b/src/guides/v2.4/rest/tutorials/inventory/run-ssa.md index 91aab43717e..3d27858f0a0 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/run-ssa.md +++ b/src/guides/v2.4/rest/tutorials/inventory/run-ssa.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 11. Run the Source Selection Algorithms -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/run-ssa/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/run-ssa/ subtitle: Order processing with Inventory Management menu_title: Step 11. Run the Source Selection Algorithms menu_order: 110 @@ -60,7 +60,7 @@ Not applicable ## Run an SSA -The `POST V1/inventory/source-selection-algorithm-result` endpoint uses the algorithm defined by the `algorithmCode` attribute to calculate the recommended sources and quantities for each item defined in the `items` array. In this example, we'll select the `priority` SSA. [Manage source selection algorithms](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-source-selection.html) includes an example using the `distance` priority. +The `POST V1/inventory/source-selection-algorithm-result` endpoint uses the algorithm defined by the `algorithmCode` attribute to calculate the recommended sources and quantities for each item defined in the `items` array. In this example, we'll select the `priority` SSA. [Manage source selection algorithms](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/) includes an example using the `distance` priority. This tutorial does not consider complications, such as selling out of products or back ordering. We can ask the SSA to determine the best way to immediately ship all the items ordered (40 items of product `24-WB01` and 20 items of product `24-WB03`). If the `shippable` attribute in the response is `false`, there are not enough salable items to complete a full shipment, but the merchant can still perform a partial shipment. diff --git a/src/guides/v2.4/rest/tutorials/orders/order-admin-token.md b/src/guides/v2.4/rest/tutorials/orders/order-admin-token.md index e9f29ed8e77..8c05170bd7f 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-admin-token.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-admin-token.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 2. Get the admin token -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-admin-token/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-admin-token/ subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-config-store.md b/src/guides/v2.4/rest/tutorials/orders/order-config-store.md index 0d7cb1c817c..f3bd17e74a9 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-config-store.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-config-store.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 1. Configure the store -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-config-store/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-config-store/ subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-intro.md b/src/guides/v2.4/rest/tutorials/orders/order-intro.md index f533cd21220..a0c1ccf6d49 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-intro.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-intro.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Order processing tutorial -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-intro/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/ menu_title: Initial tasks return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md b/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md index 0247e8caaec..594a58027a0 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md @@ -2,7 +2,7 @@ layout: tutorial group: rest-api title: Step 10. Issue a partial refund -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/order-issue-refund/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-issue-refund/ subtitle: Order processing tutorial return_to: title: REST tutorials @@ -83,6 +83,6 @@ Log in to [Admin](https://glossary.magento.com/admin). Click **Sales** > **Credi Related topics * [Getting Started with Magento Web APIs](https://developer.adobe.com/commerce/webapi/get-started/bk-get-started-api.html) -* [Create a configurable product Tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/config-product-intro.html) -* [REST API Reference Overview](https://developer.adobe.com/commerce/webapi/rest/bk-rest.html) +* [Create a configurable product Tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/) +* [REST API Reference Overview](https://developer.adobe.com/commerce/webapi/rest/) * [REST API documentation]({{site.baseurl}}/redoc/{{page.guide_version}}/) diff --git a/src/guides/v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md b/src/guides/v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md index 623da8b78ba..d379d1d4c50 100644 --- a/src/guides/v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md +++ b/src/guides/v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md @@ -1,7 +1,7 @@ --- group: rest-api title: Generate the admin token -migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/create-admin-token/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/ functional_areas: - Integration - Orders From 404c24c987420eae827aebcb8b1185d276ab295b Mon Sep 17 00:00:00 2001 From: jhadobe Date: Wed, 22 Jun 2022 17:55:06 -0500 Subject: [PATCH 215/776] Fixing migrated_to links --- src/guides/v2.4/get-started/authentication/gs-authentication.md | 2 +- src/guides/v2.4/get-started/bk-get-started-api.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/guides/v2.4/get-started/authentication/gs-authentication.md b/src/guides/v2.4/get-started/authentication/gs-authentication.md index 445c36252b2..3a239832e9f 100644 --- a/src/guides/v2.4/get-started/authentication/gs-authentication.md +++ b/src/guides/v2.4/get-started/authentication/gs-authentication.md @@ -3,7 +3,7 @@ group: web-api title: Authentication functional_areas: - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication/ +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/authentication/ layout: migrated --- diff --git a/src/guides/v2.4/get-started/bk-get-started-api.md b/src/guides/v2.4/get-started/bk-get-started-api.md index 0198aba818c..1640ebb273c 100644 --- a/src/guides/v2.4/get-started/bk-get-started-api.md +++ b/src/guides/v2.4/get-started/bk-get-started-api.md @@ -8,7 +8,7 @@ menu_order: 1 menu_node: parent functional_areas: - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/get-started/bk-get-started-api/ +migrated_to: https://developer.adobe.com/commerce/webapi/get-started/ layout: migrated --- From 94417c744b6e3e4fc6cc5c1ee1ef49ce3766dca3 Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Thu, 23 Jun 2022 07:25:09 -0500 Subject: [PATCH 216/776] Fix migration link in upgrade tool --- src/upgrade-compatibility-tool/run.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/upgrade-compatibility-tool/run.md b/src/upgrade-compatibility-tool/run.md index 4dc3e636be6..0762a665db0 100644 --- a/src/upgrade-compatibility-tool/run.md +++ b/src/upgrade-compatibility-tool/run.md @@ -6,7 +6,7 @@ redirect_from: - /safe-upgrade-tool/run.html functional_areas: - Upgrade -migrated_to: https://experienceleague.adobe.com/docs/commerce-operations/upgrade-guide/upgrade-compatibility-tool/run.html +migrated_to: https://experienceleague.adobe.com/docs/commerce-operations/upgrade-guide/upgrade-compatibility-tool/use-upgrade-compatibility-tool/run.html layout: migrated --- From 3240a9e20a08fcb70112e181018161f946d4c049 Mon Sep 17 00:00:00 2001 From: jfrontain Date: Thu, 23 Jun 2022 11:50:32 -0500 Subject: [PATCH 217/776] updated number of fixed issues in security release notes --- src/guides/v2.3/release-notes/2-3-7-p4.md | 2 +- src/guides/v2.4/release-notes/2-4-3-p3.md | 2 +- src/guides/v2.4/release-notes/2-4-4-p1.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/guides/v2.3/release-notes/2-3-7-p4.md b/src/guides/v2.3/release-notes/2-3-7-p4.md index e7fa0a836c6..53cbdbc5f27 100644 --- a/src/guides/v2.3/release-notes/2-3-7-p4.md +++ b/src/guides/v2.3/release-notes/2-3-7-p4.md @@ -3,7 +3,7 @@ group: release-notes title: Adobe Commerce 2.3.7-p4 Release Notes --- -{{ site.data.var.ee }} 2.3.7-p4 provides 16 security fixes that enhance your {{ site.data.var.ee }} 2.3.7 or {{ site.data.var.ce }} 2.3.7 deployment. It provides fixes for vulnerabilities that have been identified in the previous release ({{ site.data.var.ee }} 2.3.7-p3). +{{ site.data.var.ee }} 2.3.7-p4 provides 15 security fixes that enhance your {{ site.data.var.ee }} 2.3.7 or {{ site.data.var.ce }} 2.3.7 deployment. It provides fixes for vulnerabilities that have been identified in the previous release ({{ site.data.var.ee }} 2.3.7-p3). {:.bs-callout-info} PHP 7.3 reached end of support in December 2021, and {{ site.data.var.ee }} 2.3.x and {{ site.data.var.ce }} 2.3.x will reach end of support in September 2022. **We strongly recommend planning your upgrade now to {{ site.data.var.ee }} 2.4.x or {{ site.data.var.ce }} 2.4.x deployment to help maintain PCI compliance**. diff --git a/src/guides/v2.4/release-notes/2-4-3-p3.md b/src/guides/v2.4/release-notes/2-4-3-p3.md index 6a098979c2e..ce431ce7f52 100644 --- a/src/guides/v2.4/release-notes/2-4-3-p3.md +++ b/src/guides/v2.4/release-notes/2-4-3-p3.md @@ -3,7 +3,7 @@ group: release-notes title: Adobe Commerce 2.4.3-p3 Release Notes --- -{{ site.data.var.ee }} 2.4.3-p3 is a security release that provides 18 security fixes that enhance your {{ site.data.var.ee }} 2.4.3 or {{ site.data.var.ce }} 2.4.3 deployment. It provides fixes for vulnerabilities that have been identified in the previous release ({{ site.data.var.ee }} 2.4.3 and {{ site.data.var.ce }} 2.4.3). +{{ site.data.var.ee }} 2.4.3-p3 is a security release that provides 17 security fixes that enhance your {{ site.data.var.ee }} 2.4.3 or {{ site.data.var.ce }} 2.4.3 deployment. It provides fixes for vulnerabilities that have been identified in the previous release ({{ site.data.var.ee }} 2.4.3 and {{ site.data.var.ce }} 2.4.3). {:.bs-callout-info} Releases may contain backward-incompatible changes (BIC). To review minor backward-incompatible changes, see [BIC reference]({{page.baseurl}}/release-notes/backward-incompatible-changes/reference.html). (Major backward-incompatible issues are described in [BIC highlights]({{page.baseurl}}/release-notes/backward-incompatible-changes/index.html). Not all releases introduce major BICs.) diff --git a/src/guides/v2.4/release-notes/2-4-4-p1.md b/src/guides/v2.4/release-notes/2-4-4-p1.md index 6b290f514e5..e52577597f3 100644 --- a/src/guides/v2.4/release-notes/2-4-4-p1.md +++ b/src/guides/v2.4/release-notes/2-4-4-p1.md @@ -3,7 +3,7 @@ group: release-notes title: Adobe Commerce 2.4.4-p1 Release Notes --- -{{ site.data.var.ee }} 2.4.4-p1 is a security release that provides 18 security fixes that enhance your {{ site.data.var.ee }} 2.4.4 or {{ site.data.var.ce }} 2.4.4 deployment. It provides fixes for vulnerabilities that have been identified in the previous release ({{ site.data.var.ee }} 2.4.4 and {{ site.data.var.ce }} 2.4.4). +{{ site.data.var.ee }} 2.4.4-p1 is a security release that provides 17 security fixes that enhance your {{ site.data.var.ee }} 2.4.4 or {{ site.data.var.ce }} 2.4.4 deployment. It provides fixes for vulnerabilities that have been identified in the previous release ({{ site.data.var.ee }} 2.4.4 and {{ site.data.var.ce }} 2.4.4). {:.bs-callout-info} Releases may contain backward-incompatible changes (BIC). To review minor backward-incompatible changes, see [BIC reference]({{page.baseurl}}/release-notes/backward-incompatible-changes/reference.html). (Major backward-incompatible issues are described in [BIC highlights]({{page.baseurl}}/release-notes/backward-incompatible-changes/index.html). Not all releases introduce major BICs.) From fb108cb4c4542838291cd43570b1366cdf639198 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Thu, 23 Jun 2022 15:32:29 -0500 Subject: [PATCH 218/776] Fixed migrated_to link --- .../templates/template-email-layout-handle.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/frontend-dev-guide/templates/template-email-layout-handle.md b/src/guides/v2.4/frontend-dev-guide/templates/template-email-layout-handle.md index 886b2e450cb..6e0b47cb89f 100644 --- a/src/guides/v2.4/frontend-dev-guide/templates/template-email-layout-handle.md +++ b/src/guides/v2.4/frontend-dev-guide/templates/template-email-layout-handle.md @@ -3,7 +3,7 @@ group: frontend-developer-guide title: Email templates layout handle functional_areas: - Frontend -migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/templates/email-migration/ +migrated_to: https://developer.adobe.com/commerce/frontend-core/guide/templates/email-layout-handle/ layout: migrated --- From 01c57dfc99fe5cee1823ac312797c385764a76a9 Mon Sep 17 00:00:00 2001 From: magedocs Date: Mon, 27 Jun 2022 14:38:51 +0000 Subject: [PATCH 219/776] Update News data --- src/_data/whats-new.yml | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/_data/whats-new.yml b/src/_data/whats-new.yml index b2e9bf88def..62398ff43a3 100644 --- a/src/_data/whats-new.yml +++ b/src/_data/whats-new.yml @@ -4,8 +4,34 @@ description: This page contains recent changes that we think you'd like to know We exclude from this list proofreading, spelling checks, and all minor updates. link: "/whats-new.html" thread: "/whatsnew-feed.xml" -updated: Mon Jun 20 14:38:46 2022 +updated: Mon Jun 27 14:38:49 2022 entries: +- description: The [Frontend Developer Guide](https://devdocs.magento.com/guides/v2.4/frontend-dev-guide/bk-frontend-dev-guide.html) + topics moved to the [Adobe Developer documentation](https://developer.adobe.com/commerce/frontend-core/guide/) + and will be redirected soon. + versions: 2.4.x + type: Major Update + date: June 23, 2022 + link: https://github.com/magento-commerce/devdocs/pull/3028 + merge_commit: 0ef38846fef7b6081985a05b000eeda384033b4d + contributor: jeff-matthews + membership: true + labels: + - Major Update + - 2.4.x + - migration +- description: Added descriptions and examples of using [built-in PHP attributes](https://devdocs.magento.com/guides/v2.4/test/integration/attributes.html) + for testing. + versions: 2.4.x + type: New Topic + date: June 21, 2022 + link: https://github.com/magento-commerce/devdocs/pull/3009 + merge_commit: 6876de966855ce4012d5af61975a0d8ce14aa792 + contributor: thiaramus + membership: true + labels: + - New Topic + - 2.4.x - description: The following PHP tutorials moved to the [Adobe Developer documentation](https://developer.adobe.com/commerce/php/best-practices/) and will be redirected soon:
    - [Custom attributes](https://devdocs.magento.com/guides/v2.4/howdoi/custom-attributes/introduction.html)
    - [Customize product creation form](https://devdocs.magento.com/guides/v2.4/howdoi/customize_product.html)
    - From 155938dc69db757be1f7da8db5471a790e56eae0 Mon Sep 17 00:00:00 2001 From: jhadobe Date: Tue, 28 Jun 2022 12:11:31 -0400 Subject: [PATCH 220/776] Breaking symlinks --- .../v2.4/rest/anonymous-api-security.md | 108 +- .../v2.4/rest/asynchronous-web-endpoints.md | 110 +- src/guides/v2.4/rest/bulk-endpoints.md | 160 +- src/guides/v2.4/rest/generate-local.md | 2 +- .../v2.4/rest/modules/catalog-pricing.md | 604 ++++++- src/guides/v2.4/rest/modules/catalog.md | 143 +- .../rest/modules/inventory/bulk-inventory.md | 181 +- .../modules/inventory/link-stocks-sources.md | 204 ++- .../modules/inventory/manage-low-quantity.md | 125 +- .../inventory/manage-source-selection.md | 302 +++- .../rest/modules/inventory/manage-stocks.md | 211 ++- src/guides/v2.4/rest/modules/sales/refunds.md | 48 +- src/guides/v2.4/rest/notes.md | 165 +- .../v2.4/rest/operation-status-endpoints.md | 154 +- .../v2.4/rest/operation-status-search.md | 127 +- src/guides/v2.4/rest/performing-searches.md | 278 ++- .../v2.4/rest/retrieve-filtered-responses.md | 196 +- src/guides/v2.4/rest/search-endpoint.md | 144 +- .../config-product-intro.md | 38 +- .../create-configurable-simple-products.md | 320 +++- .../create-personalization-option.md | 81 +- .../define-config-product-options.md | 168 +- .../bulk-configurable-product/plan-product.md | 147 +- .../bundle-product/bundle-product-intro.md | 23 +- .../bundle-product/create-bundle-product.md | 312 +++- .../bundle-product/create-simple-products.md | 577 +++++- .../tutorials/bundle-product/plan-product.md | 197 +- .../config-product-intro.md | 35 +- .../create-configurable-product.md | 223 ++- .../create-personalization-option.md | 80 +- .../create-simple-products.md | 239 ++- .../define-config-product-options.md | 113 +- .../configurable-product/plan-product.md | 226 ++- .../create-and-manage-grouped-products.md | 251 ++- src/guides/v2.4/rest/tutorials/index.md | 2 +- .../v2.4/rest/tutorials/inventory/index.md | 2 +- .../rest/tutorials/orders/order-add-items.md | 432 ++++- .../tutorials/orders/order-create-customer.md | 165 +- .../tutorials/orders/order-create-invoice.md | 298 +++- .../tutorials/orders/order-create-order.md | 1586 ++++++++++++++++- .../tutorials/orders/order-create-quote.md | 68 +- .../tutorials/orders/order-create-shipment.md | 81 +- .../v2.4/rest/tutorials/orders/order-intro.md | 2 +- .../orders/order-prepare-checkout.md | 358 +++- 44 files changed, 9242 insertions(+), 44 deletions(-) mode change 120000 => 100644 src/guides/v2.4/rest/anonymous-api-security.md mode change 120000 => 100644 src/guides/v2.4/rest/asynchronous-web-endpoints.md mode change 120000 => 100644 src/guides/v2.4/rest/bulk-endpoints.md mode change 120000 => 100644 src/guides/v2.4/rest/modules/catalog-pricing.md mode change 120000 => 100644 src/guides/v2.4/rest/modules/catalog.md mode change 120000 => 100644 src/guides/v2.4/rest/modules/inventory/bulk-inventory.md mode change 120000 => 100644 src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md mode change 120000 => 100644 src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md mode change 120000 => 100644 src/guides/v2.4/rest/modules/inventory/manage-source-selection.md mode change 120000 => 100644 src/guides/v2.4/rest/modules/inventory/manage-stocks.md mode change 120000 => 100644 src/guides/v2.4/rest/modules/sales/refunds.md mode change 120000 => 100644 src/guides/v2.4/rest/notes.md mode change 120000 => 100644 src/guides/v2.4/rest/operation-status-endpoints.md mode change 120000 => 100644 src/guides/v2.4/rest/operation-status-search.md mode change 120000 => 100644 src/guides/v2.4/rest/performing-searches.md mode change 120000 => 100644 src/guides/v2.4/rest/retrieve-filtered-responses.md mode change 120000 => 100644 src/guides/v2.4/rest/search-endpoint.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/orders/order-add-items.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/orders/order-create-customer.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/orders/order-create-order.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/orders/order-create-quote.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md mode change 120000 => 100644 src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md diff --git a/src/guides/v2.4/rest/anonymous-api-security.md b/src/guides/v2.4/rest/anonymous-api-security.md deleted file mode 120000 index b80e4fdde0e..00000000000 --- a/src/guides/v2.4/rest/anonymous-api-security.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/rest/anonymous-api-security.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/anonymous-api-security.md b/src/guides/v2.4/rest/anonymous-api-security.md new file mode 100644 index 00000000000..970ce3a2541 --- /dev/null +++ b/src/guides/v2.4/rest/anonymous-api-security.md @@ -0,0 +1,107 @@ +--- +group: rest-api +title: Restricting access to anonymous web APIs + +--- + +Magento 2 allows some web APIs to be accessed by unauthenticated (anonymous) users. Many of these APIs allow a customer to have a robust shopping experience on the [website](https://glossary.magento.com/website) without having to log in. + +A subset of these APIs can return information about products, promotions, and storefronts that a merchant might consider proprietary. For example, [Catalog](https://glossary.magento.com/catalog) [module](https://glossary.magento.com/module) APIs can provide information about an item’s pricing and quantity, as well as items that are currently not for sale. The [CMS](https://glossary.magento.com/cms) module could reveal information about upcoming promotional landing pages and coupons. The Store module can reveal too much information about individual websites. + +For this reason, by default, Magento 2 now prevents anonymous users from accessing the APIs that could reveal sensitive information. When the feature is enabled, the user must have administrator privileges to execute the affected APIs. + +The following table lists the APIs that are no longer available to an anonymous user by default: + +| Product | Module | API | Action | +| --- | --- | --- | --- | +| Open Source | Catalog | /V1/products | GET | +| Open Source | Catalog | /V1/products/:sku | GET | +| Open Source | Catalog | /V1/products/attributes/:attributeCode | GET | +| Open Source | Catalog | /V1/products/types | GET | +| Open Source | Catalog | /V1/products/attribute-sets/sets/list | GET | +| Open Source | Catalog | /V1/products/attribute-sets/:attributeSetId | GET | +| Open Source | Catalog | /V1/products/attribute-sets/:attributeSetId/attributes | GET | +| Open Source | Catalog | /V1/products/attribute-sets/groups/list | GET | +| Open Source | Catalog | /V1/products/attributes/:attributeCode/options | GET | +| Open Source | Catalog | /V1/products/media/types/:attributeSetName | GET | +| Open Source | Catalog | /V1/products/:sku/media/:entryId | GET | +| Open Source | Catalog | /V1/products/:sku/media | GET | +| Open Source | Catalog | /V1/products/:sku/group-prices/:customerGroupId/tiers | GET | +| Open Source | Catalog | /V1/categories/:categoryId | GET | +| Open Source | Catalog | /V1/categories | GET | +| Open Source | Catalog | /V1/products/:sku/options | GET | +| Open Source | Catalog | /V1/products/:sku/options/:optionId | GET | +| Open Source | Catalog | /V1/products/links/types | GET | +| Open Source | Catalog | /V1/products/links/:type/attributes | GET | +| Open Source | Catalog | /V1/products/:sku/links/:type | GET | +| Open Source | Catalog | /V1/categories/:categoryId/products | GET | +| Open Source | CatalogInventory | /V1/stockStatuses/:productSku | GET | +| Open Source | Cms | /V1/cmsPage/:pageId | GET | +| Open Source | Cms | /V1/cmsBlock/:blockId | GET | +| Open Source | ConfigurableProduct | /V1/configurable-products/:sku/children | GET | +| Open Source | ConfigurableProduct | /V1/configurable-products/:sku/options/:id | GET | +| Open Source | ConfigurableProduct | /V1/configurable-products/:sku/options/all | GET | +| Open Source | Store | /V1/store/storeViews | GET | +| Open Source | Store | /V1/store/storeGroups | GET | +| Open Source | Store | /V1/store/websites | GET | +| Open Source | Store | /V1/store/storeConfigs | GET | + +{% +include note.html +type='warning' +content='Preventing anonymous access to these endpoints could cause third-party integrations to fail. If a third-party integration calls any of these endpoints, it will receive an authentication error instead of the expected response. In this case, you might need to disable this feature. + +To disable this feature, log in to the Admin panel and navigate to **Stores** > **Settings** > **Configuration** > **Services** > **Magento Web API** > **Web API Security**. Then select **Yes** from the **Allow Anonymous Guest Access** menu.' +%} + +If the list of APIs that are inaccessible to anonymous users must be updated for a third-party extension, an integrator can add to their extension's `di.xml` file to update or replace the functionality defined in the WebapiSecurity module. + +The following APIs remain accessible to anonymous users. Most of these must remain accessible to support the [checkout](https://glossary.magento.com/checkout) and add-to-cart Ajax functionalities. + +| Product | Module | API | Action | +| --- | --- | --- | --- | +| Open Source | Catalog | /V1/products-render-info | GET | +| Open Source | Checkout | /V1/guest-carts/:cartId/payment-information | POST | +| Open Source | Checkout | /V1/guest-carts/:cartId/payment-information | GET | +| Open Source | Checkout | /V1/guest-carts/:cartId/set-payment-information | POST | +| Open Source | Checkout | /V1/guest-carts/:cartId/shipping-information | POST | +| Open Source | Checkout | /V1/guest-carts/:cartId/totals-information | POST | +| Open Source | Customer | /V1/customers | POST | +| Open Source | Customer | /V1/customers/:customerId/password/resetLinkToken/:resetPasswordLinkToken | GET | +| Open Source | Customer | /V1/customers/password | PUT | +| Open Source | Customer | /V1/customers/resetPassword | POST | +| Open Source | Customer | /V1/customers/isEmailAvailable | POST | +| Open Source | Directory | /V1/directory/countries | GET | +| Open Source | Directory | /V1/directory/countries/:countryId | GET | +| Open Source | Directory | /V1/directory/currency | GET | +| Open Source | GiftMessage | /V1/guest-carts/:cartId/gift-message | GET | +| Open Source | GiftMessage | /V1/guest-carts/:cartId/gift-message | POST | +| Open Source | GiftMessage | /V1/guest-carts/:cartId/gift-message/:itemId | GET | +| Open Source | GiftMessage | /V1/guest-carts/:cartId/gift-message/:itemId | POST | +| Open Source | Integration | /V1/integration/admin/token | POST | +| Open Source | Integration | /V1/integration/customer/token | POST | +| Open Source | Quote | /V1/guest-carts/:cartId/billing-address | GET | +| Open Source | Quote | /V1/guest-carts/:cartId/billing-address | POST | +| Open Source | Quote | /V1/guest-carts/:cartId/items | GET | +| Open Source | Quote | /V1/guest-carts/:cartId/items | POST | +| Open Source | Quote | /V1/guest-carts/:cartId/items/:itemId | PUT | +| Open Source | Quote | /V1/guest-carts/:cartId/items/:itemId | DELETE | +| Open Source | Quote | /V1/guest-carts | POST | +| Open Source | Quote | /V1/guest-carts/:cartId/order | PUT | +| Open Source | Quote | /V1/guest-carts/:cartId | GET | +| Open Source | Quote | /V1/guest-carts/:cartId/collect-totals | PUT | +| Open Source | Quote | /V1/guest-carts/:cartId/totals | GET | +| Open Source | Quote | /V1/guest-carts/:cartId/coupons | GET | +| Open Source | Quote | /V1/guest-carts/:cartId/coupons/:couponCode | PUT | +| Open Source | Quote | /V1/guest-carts/:cartId/coupons | DELETE | +| Open Source | Quote | /V1/guest-carts/:cartId/selected-payment-method | GET | +| Open Source | Quote | /V1/guest-carts/:cartId/selected-payment-method | PUT | +| Open Source | Quote | /V1/guest-carts/:cartId/payment-methods | GET | +| Open Source | Quote | /V1/guest-carts/:cartId/estimate-shipping-methods | POST | +| Open Source | Quote | /V1/guest-carts/:cartId/shipping-methods | GET | +| Open Source | Search | /V1/search | GET | +| Commerce | GiftCardAccount | /V1/carts/guest-carts/:cartId/giftCards/:giftCardCode | DELETE | +| Commerce | GiftCardAccount | /V1/carts/guest-carts/:cartId/giftCards | POST | +| Commerce | GiftCardAccount | /V1/carts/guest-carts/:cartId/checkGiftCard/:giftCardCode | GET | +| Commerce | GiftRegistry | /V1/guest-giftregistry/:cartId/estimate-shipping-methods | POST | +| Commerce | WorldPay | /V1/worldpay-guest-carts/:cartId/payment-information | POST diff --git a/src/guides/v2.4/rest/asynchronous-web-endpoints.md b/src/guides/v2.4/rest/asynchronous-web-endpoints.md deleted file mode 120000 index c33ea1280a4..00000000000 --- a/src/guides/v2.4/rest/asynchronous-web-endpoints.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/rest/asynchronous-web-endpoints.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/asynchronous-web-endpoints.md b/src/guides/v2.4/rest/asynchronous-web-endpoints.md new file mode 100644 index 00000000000..53e58957b8d --- /dev/null +++ b/src/guides/v2.4/rest/asynchronous-web-endpoints.md @@ -0,0 +1,109 @@ +--- +group: rest-api +title: Asynchronous web endpoints + +contributor_name: comwrap GmbH +contributor_link: http://comwrap.com/ +functional_areas: + - Integration +--- + +An asynchronous web endpoint intercepts messages to a Web API and writes them to the message queue. Each time the system accepts such an API request, it generates a UUID identifier. Magento includes this UUID when it adds the message to the queue. Then, a consumer reads the messages from the queue and executes them one-by-one. + +{:.bs-callout-tip} +Use the `bin/magento queue:consumers:start async.operations.all` command to start the consumer that handles asynchronous and bulk API messages. + +Magento supports the following types of asynchronous requests: + +* POST +* PUT +* DELETE +* PATCH + +{:.bs-callout-info} +GET requests are not supported. Although Magento does not currently implement any PATCH requests, they are supported in custom extensions. + +The route to all asynchronous calls contains the prefix `/async`, added before `/V1` of a standard synchronous endpoint. For example: + +```http +POST /async/V1/products +PUT /async/V1/products/:sku +``` + +{{site.data.var.ce}} and {{site.data.var.ee}} installations support asynchronous web endpoints. + +The [REST API documentation](https://developer.adobe.com/commerce/webapi/rest/) provides a list of all current synchronous Magento API routes. + +The response of an asynchronous request contains the following fields: + +Field name | Data type | Description +--- | --- | --- +`bulk_uuid` | String | A generated universally unique identifier. +`request_items` | Object | An array containing information about the status of the asynchronous request. +`id` | Integer | A generated ID that identifies the request. +`data_hash` | String | SHA256 encoded content of incoming message. +`status` | String | Reserved for future use. Currently, the value is always `accepted`. +`errors` | Boolean | Reserved for future use. Currently, the value is always `false`. If an error occurs, the system provides all error-related information as a standard `webapi` exception. + +## Sample usage + +The following call asynchronously changes the price of the product that has a `sku` of `24-MB01`: + +```http +PUT /rest//async/V1/products/24-MB01 +``` + +## Payload + +```json +{ + "product": { + "price": 29 + } +} +``` + +## Response + +Magento generates a `bulk_uuid` for each asynchronous request. Use the `bulk_uuid` to determine the [operation status](https://developer.adobe.com/commerce/webapi/rest/operation-status-endpoints.html) of your request. + +```json +{ + "bulk_uuid": "fbfca270-7a90-4c4e-9f32-d6cf3728cdc7", + "request_items": [ + { + "id": 0, + "data_hash": "9c1bd4bfd8defcc856ddf129cc01d172625d139d5f7dcf53b6cb09a0e9a843a3", + "status": "accepted" + } + ], + "errors": false +} +``` + +## Store scopes + +You can specify a store code (which is labeled in the Admin as store view code) in the route of an asynchronous endpoint so that it operates on a specific store, as shown below: + +```http +POST //async/V1/products +PUT //async/V1/products/:sku +``` + +As a result, the asynchronous calls update the products on the specific store, instead of the default store. + +You can specify the `all` store code to perform operations on all existing stores: + +```http +POST /all/async/V1/products +PUT /all/async/V1/products/:sku +``` + +### Fallback and creating/updating objects when setting store scopes + +The following rules apply when you create or update an object, such as a product. + +* If you do not set the store code while creating a new product, Magento creates a new object with all values set globally for each scope. +* If you do not set the store code while updating a product, then by fallback, Magento updates values for the default store only. +* If you include the `all` parameter, then Magento updates values for all store scopes (in case a particular store doesn't yet have its own value set). +* If `` parameter is set, then values for only defined store will be updated. diff --git a/src/guides/v2.4/rest/bulk-endpoints.md b/src/guides/v2.4/rest/bulk-endpoints.md deleted file mode 120000 index 59882d27f19..00000000000 --- a/src/guides/v2.4/rest/bulk-endpoints.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/rest/bulk-endpoints.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/bulk-endpoints.md b/src/guides/v2.4/rest/bulk-endpoints.md new file mode 100644 index 00000000000..a3cb54768f9 --- /dev/null +++ b/src/guides/v2.4/rest/bulk-endpoints.md @@ -0,0 +1,159 @@ +--- +group: rest-api +title: Bulk endpoints + +contributor_name: comwrap GmbH +contributor_link: http://comwrap.com/ +functional_areas: + - Integration +--- + +Bulk API endpoints differ from other REST endpoints in that they combine multiple calls of the same type into an array and execute them as a single request. The endpoint handler splits the array into individual entities and writes them as separate messages to the message queue. + +{:.bs-callout-info} +Use the [`bin/magento queue:consumers:start async.operations.all`]({{ page.baseurl }}/config-guide/cli/config-cli-subcommands-queue.html) command to start the consumer that handles asynchronous and bulk API messages. Also, before using the Bulk API to process messages, you must install and configure RabbitMQ, which is the default message broker. See [RabbitMQ]({{ page.baseurl }}/install-gde/prereq/install-rabbitmq.html). + +## Routes + +To call a bulk endpoint, add the prefix `/async/bulk` before the `/V1` of a synchronous endpoint route. For example: + +```http +POST /async/bulk/V1/products +POST /async/bulk/V1/customers +``` + +Endpoint routes that contain input parameters require additional changes. For example, `PUT /V1/products/:sku/media/:entryId` contains the `:sku` and `:entryId` input parameters. The route of a bulk request cannot contain input parameters, so you must change the route so that it does not contain any. To do this, replace the colon (`:`) with `by` and change the first letter of the parameter to uppercase. + +The following table provides several examples: + +Synchronous route | Bulk route +--- | --- +`PUT /V1/products/:sku/media/:entryId` | `PUT async/bulk/V1/products/bySku/media/byEntryId` +`POST /V1/carts/:quoteId/items` | `POST async/bulk/V1/carts/byQuoteId/items` + +{:.bs-callout-info} +GET requests are not supported. + +## Payloads + +The payload of a bulk request contains an array of request bodies. For example, the minimal payload for creating four customers with `POST /async/bulk/V1/customers` would be structured as follows: + +```json +[{ + "customer": { + "email": "mshaw@example.com", + "firstname": "Melanie Shaw", + "lastname": "Doe" + }, + "password": "Strong-Password" +}, +{ + "customer": { + "email": "bmartin@example.com", + "firstname": "Bryce", + "lastname": "Martin" + }, + "password": "Strong-Password" +}, +{ + "customer": { + "email": "bmartin@example.com", + "firstname": "Bryce", + "lastname": "Martin" + }, + "password": "Strong-Password" +}, +{ + "customer": { + "email": "tgomez@example.com", + "firstname": "Teresa", + "lastname": "Gomez" + }, + "password": "Strong-Password" +} +] +``` + +{:.bs-callout-tip} +The second and third requests are duplicates. + +## Responses + +The response contains an array that indicates whether the call successfully added each request to the message queue. Although the duplicated request to create a customer will fail, Magento added it to the message queue successfully. + +```json +{ + "bulk_uuid": "799a59c0-09ca-4d60-b432-2953986c1c38", + "request_items": [ + { + "id": 0, + "data_hash": "3d3d853839dd442d0b99a1badea756a03f19ffb0fb7aab672c05f83d5a914181", + "status": "accepted" + }, + { + "id": 1, + "data_hash": "bf8859d03545f0fa80084a47348a629cdf571fc064b952e7396c338d5cf3bf6e", + "status": "accepted" + }, + { + "id": 2, + "data_hash": "876f3f2e4b226d54dcbf3f5ce752a9f748a45310261d2dd5cc7a7c9ef74b4369", + "status": "accepted" + }, + { + "id": 3, + "data_hash": "9c1bd4bfd8defcc856ddf129cc01d172625d139d5f7dcf53b6cb09a0e9a843a3", + "status": "accepted" + } + ], + "errors": false +} +``` + +## DELETE requests + +The following call asynchronously deletes CMS blocks with IDs `1` and `2`: + +```http +DELETE /rest/async/bulk/V1/cmsPage/byPageId +``` + +### DELETE request payload + +```json +[ + { + "pageId": "1" + }, + { + "pageId": "2" + } +] +``` + +## Store scopes + +You can specify a store code (which is labeled in the Admin as store view code) in the route of an asynchronous endpoint so that it operates on a specific store, as shown below: + +```http +POST //async/bulk/V1/products +PUT //async/bulk/V1/products/bySku +``` + +As a result, the asynchronous calls update the products on the specific store, instead of the default store. + +You can specify the `all` store code to perform operations on all existing stores: + +```http +POST /all/async/bulk/V1/products +PUT /all/async/bulk/V1/products/bySku +``` + +## Fallback and creating/updating objects when setting store scopes + +The following rules apply when you create or update an object, such as a product. + +* If you do not set the store code while creating a new product, Magento creates a new object with all values set globally for each scope. +* If you do not set the store code while updating a product, then by fallback, Magento updates values for the default store only. +* If you include the `all` parameter, then Magento updates values for all store scopes (in case a particular store doesn't yet have its own value set). +* If `` parameter is set, then values for only defined store will be updated. diff --git a/src/guides/v2.4/rest/generate-local.md b/src/guides/v2.4/rest/generate-local.md index 0fbbef00b6b..bad81892004 100644 --- a/src/guides/v2.4/rest/generate-local.md +++ b/src/guides/v2.4/rest/generate-local.md @@ -1,7 +1,7 @@ --- group: rest-api title: Generate a local REST reference -migrated_to: https://developer.adobe.com/commerce/webapi/rest/generate-local/ +migrated_to: https://developer.adobe.com/commerce/webapi/quick_reference/rest/generate-local/ functional_areas: - Integration --- diff --git a/src/guides/v2.4/rest/modules/catalog-pricing.md b/src/guides/v2.4/rest/modules/catalog-pricing.md deleted file mode 120000 index bf8a965240d..00000000000 --- a/src/guides/v2.4/rest/modules/catalog-pricing.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/rest/modules/catalog-pricing.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/modules/catalog-pricing.md b/src/guides/v2.4/rest/modules/catalog-pricing.md new file mode 100644 index 00000000000..876f2047b99 --- /dev/null +++ b/src/guides/v2.4/rest/modules/catalog-pricing.md @@ -0,0 +1,603 @@ +--- +group: rest-api +title: Manage prices for multiple products + +functional_areas: + - Integration +--- + +Magento provides REST endpoints that allow you to update multiple special prices, tier prices, base prices, or cost values with a single call. + +The calls that update special and tier prices mimic the options available on a product's **Advanced Pricing** screen in Admin. + +## Manage special prices + +The `SpecialPriceStorageInterface` service provides the means to efficiently schedule special prices for one or more products in a store's catalog. When you use these calls, you do not provide detailed information about the product. + +The `POST /V1/products/special-price` call sets special prices for the following product types: + +* Simple +* Bundle +* Virtual +* Downloadable + +**Service Name:** + +`SpecialPriceStorageInterface` + +**REST Endpoints:** + +```http +POST /V1/products/special-price +POST /V1/products/special-price-information +POST /V1/products/special-price-delete +``` + +**SpecialPriceStorageInterface Parameters:** + +Name | Description | Format | Requirements +--- | --- | --- | --- +`price` | The special price of the product | float | Required for setting or deleting a special price +`store_id` | The store ID to apply the special price | integer | Required for setting or deleting a special price +`sku` | The SKU of the product | string | Required for setting or deleting a special price +`skus` | An array of SKU values that is specified when retrieving a list of special prices | array | Required for retrievals +`price_from` | The date and time the special price goes into effect. The date/time format is `YYYY-MM-DD hh:mm:ss`. The specified time must be later than the current time. | string | Required in {{site.data.var.ee}}. Optional in {{site.data.var.ce}}. +`price_to` | The date and time the special price ends. The date/time format is `YYYY-MM-DD hh:mm:ss` If no value is specified, the special price does not expire. | string | Required in {{site.data.var.ee}}. Optional in {{site.data.var.ce}}. + +### Set special prices + +All calls to set special prices must include the `store_id`, `sku`, and `price` parameters. If the call is sent to an {{site.data.var.ee}} installation, the call must also include the `price_from` parameter. If the call is sent to a {{site.data.var.ce}} installation, then the `price_from` parameter is optional. + +For bundled products, the value of the `price` parameter must be expressed as a discount percentage. + +You can set multiple special prices in a single call, as shown in the example below. The call sets special prices for a simple product, downloadable product, and bundle product for two days. + +**Sample Usage:** + +`POST /rest//V1/products/special-price` + +**Payload:** + +```json +{ + "prices": [ + { + "price": 29.95, + "store_id": 0, + "price_from": "2017-07-15 00:00:00", + "price_to": "2017-07-16 23:59:59", + "sku": "24-WB06" + }, + { + "price": 19.95, + "store_id": 0, + "price_from": "2017-07-15 00:00:00", + "price_to": "2017-07-16 23:59:59", + "sku": "240-LV06" + }, + { + "price": 5, + "store_id": 0, + "price_from": "2017-07-15 00:00:00", + "price_to": "2017-07-16 23:59:59", + "sku": "24-WG080" + } + ] +} + +``` + +**Response:** + +`[]` (an empty array) + +### Get special prices + +The following call returns the special price information for three SKU values. + +**Sample Usage:** + +`POST /rest//V1/products/special-price-information` + +**Payload:** + +```json +{ + "skus": [ + "24-WB06", + "240-LV06", + "24-WG080" + ] +} +``` + +**Response:** + +```json +[ + { + "price": 29.949999999999999, + "store_id": 0, + "sku": "24-WB06", + "price_from": "2017-07-15 00:00:00", + "price_to": "2017-07-16 23:59:59" + }, + { + "price": 19.949999999999999, + "store_id": 0, + "sku": "240-LV06", + "price_from": "2017-07-15 00:00:00", + "price_to": "2017-07-16 23:59:59" + }, + { + "price": 5, + "store_id": 0, + "sku": "24-WG080", + "price_from": "2017-07-15 00:00:00", + "price_to": "2017-07-16 23:59:59" + } +] +``` + +### Delete a special price + +If any item to be deleted has an invalid `price`, `store_id`, `sku` or `date`, Magento marks the item as failed and excludes it from the delete list. Valid items are deleted as requested. + +**Sample Usage:** + +`POST /rest//V1/products/special-price-delete` + +**Payload:** + +```json +{ + "prices": [ + { + "price": 29.95, + "store_id": 0, + "price_from": "2017-07-15 00:00:00", + "price_to": "2017-07-16 23:59:59", + "sku": "24-WB06" + }, + { + "price": 19.95, + "store_id": 0, + "price_from": "2017-07-15 00:00:00", + "price_to": "2017-07-16 23:59:59", + "sku": "240-LV06" + }, + { + "price": 5, + "store_id": 0, + "price_from": "2017-07-15 00:00:00", + "price_to": "2017-07-16 23:59:59", + "sku": "24-WG080" + } + ] +} +``` + +**Response:** + +`[]` (an empty array) + +## Manage tier prices + +Tier pricing offers a quantity discount to members of a specific customer group and website. The `TierPriceStorageInterface` service provides an efficient means to set tier prices for one or more products without requiring detailed information about each product. + +You can use REST endpoints to set tier prices for the following product types: + +Product type | Tier price types +--- | --- +Simple | fixed, discount +Bundle | discount +Virtual | fixed, discount +Downloadable | fixed, discount + +**Service Name:** + +`TierPriceStorageInterface` + +**REST Endpoints:** + +```http +POST /V1/products/tier-prices +PUT /V1/products/tier-prices +POST /V1/products/tier-prices-information +POST /V1/products/tier-prices-delete +``` + +**TierPriceStorageInterface Parameters:** + +Name | Description | Format | Requirements +--- | --- | --- | --- +`price` | The discounted product price for the quantity purchased | float | Required to set, update, or delete a tier price +`price_type` | Must be `fixed` (the set price) or `discount` (percent discount) | string | Required to set, update, or delete a tier price +`website_id` | The website ID to apply the tier price | integer | Required to set, update, or delete a tier price +`sku` | The SKU of the product | string | Required to set, update, or delete a tier price +`skus` | An array of SKU values that is specified when retrieving a list of tier prices | array | Required for retrievals +`customer_group` | A specific customer group that qualifies to receive the tier price discount | string | Required to set, update, or delete a tier price +`quantity` | The quantity that must be purchased to receive the tier price | float | Required to set, update, or delete a tier price + +### Set tier prices + +The `POST /V1/products/tier-prices` call adds new tier prices or updates existing prices. You can specify tier prices for multiple products in the same call. + +**Sample Usage:** + +`POST /rest//V1/products/tier-prices` + +**Payload:** + +```json + +{ + "prices": [ + { + "price": 10, + "price_type": "fixed", + "website_id": 0, + "sku": "24-UG04", + "customer_group": "General", + "quantity": 3 + }, + { + "price": 8, + "price_type": "fixed", + "website_id": 0, + "sku": "24-UG04", + "customer_group": "General", + "quantity": 5 + }, + { + "price": 6, + "price_type": "fixed", + "website_id": 0, + "sku": "24-UG04", + "customer_group": "General", + "quantity": 10 + } + ] +} +``` + +**Response:** + +`[]` (an empty array) + +### Replace existing tier prices + +The replace request removes all existing tier prices for a specified product and adds new rows for this same product instead. + +The following example removes the $10 tier price for `sku` 24-UG04 and changes the customer group for the `sku`'s other tier prices. + +**Sample Usage:** + +`PUT /rest//V1/products/tier-prices` + +**Payload:** + +```json +{ + "prices": [ + { + "price": 8, + "price_type": "fixed", + "website_id": 0, + "sku": "24-UG04", + "customer_group": "NOT LOGGED IN", + "quantity": 5 + }, + { + "price": 5, + "price_type": "fixed", + "website_id": 0, + "sku": "24-UG04", + "customer_group": "NOT LOGGED IN", + "quantity": 310 + } + ] +} +``` + +**Response:** + +`[]` (an empty array) + +### Get tier prices + +Magento returns all active tier prices for the specified list of `skus`. + +**Sample Usage:** + +`POST /rest//V1/products/tier-prices-information` + +**Payload:** + +```json +{ + "skus": [ + "24-UG04", + "24-UG01" + ] +} +``` + +**Response:** + +```json +[ + { + "price": 8, + "price_type": "fixed", + "website_id": 0, + "sku": "24-UG04", + "customer_group": "General", + "quantity": 5 + }, + { + "price": 6, + "price_type": "fixed", + "website_id": 0, + "sku": "24-UG04", + "customer_group": "General", + "quantity": 10 + }, + { + "price": 10, + "price_type": "fixed", + "website_id": 0, + "sku": "24-UG04", + "customer_group": "General", + "quantity": 3 + }, + { + "price": 5, + "price_type": "discount", + "website_id": 0, + "sku": "24-UG01", + "customer_group": "General", + "quantity": 3 + } +] +``` + +### Delete tier prices + +You must specify each tier price that is to be deleted. You can delete multiple tier prices in a single call. + +**Sample Usage:** + +`POST /rest//V1/products/tier-prices-delete` + +**Payload:** + +```json +{ + "prices": [ + { + "price": 10, + "price_type": "fixed", + "website_id": 0, + "sku": "24-UG04", + "customer_group": "General", + "quantity": 3 + } + ] +} +``` + +**Response:** + +`[]` (an empty array) + +## Manage base prices + +A base price is the price of a product, before any discounts or extra costs (such as shipping or taxes) are applied. The `BasePriceStorageInterface` service provides an efficient means to set base prices for one or more products without requiring detailed information about each product. + +{:.bs-callout-info} +You cannot delete a base price. It can only be changed to another value (0 or greater). + +**REST Endpoints:** + +```http +POST /V1/products/base-prices +POST /V1/products/base-prices-information +``` + +**BasePriceStorageInterface Parameters:** + +Name | Description | Format | Requirements +--- | --- | --- | --- +`price` | The base price of the item | float | Required to set a base price +`store_id` | The store ID to apply the base price | integer | Required to set a base price +`sku` | The SKU of the product | string | Required to set a base price +`skus` | An array of SKU values that is specified when retrieving a list of base prices | array | Required for retrievals + +### Set base prices + +The `POST /V1/products/base-price` call can set base prices for the following types of products: + +* Simple +* Virtual +* Downloadable +* Bundle (fixed price type only) + +The following example sets the base price for a simple and a downloadable product. + +**Sample Usage:** + +`POST /rest//V1/products/base-prices` + +**Payload:** + +```json +{ + "prices": [ + { + "price": 12, + "store_id": 0, + "sku": "24-UG04" + }, + { + "price": 22, + "store_id": 0, + "sku": "240-LV06" + } + ] +} +``` + +**Response:** + +`[]` (an empty array) + +### Get base prices + +The following example returns the base prices for a simple and a downloadable product. + +**Sample Usage:** + +`POST /rest//V1/products/base-prices-information` + +**Payload:** +```json +{ + "skus": [ + "24-UG04", + "240-LV06" + ] +} +``` + +**Response:** + +```json +[ + { + "price": 12, + "store_id": 0, + "sku": "24-UG04" + }, + { + "price": 22, + "store_id": 0, + "sku": "240-LV06" + } +] +``` + +## Manage cost values + +The cost is the actual cost of a product. Tracking costs is optional, but having this information available can be helpful when you are setting discounts. + +**REST Endpoints:** + +```http +POST /V1/products/cost +POST /V1/products/cost-information +POST /V1/products/cost-delete +``` + +**CostStorageInterface Parameters:** + +Name | Description | Format | Requirements +--- | --- | --- | --- +`cost` | The amount the item costs | float | Required to set or delete a cost value +`store_id` | The store ID to apply the cost value | integer | Required to set or delete a cost value +`sku` | The SKU of the product | string | Required to set or delete a cost value +`skus` | An array of SKU values that is specified when retrieving a list of cost values | array | Required for retrievals + +### Set cost values + +The `POST /V1/products/cost` call can set the cost values for the following types of products: + +* Simple +* Virtual +* Downloadable + +The following example sets the cost value for a simple and a downloadable product. + +**Sample Usage:** + +`POST /rest//V1/products/cost` + +**Payload:** + +```json +{ + "prices": [ + { + "cost": 18, + "store_id": 0, + "sku": "24-WB03" + }, + { + "cost": 2, + "store_id": 0, + "sku": "240-LV09" + } + ] +} +``` + +**Response:** + +`[]` (an empty array) + +### Get cost values + +The following example returns the cost values for a simple and a downloadable product. + +**Sample Usage:** + +`POST /rest//V1/products/cost-information` + +**Payload:** +```json +{ + "skus": [ + "24-WB03", + "240-LV09" + ] +} +``` + +**Response:** + +```json +[ + { + "cost": 18, + "store_id": 0, + "sku": "24-WB03" + }, + { + "cost": 2, + "store_id": 0, + "sku": "240-LV09" + } +] +``` + +### Delete cost values + +The following example deletes the previously-defined cost values for a simple and a downloadable product. + +**Sample Usage:** + +`POST /rest//V1/products/cost-delete` + +**Payload:** +```json +{ + "skus": [ + "24-WB03", + "240-LV09" + ] +} +``` + +**Response:** + +`true`, indicating the cost values were deleted diff --git a/src/guides/v2.4/rest/modules/catalog.md b/src/guides/v2.4/rest/modules/catalog.md deleted file mode 120000 index 3f06fe4c1f8..00000000000 --- a/src/guides/v2.4/rest/modules/catalog.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/rest/modules/catalog.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/modules/catalog.md b/src/guides/v2.4/rest/modules/catalog.md new file mode 100644 index 00000000000..0835da832c7 --- /dev/null +++ b/src/guides/v2.4/rest/modules/catalog.md @@ -0,0 +1,142 @@ +--- +group: rest-api +title: Catalog module + +functional_areas: + - Integration + - Catalog +--- + +The `Catalog` module provides functionality for creating and maintaining products and categories. + +## Categories + +When you create a [category](https://glossary.magento.com/category) from Admin, you have the option to configure display and [search engine optimization](https://glossary.magento.com/search-engine-optimization) settings. To configure these settings using `POST V1/categories`, you can specify the following parameters as `attribute_code` values: + +```text +all_children +children +children_count +custom_apply_to_products +custom_design +custom_design_from +custom_design_to +custom_layout_update +custom_use_parent_settings +default_sort_by +description +display_mode +filter_price_range +image +is_anchor +landing_page +meta_description +meta_keywords +meta_title +page_layout +path +path_in_store +url_key +url_path +``` + +Third-party modules may define other custom attributes. + +The following example uses the `POST V1/categories` call to assign four custom attributes to the "My New Category" category. + +## Request + +```json +{ + "category": { + "parent_id": 2, + "name": "Kids", + "is_active": true, + "level": 2, + "include_in_menu": true, + "custom_attributes": [ + { + "attribute_code": "description", + "value": "kids category description" + }, + { + "attribute_code": "meta_title", + "value": "Kids meta title" + }, + { + "attribute_code": "meta_keywords", + "value": "Kids meta keywords" + }, + { + "attribute_code": "meta_description", + "value": "Kids meta description" + }, + { + "attribute_code": "url_key", + "value": "kids" + }, + { + "attribute_code": "url_path", + "value": "kids" + } + ] + } +} +``` + +## Response + +```json +{ + "id": 42, + "parent_id": 2, + "name": "Kids", + "is_active": true, + "position": 9, + "level": 2, + "children": "", + "created_at": "2020-12-18 08:50:47", + "updated_at": "2020-12-18 08:50:47", + "path": "1/2/43", + "available_sort_by": [], + "include_in_menu": true, + "custom_attributes": [ + { + "attribute_code": "description", + "value": "kids category description" + }, + { + "attribute_code": "meta_title", + "value": "Kids meta title" + }, + { + "attribute_code": "meta_keywords", + "value": "Kids meta keywords" + }, + { + "attribute_code": "meta_description", + "value": "Kids meta description" + }, + { + "attribute_code": "is_anchor", + "value": "1" + }, + { + "attribute_code": "path", + "value": "1/2/43" + }, + { + "attribute_code": "children_count", + "value": "0" + }, + { + "attribute_code": "url_key", + "value": "kids" + }, + { + "attribute_code": "url_path", + "value": "kids" + } + ] +} +``` diff --git a/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md b/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md deleted file mode 120000 index d0454a7b995..00000000000 --- a/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/modules/inventory/bulk-inventory.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md b/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md new file mode 100644 index 00000000000..c6e38818c18 --- /dev/null +++ b/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md @@ -0,0 +1,180 @@ +--- +group: rest-api +title: Inventory mass actions + +--- + +Magento provides several endpoints that allow Multi Source merchants to make quick updates across multiple products. This is helpful for transferring inventory between sources and removing a source without editing each product individually. + +* The bulk transfer endpoint moves all quantities of products from one source to another. +* The bulk assign source endpoint adds sources to multiple products. +* The bulk unassign source endpoint removes sources from the products. Any inventory quantity assigned to that source is no longer available. + +**Service names:** + +```http +inventoryCatalogApiBulkInventoryTransferV1 +inventoryCatalogApiBulkPartialInventoryTransferV1 +inventoryCatalogApiBulkSourceAssignV1 +inventoryCatalogApiBulkSourceUnassignV1 +``` + +**REST endpoints:** + +```http +POST /V1/inventory/bulk-product-source-transfer +POST /V1/inventory/bulk-partial-source-transfer +POST /V1/inventory/bulk-product-source-assign +POST /V1/inventory/bulk-product-source-unassign +``` + +## Bulk transfer + +Multi Source merchants may need to transfer product inventory from one source location to another. For example, the merchant might decide to stop shipping specific products from a location or completely close the facility. In these cases, all operations for those products move to a new location. + +Bulk transfer allows you to specify multiple products, the origin source from which to transfer inventory, and the destination source to receive quantities. The bulk transfer process moves all product inventory from the origin source. Use [bulk partial transfer](#bulk-partial-transfer) to transfer specific quantities of one or more products. + + Unlike an unassign source action, Magento also retains product data by moving the status (in stock/out of stock), and the Notify Quantity from one source to another. If the origin and destination sources are in different stocks, performing a bulk transfer affects the aggregated Salable Quantity and reservations for in-progress orders. + +**Parameters:** + +Name | Description | Type | Requirements +--- | --- | --- | --- +`skus` | A comma-separated list of existing SKUs to transfer | Array | Required +`originSource` | The current source of the SKUs | String | Required +`destinationSource` | The target source for the SKUs. This source must be already defined. | String | Required +`unassignFromOrigin` | If `true`, the current source is removed as a source for the products. If `false`, the original source is retained, but the products are marked as being out of stock with a quantity of 0. | Boolean | Required + +**Sample usage:** + +`POST /rest//V1/inventory/bulk-product-source-transfer` + +**Payload:** + +```json +{ + "skus": [ + "testConfigProduct-red", + "testConfigProduct-blue" + ], + "originSource": "default", + "destinationSource": "central", + "unassignFromOrigin": true +} +``` + +**Response:** + +`true` if the request was successful + +## Bulk partial transfer + +You can use the `V1/inventory/bulk-partial-source-transfer` endpoint to transfer a limited quantity of a product from one source to another. As with full transfers, Magento keeps track of the stock status as well as the Notify Quantity when you move products from one source to another. + +**Parameters:** + +Name | Description | Type | Requirements +--- | --- | --- | --- +`originSourceCode` | The current source of the products to be transferred | String | Required +`destinationSourceCode` | The target source. This source must be already defined. | String | Required +`items` | An array containing a set of products to be transferred | Array | Required +`sku` | A product to transfer | String | Required +`qty` | The quantity of the product to transfer | Float | Required + +**Sample usage:** + +`POST /rest//V1/inventory/bulk-partial-source-transfer` + +**Payload:** + +```json +{ + "originSourceCode": "default", + "destinationSourceCode": "central", + "items": [ + { + "sku": "testConfigProduct-yellow", + "qty": 10 + }, + { + "sku": "testConfigProduct-green", + "qty": 50 + } + ] +} +``` + +**Response:** + +An empty array + +## Bulk assign sources + +Use the `POST /V1/inventory/bulk-product-source-assign` endpoint to add one or more sources to your products. This endpoint helps when creating and assigning custom sources to your default or custom stocks and preparing new locations and inventory. + +After adding new custom sources, you can add inventory quantities per product or for multiple products using the `POST V1/inventory/source-items` endpoint. [Assign products to a source](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-source-items) describes this endpoint. + +The sources are added to the products with an inventory quantity of 0. You can add inventory amounts as available per source. + +**Parameters:** + +Name | Description | Type | Requirements +--- | --- | --- | --- +`skus` | A comma-separated list of existing SKUs to assign | Array | Required +`sourceCodes` | A comma-separated list of existing sources | Array | Required + +**Sample usage:** + +`POST /rest//V1/inventory/bulk-product-source-assign` + +**Payload:** + +```json +{ + "skus": [ + "new-product3", + "new-product4" + ], + "sourceCodes": [ + "central", + "east" + ] +} +``` + +**Response:** + +An ID that identifies the request, such as `1`. + +## Bulk unassign sources + +When unassigning a source from a product, you are indicating the product will no longer be stocked at that location. This process completely clears all inventory data (quantity, stock status, Notify Quantity threshold) for the source currently assigned to the product. If you need to move the existing inventory to a new location, consider using the bulk transfer endpoint (`POST /V1/inventory/bulk-product-source-transfer`). + +{:.bs-callout-warning} +When you unassign a source from a product, Magento deletes all source data, including inventory amounts, from that product. This can affect salable quantities and reservations for unprocessed orders. After checkout and before shipment, all product quantities in the order have associated reservations. If you unassign a source, you can cause issues with reservations and processing orders. + +We strongly recommend completing all orders and shipments for those products prior to removing the source. + +If you unassign all sources from a product, you will not be able to sell the product. + +**Sample usage:** + +`POST /rest//V1/inventory/bulk-product-source-unassign` + +**Payload:** + +```json +{ + "skus": [ + "testSimpleProduct", + "testSimpleProduct2" + ], + "sourceCodes": [ + "default" + ] +} +``` + +**Response:** + +An ID that identifies the request, such as `1`. \ No newline at end of file diff --git a/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md b/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md deleted file mode 120000 index fdfd788fe8b..00000000000 --- a/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/modules/inventory/link-stocks-sources.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md b/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md new file mode 100644 index 00000000000..996c25f6e12 --- /dev/null +++ b/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md @@ -0,0 +1,203 @@ +--- +group: rest-api +title: Link and unlink stocks and sources + + +--- + +In Admin, you can assign (link) sources to a stock when you create the stock. In REST, creating a stock and assigning sources to it are separate steps. + +To link a source to a stock, you must specify the `source_code`, `stock_id`, and `priority` attributes. The `priority` value indicates where the source ranks in descending order. The Source Selection Algorithm uses this priority order when recommending order fulfillment. All sources linked to a stock are displayed in prioritized order in the Admin. + +**Service names:** + +```http +inventoryApiStockSourceLinksSaveV1 +inventoryApiStockSourceLinksDeleteV1 +InventoryApiGetStockSourceLinksV1 +inventoryApiGetSourcesAssignedToStockOrderedByPriorityV1 +``` + +**REST endpoints:** + +```http +POST /V1/inventory/stock-source-links +POST /V1/inventory/stock-source-links-delete +GET /V1/inventory/stock-source-links +``` + +**StockSourceLink parameters:** + +Name | Description | Type | Requirements +--- | --- | --- | --- +`stock_id` | Stock ID | Integer | Required for POST operations +`source_code` | Source code of the link | String | Required for POST operations +`priority` | Priority of the link | Integer | Required when linking a stock to a source + +## Link stocks and sources + +If you specify a sales channel that is already assigned to another stock, Magento reassigns the sales channel from the previous stock to the current stock. + +**Sample usage:** + +`POST /rest//V1/inventory/stock-source-links` + +**Payload:** + +```json +{ + "links" : [ + { + "source_code" : "central", + "stock_id" : 4, + "priority" : 1 + }, + { + "source_code" : "east", + "stock_id" : 4, + "priority" : 2 + } + ] +} +``` + +**Response:** + +Magento returns empty array. + +`[]` + +## Delete links between stocks and sources + +The `POST /V1/inventory/stock-source-links-delete` endpoint breaks the link between a stock and one or more sources. Magento does not recalculate priority of sources after you delete links. + +**Sample Usage:** + +`POST /rest//V1/inventory/stock-source-links-delete` + +**Payload:** + +```json +{ + "links" : [ + { + "source_code" : "south", + "stock_id" : 4 + } + ] +} +``` + +**Response:** + +Magento returns empty array. + +`[]` + +## Search for links + +The following call returns the link information for `stock_id = 4`. + +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. + +**Sample Usage:** + +`GET /rest//V1/inventory/stock-source-links?searchCriteria[filter_groups][0][filters][0][field]=stock_id&searchCriteria[filter_groups][0][filters][0][value]=4&searchCriteria[filter_groups][0][filters][0][condition_type]=eq` + +**Payload:** + +None + +**Response:** + +{% collapsible Show code sample %} + +```json +{ + "items": [ + { + "stock_id": 4, + "source_code": "central", + "priority": 1 + }, + { + "stock_id": 4, + "source_code": "east", + "priority": 2 + } + ], + "search_criteria": { + "filter_groups": [ + { + "filters": [ + { + "field": "stock_id", + "value": "4", + "condition_type": "eq" + } + ] + } + ] + }, + "total_count": 2 +} +``` + +{% endcollapsible %} + +## Get sources assigned to a stock + +The `GET /V1/inventory/get-sources-assigned-to-stock-ordered-by-priority/:stock_id` endpoint returns details about each source that is assigned to the specified stock. [Manage sources](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/) provides definitions for each attribute returned. + +**Sample Usage:** + +`GET /rest//V1/inventory/get-sources-assigned-to-stock-ordered-by-priority/4` + +**Payload:** + +None + +**Response:** + +{% collapsible Show code sample %} + +```json +[ + { + "source_code": "central", + "name": "Central Shipping Center", + "email": "hsmith@example.com", + "contact_name": "Harold Smith", + "enabled": true, + "description": "Primary source for the central region", + "latitude": 38.74132, + "longitude": -90.363267, + "country_id": "US", + "region_id": 36, + "city": "St. Louis", + "street": "123 Warehouse Blvd", + "postcode": "63145", + "phone": "(314) 555-1234", + "use_default_carrier_config": true, + "carrier_links": [] + }, + { + "source_code": "east", + "name": "Eastern Shipping Center", + "email": "dsimons@example.com", + "contact_name": "Daryl Simons", + "enabled": true, + "description": "Primary source for the eastern region", + "country_id": "US", + "region_id": 45, + "city": "Raleigh", + "street": "456 Shipping Center Blvd", + "postcode": "27614", + "phone": "(919) 555-8888", + "use_default_carrier_config": true, + "carrier_links": [] + } +] +``` + +{% endcollapsible %} diff --git a/src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md b/src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md deleted file mode 120000 index 2d4343926a2..00000000000 --- a/src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/modules/inventory/manage-low-quantity.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md b/src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md new file mode 100644 index 00000000000..582c561fea2 --- /dev/null +++ b/src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md @@ -0,0 +1,124 @@ +--- +group: rest-api +title: Manage low-quantity notifications + +--- + +Low stock notification alert the merchant that the salable quantity of a stock has reached a critical threshold. The Admin allows the merchant to configure low-quantity notifications from several locations: + +* The **Notify for Quantity Below** field (**Stores** > Settings > **Configuration** > **Catalog** > **Inventory** > **Product Stock Options**) sets the default value globally for all products for the entire website/store. +* The Advanced Inventory **Notify for Quantity Below** field (**Catalog** > **Products** > specific product > **Advanced Inventory**) overrides the value set at the website/store level. The value applies to all of the product's sources. +* The **Notify Quantity** fields (**Catalog** > **Products** > specific product > **Assigned Sources** section) override all other settings. The merchant can assign a different threshold for each source for the specific product. + +Magento deducts either the global or the overriding quantity from the total salable quantity for the stock. + +The REST low-quantity notification endpoints manage the values that merchants set from the **Notify Quantity** fields. + +**Service names:** + +```http +inventoryLowQuantityNotificationApiGetSourceItemConfigurationV1 +inventoryLowQuantityNotificationApiSourceItemConfigurationsSaveV1 +inventoryLowQuantityNotificationApiDeleteSourceItemsConfigurationV1 +``` + +**REST endpoints:** + +```http +POST /V1/inventory/low-quantity-notification +GET /V1/inventory/low-quantity-notification/:sourceCode/:sku +POST /V1/inventory/low-quantity-notifications-delete +``` + +**sourceItemConfigurations parameters:** + +Name | Description | Type | Requirements +--- | --- | --- | --- +`source_code` | The product's assigned source code | String | Required to create or delete a threshold +`notify_stock_qty` | The threshold at which Magento notifies the merchant that the salable quantity of a product is low. | Float | Required to create a threshold +`sku` | The SKU of the affected product | String | Required for to create or delete a threshold + +## Create a low quantity notification + +The `POST /V1/inventory/low-quantity-notification` endpoint accepts an array of values that map a SKU to a source and specify when to notify the merchant of a low stock quantity. + +**Sample usage:** + +`POST /rest//V1/inventory/low-quantity-notification` + +**Payload:** + +```json +{ + "sourceItemConfigurations": [ + { + "source_code": "baltimore_wh", + "notify_stock_qty": 10, + "sku": "sp1" + }, + { + "source_code": "austin_wh", + "notify_stock_qty": 8, + "sku": "sp1" + }, + { + "source_code": "reno_wh", + "notify_stock_qty": 5, + "sku": "sp1" + } + ] +} +``` + +**Response:** + +An empty array `[]` + +## Return low-quantity notification information + +This call returns the `notify_stock_qty` for the specified source and SKU. + +**Sample Usage:** + +`GET /rest//V1/inventory/low-quantity-notification/reno_wh/sp1` + +**Payload:** + +None + +**Response:** + +```json +{ +"source_code": "reno_wh", +"notify_stock_qty": 5, +"sku": "sp1 +} +``` + +## Delete a low-quantity notification + +The `POST /V1/inventory/low-quantity-notifications-delete` endpoint deletes the notification threshold for an array of sourceItem objects. Each object specified a SKU amd source. + +**Sample usage:** + +`POST /rest//V1/inventory/low-quantity-notifications-delete` + +**Payload:** + +```json +{ + "sourceItems": [ + { + "sku": "sp1", + "source_code": "reno_wh" + } + ] +} +``` + +**Response:** + +Magento returns an empty array. + +`[]` diff --git a/src/guides/v2.4/rest/modules/inventory/manage-source-selection.md b/src/guides/v2.4/rest/modules/inventory/manage-source-selection.md deleted file mode 120000 index b826e0e88df..00000000000 --- a/src/guides/v2.4/rest/modules/inventory/manage-source-selection.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/modules/inventory/manage-source-selection.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/modules/inventory/manage-source-selection.md b/src/guides/v2.4/rest/modules/inventory/manage-source-selection.md new file mode 100644 index 00000000000..001e6e00819 --- /dev/null +++ b/src/guides/v2.4/rest/modules/inventory/manage-source-selection.md @@ -0,0 +1,301 @@ +--- +group: rest-api +title: Manage source selection algorithms + +--- + +Inventory Management uses the Source Selection Algorithm (SSA) to track the salable quantities of product inventory across all sources and make recommendations for partial and full shipments. + +The SSA uses stocks and sources to check the sales channel for incoming product requests and determines the available inventory. The algorithm: + +* Calculates the aggregated virtual salable quantity of all assigned sources per stock +* Subtracts the Out-of-Stock Threshold amount from salable quantity to protect against overselling and support concurrent checkout +* Reserves inventory quantities at checkout, deducting from in-stock inventory at order processing and shipment +* Supports backorders with enhanced options for negative thresholds + +The SSA also manages shipments by providing recommendations for the best sources to ship partial or all products or override the selections to: + +* Ship partial shipments, sending only a few products from specific sources and completing the full order at a later date. +* Ship the entire order from one source. +* Break the order into partial shipments across multiple sources in different amounts to keep a balanced stock across all warehouses and stores. + +Third parties can also extend SSA to create customized algorithms for recommending cost-effective shipments. + +**Service names:** + +```http +inventorySourceSelectionApiGetSourceSelectionAlgorithmListV1 +inventorySourceSelectionApiSourceSelectionServiceV1 +inventoryDistanceBasedSourceSelectionApiGetDistanceProviderCodeV1 +inventoryDistanceBasedSourceSelectionApiGetDistanceV1 +inventoryDistanceBasedSourceSelectionApiGetLatLngFromAddressV1 +``` + +**REST endpoints:** + +```http +GET /V1/inventory/source-selection-algorithm-list +POST /V1/inventory/source-selection-algorithm-result +``` + +## Get the list of available source selection algorithms + +Currently, Inventory Management supports only the default SSA for priority. Third-party developers and future releases may add support for additional algorithms. + +**Sample usage:** + +`GET /rest/us/V1/inventory/source-selection-algorithm-list` + +**Payload:** + +None + +**Response:** + +An array containing a list of SSA codes, titles, and descriptions. + +```json +[ + { + "code": "distance", + "title": "Distance Priority", + "description": "Algorithm which provides Source Selections based on shipping address distance from the source" + }, + { + "code": "priority", + "title": "Source Priority", + "description": "Algorithm which provides Source Selections based on predefined priority of Source" + } +] +``` + +## Run the SSA + +The `POST V1/inventory/source-selection-algorithm-result` endpoint uses the algorithm defined by the `algorithmCode` attribute to calculate the recommended sources and quantities for each item defined in the items array. + +**Sample usage:** + +`POST /rest//V1/inventory/source-selection-algorithm-result` + +**inventoryRequest parameters:** + +Name | Description | Type | Requirements +--- | --- | --- | --- +`stock_id` | The ID of the stock | Integer | Required +`items` | An array containing the SKU and quantity of items in the order | Array | Required +`sku` | The SKU of a product to be shipped | String | Required for each item +`qty` | The quantity of a product to be shipped | Float | Required for each item +`algorithmCode` | The name of the SSA to implement. For 2.3, this value must be `priority`. | String | Required +`destination_address` | An extension attribute that defines the shipment address when the Distance Priority SSA is used. | Object | Required for the Distance Priority SSA +`country` | The country code of the shipping address | String | Required for the Distance Priority SSA +`postcode` | The postal code of the shipping address | String | Required for the Distance Priority SSA +`street` | The street address of the shipping address| String | Required for the Distance Priority SSA +`region` | The region code of the shipping address | String | Required for the Distance Priority SSA +`city` | The city of the shipping address | String | Required for the Distance Priority SSA + +### Source Priority Algorithm + +**Payload:** + +```json +{ + "inventoryRequest": { + "stockId": 2, + "items": [{ + "sku": "24-WB01", + "qty": 20 + }, + { + "sku": "24-WB03", + "qty": 50 + }] + }, + "algorithmCode": "priority" +} +``` + +**Response:** + +```json +{ + "source_selection_items": [ + { + "source_code": "baltimore_wh", + "sku": "24-WB01", + "qty_to_deduct": 20, + "qty_available": 35 + }, + { + "source_code": "austin_wh", + "sku": "24-WB01", + "qty_to_deduct": 0, + "qty_available": 10 + }, + { + "source_code": "reno_wh", + "sku": "24-WB01", + "qty_to_deduct": 0, + "qty_available": 25 + }, + { + "source_code": "baltimore_wh", + "sku": "24-WB03", + "qty_to_deduct": 19, + "qty_available": 19 + }, + { + "source_code": "reno_wh", + "sku": "24-WB03", + "qty_to_deduct": 31, + "qty_available": 42 + } + ], + "shippable": true +} +``` + +### Distance Priority algorithm + +**Payload:** + +```json +{ + "inventoryRequest": { + "stockId": 2, + "items": [{ + "sku": "24-WB01", + "qty": 20 + }, + { + "sku": "24-WB03", + "qty": 50 + }], + "extension_attributes": { + "destination_address": { + "country": "US", + "postcode": "10577", + "street": "3003 Purchase St", + "region": "43", + "city": "Purchase" + } + } + }, + "algorithmCode": "distance" +} +``` + +**Response:** + +```json +{ + "source_selection_items": [ + { + "source_code": "baltimore_wh", + "sku": "24-WB01", + "qty_to_deduct": 20, + "qty_available": 35 + }, + { + "source_code": "austin_wh", + "sku": "24-WB01", + "qty_to_deduct": 0, + "qty_available": 10 + }, + { + "source_code": "reno_wh", + "sku": "24-WB01", + "qty_to_deduct": 0, + "qty_available": 25 + }, + { + "source_code": "baltimore_wh", + "sku": "24-WB03", + "qty_to_deduct": 19, + "qty_available": 19 + }, + { + "source_code": "reno_wh", + "sku": "24-WB03", + "qty_to_deduct": 31, + "qty_available": 42 + } + ], + "shippable": true +} +``` + +## Determine distances for the Distance Priority algorithm + +Magento provides several endpoints to help determine GPS coordinates. + +### Get the distance provider code + +The `GET /V1/inventory/get-distance-provider-code` endpoint returns the configured distance provider for the Distance Priority algorithm. The value can be `google` or `offline`. + +**Sample usage:** + +`GET /rest//V1/inventory/get-distance-provider-code` + +**Payload:** + +None + +**Response:** + +`offline` + +### Get the distance between two points + +The `GET /V1/inventory/get-distance` endpoint calculates the distance between two points, given the longitude and latitude of the source and distance. + +**URL parameters:** + +Name | Description +--- | --- +`source[lat]` | The latitude of the source +`source[lng]` | The longitude of the source +`destination[lat]` | The latitude of the destination +`destination[lng]` | The longitude of the destination + +**Sample usage:** + +`GET /V1/inventory/get-distance?source[lat]=30.271129&source[lng]=-97.7437&destination[lat]=39.290882&destination[lng]=-76.610759` + +**Payload:** + +None + +**Response:** + +The distance, in kilometers + +### Get the latitude and longitude of the shipping address + +The `GET /V1/inventory/get-latlng-from-address` endpoint calculates the latitude and longitude of the shipping address. + +**URL parameters:** + +Name | Description +--- | --- +address[country] | The country code of the shipping address +address[postcode] | The postal code of the shipping address +address[street] | The street of the shipping address +address[region] | The region code of the shipping address +address[city] | The city of the shipping address + +**Sample usage:** + +`GET /V1/inventory/get-latlng-from-address?address[country]=US&address[postcode]=10577&address[street]=123%20Oak&address[region]=NY&address[city]=Purchase` + +**Payload:** + +None + +**Response:** + +```json +{ + "lat": 41.0384, + "lng": -73.7156 +} +``` diff --git a/src/guides/v2.4/rest/modules/inventory/manage-stocks.md b/src/guides/v2.4/rest/modules/inventory/manage-stocks.md deleted file mode 120000 index 84c6e841ed5..00000000000 --- a/src/guides/v2.4/rest/modules/inventory/manage-stocks.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/modules/inventory/manage-stocks.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/modules/inventory/manage-stocks.md b/src/guides/v2.4/rest/modules/inventory/manage-stocks.md new file mode 100644 index 00000000000..fc5ded47f9f --- /dev/null +++ b/src/guides/v2.4/rest/modules/inventory/manage-stocks.md @@ -0,0 +1,210 @@ +--- +group: rest-api +title: Manage stocks + +--- + +Stocks map your sources to sales channels, providing a direct link to salable quantities and inventories. + +All stores start with a default stock. When the inventory management functionality is enabled, Magento automatically assigns products to the default source and stock. Single Source merchants use the default stock only. Multi Source merchants create and configure stocks as needed to best fit their stores and order fulfillment processes. + +The `stock_id` of the default stock is `1`. You cannot delete or add sources to the default stock, but you can perform these actions with custom stocks. + +Any sales channels that are not explicitly assigned to a custom stock are assigned to the Default Stock. + +**Service name:** + +`inventoryApiStockRepositoryV1` + +**REST endpoints:** + +```http +POST /V1/inventory/stocks +PUT /V1/inventory/stocks/:stockId +GET /V1/inventory/stocks/:stockId +DELETE /V1/inventory/stocks/:stockId +GET /V1/inventory/stocks +``` + +**StockInterface parameters:** + +Name | Description | Type | Requirements +--- | --- | --- | --- +`stock_id` | An ID generated when a stock is created. | Integer | Required for PUT, DELETE, and GET operations +`name` | The display name of the stock. | String | Required for POST and PUT operations +`sales_channels` | Defines the sales channel for this stock. Currently, only websites are supported. | Array | Required for POST operations +`type` | Defines the type of sales channel. This value must be `website`. | String | Required for POST operations +`code` | Specifies a valid website code name | String | Required for POST operations + +## Create a stock + +Only one stock can be mapped to each sales channel. If you assign a sales channel that is already mapped to another stock, the sales channel will be removed from the original stock. + +**Sample usage:** + +`POST /rest//V1/inventory/stocks` + +**Payload:** + +```json +{ + "stock": { + "name": "Central Stock", + "extension_attributes": { + "sales_channels": [ + { + "type": "website", + "code": "test_site" + } + ] + } + } +} +``` + +**Response:** + +A `stock_id`, such as `4`. + +## Update a stock + +You can change the name of a custom stock and its associated sales channels. Each PUT call overwrites the previous set of assigned sales channels. If you omit the `sales_channel` array, all sales channels will be unassigned from the stock. + +If you change a sales channel between stocks, we recommend that you first complete any open orders and shipments that may need access to the assigned sources. + +**Sample Usage:** + +`PUT /rest//V1/inventory/stocks/4` + +**Payload:** + +```json +{ + "stock": { + "name": "St. Louis Stock", + "extension_attributes": { + "sales_channels": [ + { + "type": "website", + "code": "test_site" + } + ] + } + } +} +``` + +**Response:** + +A `stock_id`, such as `4`. + +## Return all information about a stock + +This call returns detailed information about the specified stock. + +**Sample Usage:** + +`GET /rest//V1/inventory/stocks/4` + +**Payload:** + +None + +**Response:** + +```json +{ + "stock": { + "name": "St. Louis Stock", + "extension_attributes": { + "sales_channels": [ + { + "type": "website", + "code": "test_site" + } + ] + } + } +} +``` + +## Delete a stock + +You cannot delete a stock if it is assigned to a sales channel. You can unassign a stock's sales channels by omitting the `sales_channels` array in a `PUT /V1/inventory/stocks/:stockId` call. + +**Sample Usage:** + +`DELETE /rest//V1/inventory/stocks/4` + +**Payload:** + +None + +**Response:** + +Magento returns an empty array. + +`[]` + +## Search for stocks + +The following call returns all stocks whose name contains the string `Stock`. + +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. + +**Sample Usage:** + +`GET /rest//V1/inventory/stocks?searchCriteria[filter_groups][0][filters][0][field]=name&searchCriteria[filter_groups][0][filters][0][value]=%25Stock%25&searchCriteria[filter_groups][0][filters][0][condition_type]=like` + +**Payload:** + +None + +**Response:** + +{% collapsible Show code sample %} +```json +{ + "items": [ + { + "stock_id": 1, + "name": "Default Stock", + "extension_attributes": { + "sales_channels": [ + { + "type": "website", + "code": "base" + } + ] + } + }, + { + "stock_id": 4, + "name": "St. Louis Stock", + "extension_attributes": { + "sales_channels": [ + { + "type": "website", + "code": "test_site" + } + ] + } + } + ], + "search_criteria": { + "filter_groups": [ + { + "filters": [ + { + "field": "name", + "value": "%Stock%", + "condition_type": "like" + } + ] + } + ] + }, + "total_count": 2 +} +``` +{% endcollapsible %} diff --git a/src/guides/v2.4/rest/modules/sales/refunds.md b/src/guides/v2.4/rest/modules/sales/refunds.md deleted file mode 120000 index c70f0779d7b..00000000000 --- a/src/guides/v2.4/rest/modules/sales/refunds.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/modules/sales/refunds.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/modules/sales/refunds.md b/src/guides/v2.4/rest/modules/sales/refunds.md new file mode 100644 index 00000000000..44ee0d81952 --- /dev/null +++ b/src/guides/v2.4/rest/modules/sales/refunds.md @@ -0,0 +1,47 @@ +--- +group: rest-api +title: Refunds + +functional_areas: + - Integration + - Catalog +--- + +There are a couple of options to choose when issuing a refund using the Magento API. + +## salesRefundInvoiceV1 service + +With this service, you can initiate and process a refund based on an invoice ID, created using an online payment method. + +The `salesRefundInvoice` service allows you to: + +* Create a credit memo (complete or partial) for an invoice +* Add details about the refunded items to the order +* Change status and state of an order according to performed actions +* Notify a customer about the performed refund operation +* Designate whether the returned items are returned to stock + +### Endpoint + +`POST V1/invoice/:invoiceId/refund` + +{:.bs-callout-warning} +If you try to apply the service to an invoice created using an offline payment method, the system will return a validation error. + +## salesRefundOrderV1 service + +This service performs the same operations as the `salesRefundInvoiceV1` service, but based on an order ID. Use this service if the invoice was created using an offline payment method. + +### Endpoint + +`POST V1/order/:orderId/refund` + +{:.bs-callout-warning} +If you try to apply the service to an invoice created using an online payment method, the system will return a validation error. + +## Other services for issuing refunds + +While we recommend you use the `Refund` services, Magento also provides the following `CreditmemoManagement` services you can use to issue a credit: + +* `salesCreditmemoManagement` +* `salesCreditmemoRepository` diff --git a/src/guides/v2.4/rest/notes.md b/src/guides/v2.4/rest/notes.md deleted file mode 120000 index edb6d78158d..00000000000 --- a/src/guides/v2.4/rest/notes.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/rest/notes.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/notes.md b/src/guides/v2.4/rest/notes.md new file mode 100644 index 00000000000..c83785dc329 --- /dev/null +++ b/src/guides/v2.4/rest/notes.md @@ -0,0 +1,164 @@ +--- +group: rest-api +title: REST usage notes + +functional_areas: + - Integration +--- + +You might encounter the following issues when using REST endpoints. + +## Duplicate parameters in an REST call + +In a REST call, it is possible that a route variable contains one value while the request body contains a different value. +Whenever this type of conflict occurs, Magento uses the value specified in the request body. + +For example: + +The REST URL to update a customer is `PUT /V1/customers/:id`. If you specify an ID value of `1` in the URL (`http:///rest//V1/customers/1`), and a body of `{ "customer": { "id": 2, "attr": "value" }}`, the customer with ID of `2` will be modified. + +This applies to all REST APIs where a parameter is passed in the URL. Any value specified in the URL with the same parameter name as in the request body is ignored. + +## Create a bundle product + +The following sample code creates a bundle product. The `price_type` attribute code defined in the `custom_attributes` object is set to `1` to allow the product to have a fixed price. + +```json +{ + "product":{ + "sku":"box-of-watches", + "name":"Box of Watches", + "attribute_set_id":11, + "price":100, + "status":1, + "visibility":4, + "type_id":"bundle", + "extension_attributes":{ + "website_ids":[ + 1, + 2 + ], + "category_links":[ + { + "position":0, + "category_id":"3" + }, + { + "position":0, + "category_id":"6" + } + ], + "bundle_product_options":[ + { + "title":"Men's Watches", + "required":true, + "type":"radio", + "position":1, + "sku":"box-of-watches", + "product_links":[ + { + "sku":"24-MG04", + "qty":50, + "position":2, + "is_default":false, + "price":0, + "price_type":0, + "can_change_quantity":0 + }, + { + "sku":"24-MG05", + "qty":50, + "position":4, + "is_default":false, + "price":0, + "price_type":0, + "can_change_quantity":0 + } + ] + }, + { + "title":"Women's Watches", + "required":true, + "type":"radio", + "position":2, + "sku":"box-of-watches", + "product_links":[ + { + "sku":"24-WG01", + "qty":50, + "position":1, + "is_default":false, + "price":0, + "price_type":0, + "can_change_quantity":0 + }, + { + "sku":"24-WG09", + "qty":50, + "position":2, + "is_default":false, + "price":0, + "price_type":0, + "can_change_quantity":0 + } + ] + } + ] + }, + "custom_attributes":[ + { + "attribute_code":"price_type", + "value":"1" + }, + { + "attribute_code":"price_view", + "value":"0" + }, + { + "attribute_code":"required_options", + "value":"1" + }, + { + "attribute_code":"has_options", + "value":"1" + }, + { + "attribute_code":"meta_title", + "value":"watch-test" + }, + { + "attribute_code":"sku_type", + "value":"1" + }, + { + "attribute_code":"meta_description", + "value":"watch-test This is a box of watches!" + }, + { + "attribute_code":"weight_type", + "value":"0" + }, + { + "attribute_code":"category_ids", + "value":[ + "3", + "6" + ] + }, + { + "attribute_code":"description", + "value":"

    This is a box of watches!

    " + }, + { + "attribute_code":"short_description", + "value":"

    A box of watches

    " + } + ] + } +} +``` + +{:.ref-header} +Related topics + +[Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) diff --git a/src/guides/v2.4/rest/operation-status-endpoints.md b/src/guides/v2.4/rest/operation-status-endpoints.md deleted file mode 120000 index e5ce2771201..00000000000 --- a/src/guides/v2.4/rest/operation-status-endpoints.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/rest/operation-status-endpoints.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/operation-status-endpoints.md b/src/guides/v2.4/rest/operation-status-endpoints.md new file mode 100644 index 00000000000..837e0797016 --- /dev/null +++ b/src/guides/v2.4/rest/operation-status-endpoints.md @@ -0,0 +1,153 @@ +--- +group: rest-api +title: Bulk operation status endpoints + +contributor_name: comwrap GmbH +contributor_link: https://www.comwrap.com/ +functional_areas: + - Integration +--- + +Magento generates a `bulk_uuid` each time it executes an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html). You can track the status of an asynchronous operation with the following endpoints: + +* `GET /V1/bulk/:bulkUuid/status` +* `GET /V1/bulk/:bulkUuid/operation-status/:status` +* `GET /V1/bulk/:bulkUuid/detailed-status` + +## Get the status summary + +The `GET /rest//V1/bulk/:bulkUuid/status` endpoint returns the abbreviated status of the specified operation: + +Field name | Data type | Description +--- | --- | --- +`operations_list` | Object | An array containing information about each operation in a bulk or asynchronous request. +`id` | Integer | Identifies the bulk or asynchronous request. +`status` | Integer | The operation status
    \* `1` = Complete
    \* `2` = The operation failed, but you can try to perform it again
    \* `3` = The operation failed. You must change something to retry it.
    \* `4` = Open
    \* `5` = Rejected +`result_message` | String | Describes the result of the operation. If successful, the value contains the string `Service execution success` as well as the method that executed the operation. +`error_code` | Integer | If applicable, an error code associated with the operation. +`user_type` | Integer | Type of user who made this request. Possible values are:
    \* `1` = Integration
    \* `2` = Administrator
    \* `3` = Customer
    \* `4` = Guest User +`bulk_id` | String | UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html). +`description` | String | Contains the message queue topic. +`start_time` | String | The time that a bulk or asynchronous operation started. +`user_id` | Integer | The user ID that executed the request. +`operation_count` | Integer | The number of operations processed in the request. + +**Response:** + +```json +{ + "operations_list": [ + { + "id": 12, + "status": 1, + "result_message": "Service execution success Magento\\Catalog\\Model\\ProductRepository\\Interceptor::save", + "error_code": null + } + ], + "user_type": 2, + "bulk_id": "fbfca270-7a90-4c4e-9f32-d6cf3728cdc7", + "description": "Topic async.magento.catalog.api.productrepositoryinterface.save.put", + "start_time": "2018-07-12 16:07:53", + "user_id": 1, + "operation_count": 1 +} +``` + +## Get operations count by bulk uuid and status + +The `GET /rest//V1/bulk/:bulkUuid/operation-status/:status` endpoint returns the number of operations from the bulk batch that have the specified status. + +Status | Description +--- | --- +`1` | Complete +`2` | The operation failed, but you can try to perform it again. +`3` | The operation failed. You must change something to retry it. +`4` | Open +`5` | Rejected + +**Response:** + +```json +0 +``` + +## Get the detailed status + +The `GET /V1/bulk/:bulkUuid/detailed-status` endpoint returns detailed information about status of a specified operation. It is similar to the `GET /V1/bulk/:bulkUuid/status` endpoint, except that the `operations_list` array also contains the message queue topic name and serialized data for each operation. + +```http +GET /rest//V1/bulk/:bulkUuid/detailed-status +``` + +Field name | Data type | Description +--- | --- | --- +`operations_list` | Object | An array containing information about each operation in a bulk or asynchronous request. +`id` | Integer | Identifies the bulk or asynchronous request. +`bulk_uuid` | String | UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html). +`topic_name` | String | The name of the message queue topic, in the format `async..`. The service contract path is lowercase, and the method is either `post`, `put`, or `delete`. +`serialized_data` | String | An array of serialized input data. It contains serialized JSON with the following keys: `entity_id` - `null`, `entity_link` - an empty string, `meta_info` - the body of the API request that was executed. +`result_serialized_data` | String | Contains serialized output of the corresponding synchronous API call. For example, if you call `POST /async/V1/products`, this field contains serialized response from `POST /V1/products`. +`status` | Integer | The operation status
    \* `1` = Complete
    \* `2` = The operation failed, but you can try to perform it again
    \* `3` = The operation failed. You must change something to retry it.
    \* `4` = Open
    \* `5` = Rejected +`result_message` | String | Describes the result of the operation. If successful, the value contains the string `Service execution success` as well as the method that executed the operation. +`error_code` | Integer | If applicable, an error code associated with the operation. +`user_type` | Integer | Type of user who made this request. Possible values are:
    \* `1` = Integration
    \* `2` = Administrator
    \* `3` = Customer
    \* `4` = Guest User +`bulk_id` | String | UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html). +`description` | String | Contains the message queue topic name. +`start_time` | String | The time that a bulk or asynchronous operation started. +`user_id` | Integer | The user ID that executed the request. +`operation_count` | Integer | The number of operations processed in the request. + +**Response:** + +```json +{ + "operations_list": [ + { + "id": 4, + "bulk_uuid": "c43ed402-3dd3-4100-92e2-dc5852d3009b", + "topic_name": "async.magento.customer.api.accountmanagementinterface.createaccount.post", + "serialized_data": "{\"entity_id\":null,\"entity_link\":\"\",\"meta_information\":\"{\\\"customer\\\":{\\\"email\\\":\\\"mshaw@example.com\\\",\\\"firstname\\\":\\\"Melanie Shaw\\\",\\\"lastname\\\":\\\"Doe\\\"},\\\"password\\\":\\\"Password1\\\",\\\"redirectUrl\\\":\\\"\\\"}\"}", + "result_serialized_data": null, + "status": 3, + "result_message": "A customer with the same email address already exists in an associated website.", + "error_code": 0 + }, + { + "id": 5, + "bulk_uuid": "c43ed402-3dd3-4100-92e2-dc5852d3009b", + "topic_name": "async.magento.customer.api.accountmanagementinterface.createaccount.post", + "serialized_data": "{\"entity_id\":null,\"entity_link\":\"\",\"meta_information\":\"{\\\"customer\\\":{\\\"email\\\":\\\"bmartin@example.com\\\",\\\"firstname\\\":\\\"Bryce\\\",\\\"lastname\\\":\\\"Martin\\\"},\\\"password\\\":\\\"Password1\\\",\\\"redirectUrl\\\":\\\"\\\"}\"}", + "result_serialized_data": null, + "status": 3, + "result_message": "A customer with the same email address already exists in an associated website.", + "error_code": 0 + }, + { + "id": 6, + "bulk_uuid": "c43ed402-3dd3-4100-92e2-dc5852d3009b", + "topic_name": "async.magento.customer.api.accountmanagementinterface.createaccount.post", + "serialized_data": "{\"entity_id\":null,\"entity_link\":\"\",\"meta_information\":\"{\\\"customer\\\":{\\\"email\\\":\\\"bmartin@example.com\\\",\\\"firstname\\\":\\\"Bryce\\\",\\\"lastname\\\":\\\"Martin\\\"},\\\"password\\\":\\\"Password1\\\",\\\"redirectUrl\\\":\\\"\\\"}\"}", + "result_serialized_data": null, + "status": 3, + "result_message": "A customer with the same email address already exists in an associated website.", + "error_code": 0 + }, + { + "id": 7, + "bulk_uuid": "c43ed402-3dd3-4100-92e2-dc5852d3009b", + "topic_name": "async.magento.customer.api.accountmanagementinterface.createaccount.post", + "serialized_data": "{\"entity_id\":null,\"entity_link\":\"\",\"meta_information\":\"{\\\"customer\\\":{\\\"email\\\":\\\"tgomez@example.com\\\",\\\"firstname\\\":\\\"Teresa\\\",\\\"lastname\\\":\\\"Gomez\\\"},\\\"password\\\":\\\"Password1\\\",\\\"redirectUrl\\\":\\\"\\\"}\"}", + "result_serialized_data": null, + "status": 3, + "result_message": "A customer with the same email address already exists in an associated website.", + "error_code": 0 + } + ], + "user_type": 2, + "bulk_id": "c43ed402-3dd3-4100-92e2-dc5852d3009b", + "description": "Topic async.magento.customer.api.accountmanagementinterface.createaccount.post", + "start_time": "2018-07-11 20:07:14", + "user_id": null, + "operation_count": 4 +} +``` diff --git a/src/guides/v2.4/rest/operation-status-search.md b/src/guides/v2.4/rest/operation-status-search.md deleted file mode 120000 index 8450297e9b4..00000000000 --- a/src/guides/v2.4/rest/operation-status-search.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/rest/operation-status-search.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/operation-status-search.md b/src/guides/v2.4/rest/operation-status-search.md new file mode 100644 index 00000000000..c7c02a32fd9 --- /dev/null +++ b/src/guides/v2.4/rest/operation-status-search.md @@ -0,0 +1,126 @@ +--- +group: rest-api +title: Search for the status of a bulk operation + +contributor_name: comwrap GmbH +contributor_link: https://www.comwrap.com +functional_areas: + - Integration +--- + +The Status Operation Search endpoint (`GET /V1/bulk/?searchCriteria`) allows you to search for bulk operation statuses. + +You can specify any of the following fields to filter on operation statuses: + +* `start_time` - The time that a bulk operation started. +* `status` - The operation status: + * `1` = Complete + * `2` = The operation failed, but you can try to perform it again. + * `3` = The operation failed. You must change something to retry it. + * `4` = Open + * `5` = Rejected +* `bulk_uuid` - UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html). +* `topic_name` - Queue topic name + +**Sample usage:** + +The following call returns bulk operations that contain an error that cannot be retried. + +```http +GET /rest//V1/bulk/? +searchCriteria[filter_groups][0][filters][0][field]=status& +searchCriteria[filter_groups][0][filters][0][value]=3& +searchCriteria[filter_groups][0][filters][0][condition_type]=eq +``` + +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for more information about the syntax of search requests. + +**Response:** + +The operation with bulk UUID `c43ed402-3dd3-4100-92e2-dc5852d3009b` contains a `status` code of 3. + +```json +{ + "items": [ + { + "extension_attributes": { + "start_time": "2018-07-11 20:07:14" + }, + "id": 4, + "bulk_uuid": "c43ed402-3dd3-4100-92e2-dc5852d3009b", + "topic_name": "async.magento.customer.api.accountmanagementinterface.createaccount.post", + "serialized_data": "{\"entity_id\":null,\"entity_link\":\"\",\"meta_information\":\"{\\\"customer\\\":{\\\"email\\\":\\\"mshaw@example.com\\\",\\\"firstname\\\":\\\"Melanie Shaw\\\",\\\"lastname\\\":\\\"Doe\\\"},\\\"password\\\":\\\"Password1\\\",\\\"redirectUrl\\\":\\\"\\\"}\"}", + "result_serialized_data": null, + "status": 3, + "result_message": "A customer with the same email address already exists in an associated website.", + "error_code": 0 + }, + { + "extension_attributes": { + "start_time": "2018-07-11 20:07:14" + }, + "id": 5, + "bulk_uuid": "c43ed402-3dd3-4100-92e2-dc5852d3009b", + "topic_name": "async.magento.customer.api.accountmanagementinterface.createaccount.post", + "serialized_data": "{\"entity_id\":null,\"entity_link\":\"\",\"meta_information\":\"{\\\"customer\\\":{\\\"email\\\":\\\"bmartin@example.com\\\",\\\"firstname\\\":\\\"Bryce\\\",\\\"lastname\\\":\\\"Martin\\\"},\\\"password\\\":\\\"Password1\\\",\\\"redirectUrl\\\":\\\"\\\"}\"}", + "result_serialized_data": null, + "status": 3, + "result_message": "A customer with the same email address already exists in an associated website.", + "error_code": 0 + }, + { + "extension_attributes": { + "start_time": "2018-07-11 20:07:14" + }, + "id": 6, + "bulk_uuid": "c43ed402-3dd3-4100-92e2-dc5852d3009b", + "topic_name": "async.magento.customer.api.accountmanagementinterface.createaccount.post", + "serialized_data": "{\"entity_id\":null,\"entity_link\":\"\",\"meta_information\":\"{\\\"customer\\\":{\\\"email\\\":\\\"bmartin@example.com\\\",\\\"firstname\\\":\\\"Bryce\\\",\\\"lastname\\\":\\\"Martin\\\"},\\\"password\\\":\\\"Password1\\\",\\\"redirectUrl\\\":\\\"\\\"}\"}", + "result_serialized_data": null, + "status": 3, + "result_message": "A customer with the same email address already exists in an associated website.", + "error_code": 0 + }, + { + "extension_attributes": { + "start_time": "2018-07-11 20:07:14" + }, + "id": 7, + "bulk_uuid": "c43ed402-3dd3-4100-92e2-dc5852d3009b", + "topic_name": "async.magento.customer.api.accountmanagementinterface.createaccount.post", + "serialized_data": "{\"entity_id\":null,\"entity_link\":\"\",\"meta_information\":\"{\\\"customer\\\":{\\\"email\\\":\\\"tgomez@example.com\\\",\\\"firstname\\\":\\\"Teresa\\\",\\\"lastname\\\":\\\"Gomez\\\"},\\\"password\\\":\\\"Password1\\\",\\\"redirectUrl\\\":\\\"\\\"}\"}", + "result_serialized_data": null, + "status": 3, + "result_message": "A customer with the same email address already exists in an associated website.", + "error_code": 0 + }, + { + "extension_attributes": { + "start_time": "2018-07-11 20:58:31" + }, + "id": 10, + "bulk_uuid": "799a59c0-09ca-4d60-b432-2953986c1c38", + "topic_name": "async.magento.customer.api.accountmanagementinterface.createaccount.post", + "serialized_data": "{\"entity_id\":null,\"entity_link\":\"\",\"meta_information\":\"{\\\"customer\\\":{\\\"email\\\":\\\"bmartin@example.com\\\",\\\"firstname\\\":\\\"Bryce\\\",\\\"lastname\\\":\\\"Martin\\\"},\\\"password\\\":\\\"Password1\\\",\\\"redirectUrl\\\":\\\"\\\"}\"}", + "result_serialized_data": null, + "status": 3, + "result_message": "A customer with the same email address already exists in an associated website.", + "error_code": 0 + } + ], + "search_criteria": { + "filter_groups": [ + { + "filters": [ + { + "field": "status", + "value": "3", + "condition_type": "eq" + } + ] + } + ] + }, + "total_count": 5 +} +``` diff --git a/src/guides/v2.4/rest/performing-searches.md b/src/guides/v2.4/rest/performing-searches.md deleted file mode 120000 index a3de8abdb58..00000000000 --- a/src/guides/v2.4/rest/performing-searches.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/rest/performing-searches.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/performing-searches.md b/src/guides/v2.4/rest/performing-searches.md new file mode 100644 index 00000000000..b8ef346f6dc --- /dev/null +++ b/src/guides/v2.4/rest/performing-searches.md @@ -0,0 +1,277 @@ +--- +group: rest-api +title: Search using REST endpoints + +--- + +POST, PUT, and DELETE requests to the REST Web [API](https://glossary.magento.com/api) require the service method parameters to be in the body of the request. For example, to create a Customer, you would specify a JSON array (or [XML](https://glossary.magento.com/xml) structure) in the body of the message. + +For search APIs that invoke a `*Repository::getList(SearchCriteriaInterface *)` call, the searchCriteria must be specified in the [URL](https://glossary.magento.com/url) of the GET request. The basic pattern for specifying the criteria is + +```http +searchCriteria[filter_groups][][filters][][field]= +searchCriteria[filter_groups][][filters][][value]= +searchCriteria[filter_groups][][filters][][condition_type]= +``` + +where: + +* `field` is an attribute name. +* `value` specifies the value to search for. +* `condition_type` is one of the following values: + +Condition | Notes +--- | --- +`eq` | Equals +`finset` | A value within a set of values +`from` | The beginning of a range. Must be used with `to`. +`gt` | Greater than +`gteq` | Greater than or equal +`in` | In. The `value` can contain a comma-separated list of values. +`like` | Like. The `value` can contain the SQL wildcard characters when `like` is specified. +`lt` | Less than +`lteq` | Less than or equal +`moreq` | More or equal +`neq` | Not equal +`nfinset` | A value that is not within a set of values. +`nin` | Not in. The `value` can contain a comma-separated list of values. +`nlike` | Not like +`notnull` | Not null +`null` | Null +`to` | The end of a range. Must be used with `from`. + +{:.bs-callout-info} +`condition_type` is optional if the operator is `eq`. + +The `filter_groups` array defines one or more `filters`. Each filter defines a search term, and the `field`, `value`, and `condition_type` of a search term must be assigned the same index number, starting with 0. Increment additional terms as needed. + +When constructing a search, keep the following in mind: + +* To perform a logical OR, specify multiple `filters` within a `filter_groups`. +* To perform a logical AND, specify multiple `filter_groups`. +* You cannot perform a logical OR across different `filter_groups`, such as `(A AND B) OR (X AND Y)`. ORs can be performed only within the context of a single `filter_groups`. +* You can only search top-level attributes. + +The following sections provide examples of each type of search. These examples use the {{site.data.var.ce}} sample data. + +## Simple search + +The {{site.data.var.ce}} sample data uses the `category_gear` field to describe the categories for each item listed under Gear on sample store. Each item can be assigned to multiple categories. Electronics are assigned the code 86. The following example returns all gear tagged as electronics. + +```http +GET /rest//V1/products/? +searchCriteria[filter_groups][0][filters][0][field]=category_gear& +searchCriteria[filter_groups][0][filters][0][value]=86& +searchCriteria[filter_groups][0][filters][0][condition_type]=finset +``` + +The system creates an array, as shown in the following pseudo-code. + +```http +searchCriteria => [ +  'filterGroups' => [ +    0 => [ +      'filters' => [ +         0 => [ +           'field' => 'category_gear', +           'value' => '86', +           'condition_type' => 'finset' +         ] +      ] +    ] +  ] +``` + +The query returns 9 items. + +## Simple search using a timestamp + +The following search finds all invoices created after the specified time (midnight, July 1 2016). You can set up a similar search to run periodically to poll for changes. + +```http +GET /rest//V1/invoices? +searchCriteria[filter_groups][0][filters][0][field]=created_at& +searchCriteria[filter_groups][0][filters][0][value]=2016-07-01 00:00:00& +searchCriteria[filter_groups][0][filters][0][condition_type]=gt +``` + +## Simple search using an `in` conditions type + +The following search finds all the products that are provided in the value field. When you specify the `in` condition type, the value field must be a comma separated list. + +```http +GET /rest//V1/products? +searchCriteria[filter_groups][0][filters][0][field]=entity_id& +searchCriteria[filter_groups][0][filters][0][value]=1,2,3,4,5& +searchCriteria[filter_groups][0][filters][0][condition_type]=in +``` +The query returns 5 items. + +### Logical OR search + +The following example searches for all products whose names contain the string `Leggings` or `Parachute`. The instances of `%25` in the example are converted into the SQL wildcard character `%`. + +```http +GET /rest//V1/products? +searchCriteria[filter_groups][0][filters][0][field]=name& +searchCriteria[filter_groups][0][filters][0][value]=%25Leggings%25& +searchCriteria[filter_groups][0][filters][0][condition_type]=like& +searchCriteria[filter_groups][0][filters][1][field]=name& +searchCriteria[filter_groups][0][filters][1][value]=%25Parachute%25& +searchCriteria[filter_groups][0][filters][1][condition_type]=like +``` + +The system creates an array, as shown in the following pseudo-code. + +```http +searchCriteria => [ +  'filterGroups' => [ +    0 => [ +      'filters' => [ +         0 => [ +           'field' => 'name', +           'value' => '%25Leggings%25', +           'condition_type' => 'like' +         ] +         1 => [ +          'field' => 'name', +          'value' => '%25Parachute%25', +          'condition_type' => 'like' +         ] +      ] +    ] +  ] +``` + +The search returns 14 products that contain the string `Leggings` in the `name` field and 14 products that contain the string `Parachute`. + +### Logical AND search + +This sample searches for women's shorts that are size 31 and costs less than $30. In the CE sample data, women's shorts have a `sku` value that begins with `WSH`. The `sku` also contains the size and color, such as `WSH02-31-Yellow`. + +```http +GET /rest//V1/products? +searchCriteria[filter_groups][0][filters][0][field]=sku& +searchCriteria[filter_groups][0][filters][0][value]=WSH%2531%25& +searchCriteria[filter_groups][0][filters][0][condition_type]=like& +searchCriteria[filter_groups][1][filters][0][field]=price& +searchCriteria[filter_groups][1][filters][0][value]=30& +searchCriteria[filter_groups][1][filters][0][condition_type]=lt +``` + +The system creates an array, as shown in the following pseudo-code. + +```http +searchCriteria => [ +  'filterGroups' => [ +    0 => [ +      'filters' => [ +         0 => [ +           'field' => 'sku', +           'value' => 'WSH%31%', +           'condition_type' => 'like' +         ] +    1 => [ + 'filters' => [ +         0 => [ +          'field' => 'price', +          'value' => '30', +          'condition_type' => 'lt' +         ] +      ] +    ] +  ] +``` + +The query returns 9 items. + +### Logical AND and OR search + +This sample is similar the Logical AND sample. It searches the `sku`s for women's shorts (WSH%) or pants (WP%)in size 29. The system performs two logical ANDs to restrict the results to those that cost from $40 to $49.99 + +```http +GET /rest//V1/products? +searchCriteria[filter_groups][0][filters][0][field]=sku& +searchCriteria[filter_groups][0][filters][0][value]=WSH%2529%25& +searchCriteria[filter_groups][0][filters][0][condition_type]=like& +searchCriteria[filter_groups][0][filters][1][field]=sku& +searchCriteria[filter_groups][0][filters][1][value]=WP%2529%25& +searchCriteria[filter_groups][0][filters][1][condition_type]=like& +searchCriteria[filter_groups][1][filters][0][field]=price& +searchCriteria[filter_groups][1][filters][0][value]=40& +searchCriteria[filter_groups][1][filters][0][condition_type]=from& +searchCriteria[filter_groups][2][filters][0][field]=price& +searchCriteria[filter_groups][2][filters][0][value]=49.99& +searchCriteria[filter_groups][2][filters][0][condition_type]=to +``` + +The query returns 37 items. + +## Other search criteria + +The following searchCriteria can be used to determine the sort order and the number of items to return. + +* `searchCriteria[sortOrders][][field]=` - Specifies the field to sort on. By default, search results are returned in descending order. You can sort on multiple fields. For example, to sort on `price` first and then by `name`, call `searchCriteria[sortOrders][0][field]=price&searchCriteria[sortOrders][1][field]=name`. + +* `searchCriteria[sortOrders][][direction]=ASC | DESC` - Specifies whether to return results in ascending (ASC) or descending (DESC) order. To expand the previous example and sort the `price` fields in descending order and the `name` fields in ascending order, call `searchCriteria[sortOrders][0][field]=price&searchCriteria[sortOrders][1][field]=name&searchCriteria[sortOrders][1][direction]=ASC`. + +* `searchCriteria[pageSize]` - Specifies the maximum number of items to return. The value must be an integer. If the `pageSize` is not specified, the system returns all matches. + +* `searchCriteria[currentPage]` - Returns the current page. + +### Example for search criteria to determine the sort order and attributes to return + +This example shows how to use search criteria to determine the sort order and attributes to return. It returns orders with status `pending`. + +**Endpoint:** + +`GET /rest//V1/orders/` + +**Headers:** + +`Content-Type` `application/json` + +`Authorization` `Bearer ` + +**Parameters:** + +Parameter | Value | Description +--- | --- | --- +searchCriteria[filter_groups][0][filters][0][field] | status | Attribute name to filter +searchCriteria[filter_groups][0][filters][0][value] | pending | Attribute value to filter +fields | items[increment_id,entity_id] | Attributes to return in the response. If you do not specify this parameter, all attributes will be returned. + +**Payload:** + +Not applicable + +**Request:** + +```http +GET /rest/V1/orders? +searchCriteria[filter_groups][0][filters][0][field]=status& +searchCriteria[filter_groups][0][filters][0][value]=pending& +searchCriteria[sortOrders][0][field]=increment_id& +fields=items[increment_id,entity_id] +``` + +**Response:** + +```json +{ + "items": [ + { + "entity_id": 3003, + "increment_id": "WA0003003" + }, + { + "entity_id": 3140, + "increment_id": "WA0003140" + }, + { + "entity_id": 9435, + "increment_id": "WA0009435" + } + ] +} +``` diff --git a/src/guides/v2.4/rest/retrieve-filtered-responses.md b/src/guides/v2.4/rest/retrieve-filtered-responses.md deleted file mode 120000 index 09b374e59bb..00000000000 --- a/src/guides/v2.4/rest/retrieve-filtered-responses.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/rest/retrieve-filtered-responses.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/retrieve-filtered-responses.md b/src/guides/v2.4/rest/retrieve-filtered-responses.md new file mode 100644 index 00000000000..fe142e676a7 --- /dev/null +++ b/src/guides/v2.4/rest/retrieve-filtered-responses.md @@ -0,0 +1,195 @@ +--- +group: rest-api +title: Retrieve filtered responses for REST endpoints + +--- + +Some REST calls return dozens or even hundreds of parameters, and parsing through all this data can be unwieldy. In addition, mobile app developers might find the bandwidth needed to process a request to be excessive. To resolve these problems, Magento provides a query parameter-based syntax for REST requests that return partial responses. + +{:.bs-callout-tip} +This feature is not available for SOAP, because SOAP does not allow partial responses. + +You can append `?fields=,,...` to any GET, POST, or PUT operation to filter unimportant information from the response. `` can be any of the following: + +* Simple top-level field +* Top-level object that includes all fields +* Top-level object with selected fields +* Nested objects + +Separate each field or object with a comma. + +On POST and PUT requests, Magento ignores the `fields` parameter as input, but the response includes only the requested fields and objects. + +## Examples +{:.no_toc} + +All examples use {{site.data.var.ce}} sample data. + +## Simple fields + +The following example returns only the `sku`, `price`, and `name` for the specified product: + +`GET /rest//V1/products/24-MB01?fields=sku,price,name` + +```json +{ + "sku": "24-MB01" + "name": "Joust Duffle Bag" + "price": 24.99 +} +``` + +## Simple fields and top-level objects with all fields + +The following example returns only the customer first name, last name, and the entire `billing_address` object from a specified order. Do not include brackets `[]` after an object name when you want to return all of the object's contents. + +`GET /rest//V1/orders/2?fields=billing_address,customer_firstname,customer_lastname` + +```json +{ +"customer_firstname": "Veronica" +"customer_lastname": "Costello" +"billing_address": { + "address_type": "billing" + "city": "Calder" + "country_id": "US" + "customer_address_id": 1 + "email": "roni_cost@example.com" + "entity_id": 4 + "firstname": "Veronica" + "lastname": "Costello" + "parent_id": 2 + "postcode": "49628-7978" + "region": "Michigan" + "region_code": "MI" + "region_id": 33 + "street": "6146 Honey Bluff Parkway" + "telephone": "(555) 229-3326" + } +} +``` + +## Top-level object with selected fields + +The following example returns only the `name`, `qty`, and `sku` fields defined in an `items` object from a specified shipment: + +`GET /rest//V1/shipment/2?fields=items[name,qty,sku]` + +```json +"items": [ + { + "name": "Minerva LumaTech™ V-Tee-XS-Blue", + "qty": 1, + "sku": "WS08-XS-Blue", + } +] +``` + +## Nested objects + +This example returns only the following: + +* The product's `sku` and `name` +* The entire `category_links` object, which is defined in `extension_attributes` +* The `item_id` and `qty` fields of the `stock_item` object, which is also defined in `extension_attributes` + +`GET /rest//V1/products/MT12?fields=name,sku,extension_attributes[category_links,stock_item[item_id,qty]]` + +```json +{ + "sku": "MT12" + "name": "Cassius Sparring Tank" + "extension_attributes": { + "category_links": { + "position": 1 + "category_id": "18" + } + "stock_item": { + "item_id": 732 + "qty": 0 + } + } +} +``` + +## POST operation + +The following POST operation and payload creates a [catalog](https://glossary.magento.com/catalog) category named `New Category`. Magento returns only the `id`, `parent_id`, and `name` attributes + +`POST /rest//V1/categories?fields=id,parent_id,name` + +**Payload:** + +```json +{ + "category": { + "name": "New Category", + "is_active": true + } +} +``` + +**Response:** + +```json +{ +"id": 43 +"parent_id": 2 +"name": "New Category" +} +``` + +## Using with searchCriteria + +The [`searchCriteria` query parameter](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) allows you to search across multiple objects in a collection. You can use the `fields` query parameter in conjunction with `searchCriteria` to limit the output. The question mark (?) that precedes `fields` in all the other examples in this document is replaced with an ampersand (&). + +The following query returns only the `sku` and `name` parameters for product items whose `category_gear` attribute includes the value `86`. + +`GET /rest//V1/products/?searchCriteria[filter_groups][0][filters][0][field]=category_gear&searchCriteria[filter_groups][0][filters][0][value]=86&searchCriteria[filter_groups][0][filters][0][condition_type]=finset&fields=items[sku,name]` + +```json +{ +"items": + { + "sku": "24-MG04" + "name": "Aim Analog Watch" + } + { + "sku": "24-MG01" + "name": "Endurance Watch" + } + { + "sku": "24-MG03" + "name": "Summit Watch" + } + { + "sku": "24-MG05" + "name": "Cruise Dual Analog Watch" + } + { + "sku": "24-MG02" + "name": "Dash Digital Watch" + } + { + "sku": "24-WG09" + "name": "Luma Analog Watch" + } + { + "sku": "24-WG01" + "name": "Bolo Sport Watch" + } + { + "sku": "24-WG03" + "name": "Clamber Watch" + } + { + "sku": "24-WG02" + "name": "Didi Sport Watch" + } +} +``` + +{:.ref-header} +Related topics + +* [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) diff --git a/src/guides/v2.4/rest/search-endpoint.md b/src/guides/v2.4/rest/search-endpoint.md deleted file mode 120000 index fd5f607c496..00000000000 --- a/src/guides/v2.4/rest/search-endpoint.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/rest/search-endpoint.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/search-endpoint.md b/src/guides/v2.4/rest/search-endpoint.md new file mode 100644 index 00000000000..4e754ec95cc --- /dev/null +++ b/src/guides/v2.4/rest/search-endpoint.md @@ -0,0 +1,143 @@ +--- +group: rest-api +title: Search for products with the /search endpoint + +contributor_name: comwrap GmbH +contributor_link: https://www.comwrap.com/ +--- + +Magento provides two endpoints for searching products: + +* `GET V1/search` +* `GET V1/products` + +The `GET V1/search` endpoint replicates the search capabilities that customers and guests use to find products on the storefront. The `GET V1/products` endpoint returns results like you would receive by searching on the product grid page in the Admin. + +The following table highlights the differences between these two endpoints: + +Property | V1/products | V1/search +--- | --- | --- +Requires authorization token? | Yes | No +Has direct access to product data? | Yes | No (the Search engine acts as proxy) +Can specify any product attribute? | Yes | No +Contains product data in the response? | Yes | No +Are results sorted by search relevance? | No | Yes +Contains aggregations/buckets in the response? | No | Yes, for `quick_search_container` and `catalog_view_container` searches + +The `V1/search` endpoint is generally more useful when you have only human (or human-like) search terms at hand, targeted to isolate a single product or a limited set of products. An added benefit is that the results are pre-sorted by their applicable search relevance. + +In all other cases, for example when building and filtering product collections, and especially when other non-human backend data is available, such as an attribute's option IDs, the `V1/products` endpoint is a good choice. + +## Build queries for V1/search + +When you use `V1/search`, you are searching for products through the catalog. The response comes from the configured search engine (**Stores** > Settings > **Configuration** > **Catalog** > **Catalog Search** > **Search engine**), and the results are the same as those returned by using the regular frontend search. + +All search queries run against the `catalogsearch_fulltext` index. + +The basic structure of a REST call using `V1/search` follows: + +```http +GET /rest//V1/search?searchCriteria[requestName]=& +searchCriteria[filter_groups][0][filters][0][field]=& +searchCriteria[filter_groups][0][filters][0][value]= +``` + +By default, the container name can be one of these values: + +* quick_search_container +* advanced_search_container +* catalog_view_container + +The possible values for the filter name and the search value are specific for each container. + +Each searchable attribute defines a search boost value, which defaults to 1. However, some predefined attributes have higher values. For example, the default boost value for `sku` is 6, while the `name` has a default value of 5. + +For more details about the capabilities of searches using `V1/search`, review `Magento/CatalogSearch/etc/search_request.xml`. + +### Quick searches + +The `quick_search_container` request allows you to perform the same search that a customer performs on the storefront. + +By default, a filter name can be one of these: + +* `category_ids` +* `price.from` +* `price.to` +* `search_term` +* `visibility` + +Quick searches return aggreggations and buckets. + +#### Example + +The following example performs a quick search for `digital watch`: + +```http +GET /rest//V1/search?searchCriteria[requestName]=quick_search_container& +searchCriteria[filter_groups][0][filters][0][field]=search_term& +searchCriteria[filter_groups][0][filters][0][value]=digital watch +``` + +### Advanced searches + +The `advanced_search_container` request performs more complex searches, like those possible on the Advanced Search page. + +The default filters for advanced searches can use the following [field] value: + +* `category_ids` +* `price.from` +* `price.to` +* `sku` + +The filter can also be any searchable attribute. To make an attribute searchable, set **Stores** > Attributes > **Product** > > **Storefront Properties** > **Use in Search** to **Yes**. The search query can include attributes such as the product name, SKU, or any other custom attribute. + +Advanced searches can use any condition type to make comparisions, such as `like`, `eq`, or `finset`. See [Search using REST](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) describes condition types. + +Advanced searches do not return aggregation data. + +#### Examples + +The following example get products within a price range: + +```http +GET /rest//V1/search?searchCriteria[requestName]=advanced_search_container& +searchCriteria[filter_groups][0][filters][0][field]=price.from& +searchCriteria[filter_groups][0][filters][0][value]=2& +searchCriteria[filter_groups][0][filters][1][field]=price.to& +searchCriteria[filter_groups][0][filters][1][value]=3 +``` + +The following example gets products where the SKU might contain a specified string: + +```http +GET /rest//V1/search?searchCriteria[requestName]=advanced_search_container& +searchCriteria[filter_groups][0][filters][0][field]=sku& +searchCriteria[filter_groups][0][filters][0][value]=shirt& +searchCriteria[filter_groups][0][filters][0][condition_type]=like +``` + +### Catalog view searches + +The `catalog_view_container`request accepts the following filters: + +* `category_ids` +* `price.from` +* `price.to` +* `visibility` + +Quick searches return aggreggations and buckets. + +#### Example + +The following example gets all products in a given category: + +```http +GET /rest//V1/search?searchCriteria[requestName]=catalog_view_container& +searchCriteria[filter_groups][0][filters][0][field]=category_ids& +searchCriteria[filter_groups][0][filters][0][value][0]=4& +searchCriteria[filter_groups][0][filters][0][condition_type]=eq +``` + +## Build queries for V1/products + +[Search using REST](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) provides examples that can be used to search for products. diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md deleted file mode 120000 index 8d8d1883f64..00000000000 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md new file mode 100644 index 00000000000..fb98e68dbdc --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md @@ -0,0 +1,37 @@ +--- +layout: tutorial +group: rest-api +title: Create a configurable product using bulk APIs + +menu_title: Initial tasks +menu_order: 0 +level3_subgroup: bulk-configurable-product-tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +functional_areas: + - Integration +contributor_name: comwrap GmbH +contributor_link: http://comwrap.com/ +--- + +A system integrator can use Magento REST bulk APIs to perform actions on a large scale; such as, creating multiple customers and products, changing prices across an inventory, and assigning large groups of products to a specific warehouse, all within a single call. + + To demonstrate how to use the REST bulk APIs, this tutorial will start with a _configurable product_. A configurable product is a parent product of multiple simple products. You define a configurable product so that the buyer must make one or more choices to select a product. For example, most clothing comes in a variety of colors and sizes. If you are offering a skirt in black, red, and blue colorways in sizes small, medium, and large, then you would create a configurable product with nine simple products, one for each combination of color and size. + + In this tutorial, we will create a gray t-shirt that comes in three sizes (small, medium, and large). The configurable product defines basic characteristics of the t-shirt. Then, we will create a simple product for each size and link each of them to the configurable product. Finally, we will add an option that allows the customer to specify text that can be added to the shirt. + + This **4-step tutorial** generally takes **45 minutes**. + +### Before you begin + +* Install a Magento 2.3 (or later) instance with sample data. The sample data defines a functional store, called Luma, that sells fitness clothing and accessories. +* Install a REST client. You can use any REST client to send calls to Magento. [Postman](https://www.getpostman.com/) is recommended. +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/) for more information. +* Use the `bin/magento queue:consumers:start async.operations.all` command to enable bulk endpoint processing. + +### Other resources + +* [REST Tutorials](https://developer.adobe.com/commerce/webapi/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. +* [Asynchronous web endpoints](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) provides information about how to use Magento Asynchronous API +* [Bulk endpoints](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html) provides information about how to use Magento Bulk API \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md deleted file mode 120000 index d7301bc8e39..00000000000 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md new file mode 100644 index 00000000000..094da2885a5 --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md @@ -0,0 +1,319 @@ +--- +layout: tutorial +group: rest-api +title: Step 2. Create the configurable and simple products + +subtitle: Create a configurable product using bulk APIs +menu_title: Step 2. Create the configurable and simple products +menu_order: 20 +level3_subgroup: bulk-configurable-product-tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +functional_areas: + - Integration +contributor_name: comwrap GmbH +contributor_link: http://comwrap.com/ +--- + +By providing configurable and simple product information, you can use the bulk API to create all necessary products with a single call. + +### Configurable product + +Some notes about the configurable product payload example: + +* We have the information we need to create the Champ Tee configurable product. +* The sample payload does not contain the price or the size, as these are defined in the simple products section. +* The `visibility` attribute is set to 4, which allows customers to find the product by browsing or searching. Each simple product defined in the payload can override the `visibility` attribute. + +### Simple products + + The payloads for creating a simple product and a configurable product are identical, with the following exceptions: + +* The simple product `sku` appends the configurable option (the size in this tutorial) to the configurable product `sku`. +* The `name` indicates the size. +* The `type_id` is set to `simple`. +* The `visibility` is set to `1`, indicating the simple product should not be displayed on the store. +* The `price` and `size` attributes are specified. + + Although it's not required, the simple product payload also includes `stock_item` information. By default, the Luma store hides out-of-stock items, so adding stock will make the Champ Tee visible on the website. + + {:.bs-callout-info} +Before you use this code sample, verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute searchCriteria](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. + + {:.bs-callout-info} +The payload contains both the configurable product and the simple products. + + **Endpoint:** + + `POST /rest/default/async/bulk/V1/products` + + **Payload:** + +{% collapsible Show code sample %} + + ```json +[{ + "product": { + "sku": "MS-Champ", + "name": "Champ Tee", + "attribute_set_id": 9, + "status": 1, + "visibility": 4, + "type_id": "configurable", + "weight": "0.5", + "extension_attributes": { + "category_links": [ + { + "position": 0, + "category_id": "11" + }, + { + "position": 1, + "category_id": "12" + }, + { + "position": 2, + "category_id": "16" + } + ] + }, + "custom_attributes": [ + { + "attribute_code": "description", + "value": "The Champ Tee keeps you cool and dry while you do your thing. Let everyone know who you are by adding your name on the back for only $10." + }, + { + "attribute_code": "tax_class_id", + "value": "2" + }, + { + "attribute_code": "material", + "value": "148" + }, + { + "attribute_code": "pattern", + "value": "196" + }, + { + "attribute_code": "color", + "value": "52" + } + ] + } +}, +{ + "product": { + "sku": "MS-Champ-S", + "name": "Champ Tee Small", + "attribute_set_id": 9, + "price": 25, + "status": 1, + "visibility": 1, + "type_id": "simple", + "weight": "0.5", + "extension_attributes": { + "category_links": [ + { + "position": 0, + "category_id": "11" + }, + { + "position": 1, + "category_id": "12" + }, + { + "position": 2, + "category_id": "16" + } + ], + "stock_item": { + "qty": "10", + "is_in_stock": true + } + }, + "custom_attributes": [ + { + "attribute_code": "description", + "value": "The Champ Tee keeps you cool and dry while you do your thing. Let everyone know who you are by adding your name on the back for only $10." + }, + { + "attribute_code": "tax_class_id", + "value": "2" + }, + { + "attribute_code": "material", + "value": "148" + }, + { + "attribute_code": "pattern", + "value": "196" + }, + { + "attribute_code": "color", + "value": "52" + }, + { + "attribute_code": "size", + "value": "168" + } + ] + } +}, +{ + "product": { + "sku": "MS-Champ-M", + "name": "Champ Tee Medium", + "attribute_set_id": 9, + "price": 25, + "status": 1, + "visibility": 1, + "type_id": "simple", + "weight": "0.5", + "extension_attributes": { + "category_links": [ + { + "position": 0, + "category_id": "11" + }, + { + "position": 1, + "category_id": "12" + }, + { + "position": 2, + "category_id": "16" + } + ], + "stock_item": { + "qty": "10", + "is_in_stock": true + } + }, + "custom_attributes": [ + { + "attribute_code": "description", + "value": "The Champ Tee keeps you cool and dry while you do your thing. Let everyone know who you are by adding your name on the back for only $10." + }, + { + "attribute_code": "tax_class_id", + "value": "2" + }, + { + "attribute_code": "material", + "value": "148" + }, + { + "attribute_code": "pattern", + "value": "196" + }, + { + "attribute_code": "color", + "value": "52" + }, + { + "attribute_code": "size", + "value": "169" + } + ] + } +}, +{ + "product": { + "sku": "MS-Champ-L", + "name": "Champ Tee Large", + "attribute_set_id": 9, + "price": 25, + "status": 1, + "visibility": 1, + "type_id": "simple", + "weight": "0.5", + "extension_attributes": { + "category_links": [ + { + "position": 0, + "category_id": "11" + }, + { + "position": 1, + "category_id": "12" + }, + { + "position": 2, + "category_id": "16" + } + ], + "stock_item": { + "qty": "10", + "is_in_stock": true + } + }, + "custom_attributes": [ + { + "attribute_code": "description", + "value": "The Champ Tee keeps you cool and dry while you do your thing. Let everyone know who you are by adding your name on the back for only $10." + }, + { + "attribute_code": "tax_class_id", + "value": "2" + }, + { + "attribute_code": "material", + "value": "148" + }, + { + "attribute_code": "pattern", + "value": "196" + }, + { + "attribute_code": "color", + "value": "52" + }, + { + "attribute_code": "size", + "value": "170" + } + ] + } +} +] +``` + +{% endcollapsible %} + + **Response:** + +```json +{ + "bulk_uuid": "c08a2b99-4be2-4b28-af7e-56e9664e0b39", + "request_items": [ + { + "id": 0, + "data_hash": "73170608b04187fe5939ece183711eff1bf9c4f4e30fc334db2affed1055c3f1", + "status": "accepted" + }, + { + "id": 1, + "data_hash": "73170608b04187fe5939ece183711eff1bf9c4f4e30fc334db2affed1055c3f1", + "status": "accepted" + }, + { + "id": 2, + "data_hash": "73170608b04187fe5939ece183711eff1bf9c4f4e30fc334db2affed1055c3f1", + "status": "accepted" + } + ], + "errors": false +} +``` + + {:.bs-callout-info} +For information about response fields, see the [Bulk API](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html) section. To check the status of operations, see the API for [Bulk operation status endpoints](https://developer.adobe.com/commerce/webapi/rest/operation-status-endpoints.html). + +## Verify this step + +* Log in to the Luma website and select **Catalog > Products**. The product appears in the grid. + + ![Product page with configurable product](https://developer.adobe.com/commerce/webapi/rest/images/products-page.png) + +* On the Luma storefront page, search for `Champ`. No results are returned. diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md deleted file mode 120000 index 09ca0979301..00000000000 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md new file mode 100644 index 00000000000..5863f5f53ac --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md @@ -0,0 +1,80 @@ +--- +layout: tutorial +group: rest-api +title: Step 4. Create the personalization option + +subtitle: Create a configurable product using bulk APIs +menu_title: Step 4. Create the personalization option +menu_order: 40 +level3_subgroup: bulk-configurable-product-tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +functional_areas: + - Integration +contributor_name: comwrap GmbH +contributor_link: http://comwrap.com/ +--- + +Let's add a text box to the product page that allows the customer to add his name (up to 15 characters) to the back of the shirt. + +The `product_sku` is the `sku` of the configurable product. The `sku` specified in the payload is a string that is appended to the `product_sku` when a customer selects to purchase this item. Likewise, the `price` supplied in the payload is added to the configurable product price. + +**Endpoint:** + +`POST /rest/default/async/bulk/V1/products/options` + +**Payload:** + +```json +[{ + "option": { + "product_sku": "MS-Champ", + "title": "Add Your Name (Max 15 Characters)", + "type": "field", + "sort_order": 1, + "is_require": false, + "price": 10, + "price_type": "fixed", + "sku": "Personalized", + "max_characters": 15 + } +}] + ``` + + **Response:** + + ```json +{ + "bulk_uuid": "53ef1382-904a-4ba0-bb72-ebc5edd47da5", + "request_items": [ + { + "id": 0, + "data_hash": "73170608b04187fe5939ece183711eff1bf9c4f4e30fc334db2affed1055c3f1", + "status": "accepted" + } + ], + "errors": false +} +``` + +## Verify this step + +* Log in to the Luma website and select **Catalog > Products**. Click on the **Champ Tee** configurable product and expand the **Customizable Options** section. + + ![Product page with configurable and simple products](https://developer.adobe.com/commerce/webapi/rest/images/options-section.png) + +* On the Luma storefront page, search for `Champ`. Then click on the Champ Tee product. + + ![Search results](https://developer.adobe.com/commerce/webapi/rest/images/add-your-name.png) + + {:.bs-callout-info} + If the personalization option is not displayed, go to the **Champ Tee** configuration product page in Admin and set **Stock Status** to **In Stock**. + +## Congratulations! You've finished. + {:.no_toc} + +{:.ref-header} +Related topic + +[Order Processing with REST APIs Tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/) diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md deleted file mode 120000 index 82a9c5fa195..00000000000 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md new file mode 100644 index 00000000000..2a8b31a4f86 --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md @@ -0,0 +1,167 @@ +--- +layout: tutorial +group: rest-api +title: Step 3. Define configurable product options + +subtitle: Create a configurable product using bulk APIs +menu_title: Step 3. Define configurable product options +menu_order: 30 +level3_subgroup: bulk-configurable-product-tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +functional_areas: + - Integration +contributor_name: comwrap GmbH +contributor_link: http://comwrap.com/ +--- + + Now that we've created all the Champ Tee products, we need to assign `size` as the configurable attribute and link the simple products to the configurable product. + +## Set the configurable attribute + + The `POST async/bulk/V1/configurable-products/bySku/options` call assigns the specified `attribute_id` to be the configurable attribute. + +{:.bs-callout-warning} + The `attribute_id` and its value may be different on your installation. Check the values carefully before using them in your calls. To get the correct `attribute_id`, see [Get the list of attributes defined in an attribute searchCriteria](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. + + The value assigned to the `value_index` must be unique within the system. + + **Endpoint:** + + `POST /rest/default/async/bulk/V1/configurable-products/bySku/options` + + **Payload:** + + ```json +[{ + "sku": "MS-Champ", + "option": { + "attribute_id": "141", + "label": "Size", + "position": 0, + "is_use_default": true, + "values": [ + { + "value_index": 9 + } + ] + } +}] +``` + + **Response:** + + ```json +{ + "bulk_uuid": "98c46050-cd66-4b49-9d45-69bfa04efc78", + "request_items": [ + { + "id": 0, + "data_hash": "17c5e6b0d6fdf98ea83f600c8cc7e9f5a437e7f51e21a9c40070bb6208e1334c", + "status": "accepted" + } + ], + "errors": false +} +``` + +## Link the simple products to the configurable product + +Now that you have set the configurable attribute to be `sku`, you can link all simple products to the configurable product and execute a single call with a payload that contains an array of simple products. To do this, specify the `sku` of the configurable product, and the `childSku` of each simple product. + + **Endpoint:** + + {:.bs-callout-info} +Bulk endpoint routes cannot contain input parameters, such as a `sku` value. You must replace input parameters with a string that begins with `by` and ends with the input parameter name, such as `bySku`. See [`bulk endpoints`](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html) for more information. + + `POST /rest/default/async/bulk/V1/configurable-products/bySku/child` + + **Payload:** + + ```json +[ + { + "sku": "MS-Champ", + "childSku": "MS-Champ-S" + }, + { + "sku": "MS-Champ", + "childSku": "MS-Champ-M" + }, + { + "sku": "MS-Champ", + "childSku": "MS-Champ-L" + }, + // .... you can link as many products at the same time as required .... +] +``` + + **Response:** + + ```json +{ + "bulk_uuid": "e78042d1-de13-4260-8f56-d5dd13f89e3c", + "request_items": [ + { + "id": 0, + "data_hash": "b4cfe401d84fbfadc94dd86782f18104dcaa162649f032fe105420037a44f795", + "status": "accepted" + }, + { + "id": 1, + "data_hash": "b4cfe401d84fbfadc94dd86782f18104dcaa162649f032fe105420037a44f795", + "status": "accepted" + }, + { + "id": 2, + "data_hash": "b4cfe401d84fbfadc94dd86782f18104dcaa162649f032fe105420037a44f795", + "status": "accepted" + } + ], + "errors": false +} +``` + +## Verify this step + +* Log in to the Luma website and select **Catalog > Products**. Click on the **Champ Tee** configurable product and expand the **Configurations** section. + + ![Product page with configurable and simple products](https://developer.adobe.com/commerce/webapi/rest/images/configurations-section.png) + +* On the Luma storefront page, search for `Champ`. + + ![Search results](https://developer.adobe.com/commerce/webapi/rest/images/search-results.png) + +* Call `GET /rest/default/V1/products/MS-Champ`. The response includes the `configurable_product_options` and `configurable_product_links` arrays. + + ```json +... +"configurable_product_options": [ + { + "id": 338, + "attribute_id": "141", + "label": "Size", + "position": 0, + "values": [ + { + "value_index": 168 + }, + { + "value_index": 169 + }, + { + "value_index": 170 + } + ], + "product_id": 2078 + } +], +"configurable_product_links": [ + 2079, + 2080, + 2081 +] +}, +... +``` diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md deleted file mode 120000 index 50a703349bf..00000000000 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/bulk-configurable-product/plan-product.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md new file mode 100644 index 00000000000..14ddbd0d58f --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md @@ -0,0 +1,146 @@ +--- +layout: tutorial +group: rest-api +title: Step 1. Plan the product + +subtitle: Create a configurable product using bulk APIs +menu_title: Step 1. Plan the product +menu_order: 10 +level3_subgroup: bulk-configurable-product-tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +functional_areas: + - Integration +contributor_name: comwrap GmbH +contributor_link: http://comwrap.com/ +--- + + To create a configurable product programmatically, you'll need to know the following: + +* The attribute names and values defined in the attribute set assigned to the configurable product. +* The category numbers assigned to the configurable product. +* Which attributes to use as the configuration options. + + Since this tutorial uses the sample data, we can take advantage of the options that the Top attribute set provides. This attribute set contains attributes that describe the fabric, sleeve length, and other characteristics that are specific to clothing. It also includes EAV attributes such as size and color, which are commonly available to all types of physical products. + + The size of the t-shirt will be the configurable aspect of this product. Therefore, we'll create a simple product for each size (Small, Medium, and Large). + +## Define product characteristics + + The following table lists the general characteristics of the men's t-shirt we're creating. These items are among those listed on the New Product page in Admin when the Top attribute set is selected. + + Characteristic | Description +--- | --- +Attribute Set | Top +Product Name | Champ Tee +SKU | MS-Champ +Price | 25.00 +Tax Class | Taxable Goods +Weight | 0.5 +Categories | Men, Tops, Tees +Visibility | Catalog, Search +Material | LumaTech +Pattern | Graphic Print +Color | Gray +Size | Configurable in small, medium, or large +Description | The Champ Tee keeps you cool and dry while you do your thing. Let everyone know who you are by adding your name on the back for only $10. + + A merchant typically provides the product name, SKU, price, weight, and description. The other characteristics are defined by the system. + +## Find the system-defined values + + We'll make several calls to find the values needed to create the product + +### Get the attribute set ID + + The sample data provides multiple attribute sets, including Default, Top, and Bottom. To assign the Top attribute set to the product, we need to know the corresponding `attribute_set_id`. + + Use the following call to search for the attribute set named `Top`. + + **Endpoint:** + + ```html +GET /rest//V1/eav/attribute-sets/list? +searchCriteria[filter_groups][0][filters][0][field]=attribute_set_name& +searchCriteria[filter_groups][0][filters][0][value]=Top& +searchCriteria[filter_groups][0][filters][0][condition_type]=eq +``` + + **Response:** + + The `attribute_set_id` for the Top attribute set is `9`. + + ```json +{ + "items": [ + { + "attribute_set_id": 9, + "attribute_set_name": "Top", + "sort_order": 0, + "entity_type_id": 4 + } + ], + "search_criteria": { + "filter_groups": [ + { + "filters": [ + { + "field": "attribute_set_name", + "value": "Top", + "condition_type": "eq" + } + ] + } + ] + }, + "total_count": 1 +} +``` + +### Get the list of attributes defined in an attribute searchCriteria {#get-attributes} + + Use the `GET V1/products/attribute-sets/:attributeSetId/attributes` call to return information about the attributes defined in the Top attribute set. + + **Endpoint:** + + `GET /rest/default/V1/products/attribute-sets/9/attributes` + + **Response:** + + The response contains almost 3,000 lines. The following table provides a summary of the attributes that are relevant in this tutorial. + + Admin label | Selected value | Attribute ID | attribute_code | Attribute value +--- | --- | --- | --- | --- +Tax Class | Taxable Goods | 132 | `tax_class_id` | 2 +Visibility | Catalog, Search | 99 | `visibility` | 4 +Material | LumaTech | 136 | `material` | 148 +Pattern | Graphic Print | 152 | `pattern` | 196 +Color | Gray | 93 | `color` | 52 +Size | Not applicable | 141 | `size` | 168 (small), 169 (medium), 170 (large) + + {:.bs-callout-warning} +The attribute ID and value numbers might be different on your installation. Check the values carefully before using them in your calls. + +### Get the list of category values + + You must assign the product to one or more categories to enable customers to find the product by browsing. We'll assign the Champ Tee to the Men, Tops, and Tees categories. + + Use the following call to search for all categories (`id` is greater than or equal to `0`). + + ```html +GET /rest/default/V1/categories? +searchCriteria[filter_groups][0][filters][0][field]=id& +searchCriteria[filter_groups][0][filters][0][value]=1& +searchCriteria[filter_groups][0][filters][0][condition_type]=gte +``` + + Note that women's tops and tees have different ids than men's tops and tees. The values for men's clothing are: + +* Men - `11` +* Tops - `12` +* Tees - `16` + +## Verify this step + + At this point, we're gathering information, so there is nothing to verify. \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md b/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md deleted file mode 120000 index 9de9b490c0b..00000000000 --- a/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/bundle-product/bundle-product-intro.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md b/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md new file mode 100644 index 00000000000..2645b7ccba3 --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md @@ -0,0 +1,22 @@ +--- +layout: tutorial +group: rest-api +title: Create a bundle product tutorial + +contributor_name: Goivvy LLC +contributor_link: https://www.goivvy.com/magento-optimization-service +--- + +This tutorial shows a way to use Magento REST APIs to create a _bundle product_. A bundle product is a "create your own" type of product. + +In this tutorial, we will create a desktop computer by bundling a processor, monitor, video card and RAM. We will have to create a simple product for each of these and then attach them to the bundle _computer_ product. + +This **3-step tutorial** generally takes **40 minutes**. + +### Before you begin + +* Install a Magento 2.3 (or later) instance with sample data. + +* Install a REST client. We will use Postman in this tutorial. + +* Generate an admin authorization token. All calls in this tutorial require administrator privileges. diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md b/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md deleted file mode 120000 index 3f234418161..00000000000 --- a/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/bundle-product/create-bundle-product.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md b/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md new file mode 100644 index 00000000000..c7054060f71 --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md @@ -0,0 +1,311 @@ +--- +layout: tutorial +group: rest-api +title: Step 3. Create the bundle product + +contributor_name: Goivvy LLC +contributor_link: https://www.goivvy.com/magento-optimization-service +--- + +Now we will add the bundle product. We will use two bundle options: `RAM` and `Monitor`. + +**Endpoint:** + +```html +POST http://domain.com/rest/default/V1/products +``` + +**Payload:** + +```json +{ + "product": { + "sku": "Desktop-Computer", + "name": "Desktop Computer", + "attribute_set_id": 4, + "status": 1, + "visibility": 4, + "type_id": "bundle", + "extension_attributes": { + "stock_item": { + "qty": 100, + "is_in_stock":true + }, + "website_ids": [ + 1 + ], + "category_links": [ + { + "position": 0, + "category_id": "32" + } + ], + "bundle_product_options": [ + { + "option_id": 0, + "position": 1, + "sku": "compuer-ram", + "title": "RAM", + "type": "select", + "required": true, + "product_links": [ + { + "sku": "RAM-12GB", + "option_id": 1, + "qty": 1, + "position": 1, + "is_default": false, + "price": 0, + "price_type": 0, + "can_change_quantity": 0 + }, + { + "sku": "RAM-24GB", + "option_id": 1, + "qty": 1, + "position": 2, + "is_default": false, + "price": 0, + "price_type": 0, + "can_change_quantity": 0 + } + ] + }, + { + "option_id": 1, + "position": 2, + "sku": "computer-monitor", + "title": "Monitor", + "type": "select", + "required": true, + "product_links": [ + { + "sku": "Monitor-15", + "option_id": 2, + "qty": 1, + "position": 1, + "is_default": false, + "price": 0, + "price_type": 0, + "can_change_quantity": 0 + }, + { + "sku": "Monitor-17", + "option_id": 2, + "qty": 1, + "position": 2, + "is_default": false, + "price": 0, + "price_type": 0, + "can_change_quantity": 0 + } + ] + } + ] + }, + "custom_attributes": [ + { + "attribute_code": "price_view", + "value": "0" + } + ] + }, + "saveOptions": true +} +``` + +**Response:** + +{% collapsible Show response %} + +```json +{ + "id": 25, + "sku": "Desktop-Computer", + "name": "Desktop Computer", + "attribute_set_id": 4, + "price": 0, + "status": 1, + "visibility": 4, + "type_id": "bundle", + "created_at": "2022-04-15 18:04:04", + "updated_at": "2022-04-15 18:04:04", + "weight": 0, + "extension_attributes": { + "website_ids": [ + 1 + ], + "category_links": [ + { + "position": 0, + "category_id": "32" + } + ], + "stock_item": { + "item_id": 25, + "product_id": 25, + "stock_id": 1, + "qty": 0, + "is_in_stock": true, + "is_qty_decimal": false, + "show_default_notification_message": false, + "use_config_min_qty": true, + "min_qty": 0, + "use_config_min_sale_qty": 1, + "min_sale_qty": 1, + "use_config_max_sale_qty": true, + "max_sale_qty": 10000, + "use_config_backorders": true, + "backorders": 0, + "use_config_notify_stock_qty": true, + "notify_stock_qty": 1, + "use_config_qty_increments": true, + "qty_increments": 0, + "use_config_enable_qty_inc": true, + "enable_qty_increments": false, + "use_config_manage_stock": true, + "manage_stock": true, + "low_stock_date": null, + "is_decimal_divided": false, + "stock_status_changed_auto": 0 + }, + "bundle_product_options": [ + { + "option_id": 14, + "title": "RAM", + "required": true, + "type": "select", + "position": 1, + "sku": "Desktop-Computer", + "product_links": [ + { + "id": "19", + "sku": "RAM-12GB", + "option_id": 14, + "qty": 1, + "position": 1, + "is_default": false, + "price": 25, + "price_type": null, + "can_change_quantity": 0 + }, + { + "id": "20", + "sku": "RAM-24GB", + "option_id": 14, + "qty": 1, + "position": 2, + "is_default": false, + "price": 50, + "price_type": null, + "can_change_quantity": 0 + } + ] + }, + { + "option_id": 15, + "title": "Monitor", + "required": true, + "type": "select", + "position": 2, + "sku": "Desktop-Computer", + "product_links": [ + { + "id": "21", + "sku": "Monitor-15", + "option_id": 15, + "qty": 1, + "position": 1, + "is_default": false, + "price": 100, + "price_type": null, + "can_change_quantity": 0 + }, + { + "id": "22", + "sku": "Monitor-17", + "option_id": 15, + "qty": 1, + "position": 2, + "is_default": false, + "price": 150, + "price_type": null, + "can_change_quantity": 0 + } + ] + } + ] + }, + "options": [], + "media_gallery_entries": [], + "custom_attributes": [ + { + "attribute_code": "shipment_type", + "value": "0" + }, + { + "attribute_code": "options_container", + "value": "container2" + }, + { + "attribute_code": "msrp_display_actual_price_type", + "value": "0" + }, + { + "attribute_code": "url_key", + "value": "desktop-computer" + }, + { + "attribute_code": "price_view", + "value": "0" + }, + { + "attribute_code": "required_options", + "value": "0" + }, + { + "attribute_code": "has_options", + "value": "0" + }, + { + "attribute_code": "sku_type", + "value": "0" + }, + { + "attribute_code": "price_type", + "value": "0" + }, + { + "attribute_code": "tax_class_id", + "value": "2" + }, + { + "attribute_code": "weight_type", + "value": "0" + }, + { + "attribute_code": "category_ids", + "value": [ + "32" + ] + } + ] +} +``` +{% endcollapsible %} +## Verify this step + +1. On the Luma storefront page, search for `Desktop Computer`. There should be one result. + + ![Search](https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/images/search-desktop-computer.png) + +1. Click on the Desktop Computer product. + + ![Product](https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/images/site-desktop-computer.png) + +1. Customize Desktop Computer and add it to the shopping cart. + + ![Shopping Cart](https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/images/shopping-cart-desktop-computer.png) + + {:.bs-callout-info} +If you do not see the bundle product on the frontend, you can try reindexing and clearing the cache. diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md b/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md deleted file mode 120000 index dffcd7c3941..00000000000 --- a/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/bundle-product/create-simple-products.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md b/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md new file mode 100644 index 00000000000..57585c31d7b --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md @@ -0,0 +1,576 @@ +--- +layout: tutorial +group: rest-api +title: Step 2. Create the simple products + +contributor_name: Goivvy LLC +contributor_link: https://www.goivvy.com/magento-optimization-service +--- + +{:.bs-callout-info} +Before you run the code, please verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute set](https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/plan-product.html#get-attributes) for more information. + +We will create four simple products: `RAM 12GB`, `RAM 24GB`, `Monitor 15"` and `Monitor 17"`. + +**Endpoint:** + +```html +POST http://domain.com/rest/default/V1/products +``` + +**Payload 1:** + +```json +{ + "product": { + "sku": "RAM-12GB", + "name": "RAM 12GB", + "attribute_set_id": 4, + "price": 25, + "status": 1, + "visibility": 4, + "type_id": "simple", + "weight": "0.5", + "extension_attributes": { + "category_links": [ + { + "position": 0, + "category_id": "32" + } + ], + "stock_item": { + "qty": "10", + "is_in_stock": true + } + }, + "custom_attributes": [ + { + "attribute_code": "description", + "value": "RAM 12GB Unit" + }, + { + "attribute_code": "tax_class_id", + "value": "2" + } + ] + } +} +``` + +**Response 1:** + +{% collapsible Show code sample %} + +```json +{ + "id": 16, + "sku": "RAM-12GB", + "name": "RAM 12GB", + "attribute_set_id": 4, + "price": 25, + "status": 1, + "visibility": 4, + "type_id": "simple", + "created_at": "2022-04-08 21:57:34", + "updated_at": "2022-04-08 21:57:34", + "weight": 0.5, + "extension_attributes": { + "website_ids": [ + 1 + ], + "category_links": [ + { + "position": 0, + "category_id": "32" + } + ], + "stock_item": { + "item_id": 16, + "product_id": 16, + "stock_id": 1, + "qty": 10, + "is_in_stock": true, + "is_qty_decimal": false, + "show_default_notification_message": false, + "use_config_min_qty": true, + "min_qty": 0, + "use_config_min_sale_qty": 1, + "min_sale_qty": 1, + "use_config_max_sale_qty": true, + "max_sale_qty": 10000, + "use_config_backorders": true, + "backorders": 0, + "use_config_notify_stock_qty": true, + "notify_stock_qty": 1, + "use_config_qty_increments": true, + "qty_increments": 0, + "use_config_enable_qty_inc": true, + "enable_qty_increments": false, + "use_config_manage_stock": true, + "manage_stock": true, + "low_stock_date": null, + "is_decimal_divided": false, + "stock_status_changed_auto": 0 + } + }, + "options": [], + "media_gallery_entries": [], + "custom_attributes": [ + { + "attribute_code": "options_container", + "value": "container2" + }, + { + "attribute_code": "msrp_display_actual_price_type", + "value": "0" + }, + { + "attribute_code": "url_key", + "value": "ram-12g" + }, + { + "attribute_code": "required_options", + "value": "0" + }, + { + "attribute_code": "has_options", + "value": "0" + }, + { + "attribute_code": "tax_class_id", + "value": "2" + }, + { + "attribute_code": "category_ids", + "value": [ + "32" + ] + }, + { + "attribute_code": "description", + "value": "RAM 12GB Unit" + } + ] +} +``` +{% endcollapsible %} + +**Payload 2:** + +```json +{ + "product": { + "sku": "RAM-24GB", + "name": "RAM 24GB", + "attribute_set_id": 4, + "price": 50, + "status": 1, + "visibility": 4, + "type_id": "simple", + "weight": "0.5", + "extension_attributes": { + "category_links": [ + { + "position": 0, + "category_id": "32" + } + ], + "stock_item": { + "qty": "10", + "is_in_stock": true + } + }, + "custom_attributes": [ + { + "attribute_code": "description", + "value": "RAM 24GB Unit" + }, + { + "attribute_code": "tax_class_id", + "value": "2" + } + ] + } +} +``` + +**Response 2:** + +{% collapsible Show code sample %} + +```json +{ + "id": 17, + "sku": "RAM-24GB", + "name": "RAM 24GB", + "attribute_set_id": 4, + "price": 50, + "status": 1, + "visibility": 4, + "type_id": "simple", + "created_at": "2022-04-08 22:02:40", + "updated_at": "2022-04-08 22:02:40", + "weight": 0.5, + "extension_attributes": { + "website_ids": [ + 1 + ], + "category_links": [ + { + "position": 0, + "category_id": "32" + } + ], + "stock_item": { + "item_id": 17, + "product_id": 17, + "stock_id": 1, + "qty": 10, + "is_in_stock": true, + "is_qty_decimal": false, + "show_default_notification_message": false, + "use_config_min_qty": true, + "min_qty": 0, + "use_config_min_sale_qty": 1, + "min_sale_qty": 1, + "use_config_max_sale_qty": true, + "max_sale_qty": 10000, + "use_config_backorders": true, + "backorders": 0, + "use_config_notify_stock_qty": true, + "notify_stock_qty": 1, + "use_config_qty_increments": true, + "qty_increments": 0, + "use_config_enable_qty_inc": true, + "enable_qty_increments": false, + "use_config_manage_stock": true, + "manage_stock": true, + "low_stock_date": null, + "is_decimal_divided": false, + "stock_status_changed_auto": 0 + } + }, + "options": [], + "media_gallery_entries": [], + "custom_attributes": [ + { + "attribute_code": "options_container", + "value": "container2" + }, + { + "attribute_code": "msrp_display_actual_price_type", + "value": "0" + }, + { + "attribute_code": "url_key", + "value": "ram-24g" + }, + { + "attribute_code": "required_options", + "value": "0" + }, + { + "attribute_code": "has_options", + "value": "0" + }, + { + "attribute_code": "tax_class_id", + "value": "2" + }, + { + "attribute_code": "category_ids", + "value": [ + "32" + ] + }, + { + "attribute_code": "description", + "value": "RAM 24GB Unit" + } + ] +} +``` +{% endcollapsible %} + +**Payload 3:** + +```json +{ + "product": { + "sku": "Monitor-15", + "name": "Monitor 15\"", + "attribute_set_id": 4, + "price": 100, + "status": 1, + "visibility": 4, + "type_id": "simple", + "weight": "0.5", + "extension_attributes": { + "category_links": [ + { + "position": 0, + "category_id": "32" + } + ], + "stock_item": { + "qty": "10", + "is_in_stock": true + } + }, + "custom_attributes": [ + { + "attribute_code": "description", + "value": "Monitor 15\"" + }, + { + "attribute_code": "tax_class_id", + "value": "2" + } + ] + } +} +``` + +**Response 3:** + +{% collapsible Show code sample %} + +```json +{ + "id": 18, + "sku": "Monitor-15", + "name": "Monitor 15\"", + "attribute_set_id": 4, + "price": 100, + "status": 1, + "visibility": 4, + "type_id": "simple", + "created_at": "2022-04-08 22:04:11", + "updated_at": "2022-04-08 22:04:11", + "weight": 0.5, + "extension_attributes": { + "website_ids": [ + 1 + ], + "category_links": [ + { + "position": 0, + "category_id": "32" + } + ], + "stock_item": { + "item_id": 18, + "product_id": 18, + "stock_id": 1, + "qty": 10, + "is_in_stock": true, + "is_qty_decimal": false, + "show_default_notification_message": false, + "use_config_min_qty": true, + "min_qty": 0, + "use_config_min_sale_qty": 1, + "min_sale_qty": 1, + "use_config_max_sale_qty": true, + "max_sale_qty": 10000, + "use_config_backorders": true, + "backorders": 0, + "use_config_notify_stock_qty": true, + "notify_stock_qty": 1, + "use_config_qty_increments": true, + "qty_increments": 0, + "use_config_enable_qty_inc": true, + "enable_qty_increments": false, + "use_config_manage_stock": true, + "manage_stock": true, + "low_stock_date": null, + "is_decimal_divided": false, + "stock_status_changed_auto": 0 + } + }, + "options": [], + "media_gallery_entries": [], + "custom_attributes": [ + { + "attribute_code": "options_container", + "value": "container2" + }, + { + "attribute_code": "msrp_display_actual_price_type", + "value": "0" + }, + { + "attribute_code": "url_key", + "value": "monitor-15" + }, + { + "attribute_code": "required_options", + "value": "0" + }, + { + "attribute_code": "has_options", + "value": "0" + }, + { + "attribute_code": "tax_class_id", + "value": "2" + }, + { + "attribute_code": "category_ids", + "value": [ + "32" + ] + }, + { + "attribute_code": "description", + "value": "Monitor 15\"" + } + ] +} +``` +{% endcollapsible %} + +**Payload 4:** + +```json +{ + "product": { + "sku": "Monitor-17", + "name": "Monitor 17\"", + "attribute_set_id": 4, + "price": 150, + "status": 1, + "visibility": 4, + "type_id": "simple", + "weight": "0.5", + "extension_attributes": { + "category_links": [ + { + "position": 0, + "category_id": "32" + } + ], + "stock_item": { + "qty": "10", + "is_in_stock": true + } + }, + "custom_attributes": [ + { + "attribute_code": "description", + "value": "Monitor 17\"" + }, + { + "attribute_code": "tax_class_id", + "value": "2" + } + ] + } +} +``` + +**Response 4:** + +{% collapsible Show code sample %} + +```json +{ + "id": 19, + "sku": "Monitor-17", + "name": "Monitor 17\"", + "attribute_set_id": 4, + "price": 150, + "status": 1, + "visibility": 4, + "type_id": "simple", + "created_at": "2022-04-08 22:06:21", + "updated_at": "2022-04-08 22:06:21", + "weight": 0.5, + "extension_attributes": { + "website_ids": [ + 1 + ], + "category_links": [ + { + "position": 0, + "category_id": "32" + } + ], + "stock_item": { + "item_id": 19, + "product_id": 19, + "stock_id": 1, + "qty": 10, + "is_in_stock": true, + "is_qty_decimal": false, + "show_default_notification_message": false, + "use_config_min_qty": true, + "min_qty": 0, + "use_config_min_sale_qty": 1, + "min_sale_qty": 1, + "use_config_max_sale_qty": true, + "max_sale_qty": 10000, + "use_config_backorders": true, + "backorders": 0, + "use_config_notify_stock_qty": true, + "notify_stock_qty": 1, + "use_config_qty_increments": true, + "qty_increments": 0, + "use_config_enable_qty_inc": true, + "enable_qty_increments": false, + "use_config_manage_stock": true, + "manage_stock": true, + "low_stock_date": null, + "is_decimal_divided": false, + "stock_status_changed_auto": 0 + } + }, + "options": [], + "media_gallery_entries": [], + "custom_attributes": [ + { + "attribute_code": "options_container", + "value": "container2" + }, + { + "attribute_code": "msrp_display_actual_price_type", + "value": "0" + }, + { + "attribute_code": "url_key", + "value": "monitor-17" + }, + { + "attribute_code": "required_options", + "value": "0" + }, + { + "attribute_code": "has_options", + "value": "0" + }, + { + "attribute_code": "tax_class_id", + "value": "2" + }, + { + "attribute_code": "category_ids", + "value": [ + "32" + ] + }, + { + "attribute_code": "description", + "value": "Monitor 17\"" + } + ] +} +``` +{% endcollapsible %} + +## Verify this step + +* Log in to the Adobe Commerce Admin Panel and select Catalog > Products and confirm that your products appear in the grid. + + ![Simple products](https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/images/simple-products-admin-grid.png) + + {:.bs-callout-info} +If you do not see your products in the catalog, you can try reindexing and clearing the cache. diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md b/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md deleted file mode 120000 index f55e5f77746..00000000000 --- a/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/bundle-product/plan-product.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md b/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md new file mode 100644 index 00000000000..acd185007c9 --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md @@ -0,0 +1,196 @@ +--- +layout: tutorial +group: rest-api +title: Step 1. Plan the product + +contributor_name: Goivvy LLC +contributor_link: https://www.goivvy.com/magento-optimization-service +--- + +To create a bundle product with REST, you need: + +* The attribute names and values for the attribute set assigned to a bundle product. +* The category IDs assigned to a bundle product. +* Simple product SKUs assigned to a bundle product. + +We will use a `Default` attribute set. + +RAM and Monitor sizes will be the customizable aspect of the bundle product. We will create a simple product for each size of RAM and Monitor (12GB, 24GB, 15" and 20"). + +## Define product characteristics + +The table below has the general characteristics of the desktop computer we are creating: + +Characteristic | Description +--- | --- +Attribute Set | Default +Product Name | Desktop Computer +SKU | Desktop-Computer +Tax Class | Taxable Goods +Visibility | Catalog, Search +Description | Desktop computer + +## Find attribute values + +We will make several API calls to find values needed to create simple/bundle products. We will use `default` as the store code. + +### Find attribute set ID + +We will use the `Default` attribute set. We will need to find the corresponding `attribute_set_id`. + +The following API call can be used to search for the attribute set named `Default` and `entity_type_id` equals `4`. The `catalog_product` entity has an `entity_type_id` value of `4`. + +**Endpoint:** + +```html +GET http://domain.com/rest/default/V1/eav/attribute-sets/list?searchCriteria[filter_groups][0][filters][0][field]=attribute_set_name&searchCriteria[filter_groups][0][filters][0][value]=Default&searchCriteria[filter_groups][0][filters][0][condition_type]=eq&searchCriteria[filter_groups][1][filters][0][field]=entity_type_id&searchCriteria[filter_groups][1][filters][0][value]=4&searchCriteria[filter_groups][1][filters][0][condition_type]=eq +``` + +**Response:** + +The `attribute_set_id` for the `Default` attribute set is `4`: + +```json +{ + "items": [ + { + "attribute_set_id": 4, + "attribute_set_name": "Default", + "sort_order": 1, + "entity_type_id": 4 + } + ], + "search_criteria": { + "filter_groups": [ + { + "filters": [ + { + "field": "attribute_set_name", + "value": "Default", + "condition_type": "eq" + } + ] + }, + { + "filters": [ + { + "field": "entity_type_id", + "value": "4", + "condition_type": "eq" + } + ] + } + ], + "page_size": 20 + }, + "total_count": 1 +} +``` + +### List attributes for the attribute set + +**Endpoint:** + +```html +GET http://domain.com/rest/default/V1/products/attribute-sets/4/attributes +``` + +**Response:** + +```json +[ + { + "attribute_id": 87, + "attribute_code": "image", + "frontend_input": "media_image", + "entity_type_id": "4", + "is_required": false, + "options": [], + "is_user_defined": false, + "default_frontend_label": "Base", + "frontend_labels": [], + "backend_type": "varchar", + "is_unique": "0", + "validation_rules": [] + }, + { + "attribute_id": 125, + "attribute_code": "shipment_type", + "frontend_input": "select", + "entity_type_id": "4", + "is_required": true, + "options": [ + { + "label": "Together", + "value": "0" + }, + { + "label": "Separately", + "value": "1" + } + ], + "is_user_defined": false, + "default_frontend_label": "Ship Bundle Items", + "frontend_labels": [], + "backend_type": "int", + "source_model": "Magento\\Bundle\\Model\\Product\\Attribute\\Source\\Shipment\\Type", + "default_value": "0", + "is_unique": "0", + "validation_rules": [] + } +] +``` + +Because this response can be very long, we have abbreviated the example response above. The table below has attributes that are relevant in this tutorial. + +Admin label | Selected value | Attribute ID | attribute_code | Attribute value +--- | --- | --- | --- | --- +Tax Class | Taxable Goods | 134 | `tax_class_id` | 2 +Visibility | Catalog, Search | 99 | `visibility` | 4 + +{:.bs-callout-warning} +The attribute ID and value numbers will vary between different installations. Check the values carefully before using them in your calls. + +### List category values + +We will assign our Desktop Computer to the `What's New` category. + +Use the following endpoint to find out category's ID. + +**Endpoint:** + +```html +GET http://domain.com/rest/default/V1/categories?searchCriteria[filter_groups][0][filters][0][field]=id&searchCriteria[filter_groups][0][filters][0][value]=1&searchCriteria[filter_groups][0][filters][0][condition_type]=gte +``` + +**Response:** + +```json +{ + "id": 2, + "parent_id": 1, + "name": "Default Category", + "is_active": true, + "position": 1, + "level": 1, + "product_count": 0, + "children_data": [ + { + "id": 32, + "parent_id": 2, + "name": "What's New", + "is_active": true, + "position": 1, + "level": 2, + "product_count": 0, + "children_data": [] + } + ] +} +``` + +We can see from the above response that the `id` for `What's New` is equal to `32`. + +## Verify this step + +Since we are only gathering information, there is nothing to verify. diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md b/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md deleted file mode 120000 index 579aede7560..00000000000 --- a/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/configurable-product/config-product-intro.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md b/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md new file mode 100644 index 00000000000..5f7a510e070 --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md @@ -0,0 +1,34 @@ +--- +layout: tutorial +group: rest-api +title: Create a configurable product tutorial + +menu_title: Initial tasks +menu_order: 0 +level3_subgroup: configurable-product-tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +functional_areas: + - Integration +--- + +This tutorial shows a system integrator how to use Magento REST APIs to create a _configurable product_. A configurable product is a parent product of multiple simple products. You define a configurable product so that the buyer must make one or more choices to select a product. For example, most clothing comes in a variety of colors and sizes. If you are offering a skirt in black, red, and blue colorways in sizes small, medium, and large, then you would create a configurable product with 9 simple products, one for each combination of color and size. + +In this tutorial, we will create a gray t-shirt that comes in three sizes (small, medium, and large). The configurable product defines basic characteristics of the t-shirt. Then we will create a simple product for each size and link each of them to the configurable product. Finally, we will add an option that allows the customer to specify text that can be added to the shirt. + +This **5-step tutorial** generally takes **45 minutes**. + +### Before you begin + +* Install a Magento 2.2 (or later) instance with sample data. The sample data defines a functional store, called Luma, that sells fitness clothing and accessories. + +* Install a REST client. You can use any REST client to send calls to Magento. [Postman](https://www.getpostman.com/) is recommended. + +* [Install and configure RabbitMQ]({{ page.baseurl }}/install-gde/prereq/install-rabbitmq.html), which is the default message broker for bulk API endpoints. + +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/) for more information. + +### Other resources + +* [REST Tutorials](https://developer.adobe.com/commerce/webapi/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md b/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md deleted file mode 120000 index 1ee0eede386..00000000000 --- a/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/configurable-product/create-configurable-product.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md b/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md new file mode 100644 index 00000000000..068b4521c21 --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md @@ -0,0 +1,222 @@ +--- +layout: tutorial +group: rest-api +title: Step 2. Create the configurable product + +subtitle: Create a configurable product tutorial +menu_title: Step 2. Create the configurable product +menu_order: 20 +level3_subgroup: configurable-product-tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +functional_areas: + - Integration +--- + +We have the information we need to create the Champ Tee configurable product. + +The sample payload does not contain the price or the size. These attributes will be defined in the simple products. + +The `visibility` attribute is set to 4, meaning the product can be found by browsing or searching. This value will be changed for the simple products. + +The below table shows the equivalent code for the visibility attribute + +Visibility | Code +--- | --- +`Not Visible Individually` | 1 +`Catalog` | 2 +`Search` | 3 +`Catalog, Search` | 4 + +{:.bs-callout-info} +Before you using this code sample, verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute searchCriteria](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. + +**Endpoint:** + +`POST /rest/default/V1/products` + +**Payload:** + +```json +{ + "product": { + "sku": "MS-Champ", + "name": "Champ Tee", + "attribute_set_id": 9, + "status": 1, + "visibility": 4, + "type_id": "configurable", + "weight": "0.5", + "extension_attributes": { + "category_links": [ + { + "position": 0, + "category_id": "11" + }, + { + "position": 1, + "category_id": "12" + }, + { + "position": 2, + "category_id": "16" + } + ] + }, + "custom_attributes": [ + { + "attribute_code": "description", + "value": "The Champ Tee keeps you cool and dry while you do your thing. Let everyone know who you are by adding your name on the back for only $10." + }, + { + "attribute_code": "tax_class_id", + "value": "2" + }, + { + "attribute_code": "material", + "value": "148" + }, + { + "attribute_code": "pattern", + "value": "196" + }, + { + "attribute_code": "color", + "value": "52" + } + ] + } +} +``` + +**Response:** + +{% collapsible Show code sample %} +```json +{ + "id": 2078, + "sku": "MS-Champ", + "name": "Champ Tee", + "attribute_set_id": 9, + "price": 0, + "status": 1, + "visibility": 4, + "type_id": "configurable", + "created_at": "2017-11-29 19:57:20", + "updated_at": "2017-11-29 19:57:20", + "weight": 0.5, + "extension_attributes": { + "website_ids": [ + 1 + ], + "category_links": [ + { + "position": 0, + "category_id": "11" + }, + { + "position": 1, + "category_id": "12" + }, + { + "position": 2, + "category_id": "16" + } + ], + "stock_item": { + "item_id": 2078, + "product_id": 2078, + "stock_id": 1, + "qty": 0, + "is_in_stock": false, + "is_qty_decimal": false, + "show_default_notification_message": false, + "use_config_min_qty": true, + "min_qty": 0, + "use_config_min_sale_qty": 1, + "min_sale_qty": 1, + "use_config_max_sale_qty": true, + "max_sale_qty": 10000, + "use_config_backorders": true, + "backorders": 0, + "use_config_notify_stock_qty": true, + "notify_stock_qty": 1, + "use_config_qty_increments": true, + "qty_increments": 0, + "use_config_enable_qty_inc": true, + "enable_qty_increments": false, + "use_config_manage_stock": true, + "manage_stock": true, + "low_stock_date": null, + "is_decimal_divided": false, + "stock_status_changed_auto": 0 + }, + "configurable_product_options": [], + "configurable_product_links": [] + }, + "product_links": [], + "options": [], + "media_gallery_entries": [], + "tier_prices": [], + "custom_attributes": [ + { + "attribute_code": "description", + "value": "The Champ Tee keeps you cool and dry while you do your thing. Let everyone know who you are by adding your name on the back for only $10." + }, + { + "attribute_code": "color", + "value": "52" + }, + { + "attribute_code": "category_ids", + "value": [ + "11", + "12", + "16" + ] + }, + { + "attribute_code": "options_container", + "value": "container2" + }, + { + "attribute_code": "required_options", + "value": "0" + }, + { + "attribute_code": "has_options", + "value": "0" + }, + { + "attribute_code": "url_key", + "value": "champ-tee" + }, + { + "attribute_code": "tax_class_id", + "value": "2" + }, + { + "attribute_code": "material", + "value": "148" + }, + { + "attribute_code": "size", + "value": "91" + }, + { + "attribute_code": "pattern", + "value": "196" + } + ] +} +``` +{% endcollapsible %} + +## Verify this step + +* Log in to the Luma website and select **Catalog > Products**. The product appears in the grid. + + ![Product page with configurable product](https://developer.adobe.com/commerce/webapi/rest/images/products-page.png) + +* On the Luma storefront page, search for `Champ`. No results are returned. diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md b/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md deleted file mode 120000 index e4fdb945b62..00000000000 --- a/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/configurable-product/create-personalization-option.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md b/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md new file mode 100644 index 00000000000..e8d2c6a29e0 --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md @@ -0,0 +1,79 @@ +--- +layout: tutorial +group: rest-api +title: Step 5. Create the personalization option + +subtitle: Create a configurable product tutorial +menu_title: Step 5. Create the personalization option +menu_order: 50 +level3_subgroup: configurable-product-tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +functional_areas: + - Integration +--- + +Let's add a text box to the product page that allows the customer to add his name (up to 15 characters) to the back of shirt. + +The `product_sku` is the `sku` of the configurable product. The `sku` specified in the payload is a string that is appended to the `product_sku` when a customer decides to purchase this option. Likewise, the `price` supplied in the payload is added to the configurable product price. + +**Endpoint:** + +`POST /rest/default/V1/products/options` + +**Payload:** + +```json +{ + "option": { + "product_sku": "MS-Champ", + "title": "Add Your Name (Max 15 Characters)", + "type": "field", + "sort_order": 1, + "is_require": false, + "price": 10, + "price_type": "fixed", + "sku": "Personalized", + "max_characters": 15 + } +} +``` + +**Response:** + +```json +{ + "product_sku": "MS-Champ", + "option_id": 7, + "title": "Add Your Name (Max 15 Characters)", + "type": "field", + "sort_order": 1, + "is_require": false, + "price": 10, + "price_type": "fixed", + "sku": "Personalized", + "max_characters": 15 +} +``` + +## Verify this step + +* Log in to the Luma website and select **Catalog > Products**. Click on the **Champ Tee** configurable product and expand the **Customizable Options** section. + + ![Product page with configurable and simple products](https://developer.adobe.com/commerce/webapi/rest/images/options-section.png) + +* On the Luma storefront page, search for `Champ`. Then click on the Champ Tee product. + + ![Search results](https://developer.adobe.com/commerce/webapi/rest/images/add-your-name.png) + + {:.bs-callout-info} + If the personalization option is not displayed, go to the **Champ Tee** configuration product page in Admin and set **Stock Status** to **In Stock**. + +## Congratulations! You've finished. +{:.no_toc} + +{:.ref-header} +Related topic + +[Order Processing with REST APIs Tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/) diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md b/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md deleted file mode 120000 index 446ba8ad706..00000000000 --- a/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/configurable-product/create-simple-products.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md b/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md new file mode 100644 index 00000000000..646d83bbe6f --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md @@ -0,0 +1,238 @@ +--- +layout: tutorial +group: rest-api +title: Step 3. Create the simple products + +subtitle: Create a configurable product tutorial +menu_title: Step 3. Create the simple products +menu_order: 30 +level3_subgroup: configurable-product-tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +functional_areas: + - Integration +--- + +The payloads for creating a simple product and a configurable product are identical, with the following exceptions: + +* The simple product `sku` appends the configurable option (the size in this tutorial) to the configurable product `sku`. +* The `name` indicates the size. +* The `type_id` is set to `simple`. +* The `visibility` is set to `1`, indicating the simple product should not be displayed on the store. +* The `price` and `size` attributes are specified. + +Although it's not required, the simple product payload also includes `stock_item` information. By default, the Luma store hides out-of-stock items, so adding stock will make the Champ Tee visible on the website. + +## Create the first simple product + + {:.bs-callout-info} +Before you using this code sample, verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute searchCriteria](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. + +**Endpoint:** + +`POST /rest/default/V1/products` + +**Payload:** + +```json +{ + "product": { + "sku": "MS-Champ-S", + "name": "Champ Tee Small", + "attribute_set_id": 9, + "price": 25, + "status": 1, + "visibility": 1, + "type_id": "simple", + "weight": "0.5", + "extension_attributes": { + "category_links": [ + { + "position": 0, + "category_id": "11" + }, + { + "position": 1, + "category_id": "12" + }, + { + "position": 2, + "category_id": "16" + } + ], + "stock_item": { + "qty": "10", + "is_in_stock": true + } + }, + "custom_attributes": [ + { + "attribute_code": "description", + "value": "The Champ Tee keeps you cool and dry while you do your thing. Let everyone know who you are by adding your name on the back for only $10." + }, + { + "attribute_code": "tax_class_id", + "value": "2" + }, + { + "attribute_code": "material", + "value": "148" + }, + { + "attribute_code": "pattern", + "value": "196" + }, + { + "attribute_code": "color", + "value": "52" + }, + { + "attribute_code": "size", + "value": "168" + } + ] + } +} +``` + +**Response:** + +{% collapsible Show code sample %} + +```json +{ + "id": 2079, + "sku": "MS-Champ-S", + "name": "Champ Tee Small", + "attribute_set_id": 9, + "price": 25, + "status": 1, + "visibility": 1, + "type_id": "simple", + "created_at": "2017-11-29 20:40:07", + "updated_at": "2017-11-29 20:40:07", + "weight": 0.5, + "extension_attributes": { + "website_ids": [ + 1 + ], + "category_links": [ + { + "position": 0, + "category_id": "11" + }, + { + "position": 1, + "category_id": "12" + }, + { + "position": 2, + "category_id": "16" + } + ], + "stock_item": { + "item_id": 2079, + "product_id": 2079, + "stock_id": 1, + "qty": 10, + "is_in_stock": true, + "is_qty_decimal": false, + "show_default_notification_message": false, + "use_config_min_qty": true, + "min_qty": 0, + "use_config_min_sale_qty": 1, + "min_sale_qty": 1, + "use_config_max_sale_qty": true, + "max_sale_qty": 10000, + "use_config_backorders": true, + "backorders": 0, + "use_config_notify_stock_qty": true, + "notify_stock_qty": 1, + "use_config_qty_increments": true, + "qty_increments": 0, + "use_config_enable_qty_inc": true, + "enable_qty_increments": false, + "use_config_manage_stock": true, + "manage_stock": true, + "low_stock_date": null, + "is_decimal_divided": false, + "stock_status_changed_auto": 0 + } + }, + "product_links": [], + "options": [], + "media_gallery_entries": [], + "tier_prices": [], + "custom_attributes": [ + { + "attribute_code": "description", + "value": "The Champ Tee keeps you cool and dry while you do your thing. Let everyone know who you are by adding your name on the back for only $10." + }, + { + "attribute_code": "color", + "value": "52" + }, + { + "attribute_code": "category_ids", + "value": [ + "11", + "12", + "16" + ] + }, + { + "attribute_code": "options_container", + "value": "container2" + }, + { + "attribute_code": "required_options", + "value": "0" + }, + { + "attribute_code": "has_options", + "value": "0" + }, + { + "attribute_code": "url_key", + "value": "champ-tee-small" + }, + { + "attribute_code": "tax_class_id", + "value": "2" + }, + { + "attribute_code": "material", + "value": "148" + }, + { + "attribute_code": "size", + "value": "168" + }, + { + "attribute_code": "pattern", + "value": "196" + } + ] +} +``` + +{% endcollapsible %} + +## Create the other simple products + +Repeat the call with the following changes to the payload: + +Attribute | Medium Value | Large Value +--- | --- +`sku` | MS-Champ-M | MS-Champ-L +`name` | Champ Tee Medium | Champ Tee Large +`size` | 169 | 170 + +## Verify this step + +* Log in to the Luma website and select Catalog > Products. The product appears in the grid. + + ![Product page with configurable and simple products](https://developer.adobe.com/commerce/webapi/rest/images/products-page-all.png) + +* On the Luma storefront page, search for `Champ`. No results are returned. diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md b/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md deleted file mode 120000 index 150f80e9535..00000000000 --- a/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/configurable-product/define-config-product-options.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md b/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md new file mode 100644 index 00000000000..b35c2e2575f --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md @@ -0,0 +1,112 @@ +--- +layout: tutorial +group: rest-api +title: Step 4. Define configurable product options + +subtitle: Create a configurable product tutorial +menu_title: Step 4. Define configurable product options +menu_order: 40 +level3_subgroup: configurable-product-tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +functional_areas: + - Integration +--- + +Now that we've created all the Champ Tee products, we need to assign `size` as the configurable attribute and link the simple products to the configurable product. + +## Set the configurable attribute + +The `POST V1/configurable-products/:sku/options` call assigns the specified `attribute_id` to be the configurable attribute. Specify the `sku` of the configurable product in the URI. + +The value assigned to the `value_index` must be unique within the system. + +**Endpoint:** + +`POST /rest/default/V1/configurable-products/MS-Champ/options` + +**Payload:** + +```json +{ + "option": { + "attribute_id": "141", + "label": "Size", + "position": 0, + "is_use_default": true, + "values": [ + { + "value_index": 9 + } + ] + } +} +``` + +**Response:** + +A configurable option ID number, such as `"335"`. + +## Link the simple products to the configurable product + +The call to link a simple (child) product to the configurable product accepts only one `childSku` value. You must repeat this call for the `MS-Champ-M` and `MS-Champ-L` products. + +**Endpoint:** + +`POST /rest/default/V1/configurable-products/MS-Champ/child` + +**Payload:** + +```json +{ + "childSku": "MS-Champ-S" +} +``` + +**Response:** + +`true` + +## Verify this step + +* Log in to the Luma website and select **Catalog > Products**. Click on the **Champ Tee** configurable product and expand the **Configurations** section. + +![Product page with configurable and simple products](https://developer.adobe.com/commerce/webapi/rest/images/configurations-section.png) + +* On the Luma storefront page, search for `Champ`. + +![Search results](https://developer.adobe.com/commerce/webapi/rest/images/search-results.png) + +* Call `GET /V1/products/MS-Champ`. The response includes the `configurable_product_options` and `configurable_product_links` arrays. + +```json +... +"configurable_product_options": [ + { + "id": 338, + "attribute_id": "141", + "label": "Size", + "position": 0, + "values": [ + { + "value_index": 168 + }, + { + "value_index": 169 + }, + { + "value_index": 170 + } + ], + "product_id": 2078 + } +], +"configurable_product_links": [ + 2079, + 2080, + 2081 +] +}, +... +``` diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md b/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md deleted file mode 120000 index a6c1f3cee9c..00000000000 --- a/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/configurable-product/plan-product.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md b/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md new file mode 100644 index 00000000000..b978d0d21e3 --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md @@ -0,0 +1,225 @@ +--- +layout: tutorial +group: rest-api +title: Step 1. Plan the product + +subtitle: Create a configurable product tutorial +menu_title: Step 1. Plan the product +menu_order: 10 +level3_subgroup: configurable-product-tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +functional_areas: + - Integration +--- + +To create a configurable product programmatically, you'll need to know the following: + +* The attribute names and values defined in the attribute set assigned to the configurable product. +* The categories numbers assigned to the configurable product. +* Which attributes to use as the configuration options. + +Since this tutorial uses the sample data, we can take advantage of the options that the Top attribute set provides. This attribute set contains attributes that describe the fabric, sleeve length, and other characteristics that are specific to clothing. It also includes EAV attributes such as size and color, which are commonly available to all types of physical products. + +The size of the t-shirt will be the configurable aspect of this product. Therefore, we'll create a simple product for each size (Small, Medium, and Large). + +## Define product characteristics + +The following table lists the general characteristics of men's t-shirt we're creating. These items are among those listed on the New Product page in Admin when the Top attribute set is selected. + +Characteristic | Description +--- | --- +Attribute Set | Top +Product Name | Champ Tee +SKU | MS-Champ +Price | 25.00 +Tax Class | Taxable Goods +Weight | 0.5 +Categories | Men, Tops, Tees +Visibility | Catalog, Search +Material | LumaTech +Pattern | Graphic Print +Color | Gray +Size | Configurable in small, medium, or large +Description | The Champ Tee keeps you cool and dry while you do your thing. Let everyone know who you are by adding your name on the back for only $10. + +A merchant typically provides the product name, SKU, price, weight, and description. The other characteristics are defined by the system. + +## Find the system-defined values + +We'll make several calls to find the values needed to create the product + +### Get the attribute set ID + +The sample data provides multiple attribute sets, including Default, Top, and Bottom. To assign the Top attribute set to the product, we need to know the corresponding `attribute_set_id`. + +Use the following call to search for the attribute set named `Top` and `entity_type_id` equals to `4`. +By default, the `catalog_product` entity has the `entity_type_id` value as `4`. + +**Endpoint:** + +```html +GET /rest//V1/eav/attribute-sets/list? +searchCriteria[filter_groups][0][filters][0][field]=attribute_set_name& +searchCriteria[filter_groups][0][filters][0][value]=Top& +searchCriteria[filter_groups][0][filters][0][condition_type]=eq& +searchCriteria[filter_groups][1][filters][0][field]=entity_type_id& +searchCriteria[filter_groups][1][filters][0][value]=4& +searchCriteria[filter_groups][1][filters][0][condition_type]=eq +``` + +**Response:** + +The `attribute_set_id` for the Top attribute set is `9`. + +```json +{ + "items": [ + { + "attribute_set_id": 9, + "attribute_set_name": "Top", + "sort_order": 0, + "entity_type_id": 4 + } + ], + "search_criteria": { + "filter_groups": [ + { + "filters": [ + { + "field": "attribute_set_name", + "value": "Top", + "condition_type": "eq" + } + ] + }, + { + "filters": [ + { + "field": "entity_type_id", + "value": "4", + "condition_type": "eq" + } + ] + } + ] + }, + "total_count": 1 +} +``` + +### Get the list of attributes defined in an attribute searchCriteria {#get-attributes} + +Use the `GET V1/products/attribute-sets/:attributeSetId/attributes` call to return information about the attributes defined in the Top attribute set. + +**Endpoint:** + +```html +GET /rest/default/V1/products/attribute-sets/9/attributes +``` + +**Response:** + +```json +[ + { + "attribute_id": 141, + "attribute_code": "size", + "frontend_input": "select", + "entity_type_id": "4", + "is_required": false, + "options": [ + { + "label": " ", + "value": "" + }, + { + "label": "Small", + "value": "168" + }, + { + "label": "Medium", + "value": "169" + }, + { + "label": "Large", + "value": "170" + } + ], + "is_user_defined": true, + "default_frontend_label": "Size", + "frontend_labels": [], + "backend_type": "int", + "source_model": "Magento\\Eav\\Model\\Entity\\Attribute\\Source\\Table", + "default_value": "", + "is_unique": "0", + "validation_rules": [] + } +] +``` + +The response contains almost 3,000 lines and the above is a part of the response from the endpoint. The following table provides a summary of the attributes that are relevant in this tutorial. + +Admin label | Selected value | Attribute ID | attribute_code | Attribute value +--- | --- | --- | --- | --- +Tax Class | Taxable Goods | 132 | `tax_class_id` | 2 +Visibility | Catalog, Search | 99 | `visibility` | 4 +Material | LumaTech | 136 | `material` | 148 +Pattern | Graphic Print | 152 | `pattern` | 196 +Color | Gray | 93 | `color` | 52 +Size | Not applicable | 141 | `size` | 168 (small), 169 (medium), 170 (large) + +{:.bs-callout-warning} +The attribute ID and value numbers might be different on your installation. Check the values carefully before using them in your calls. + +### Get the list of category values + +You must assign the product to one or more categories to enable customers to find the product by browsing. We'll assign the Champ Tee to the Men, Tops, and Tees categories. + +Use the following call to search for all categories (`id` is greater than or equal to `0`). + +**Endpoint:** + +```html +GET /rest/default/V1/categories? +searchCriteria[filter_groups][0][filters][0][field]=id& +searchCriteria[filter_groups][0][filters][0][value]=1& +searchCriteria[filter_groups][0][filters][0][condition_type]=gte +``` + +**Response:** + +```json +{ + "id": 2, + "parent_id": 1, + "name": "Default Category", + "is_active": true, + "position": 1, + "level": 1, + "product_count": 0, + "children_data": [ + { + "id": 11, + "parent_id": 2, + "name": "Men", + "is_active": true, + "position": 1, + "level": 2, + "product_count": 1, + "children_data": [] + } + ] +} +``` + +Note that women's tops and tees have different ids than men's tops and tees. The values for men's clothing are: + +* Men - `11` +* Tops - `12` +* Tees - `16` + +## Verify this step + +At this point, we're gathering information, so there is nothing to verify. diff --git a/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md b/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md deleted file mode 120000 index 19e31f2aeae..00000000000 --- a/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md b/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md new file mode 100644 index 00000000000..4d47f31c975 --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md @@ -0,0 +1,250 @@ +--- +group: rest-api +title: Create and manage grouped products tutorial + +functional_areas: + - Integration +--- + +A grouped product consists of simple standalone products that are presented as a group. A group can contain variations of a single product or a collection of products that are to be sold together. + +This tutorial describes how you can use the Magento REST API to create and manage grouped products. + +### Before you begin + +* Install a Magento 2.2 (or later) instance with sample data. The sample data defines a functional store, called Luma, that sells fitness clothing and accessories. + +* Install a REST client. You can use any REST client to send calls to Magento. [Postman](https://www.getpostman.com/) is recommended. + +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/) for more information. + +### Other resources + +* [REST Tutorials](https://developer.adobe.com/commerce/webapi/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. + +## 1. Create an empty grouped product + +The first step is to create the grouped product container. In the next step, we'll add individual products to the grouped product. + +### Endpoint + +`POST V1/products` + +### Payload + +The `attribute_set_id: 11` line corresponds to gear. The value of `4` for the `visibility` attribute indicates the product will be displayed on the storefront and can be searched. + +```json + { + "product":{ + "sku":"new-grouped", + "name":"New Grouped Product", + "attribute_set_id":11, + "type_id":"grouped", + "visibility":4 + } + } +``` + +### Response + +```json +{ + "id": 2053, + "sku": "new-grouped", + "name": "New Grouped Product", + "attribute_set_id": 11, + "status": 1, + "visibility": 4, + "type_id": "grouped", + "created_at": "2019-08-15 17:51:13", + "updated_at": "2019-08-15 17:51:13", + "extension_attributes": { + "website_ids": [ + 1 + ], + "stock_item": { + "item_id": 2053, + "product_id": 2053, + "stock_id": 1, + "qty": 0, + "is_in_stock": false, + "is_qty_decimal": false, + "show_default_notification_message": false, + "use_config_min_qty": true, + "min_qty": 0, + "use_config_min_sale_qty": 1, + "min_sale_qty": 1, + "use_config_max_sale_qty": true, + "max_sale_qty": 10000, + "use_config_backorders": true, + "backorders": 0, + "use_config_notify_stock_qty": true, + "notify_stock_qty": 1, + "use_config_qty_increments": true, + "qty_increments": 0, + "use_config_enable_qty_inc": true, + "enable_qty_increments": false, + "use_config_manage_stock": true, + "manage_stock": true, + "low_stock_date": null, + "is_decimal_divided": false, + "stock_status_changed_auto": 0 + } + }, + "product_links": [], + "options": [], + "media_gallery_entries": [], + "tier_prices": [], + "custom_attributes": [ + { + "attribute_code": "options_container", + "value": "container2" + }, + { + "attribute_code": "url_key", + "value": "new-grouped-product" + }, + { + "attribute_code": "required_options", + "value": "0" + }, + { + "attribute_code": "has_options", + "value": "0" + }, + { + "attribute_code": "category_ids", + "value": [] + } + ] +} +``` + +## 2. Populate the grouped product with simple products + +Now that we have created a grouped product, we need to add simple items to it. In this example, we add three types of backpacks. + +### Endpoint + +`POST V1/products/new-grouped/links` + +### Payload + +```json + { + "items":[ + { + "sku":"new-grouped", + "link_type":"associated", + "linked_product_sku":"24-WB01", + "linked_product_type":"simple", + "position":1, + "extension_attributes":{ + "qty":1 + } + }, + { + "sku":"new-grouped", + "link_type":"associated", + "linked_product_sku":"24-WB02", + "linked_product_type":"simple", + "position":2, + "extension_attributes":{ + "qty":1 + } + }, + { + "sku":"new-grouped", + "link_type":"associated", + "linked_product_sku":"24-WB05", + "linked_product_type":"simple", + "position":3, + "extension_attributes":{ + "qty":1 + } + } + ] + } +``` + +### Response + +`true` + +## 3. Add another simple product to the grouped product + +This step uses the `PUT /V1/products/new-grouped/links` endpoint to add an item to the grouped product. + +### Endpoint + +`PUT /V1/products/new-grouped/links` + +### Payload + +```json + { + "entity":{ + "sku":"new-grouped", + "link_type":"associated", + "linked_product_sku":"24-UG01", + "linked_product_type":"simple", + "position":4, + "extension_attributes":{ + "qty":1 + } + } + } +``` + +### Response + +`true` + +{:.bs-callout-tip} +You also can use the `DELETE` endpoint to delete a simple product from the group product: +`DELETE /V1/products/{sku}/links/{type}/{linkedProductSku}` + +## Verify the steps + +1. Log into the Admin. +1. Select **Catalog > Products**. +1. Click on the **New Grouped Product** grouped product and expand the **Grouped Products** section. + + ![New grouped product](https://developer.adobe.com/commerce/webapi/rest/images/new-grouped-product.png) + +## Add a grouped product to a cart + +Customers can now add this grouped products to their carts, as shown below. + +Refer to the [Order processing tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/) for more information about how to add items to a cart with REST. + +### Endpoint + +`POST /V1/carts/mine/items` + +### Payload + +```json +{ + "cartItem": { + "sku": "new-grouped", + "qty": 1, + "quote_id": "3" + } +} +``` + +### Response + +```json +{ + "item_id": 5, + "sku": "24-WB01", + "qty": 1, + "name": "Voyage Yoga Bag", + "price": 32, + "product_type": "grouped", + "quote_id": "3" +} +``` diff --git a/src/guides/v2.4/rest/tutorials/index.md b/src/guides/v2.4/rest/tutorials/index.md index 14c4c88e5a9..13ecabfc08b 100644 --- a/src/guides/v2.4/rest/tutorials/index.md +++ b/src/guides/v2.4/rest/tutorials/index.md @@ -32,7 +32,7 @@ Before you begin any tutorial, make sure you know the basics about {{site.data.v * Know how to construct a REST call in Magento. See [Construct a request](https://developer.adobe.com/commerce/webapi/get-started/gs-web-api-request.html) for details. -* Find the Magento REST API documentation. You can view the [static REST API documentation on devdocs]({{site.baseurl}}/redoc/{{page.guide_version}}/) or [generate a local API reference](https://developer.adobe.com/commerce/webapi/rest/generate-local.html). +* Find the Magento REST API documentation. You can view the [static REST API documentation on devdocs]({{site.baseurl}}/redoc/{{page.guide_version}}/) or [generate a local API reference](https://developer.adobe.com/commerce/webapi/quick_reference/rest/generate-local.html). * Find the Magento Merchant documentation. Refer to [Getting Started with {{site.data.var.ce}}]({{ site.user_guide_url }}/getting-started.html) for information about the Luma store that is created when you install Magento with the sample data. diff --git a/src/guides/v2.4/rest/tutorials/inventory/index.md b/src/guides/v2.4/rest/tutorials/inventory/index.md index 8c7743480c9..1d1a3fe1f8a 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/index.md +++ b/src/guides/v2.4/rest/tutorials/inventory/index.md @@ -33,4 +33,4 @@ This **14-step tutorial** generally takes **1 hour**. ### Other resources -* Magento uses [Swagger](https://swagger.io) to provide REST API documentation on local instances of Magento. See [Generate a local API reference](https://developer.adobe.com/commerce/webapi/rest/generate-local.html) for more information. You can view the [static REST API documentation]({{site.baseurl}}/redoc/{{page.guide_version}}/), which displays reference information using ReDoc. +* Magento uses [Swagger](https://swagger.io) to provide REST API documentation on local instances of Magento. See [Generate a local API reference](https://developer.adobe.com/commerce/webapi/quick_reference/rest/generate-local.html) for more information. You can view the [static REST API documentation]({{site.baseurl}}/redoc/{{page.guide_version}}/), which displays reference information using ReDoc. diff --git a/src/guides/v2.4/rest/tutorials/orders/order-add-items.md b/src/guides/v2.4/rest/tutorials/orders/order-add-items.md deleted file mode 120000 index 96f57b57357..00000000000 --- a/src/guides/v2.4/rest/tutorials/orders/order-add-items.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/orders/order-add-items.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/orders/order-add-items.md b/src/guides/v2.4/rest/tutorials/orders/order-add-items.md new file mode 100644 index 00000000000..d23ac7267c7 --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/orders/order-add-items.md @@ -0,0 +1,431 @@ +--- +layout: tutorial +group: rest-api +title: Step 5. Add items to the cart + +subtitle: Order processing tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +menu_order: 5 +level3_subgroup: order-tutorial +functional_areas: + - Integration + - Orders + - Catalog +--- + +This step shows how to add a simple product, a downloadable product, and a [bundle product](https://glossary.magento.com/bundle-product) to the cart. + +These calls are performed on behalf of a customer, and the customer's token is specified in the [authorization](https://glossary.magento.com/authorization) header. + +{:.bs-callout-info} +Use the `V1/guest-carts//items` endpoint to add items to the cart on behalf of a guest. Do not include an authorization token. The payload and response is same as the logged-in customer for all product types, except for from quote ID in the payload. + +### Add a simple product to a cart {#add-simple} + +To add a [simple product](https://glossary.magento.com/simple-product) to a cart, you must provide a `sku`, the quantity, and the [quote](https://glossary.magento.com/quote) ID, which was generated when the cart was created. + +The following example adds an orange medium-sized Radiant women's t-shirt (`sku`: `WS12-M-Orange`) to the cart. + +**Endpoint:** + +`POST /rest//V1/carts/mine/items` + +**Headers:** + +`Content-Type: application/json` + +`Authorization: Bearer ` + +**Payload:** + +```json +{ + "cartItem": { + "sku": "WS12-M-Orange", + "qty": 1, + "quote_id": "4" + } +} +``` + +**Response:** + +```json +{ + "item_id": 7, + "sku": "WS12-M-Orange", + "qty": 1, + "name": "Radiant Tee-M-Orange", + "price": 19.99, + "product_type": "simple", + "quote_id": "4" +} +``` + +### Add a downloadable product to a cart {#add-downloadable} + +The requirements for adding a [downloadable product](https://glossary.magento.com/downloadable-product) to a cart are the same as a simple product. You must specify the `sku`, the quantity, and quote ID. + +The following example adds the downloadable product Advanced Pilates & Yoga (`sku`: 240-LV08) + +**Endpoint:** + +`POST /rest//V1/carts/mine/items` + +**Headers:** + +`Content-Type: application/json` + +`Authorization: Bearer ` + +**Payload:** + +```json +{ + "cartItem": { + "sku": "240-LV08", + "qty": 1, + "quote_id": "4" + } +} +``` + +**Response:** + +```json +{ + "item_id": 8, + "sku": "240-LV08", + "qty": 1, + "name": "Advanced Pilates & Yoga (Strength)", + "price": 18, + "product_type": "downloadable", + "quote_id": "4", + "product_option": { + "extension_attributes": { + "downloadable_option": { + "downloadable_links": [ + 5 + ] + } + } + } +} +``` + +### Add a configurable product to a cart {#add-configurable} + +To add a configurable product to a cart, you must specify the `sku` as well as the set of `option_id`/`option_value` pairs that make the product configurable. + +In this example, we'll add the Chaz Kangeroo Hoodie (`sku: MH01`) configurable product to the cart. This product comes in three colors (black, gray, and orange) and five sizes (XS, S, M, L, XL). In the sample data, the `option_id` values for Size and Color are `141` and `93`, respectively. You can use the `GET /V1/configurable-products/:sku/options/all` call to determine the `option_id` values for the given SKU. + +The `GET /V1/configurable-products/:sku/children` call returns information about each combination of color and size, 15 in all for `MH01`. The following sample shows the returned values for `size` and `color` for a small gray Chaz Kangeroo Hoodie. + +```json +{ + "custom_attributes": [ + { + "attribute_code": "size", + "value": "168" + }, + { + "attribute_code": "color", + "value": "52" + } + ] +} +``` + +We now know the values for `option_value` for `size` and `color` are `168` and `52`, so we're ready to add the product to the cart. + +**Endpoint:** + +`POST /rest//V1/carts/mine/items` + +**Headers:** + +`Content-Type: application/json` + +`Authorization: Bearer ` + +**Payload:** + +```json +{ + "cartItem": { + "sku": "MH01", + "qty": 1, + "quote_id": "4", + "product_option": { + "extension_attributes": { + "configurable_item_options": [ + { + "option_id": "93", + "option_value": 52 + }, + { + "option_id": "141", + "option_value": 168 + } + ] + } + }, + "extension_attributes": {} + } +} +``` + +**Response:** + +```json +{ + "item_id": 13, + "sku": "MH01-S-Gray", + "qty": 1, + "name": "Chaz Kangeroo Hoodie", + "price": 52, + "product_type": "configurable", + "quote_id": "4", + "product_option": { + "extension_attributes": { + "configurable_item_options": [ + { + "option_id": "93", + "option_value": 52 + }, + { + "option_id": "141", + "option_value": 168 + } + ] + } + } +} +``` + +### Add a bundle product to a cart {#add-bundle} + +The sample data provides one bundled product, the Sprite Yoga Companion Kit (`sku`: `24-WG080`). The kit contains the following items: + +* Sprite Statis Ball in sizes 55 cm (`sku`: `24-WG081-blue`), 65 cm (`sku`: `24-WG082-blue`), or 75 cm (`sku`: `24-WG083-blue`) +* Sprite Foam Yoga brick (`sku`: `24-WG084`) +* Sprite Yoga Strap in lengths 6 ft (`sku`: `24-WG085`), 8 ft (`sku`: `24-WG086`), or 10 ft (`sku`: `24-WG087`) +* Sprite Foam Roller (`sku`: `24-WG088`) + +To add a bundle product to a cart, you must specify the `sku` of the bundle product, but not the individual items. You add individual items to the bundle product by specifying the `id` defined in the item's `product_links` object. The `product_links` object primarily describes the ordering and placement of options on the customization page, but it also links an item's `sku` and `id` to the `sku` of the bundle product. + +The `GET /rest//V1/bundle-products/24-WG080/options/all` call returns `id` values, as shown in the following simplified response: + +{% collapsible Show code sample %} + +```json +[ + { + "option_id": 1, + "title": "Sprite Stasis Ball", + "required": true, + "type": "radio", + "position": 1, + "sku": "24-WG080", + "product_links": [ + { + "id": "1", + "sku": "24-WG081-blue", + "option_id": 1, + "qty": 1 + }, + { + "id": "2", + "sku": "24-WG082-blue", + "option_id": 1, + "qty": 1 + }, + { + "id": "3", + "sku": "24-WG083-blue", + "option_id": 1, + "qty": 1 + } + ] + }, + { + "option_id": 2, + "title": "Sprite Foam Yoga Brick", + "required": true, + "type": "radio", + "position": 2, + "sku": "24-WG080", + "product_links": [ + { + "id": "4", + "sku": "24-WG084", + "option_id": 2, + "qty": 1 + } + ] + }, + { + "option_id": 3, + "title": "Sprite Yoga Strap", + "required": true, + "type": "radio", + "position": 3, + "sku": "24-WG080", + "product_links": [ + { + "id": "5", + "sku": "24-WG085", + "option_id": 3, + "qty": 1 + }, + { + "id": "6", + "sku": "24-WG086", + "option_id": 3, + "qty": 1 + }, + { + "id": "7", + "sku": "24-WG087", + "option_id": 3, + "qty": 1 + } + ] + }, + { + "option_id": 4, + "title": "Sprite Foam Roller", + "required": true, + "type": "radio", + "position": 4, + "sku": "24-WG080", + "product_links": [ + { + "id": "8", + "sku": "24-WG088", + "option_id": 4, + "qty": 1 + } + ] + } +] +``` + +{% endcollapsible %} + +For this example, we'll configure the Sprite Yoga Companion Kit as follows: + +* 65 cm Sprite Stasis Ball (`id`: `2`) +* Sprite Foam Yoga Brick (`id`: `4`) +* 8 ft Sprite Yoga strap (`id`: `6`) +* Sprite Foam Roller (`id`: `8`) + +**Endpoint:** + +`POST /rest//V1/carts/mine/items` + +**Headers:** + +`Content-Type: application/json` + +`Authorization: Bearer ` + +**Payload:** + +{% collapsible Show code sample %} + +```json +{ + "cartItem": { + "sku": "24-WG080", + "qty": 1, + "quote_id": "4", + "product_option": { + "extension_attributes": { + "bundle_options": [ + { + "option_id": 1, + "option_qty": 1, + "option_selections": [2] + }, + { + "option_id": 2, + "option_qty": 1, + "option_selections": [4] + }, + { + "option_id": 3, + "option_qty": 1, + "option_selections": [6] + }, + { + "option_id": 4, + "option_qty": 1, + "option_selections": [8] + } + ] + } + } + } +} +``` + +{% endcollapsible %} + +**Response:** + +{% collapsible Show code sample %} + +```json +{ + "item_id": 9, + "sku": "24-WG080-24-WG084-24-WG088-24-WG082-blue-24-WG086", + "qty": 1, + "name": "Sprite Yoga Companion Kit", + "price": 68, + "product_type": "bundle", + "quote_id": "4", + "product_option": { + "extension_attributes": { + "bundle_options": [ + { + "option_id": 1, + "option_qty": 1, + "option_selections": [ + 2 + ] + }, + { + "option_id": 2, + "option_qty": 1, + "option_selections": [ + 4 + ] + }, + { + "option_id": 3, + "option_qty": 1, + "option_selections": [ + 6 + ] + }, + { + "option_id": 4, + "option_qty": 1, + "option_selections": [ + 8 + ] + } + ] + } + } +} +``` + +{% endcollapsible %} + +### Verify this step {#verify-step} + +[Sign in](https://glossary.magento.com/sign-in-sign-out) as the customer and click on the [shopping cart](https://glossary.magento.com/shopping-cart). All the items you added are displayed. diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md b/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md deleted file mode 120000 index 03d64bad7ac..00000000000 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/orders/order-create-customer.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md b/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md new file mode 100644 index 00000000000..68d02a66f8a --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md @@ -0,0 +1,164 @@ +--- +layout: tutorial +group: rest-api +title: Step 3. Create a customer + +subtitle: Order processing tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +menu_order: 3 +level3_subgroup: order-tutorial +redirect_from: + - /guides/v2.3/get-started/order-tutorial/order-create-customer.html +functional_areas: + - Integration + - Orders + - Customers +--- + +Customers can make purchases in three ways: + +* As a logged-in user +* As a guest user who logs in or creates an account when the order is placed +* As a guest user who does not create an account + +This tutorial creates an order by a logged-in user. Magento provides additional REST endpoints for handling guest users. + +### Create a customer account + +{:.bs-callout-info} +This example shows a simplified way of creating a customer account. Typically, you would not define a customer password using plain text. Instead, you would specify the payload without the `password` parameter. By default if the call is successful, Magento sends a "Welcome" email to the customer that includes a request to set the password. You could also initiate a password reset email by calling `PUT /V1/customers/password`. + +**Endpoint:** + +`POST /rest//V1/customers` + +**Headers:** + +`Content-Type: application/json` + +**Payload:** + +It is recommended that you substitute the value of the `email` parameter with a real email address so that you receive all notifications. + +{% collapsible Show code sample %} + +```json +{ + "customer": { + "email": "jdoe@example.com", + "firstname": "Jane", + "lastname": "Doe", + "addresses": [ + { + "defaultShipping": true, + "defaultBilling": true, + "firstname": "Jane", + "lastname": "Doe", + "region": { + "regionCode": "NY", + "region": "New York", + "regionId": 43 + }, + "postcode": "10755", + "street": [ + "123 Oak Ave" + ], + "city": "Purchase", + "telephone": "512-555-1111", + "countryId": "US" + } + ] + }, + "password": "Password1" +} +``` + +{% endcollapsible %} + +**Response:** + +Magento assigned this user `id` value of `2`. + +{% collapsible Show code sample %} + +```json +{ + "id": 2, + "group_id": 1, + "default_billing": "2", + "default_shipping": "2", + "created_at": "2017-01-31 01:18:13", + "updated_at": "2017-01-31 01:18:13", + "created_in": "Default Store View", + "email": "jdoe@example.com", + "firstname": "Jane", + "lastname": "Doe", + "store_id": 1, + "website_id": 1, + "addresses": [ + { + "id": 2, + "customer_id": 2, + "region": { + "region_code": "NY", + "region": "New York", + "region_id": 43 + }, + "region_id": 43, + "country_id": "US", + "street": [ + "123 Oak Ave" + ], + "telephone": "512-555-1111", + "postcode": "10755", + "city": "Purchase", + "firstname": "Jane", + "lastname": "Doe", + "default_shipping": true, + "default_billing": true + } + ], + "disable_auto_group_change": 0 +} +``` + +{% endcollapsible %} + +You can log in to the Luma store using the username `jdoe@example.com` and password `Password1`. + +### Get the customer's access token {#get-token} + +To get a customer's access token, you must specify the customer's username and password in the payload. You do not need to specify an admin [authorization](https://glossary.magento.com/authorization) token. + +By default, a customer token is valid for 1 hour. To change this value, log in to Admin and go to **Stores** > Settings > **Configuration** > **Services** > **OAuth** > **Access Token Expiration**. + +**Endpoint:** + +`POST /rest//V1/integration/customer/token` + +**Headers:** + +`Content-Type: application/json` + +**Payload:** + +```json +{ + "username": "jdoe@example.com", + "password": "Password1" +} +``` + +**Response:** + +Magento returns the customer's access token. This token must be specified in the authorization header of every call the customer makes on his or her own behalf. + +`q0u66k8h42yaevtchv09uyy3y9gaj2ap` + +### Verify this step {#verify-step} + +1. Log in to the Luma [website](https://glossary.magento.com/website) using the email `jdoe@example.com` and password `Password1`. +1. Click the account name (Jane) in the upper right corner and select **My Account**. +1. Click **Address Book** to view the default billing and shipping addresses. diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md b/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md deleted file mode 120000 index 9f4ce06c5f8..00000000000 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/orders/order-create-invoice.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md b/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md new file mode 100644 index 00000000000..a686f5ebe83 --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md @@ -0,0 +1,297 @@ +--- +layout: tutorial +group: rest-api +title: Step 8. Create an invoice + +subtitle: Order processing tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +menu_order: 8 +level3_subgroup: order-tutorial +redirect_from: + - /guides/v2.3/get-started/order-tutorial/order-create-invoice.html +functional_areas: + - Integration + - Orders + - Sales +--- + +You create an [invoice](https://glossary.magento.com/invoice) after you receive payment for an order. In this example, the order was paid offline via a bank transfer. Therefore, you must tell Magento that payment for the order has been captured. + +### Capture payment {#capture-payment} + +This example creates a full invoice. You can create a partial invoice by adding to the payload an array of items to be invoiced. + +**Endpoint:** + +`POST /rest//V1/order/3/invoice` + +where `3` is the `orderid` + +**Headers:** + +`Content-Type: application/json` + +`Authorization: Bearer` `` + +**Payload:** + +```json +{ + "capture": true, + "notify": true +} +``` + +**Response:** + +An invoice `id`, such as `3`. + +### View the invoice {#view-invoice} + +An invoice is structurally similar to an order, but an order contains more details. + +**Endpoint:** + +`GET /rest//V1/invoices/3` + +**Headers:** + +`Content-Type: application/json` + +`Authorization: Bearer ` + +**Payload:** + +Not applicable + +**Response:** + +You will use the `order_item_id` values to create a [shipment](https://glossary.magento.com/shipment) in the next step. + +{% collapsible Show code sample %} + +```json +{ + "base_currency_code": "USD", + "base_discount_amount": 0, + "base_grand_total": 165, + "base_discount_tax_compensation_amount": 0, + "base_shipping_amount": 5, + "base_shipping_incl_tax": 5, + "base_shipping_tax_amount": 0, + "base_subtotal": 160, + "base_subtotal_incl_tax": 160, + "base_tax_amount": 0, + "base_to_global_rate": 1, + "base_to_order_rate": 1, + "billing_address_id": 6, + "can_void_flag": 0, + "created_at": "2017-08-21 22:36:02", + "discount_amount": 0, + "email_sent": 1, + "entity_id": 3, + "global_currency_code": "USD", + "grand_total": 165, + "discount_tax_compensation_amount": 0, + "increment_id": "000000003", + "order_currency_code": "USD", + "order_id": 3, + "shipping_address_id": 5, + "shipping_amount": 5, + "shipping_discount_tax_compensation_amount": 0, + "shipping_incl_tax": 5, + "shipping_tax_amount": 0, + "state": 2, + "store_currency_code": "USD", + "store_id": 1, + "store_to_base_rate": 0, + "store_to_order_rate": 0, + "subtotal": 160, + "subtotal_incl_tax": 160, + "tax_amount": 0, + "total_qty": 9, + "updated_at": "2017-08-21 22:36:03", + "items": [ + { + "base_discount_tax_compensation_amount": 0, + "base_price": 22, + "base_price_incl_tax": 22, + "base_row_total": 22, + "base_row_total_incl_tax": 22, + "base_tax_amount": 0, + "entity_id": 3, + "discount_tax_compensation_amount": 0, + "name": "Radiant Tee-M-Orange", + "parent_id": 3, + "price": 22, + "price_incl_tax": 22, + "product_id": 1553, + "row_total": 22, + "row_total_incl_tax": 22, + "sku": "WS12-M-Orange", + "tax_amount": 0, + "order_item_id": 3, + "qty": 1 + }, + { + "base_discount_tax_compensation_amount": 0, + "base_price": 18, + "base_price_incl_tax": 18, + "base_row_total": 18, + "base_row_total_incl_tax": 18, + "base_tax_amount": 0, + "entity_id": 4, + "discount_tax_compensation_amount": 0, + "name": "Advanced Pilates & Yoga (Strength)", + "parent_id": 3, + "price": 18, + "price_incl_tax": 18, + "product_id": 49, + "row_total": 18, + "row_total_incl_tax": 18, + "sku": "240-LV08", + "tax_amount": 0, + "order_item_id": 4, + "qty": 1 + }, + { + "base_price": 68, + "base_price_incl_tax": 68, + "entity_id": 5, + "name": "Sprite Yoga Companion Kit", + "parent_id": 3, + "price": 68, + "price_incl_tax": 68, + "product_id": 51, + "sku": "24-WG080-24-WG084-24-WG088-24-WG082-blue-24-WG086", + "order_item_id": 5, + "qty": 1 + }, + { + "base_discount_tax_compensation_amount": 0, + "base_price": 27, + "base_price_incl_tax": 27, + "base_row_total": 27, + "base_row_total_incl_tax": 27, + "base_tax_amount": 0, + "entity_id": 6, + "discount_tax_compensation_amount": 0, + "name": "Sprite Stasis Ball 65 cm", + "parent_id": 3, + "price": 27, + "price_incl_tax": 27, + "product_id": 29, + "row_total": 27, + "row_total_incl_tax": 27, + "sku": "24-WG082-blue", + "tax_amount": 0, + "order_item_id": 6, + "qty": 1 + }, + { + "base_discount_tax_compensation_amount": 0, + "base_price": 5, + "base_price_incl_tax": 5, + "base_row_total": 5, + "base_row_total_incl_tax": 5, + "base_tax_amount": 0, + "entity_id": 7, + "discount_tax_compensation_amount": 0, + "name": "Sprite Foam Yoga Brick", + "parent_id": 3, + "price": 5, + "price_incl_tax": 5, + "product_id": 21, + "row_total": 5, + "row_total_incl_tax": 5, + "sku": "24-WG084", + "tax_amount": 0, + "order_item_id": 7, + "qty": 1 + }, + { + "base_discount_tax_compensation_amount": 0, + "base_price": 17, + "base_price_incl_tax": 17, + "base_row_total": 17, + "base_row_total_incl_tax": 17, + "base_tax_amount": 0, + "entity_id": 8, + "discount_tax_compensation_amount": 0, + "name": "Sprite Yoga Strap 8 foot", + "parent_id": 3, + "price": 17, + "price_incl_tax": 17, + "product_id": 34, + "row_total": 17, + "row_total_incl_tax": 17, + "sku": "24-WG086", + "tax_amount": 0, + "order_item_id": 8, + "qty": 1 + }, + { + "base_discount_tax_compensation_amount": 0, + "base_price": 19, + "base_price_incl_tax": 19, + "base_row_total": 19, + "base_row_total_incl_tax": 19, + "base_tax_amount": 0, + "entity_id": 9, + "discount_tax_compensation_amount": 0, + "name": "Sprite Foam Roller", + "parent_id": 3, + "price": 19, + "price_incl_tax": 19, + "product_id": 22, + "row_total": 19, + "row_total_incl_tax": 19, + "sku": "24-WG088", + "tax_amount": 0, + "order_item_id": 9, + "qty": 1 + }, + { + "base_discount_tax_compensation_amount": 0, + "base_price": 52, + "base_price_incl_tax": 52, + "base_row_total": 52, + "base_row_total_incl_tax": 52, + "base_tax_amount": 0, + "entity_id": 10, + "discount_tax_compensation_amount": 0, + "name": "Chaz Kangeroo Hoodie", + "parent_id": 3, + "price": 52, + "price_incl_tax": 52, + "product_id": 67, + "row_total": 52, + "row_total_incl_tax": 52, + "sku": "MH01-S-Gray", + "tax_amount": 0, + "order_item_id": 10, + "qty": 1 + }, + { + "base_price": 0, + "entity_id": 11, + "name": "Chaz Kangeroo Hoodie-S-Gray", + "parent_id": 3, + "price": 0, + "product_id": 56, + "sku": "MH01-S-Gray", + "order_item_id": 11, + "qty": 1 + } + ], + "comments": [] +} +``` + +{% endcollapsible %} + +### Verify this step {#verify-step} + +Log in to [Admin](https://glossary.magento.com/admin). Click **Sales** > **Invoices**. The invoice is displayed in the grid. The status is Paid. Then click **Sales** > **Orders**. The status is Processing. diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-order.md b/src/guides/v2.4/rest/tutorials/orders/order-create-order.md deleted file mode 120000 index 89c0b2f15fc..00000000000 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-order.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/orders/order-create-order.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-order.md b/src/guides/v2.4/rest/tutorials/orders/order-create-order.md new file mode 100644 index 00000000000..069aa167524 --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-order.md @@ -0,0 +1,1585 @@ +--- +layout: tutorial +group: rest-api +title: Step 7. Create an order + +subtitle: Order processing tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +menu_order: 7 +level3_subgroup: order-tutorial +redirect_from: + - /guides/v2.3/get-started/order-tutorial/order-create-order.html +functional_areas: + - Integration + - Orders + - Sales +--- + +The [shopping cart](https://glossary.magento.com/shopping-cart) contains three items totaling $108. The shipping charges are $10, making the grand total $118. We're now ready to convert the [quote](https://glossary.magento.com/quote) to an order. + +### Send payment information {#send-payment} + +When you submit payment information, Magento creates an order and sends an order confirmation to the customer. Since we are using an offline [payment method](https://glossary.magento.com/payment-method) in this tutorial, we do not need to provide detailed payment information. The endpoint used in this example requires only the payment method and billing address information. + +{:.bs-callout-info} +Use the `V1/guest-carts//payment-information` endpoint to set the payment information on behalf of a guest. Do not include an authorization token. +You must include the `email` attribute in the payload at the same level as `paymentMethod` and `billing_address`. + +**Endpoint:** + +`POST /rest//V1/carts/mine/payment-information` + +**Headers:** + +`Content-Type: application/json` + +`Authorization: Bearer ` + +**Payload:** + +{% collapsible Show code sample %} + +```json +{ + "paymentMethod": { + "method": "banktransfer" + }, + "billing_address": { + "email": "jdoe@example.com", + "region": "New York", + "region_id": 43, + "region_code": "NY", + "country_id": "US", + "street": [ + "123 Oak Ave" + ], + "postcode": "10577", + "city": "Purchase", + "telephone": "512-555-1111", + "firstname": "Jane", + "lastname": "Doe" + } +} +``` + +{% endcollapsible %} + +**Response:** + +An `orderID`, such as `3`. + +### Review the order as an admin {#review-order} + +When you request an order object, the response contains full details about the order, including customer information, payment details, as well as totals and subtotals for the order and each individual item. + +**Endpoint:** + +`GET /rest//V1/orders/3` + +where `3` is the `orderid` + +**Headers:** + +`Content-Type: application/json` + +`Authorization: Bearer ` + +**Payload:** + +Not applicable + +**Response:** + +{% collapsible Show code sample %} + +```json +{ + "applied_rule_ids": "1", + "base_currency_code": "USD", + "base_discount_amount": 0, + "base_grand_total": 165, + "base_discount_tax_compensation_amount": 0, + "base_shipping_amount": 5, + "base_shipping_discount_amount": 0, + "base_shipping_incl_tax": 5, + "base_shipping_tax_amount": 0, + "base_subtotal": 160, + "base_subtotal_incl_tax": 160, + "base_tax_amount": 0, + "base_total_due": 165, + "base_to_global_rate": 1, + "base_to_order_rate": 1, + "billing_address_id": 6, + "created_at": "2017-08-21 22:22:19", + "customer_email": "jdoe@example.com", + "customer_firstname": "Jane", + "customer_group_id": 1, + "customer_id": 3, + "customer_is_guest": 0, + "customer_lastname": "Doe", + "customer_note_notify": 1, + "discount_amount": 0, + "email_sent": 1, + "entity_id": 3, + "global_currency_code": "USD", + "grand_total": 165, + "discount_tax_compensation_amount": 0, + "increment_id": "000000003", + "is_virtual": 0, + "order_currency_code": "USD", + "protect_code": "61f76d", + "quote_id": 4, + "shipping_amount": 5, + "shipping_description": "Best Way - Table Rate", + "shipping_discount_amount": 0, + "shipping_discount_tax_compensation_amount": 0, + "shipping_incl_tax": 5, + "shipping_tax_amount": 0, + "state": "new", + "status": "pending", + "store_currency_code": "USD", + "store_id": 1, + "store_name": "Main Website\nMain Website Store\n", + "store_to_base_rate": 0, + "store_to_order_rate": 0, + "subtotal": 160, + "subtotal_incl_tax": 160, + "tax_amount": 0, + "total_due": 165, + "total_item_count": 7, + "total_qty_ordered": 4, + "updated_at": "2017-08-21 22:22:20", + "weight": 2, + "items": [ + { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_discount_tax_compensation_amount": 0, + "base_original_price": 22, + "base_price": 22, + "base_price_incl_tax": 22, + "base_row_invoiced": 0, + "base_row_total": 22, + "base_row_total_incl_tax": 22, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "discount_tax_compensation_amount": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 3, + "name": "Radiant Tee-M-Orange", + "no_discount": 0, + "order_id": 3, + "original_price": 22, + "price": 22, + "price_incl_tax": 22, + "product_id": 1553, + "product_type": "simple", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 6, + "row_invoiced": 0, + "row_total": 22, + "row_total_incl_tax": 22, + "row_weight": 1, + "sku": "WS12-M-Orange", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 1 + }, + { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_discount_tax_compensation_amount": 0, + "base_original_price": 18, + "base_price": 18, + "base_price_incl_tax": 18, + "base_row_invoiced": 0, + "base_row_total": 18, + "base_row_total_incl_tax": 18, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "discount_tax_compensation_amount": 0, + "is_qty_decimal": 0, + "is_virtual": 1, + "item_id": 4, + "name": "Advanced Pilates & Yoga (Strength)", + "no_discount": 0, + "order_id": 3, + "original_price": 18, + "price": 18, + "price_incl_tax": 18, + "product_id": 49, + "product_type": "downloadable", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 7, + "row_invoiced": 0, + "row_total": 18, + "row_total_incl_tax": 18, + "row_weight": 0, + "sku": "240-LV08", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19" + }, + { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_original_price": 68, + "base_price": 68, + "base_price_incl_tax": 68, + "base_row_invoiced": 0, + "base_row_total": 68, + "base_row_total_incl_tax": 68, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 5, + "name": "Sprite Yoga Companion Kit", + "no_discount": 0, + "order_id": 3, + "original_price": 68, + "price": 68, + "price_incl_tax": 68, + "product_id": 51, + "product_type": "bundle", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 8, + "row_invoiced": 0, + "row_total": 68, + "row_total_incl_tax": 68, + "row_weight": 0, + "sku": "24-WG080-24-WG084-24-WG088-24-WG082-blue-24-WG086", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 0 + }, + { + "amount_refunded": 0, + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_discount_tax_compensation_amount": 0, + "base_original_price": 27, + "base_price": 27, + "base_price_incl_tax": 27, + "base_row_invoiced": 0, + "base_row_total": 27, + "base_row_total_incl_tax": 27, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "discount_tax_compensation_amount": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 6, + "name": "Sprite Stasis Ball 65 cm", + "no_discount": 0, + "order_id": 3, + "original_price": 27, + "parent_item_id": 5, + "price": 27, + "price_incl_tax": 27, + "product_id": 29, + "product_type": "simple", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 9, + "row_invoiced": 0, + "row_total": 27, + "row_total_incl_tax": 27, + "row_weight": 0, + "sku": "24-WG082-blue", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19", + "parent_item": { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_original_price": 68, + "base_price": 68, + "base_price_incl_tax": 68, + "base_row_invoiced": 0, + "base_row_total": 68, + "base_row_total_incl_tax": 68, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 5, + "name": "Sprite Yoga Companion Kit", + "no_discount": 0, + "order_id": 3, + "original_price": 68, + "price": 68, + "price_incl_tax": 68, + "product_id": 51, + "product_type": "bundle", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 8, + "row_invoiced": 0, + "row_total": 68, + "row_total_incl_tax": 68, + "row_weight": 0, + "sku": "24-WG080-24-WG084-24-WG088-24-WG082-blue-24-WG086", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 0 + } + }, + { + "amount_refunded": 0, + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_discount_tax_compensation_amount": 0, + "base_original_price": 5, + "base_price": 5, + "base_price_incl_tax": 5, + "base_row_invoiced": 0, + "base_row_total": 5, + "base_row_total_incl_tax": 5, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "discount_tax_compensation_amount": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 7, + "name": "Sprite Foam Yoga Brick", + "no_discount": 0, + "order_id": 3, + "original_price": 5, + "parent_item_id": 5, + "price": 5, + "price_incl_tax": 5, + "product_id": 21, + "product_type": "simple", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 10, + "row_invoiced": 0, + "row_total": 5, + "row_total_incl_tax": 5, + "row_weight": 0, + "sku": "24-WG084", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19", + "parent_item": { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_original_price": 68, + "base_price": 68, + "base_price_incl_tax": 68, + "base_row_invoiced": 0, + "base_row_total": 68, + "base_row_total_incl_tax": 68, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 5, + "name": "Sprite Yoga Companion Kit", + "no_discount": 0, + "order_id": 3, + "original_price": 68, + "price": 68, + "price_incl_tax": 68, + "product_id": 51, + "product_type": "bundle", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 8, + "row_invoiced": 0, + "row_total": 68, + "row_total_incl_tax": 68, + "row_weight": 0, + "sku": "24-WG080-24-WG084-24-WG088-24-WG082-blue-24-WG086", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 0 + } + }, + { + "amount_refunded": 0, + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_discount_tax_compensation_amount": 0, + "base_original_price": 17, + "base_price": 17, + "base_price_incl_tax": 17, + "base_row_invoiced": 0, + "base_row_total": 17, + "base_row_total_incl_tax": 17, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "discount_tax_compensation_amount": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 8, + "name": "Sprite Yoga Strap 8 foot", + "no_discount": 0, + "order_id": 3, + "original_price": 17, + "parent_item_id": 5, + "price": 17, + "price_incl_tax": 17, + "product_id": 34, + "product_type": "simple", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 11, + "row_invoiced": 0, + "row_total": 17, + "row_total_incl_tax": 17, + "row_weight": 0, + "sku": "24-WG086", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19", + "parent_item": { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_original_price": 68, + "base_price": 68, + "base_price_incl_tax": 68, + "base_row_invoiced": 0, + "base_row_total": 68, + "base_row_total_incl_tax": 68, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 5, + "name": "Sprite Yoga Companion Kit", + "no_discount": 0, + "order_id": 3, + "original_price": 68, + "price": 68, + "price_incl_tax": 68, + "product_id": 51, + "product_type": "bundle", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 8, + "row_invoiced": 0, + "row_total": 68, + "row_total_incl_tax": 68, + "row_weight": 0, + "sku": "24-WG080-24-WG084-24-WG088-24-WG082-blue-24-WG086", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 0 + } + }, + { + "amount_refunded": 0, + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_discount_tax_compensation_amount": 0, + "base_original_price": 19, + "base_price": 19, + "base_price_incl_tax": 19, + "base_row_invoiced": 0, + "base_row_total": 19, + "base_row_total_incl_tax": 19, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "discount_tax_compensation_amount": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 9, + "name": "Sprite Foam Roller", + "no_discount": 0, + "order_id": 3, + "original_price": 19, + "parent_item_id": 5, + "price": 19, + "price_incl_tax": 19, + "product_id": 22, + "product_type": "simple", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 12, + "row_invoiced": 0, + "row_total": 19, + "row_total_incl_tax": 19, + "row_weight": 0, + "sku": "24-WG088", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19", + "parent_item": { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_original_price": 68, + "base_price": 68, + "base_price_incl_tax": 68, + "base_row_invoiced": 0, + "base_row_total": 68, + "base_row_total_incl_tax": 68, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 5, + "name": "Sprite Yoga Companion Kit", + "no_discount": 0, + "order_id": 3, + "original_price": 68, + "price": 68, + "price_incl_tax": 68, + "product_id": 51, + "product_type": "bundle", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 8, + "row_invoiced": 0, + "row_total": 68, + "row_total_incl_tax": 68, + "row_weight": 0, + "sku": "24-WG080-24-WG084-24-WG088-24-WG082-blue-24-WG086", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 0 + } + }, + { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_discount_tax_compensation_amount": 0, + "base_original_price": 52, + "base_price": 52, + "base_price_incl_tax": 52, + "base_row_invoiced": 0, + "base_row_total": 52, + "base_row_total_incl_tax": 52, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "discount_tax_compensation_amount": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 10, + "name": "Chaz Kangeroo Hoodie", + "no_discount": 0, + "order_id": 3, + "original_price": 52, + "price": 52, + "price_incl_tax": 52, + "product_id": 67, + "product_type": "configurable", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 13, + "row_invoiced": 0, + "row_total": 52, + "row_total_incl_tax": 52, + "row_weight": 1, + "sku": "MH01-S-Gray", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 1 + }, + { + "amount_refunded": 0, + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_price": 0, + "base_row_invoiced": 0, + "base_row_total": 0, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 11, + "name": "Chaz Kangeroo Hoodie-S-Gray", + "no_discount": 0, + "order_id": 3, + "original_price": 0, + "parent_item_id": 10, + "price": 0, + "product_id": 56, + "product_type": "simple", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 14, + "row_invoiced": 0, + "row_total": 0, + "row_weight": 0, + "sku": "MH01-S-Gray", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 1, + "parent_item": { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_discount_tax_compensation_amount": 0, + "base_original_price": 52, + "base_price": 52, + "base_price_incl_tax": 52, + "base_row_invoiced": 0, + "base_row_total": 52, + "base_row_total_incl_tax": 52, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "discount_tax_compensation_amount": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 10, + "name": "Chaz Kangeroo Hoodie", + "no_discount": 0, + "order_id": 3, + "original_price": 52, + "price": 52, + "price_incl_tax": 52, + "product_id": 67, + "product_type": "configurable", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 13, + "row_invoiced": 0, + "row_total": 52, + "row_total_incl_tax": 52, + "row_weight": 1, + "sku": "MH01-S-Gray", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 1 + } + } + ], + "billing_address": { + "address_type": "billing", + "city": "Purchase", + "country_id": "US", + "email": "jdoe@example.com", + "entity_id": 6, + "firstname": "Jane", + "lastname": "Doe", + "parent_id": 3, + "postcode": "10577", + "region": "New York", + "region_code": "NY", + "region_id": 43, + "street": [ + "123 Oak Ave" + ], + "telephone": "512-555-1111" + }, + "payment": { + "account_status": null, + "additional_information": [ + "Bank Transfer Payment", + "" + ], + "amount_ordered": 165, + "base_amount_ordered": 165, + "base_shipping_amount": 5, + "cc_last4": null, + "entity_id": 3, + "method": "banktransfer", + "parent_id": 3, + "shipping_amount": 5 + }, + "status_histories": [], + "extension_attributes": { + "shipping_assignments": [ + { + "shipping": { + "address": { + "address_type": "shipping", + "city": "Purchase", + "country_id": "US", + "email": "jdoe@example.com", + "entity_id": 5, + "firstname": "Jane", + "lastname": "Doe", + "parent_id": 3, + "postcode": "10577", + "region": "New York", + "region_code": "NY", + "region_id": 43, + "street": [ + "123 Oak Ave" + ], + "telephone": "512-555-1111" + }, + "method": "tablerate_bestway", + "total": { + "base_shipping_amount": 5, + "base_shipping_discount_amount": 0, + "base_shipping_incl_tax": 5, + "base_shipping_tax_amount": 0, + "shipping_amount": 5, + "shipping_discount_amount": 0, + "shipping_discount_tax_compensation_amount": 0, + "shipping_incl_tax": 5, + "shipping_tax_amount": 0 + } + }, + "items": [ + { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_discount_tax_compensation_amount": 0, + "base_original_price": 22, + "base_price": 22, + "base_price_incl_tax": 22, + "base_row_invoiced": 0, + "base_row_total": 22, + "base_row_total_incl_tax": 22, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "discount_tax_compensation_amount": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 3, + "name": "Radiant Tee-M-Orange", + "no_discount": 0, + "order_id": 3, + "original_price": 22, + "price": 22, + "price_incl_tax": 22, + "product_id": 1553, + "product_type": "simple", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 6, + "row_invoiced": 0, + "row_total": 22, + "row_total_incl_tax": 22, + "row_weight": 1, + "sku": "WS12-M-Orange", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 1 + }, + { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_discount_tax_compensation_amount": 0, + "base_original_price": 18, + "base_price": 18, + "base_price_incl_tax": 18, + "base_row_invoiced": 0, + "base_row_total": 18, + "base_row_total_incl_tax": 18, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "discount_tax_compensation_amount": 0, + "is_qty_decimal": 0, + "is_virtual": 1, + "item_id": 4, + "name": "Advanced Pilates & Yoga (Strength)", + "no_discount": 0, + "order_id": 3, + "original_price": 18, + "price": 18, + "price_incl_tax": 18, + "product_id": 49, + "product_type": "downloadable", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 7, + "row_invoiced": 0, + "row_total": 18, + "row_total_incl_tax": 18, + "row_weight": 0, + "sku": "240-LV08", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19" + }, + { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_original_price": 68, + "base_price": 68, + "base_price_incl_tax": 68, + "base_row_invoiced": 0, + "base_row_total": 68, + "base_row_total_incl_tax": 68, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 5, + "name": "Sprite Yoga Companion Kit", + "no_discount": 0, + "order_id": 3, + "original_price": 68, + "price": 68, + "price_incl_tax": 68, + "product_id": 51, + "product_type": "bundle", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 8, + "row_invoiced": 0, + "row_total": 68, + "row_total_incl_tax": 68, + "row_weight": 0, + "sku": "24-WG080-24-WG084-24-WG088-24-WG082-blue-24-WG086", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 0 + }, + { + "amount_refunded": 0, + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_discount_tax_compensation_amount": 0, + "base_original_price": 27, + "base_price": 27, + "base_price_incl_tax": 27, + "base_row_invoiced": 0, + "base_row_total": 27, + "base_row_total_incl_tax": 27, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "discount_tax_compensation_amount": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 6, + "name": "Sprite Stasis Ball 65 cm", + "no_discount": 0, + "order_id": 3, + "original_price": 27, + "parent_item_id": 5, + "price": 27, + "price_incl_tax": 27, + "product_id": 29, + "product_type": "simple", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 9, + "row_invoiced": 0, + "row_total": 27, + "row_total_incl_tax": 27, + "row_weight": 0, + "sku": "24-WG082-blue", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19", + "parent_item": { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_original_price": 68, + "base_price": 68, + "base_price_incl_tax": 68, + "base_row_invoiced": 0, + "base_row_total": 68, + "base_row_total_incl_tax": 68, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 5, + "name": "Sprite Yoga Companion Kit", + "no_discount": 0, + "order_id": 3, + "original_price": 68, + "price": 68, + "price_incl_tax": 68, + "product_id": 51, + "product_type": "bundle", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 8, + "row_invoiced": 0, + "row_total": 68, + "row_total_incl_tax": 68, + "row_weight": 0, + "sku": "24-WG080-24-WG084-24-WG088-24-WG082-blue-24-WG086", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 0 + } + }, + { + "amount_refunded": 0, + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_discount_tax_compensation_amount": 0, + "base_original_price": 5, + "base_price": 5, + "base_price_incl_tax": 5, + "base_row_invoiced": 0, + "base_row_total": 5, + "base_row_total_incl_tax": 5, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "discount_tax_compensation_amount": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 7, + "name": "Sprite Foam Yoga Brick", + "no_discount": 0, + "order_id": 3, + "original_price": 5, + "parent_item_id": 5, + "price": 5, + "price_incl_tax": 5, + "product_id": 21, + "product_type": "simple", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 10, + "row_invoiced": 0, + "row_total": 5, + "row_total_incl_tax": 5, + "row_weight": 0, + "sku": "24-WG084", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19", + "parent_item": { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_original_price": 68, + "base_price": 68, + "base_price_incl_tax": 68, + "base_row_invoiced": 0, + "base_row_total": 68, + "base_row_total_incl_tax": 68, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 5, + "name": "Sprite Yoga Companion Kit", + "no_discount": 0, + "order_id": 3, + "original_price": 68, + "price": 68, + "price_incl_tax": 68, + "product_id": 51, + "product_type": "bundle", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 8, + "row_invoiced": 0, + "row_total": 68, + "row_total_incl_tax": 68, + "row_weight": 0, + "sku": "24-WG080-24-WG084-24-WG088-24-WG082-blue-24-WG086", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 0 + } + }, + { + "amount_refunded": 0, + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_discount_tax_compensation_amount": 0, + "base_original_price": 17, + "base_price": 17, + "base_price_incl_tax": 17, + "base_row_invoiced": 0, + "base_row_total": 17, + "base_row_total_incl_tax": 17, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "discount_tax_compensation_amount": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 8, + "name": "Sprite Yoga Strap 8 foot", + "no_discount": 0, + "order_id": 3, + "original_price": 17, + "parent_item_id": 5, + "price": 17, + "price_incl_tax": 17, + "product_id": 34, + "product_type": "simple", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 11, + "row_invoiced": 0, + "row_total": 17, + "row_total_incl_tax": 17, + "row_weight": 0, + "sku": "24-WG086", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19", + "parent_item": { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_original_price": 68, + "base_price": 68, + "base_price_incl_tax": 68, + "base_row_invoiced": 0, + "base_row_total": 68, + "base_row_total_incl_tax": 68, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 5, + "name": "Sprite Yoga Companion Kit", + "no_discount": 0, + "order_id": 3, + "original_price": 68, + "price": 68, + "price_incl_tax": 68, + "product_id": 51, + "product_type": "bundle", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 8, + "row_invoiced": 0, + "row_total": 68, + "row_total_incl_tax": 68, + "row_weight": 0, + "sku": "24-WG080-24-WG084-24-WG088-24-WG082-blue-24-WG086", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 0 + } + }, + { + "amount_refunded": 0, + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_discount_tax_compensation_amount": 0, + "base_original_price": 19, + "base_price": 19, + "base_price_incl_tax": 19, + "base_row_invoiced": 0, + "base_row_total": 19, + "base_row_total_incl_tax": 19, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "discount_tax_compensation_amount": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 9, + "name": "Sprite Foam Roller", + "no_discount": 0, + "order_id": 3, + "original_price": 19, + "parent_item_id": 5, + "price": 19, + "price_incl_tax": 19, + "product_id": 22, + "product_type": "simple", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 12, + "row_invoiced": 0, + "row_total": 19, + "row_total_incl_tax": 19, + "row_weight": 0, + "sku": "24-WG088", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19", + "parent_item": { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_original_price": 68, + "base_price": 68, + "base_price_incl_tax": 68, + "base_row_invoiced": 0, + "base_row_total": 68, + "base_row_total_incl_tax": 68, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 5, + "name": "Sprite Yoga Companion Kit", + "no_discount": 0, + "order_id": 3, + "original_price": 68, + "price": 68, + "price_incl_tax": 68, + "product_id": 51, + "product_type": "bundle", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 8, + "row_invoiced": 0, + "row_total": 68, + "row_total_incl_tax": 68, + "row_weight": 0, + "sku": "24-WG080-24-WG084-24-WG088-24-WG082-blue-24-WG086", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 0 + } + }, + { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_discount_tax_compensation_amount": 0, + "base_original_price": 52, + "base_price": 52, + "base_price_incl_tax": 52, + "base_row_invoiced": 0, + "base_row_total": 52, + "base_row_total_incl_tax": 52, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "discount_tax_compensation_amount": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 10, + "name": "Chaz Kangeroo Hoodie", + "no_discount": 0, + "order_id": 3, + "original_price": 52, + "price": 52, + "price_incl_tax": 52, + "product_id": 67, + "product_type": "configurable", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 13, + "row_invoiced": 0, + "row_total": 52, + "row_total_incl_tax": 52, + "row_weight": 1, + "sku": "MH01-S-Gray", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 1 + }, + { + "amount_refunded": 0, + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_price": 0, + "base_row_invoiced": 0, + "base_row_total": 0, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 11, + "name": "Chaz Kangeroo Hoodie-S-Gray", + "no_discount": 0, + "order_id": 3, + "original_price": 0, + "parent_item_id": 10, + "price": 0, + "product_id": 56, + "product_type": "simple", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 14, + "row_invoiced": 0, + "row_total": 0, + "row_weight": 0, + "sku": "MH01-S-Gray", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 1, + "parent_item": { + "amount_refunded": 0, + "applied_rule_ids": "1", + "base_amount_refunded": 0, + "base_discount_amount": 0, + "base_discount_invoiced": 0, + "base_discount_tax_compensation_amount": 0, + "base_original_price": 52, + "base_price": 52, + "base_price_incl_tax": 52, + "base_row_invoiced": 0, + "base_row_total": 52, + "base_row_total_incl_tax": 52, + "base_tax_amount": 0, + "base_tax_invoiced": 0, + "created_at": "2017-08-21 22:22:19", + "discount_amount": 0, + "discount_invoiced": 0, + "discount_percent": 0, + "free_shipping": 0, + "discount_tax_compensation_amount": 0, + "is_qty_decimal": 0, + "is_virtual": 0, + "item_id": 10, + "name": "Chaz Kangeroo Hoodie", + "no_discount": 0, + "order_id": 3, + "original_price": 52, + "price": 52, + "price_incl_tax": 52, + "product_id": 67, + "product_type": "configurable", + "qty_canceled": 0, + "qty_invoiced": 0, + "qty_ordered": 1, + "qty_refunded": 0, + "qty_shipped": 0, + "quote_item_id": 13, + "row_invoiced": 0, + "row_total": 52, + "row_total_incl_tax": 52, + "row_weight": 1, + "sku": "MH01-S-Gray", + "store_id": 1, + "tax_amount": 0, + "tax_invoiced": 0, + "tax_percent": 0, + "updated_at": "2017-08-21 22:22:19", + "weight": 1 + } + } + ] + } + ] + } +} +``` + +{% endcollapsible %} + +### Verify this step {#verify-step} + +1. Log in to the Luma store as the customer. The dashboard shows the order. +1. Log in to [Admin](https://glossary.magento.com/admin). Click **Sales** > **Orders**. The order is displayed in the grid. Its status is Pending. diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md b/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md deleted file mode 120000 index 164fbf5c3ac..00000000000 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/orders/order-create-quote.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md b/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md new file mode 100644 index 00000000000..fc397b4d38c --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md @@ -0,0 +1,67 @@ +--- +layout: tutorial +group: rest-api +title: Step 4. Create a quote + +subtitle: Order processing tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +menu_order: 4 +level3_subgroup: order-tutorial +redirect_from: + - /guides/v2.3/get-started/order-tutorial/order-create-quote.html +functional_areas: + - Integration + - Orders + - Cart +--- + +When a customer adds an item to their [shopping cart](https://glossary.magento.com/shopping-cart) for the first time, Magento creates a [quote](https://glossary.magento.com/quote). Magento uses a quote to perform tasks such as + +* Track each item the customer wants to buy, including the quantity and base cost +* Gather information about the customer, including billing and shipping addresses +* Determine shipping costs +* Calculate the subtotal, add costs (shipping fees, taxes, etc.) and apply coupons to determine the grand total +* Determine the [payment method](https://glossary.magento.com/payment-method) +* Place the order so that the merchant can fulfill it. + +### Types of carts {#cart-types} + +Magento identifies three types of users that can create a shopping cart: + +* An [admin](https://glossary.magento.com/admin) user can create a cart on behalf of a customer. For all admin requests, you must provide an admin [authorization](https://glossary.magento.com/authorization) token in the call's authorization header. +* A logged-in customer. Calls to create a cart and add items must contain the customer's authorization token in the authorization header. +* A guest user. These users could be customers who haven't logged in yet, or they could be users who have no intention of creating an account. An anonymous user's cart is called a guest cart. + +### Create a cart for a logged-in customer {#create-cart} + +All calls for a logged in customer must specify customer's token `q0u66k8h42yaevtchv09uyy3y9gaj2ap` in the header. + +{:.bs-callout-info} +Use the `V1/guest-carts` endpoint to create a cart on behalf of a guest. Do not include an authorization token. The `quoteId` for the guest customer quote will be masked. + +**Endpoint:** + +`POST /rest//V1/carts/mine` + +**Headers:** + +`Content-Type: application/json` + +`Authorization: Bearer ` + +**Payload:** + +None + +**Response:** + +The response is the `quoteId: 4` + +{:.bs-callout-tip} +Some calls refer to this parameter as the `cartId`. + +### Verify this step {#verify-step} + +There are no additional verification steps.`quoteId` values are not displayed on the [website](https://glossary.magento.com/website) or in Admin. diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md b/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md deleted file mode 120000 index 3c8ffa8d656..00000000000 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/orders/order-create-shipment.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md b/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md new file mode 100644 index 00000000000..66e28902fc4 --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md @@ -0,0 +1,80 @@ +--- +layout: tutorial +group: rest-api +title: Step 9. Create a shipment + +subtitle: Order processing tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +menu_order: 9 +level3_subgroup: order-tutorial +redirect_from: + - /guides/v2.3/get-started/order-tutorial/order-create-shipment.html +functional_areas: + - Integration + - Orders + - Sales + - Shipping +--- + +To create a shipment, you need the `order_item_id` of each item to be shipped. Since the Sprite Yoga Companion Kit is a bundle item, you only need to include the top-level `order_item_id` (`5`). The `order_item_id` for the Radiant Tee-M-Orange is `3`. + +To create a partial shipment, specify only those `order_item_id`s that are to be shipped now. + +If the call is successful on a full shipment, Magento changes the status of an order to Complete. + +**Endpoint:** + +`POST /rest//V1/order/3/ship` + +where `3` is the order id. + +**Headers:** + +`Content-Type: application/json` + +`Authorization: Bearer ` + +**Payload:** + +The `notify` field is used to trigger Magento to send the shipment email. The `tracks` array optionally allows you to include one or more tracking numbers for the [shipment](https://glossary.magento.com/shipment). + +{% collapsible Show code sample %} + +```json +{ + "items": [ + { + "order_item_id": 3, + "qty": 1 + }, + { + "order_item_id": 5, + "qty": 1 + }, + { + "order_item_id": 11, + "qty": 1 + } + ], + "notify": true, + "tracks": [ + { + "track_number": "1Y-9876543210", + "title": "United Parcel Service", + "carrier_code": "ups" + } + ] +} +``` + +{% endcollapsible %} + +**Response:** + +A shipment ID, such as `3`. + +## Verify this step + +Log in to [Admin](https://glossary.magento.com/admin). Click **Sales** > **Shipments**. The shipment is displayed in the grid. Then click **Sales** > **Orders**. The order status is Complete. diff --git a/src/guides/v2.4/rest/tutorials/orders/order-intro.md b/src/guides/v2.4/rest/tutorials/orders/order-intro.md index a0c1ccf6d49..5b6aa866019 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-intro.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-intro.md @@ -33,7 +33,7 @@ Complete the following prerequisites: * Know how to construct a REST call in Magento. See [Construct a request](https://developer.adobe.com/commerce/webapi/get-started/gs-web-api-request.html) for details. -* Find the Magento REST API documentation. You can view the [static REST API documentation on devdocs]({{ site.baseurl }}/redoc/{{page.guide_version}}/) or [generate a local API reference](https://developer.adobe.com/commerce/webapi/rest/generate-local.html). +* Find the Magento REST API documentation. You can view the [static REST API documentation on devdocs]({{ site.baseurl }}/redoc/{{page.guide_version}}/) or [generate a local API reference](https://developer.adobe.com/commerce/webapi/quick_reference/rest/generate-local.html). * Find the Magento Merchant documentation. Refer to [Getting Started with {{site.data.var.ce}} 2.1]({{ site.user_guide_url }}/getting-started.html) for information about the Luma store that is created when you install Magento with the sample data. diff --git a/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md b/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md deleted file mode 120000 index 89a9059d508..00000000000 --- a/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/rest/tutorials/orders/order-prepare-checkout.md \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md b/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md new file mode 100644 index 00000000000..a48253a582c --- /dev/null +++ b/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md @@ -0,0 +1,357 @@ +--- +layout: tutorial +group: rest-api +subgroup: +title: Step 6. Prepare for checkout + +subtitle: Order Processing tutorial +return_to: + title: REST tutorials + url: rest/tutorials/index.html +menu_order: 6 +level3_subgroup: order-tutorial +functional_areas: + - Integration + - Orders + - Sales + - Checkout +--- + +Now that all the items have been added to the cart, we can prepare the order for [checkout](https://glossary.magento.com/checkout). This process includes the following steps: + +* Estimate shipping costs +* Set shipping and billing information + +### Estimate shipping costs {#estimate-shipping} + +Magento calculates shipping costs for each shipping method that can be applied to the order. In this tutorial, the `flatrate` ($5 per item) and `tablerate` shipping methods are active. + +{:.bs-callout-info} +Use the `V1/guest-carts//estimate-shipping-methods` endpoint to estimate shipping costs on behalf of a guest. Do not include an authorization token. + +**Endpoint:** + +`POST /rest//V1/carts/mine/estimate-shipping-methods` + +**Headers:** + +`Content-Type: application/json` + +`Authorization: Bearer ` + +**Payload:** + +The payload contains the shipping address. + +{% collapsible Show code sample %} + +```json +{ + "address": { + "region": "New York", + "region_id": 43, + "region_code": "NY", + "country_id": "US", + "street": [ + "123 Oak Ave" + ], + "postcode": "10577", + "city": "Purchase", + "firstname": "Jane", + "lastname": "Doe", + "customer_id": 4, + "email": "jdoe@example.com", + "telephone": "(512) 555-1111", + "same_as_billing": 1 + } +} +``` + +{% endcollapsible %} + +**Response:** + +Note that the cost for the `flatrate` shipping method is $15. The Sprite Yoga Companion Kit bundled product counts as one item. The Advanced Pilates & Yoga item does not have a shipping charge because the customer downloads this item. + +{% collapsible Show code sample %} + +```json +[ + { + "carrier_code": "flatrate", + "method_code": "flatrate", + "carrier_title": "Flat Rate", + "method_title": "Fixed", + "amount": 15, + "base_amount": 15, + "available": true, + "error_message": "", + "price_excl_tax": 15, + "price_incl_tax": 15 + }, + { + "carrier_code": "tablerate", + "method_code": "bestway", + "carrier_title": "Best Way", + "method_title": "Table Rate", + "amount": 5, + "base_amount": 5, + "available": true, + "error_message": "", + "price_excl_tax": 5, + "price_incl_tax": 5 + } +] +``` + +{% endcollapsible %} + +### Set shipping and billing information {#set-addresses} + +In this call, you specify the shipping and billing addresses, as well as the selected `carrier_code` and `method_code`. Since the Table Rate shipping method costs only $5, the customer selected this option. + +Magento returns a list of payment options and calculates the order totals. + +{:.bs-callout-info} +Use the `V1/guest-carts//shipping-information` endpoint to set the billing and shipping information on behalf of a guest. Do not include an authorization token. + +**Endpoint:** + +`POST /rest//V1/carts/mine/shipping-information` + +**Headers:** + +`Content-Type: application/json` + +`Authorization: Bearer ` + +**Payload:** + +{% collapsible Show code sample %} + +```json +{ + "addressInformation": { + "shipping_address": { + "region": "New York", + "region_id": 43, + "region_code": "NY", + "country_id": "US", + "street": [ + "123 Oak Ave" + ], + "postcode": "10577", + "city": "Purchase", + "firstname": "Jane", + "lastname": "Doe", + "email": "jdoe@example.com", + "telephone": "512-555-1111" + }, + "billing_address": { + "region": "New York", + "region_id": 43, + "region_code": "NY", + "country_id": "US", + "street": [ + "123 Oak Ave" + ], + "postcode": "10577", + "city": "Purchase", + "firstname": "Jane", + "lastname": "Doe", + "email": "jdoe@example.com", + "telephone": "512-555-1111" + }, + "shipping_carrier_code": "tablerate", + "shipping_method_code": "bestway" + } +} +``` + +{% endcollapsible %} + +**Response:** + +The subtotal of the order is $160, and shipping charges are $5. The grand total is $165. + +The available payment methods are `banktransfer` and `checkmo`. The customer will specify a [payment method](https://glossary.magento.com/payment-method) in the next step. + +{% collapsible Show code sample %} + +```json +{ + "payment_methods": [ + { + "code": "cashondelivery", + "title": "Cash On Delivery" + }, + { + "code": "banktransfer", + "title": "Bank Transfer Payment" + }, + { + "code": "purchaseorder", + "title": "Purchase Order" + }, + { + "code": "checkmo", + "title": "Check / Money order" + } + ], + "totals": { + "grand_total": 165, + "base_grand_total": 165, + "subtotal": 160, + "base_subtotal": 160, + "discount_amount": 0, + "base_discount_amount": 0, + "subtotal_with_discount": 160, + "base_subtotal_with_discount": 160, + "shipping_amount": 5, + "base_shipping_amount": 5, + "shipping_discount_amount": 0, + "base_shipping_discount_amount": 0, + "tax_amount": 0, + "base_tax_amount": 0, + "weee_tax_applied_amount": null, + "shipping_tax_amount": 0, + "base_shipping_tax_amount": 0, + "subtotal_incl_tax": 160, + "shipping_incl_tax": 5, + "base_shipping_incl_tax": 5, + "base_currency_code": "USD", + "quote_currency_code": "USD", + "items_qty": 4, + "items": [ + { + "item_id": 6, + "price": 22, + "base_price": 22, + "qty": 1, + "row_total": 22, + "base_row_total": 22, + "row_total_with_discount": 0, + "tax_amount": 0, + "base_tax_amount": 0, + "tax_percent": 0, + "discount_amount": 0, + "base_discount_amount": 0, + "discount_percent": 0, + "price_incl_tax": 22, + "base_price_incl_tax": 22, + "row_total_incl_tax": 22, + "base_row_total_incl_tax": 22, + "options": "[]", + "weee_tax_applied_amount": null, + "weee_tax_applied": null, + "name": "Radiant Tee-M-Orange" + }, + { + "item_id": 7, + "price": 18, + "base_price": 18, + "qty": 1, + "row_total": 18, + "base_row_total": 18, + "row_total_with_discount": 0, + "tax_amount": 0, + "base_tax_amount": 0, + "tax_percent": 0, + "discount_amount": 0, + "base_discount_amount": 0, + "discount_percent": 0, + "price_incl_tax": 18, + "base_price_incl_tax": 18, + "row_total_incl_tax": 18, + "base_row_total_incl_tax": 18, + "options": "[{\"value\":\"Advanced Pilates & Yoga (Strength)\",\"label\":\"Downloads\"}]", + "weee_tax_applied_amount": null, + "weee_tax_applied": null, + "name": "Advanced Pilates & Yoga (Strength)" + }, + { + "item_id": 8, + "price": 68, + "base_price": 68, + "qty": 1, + "row_total": 68, + "base_row_total": 68, + "row_total_with_discount": 0, + "tax_amount": 0, + "base_tax_amount": 0, + "discount_amount": 0, + "base_discount_amount": 0, + "discount_percent": 0, + "price_incl_tax": 68, + "base_price_incl_tax": 68, + "row_total_incl_tax": 68, + "base_row_total_incl_tax": 68, + "options": "[{\"value\":\"1 x Sprite Stasis Ball 65 cm $27.00<\\/span>\",\"label\":\"Sprite Stasis Ball\"},{\"value\":\"1 x Sprite Foam Yoga Brick $5.00<\\/span>\",\"label\":\"Sprite Foam Yoga Brick\"},{\"value\":\"1 x Sprite Yoga Strap 8 foot $17.00<\\/span>\",\"label\":\"Sprite Yoga Strap\"},{\"value\":\"1 x Sprite Foam Roller $19.00<\\/span>\",\"label\":\"Sprite Foam Roller\"}]", + "weee_tax_applied_amount": null, + "weee_tax_applied": null, + "name": "Sprite Yoga Companion Kit" + }, + { + "item_id": 13, + "price": 52, + "base_price": 52, + "qty": 1, + "row_total": 52, + "base_row_total": 52, + "row_total_with_discount": 0, + "tax_amount": 0, + "base_tax_amount": 0, + "tax_percent": 0, + "discount_amount": 0, + "base_discount_amount": 0, + "discount_percent": 0, + "price_incl_tax": 52, + "base_price_incl_tax": 52, + "row_total_incl_tax": 52, + "base_row_total_incl_tax": 52, + "options": "[{\"value\":\"Gray\",\"label\":\"Color\"},{\"value\":\"S\",\"label\":\"Size\"}]", + "weee_tax_applied_amount": null, + "weee_tax_applied": null, + "name": "Chaz Kangeroo Hoodie" + } + ], + "total_segments": [ + { + "code": "subtotal", + "title": "Subtotal", + "value": 160 + }, + { + "code": "shipping", + "title": "Shipping & Handling (Best Way - Table Rate)", + "value": 5 + }, + { + "code": "tax", + "title": "Tax", + "value": 0, + "extension_attributes": { + "tax_grandtotal_details": [] + } + }, + { + "code": "grand_total", + "title": "Grand Total", + "value": 165, + "area": "footer" + } + ] + } +} +``` + +{% endcollapsible %} + +{:.bs-callout-info} +If you tried this call on your own, and the value of the `shipping_amount` parameter is `0`, then you did not deactivate the "Spend $50 or more - shipping is free!" cart price rule. See [Deactivate a cart price rule](order-config-store.html#price-rule) for details. + +### Verify this step {#verify-step} + +[Sign in](https://glossary.magento.com/sign-in-sign-out) as the customer and go to the checkout page. + +The payment method is Bank Transfer, the billing and shipping addresses are displayed, and the shipping charges have been calculated. From dc90825aa538a45fb85146b2d65714b90974905f Mon Sep 17 00:00:00 2001 From: jhadobe Date: Tue, 28 Jun 2022 12:37:19 -0400 Subject: [PATCH 221/776] adding migrated_to --- src/guides/v2.4/rest/anonymous-api-security.md | 1 + src/guides/v2.4/rest/asynchronous-web-endpoints.md | 1 + src/guides/v2.4/rest/bulk-endpoints.md | 1 + src/guides/v2.4/rest/modules/catalog-pricing.md | 2 +- src/guides/v2.4/rest/modules/catalog.md | 2 +- src/guides/v2.4/rest/modules/inventory/bulk-inventory.md | 1 + src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md | 2 +- src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md | 2 +- src/guides/v2.4/rest/modules/inventory/manage-source-items.md | 2 +- .../v2.4/rest/modules/inventory/manage-source-selection.md | 2 +- src/guides/v2.4/rest/modules/inventory/manage-sources.md | 2 +- src/guides/v2.4/rest/modules/inventory/manage-stocks.md | 2 +- src/guides/v2.4/rest/modules/sales/refunds.md | 1 + src/guides/v2.4/rest/notes.md | 2 +- src/guides/v2.4/rest/operation-status-endpoints.md | 2 +- src/guides/v2.4/rest/operation-status-search.md | 2 +- src/guides/v2.4/rest/performing-searches.md | 2 +- src/guides/v2.4/rest/retrieve-filtered-responses.md | 2 +- src/guides/v2.4/rest/search-endpoint.md | 2 +- .../tutorials/bulk-configurable-product/config-product-intro.md | 1 + .../create-configurable-simple-products.md | 1 + .../bulk-configurable-product/create-personalization-option.md | 1 + .../bulk-configurable-product/define-config-product-options.md | 1 + .../rest/tutorials/bulk-configurable-product/plan-product.md | 1 + .../v2.4/rest/tutorials/bundle-product/bundle-product-intro.md | 1 + .../v2.4/rest/tutorials/bundle-product/create-bundle-product.md | 1 + .../rest/tutorials/bundle-product/create-simple-products.md | 1 + src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md | 1 + .../rest/tutorials/configurable-product/config-product-intro.md | 1 + .../configurable-product/create-configurable-product.md | 1 + .../configurable-product/create-personalization-option.md | 1 + .../tutorials/configurable-product/create-simple-products.md | 1 + .../configurable-product/define-config-product-options.md | 1 + .../v2.4/rest/tutorials/configurable-product/plan-product.md | 1 + .../grouped-product/create-and-manage-grouped-products.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-add-items.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-create-customer.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-create-order.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-create-quote.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md | 1 + 42 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/guides/v2.4/rest/anonymous-api-security.md b/src/guides/v2.4/rest/anonymous-api-security.md index 970ce3a2541..03d624d8a0f 100644 --- a/src/guides/v2.4/rest/anonymous-api-security.md +++ b/src/guides/v2.4/rest/anonymous-api-security.md @@ -1,6 +1,7 @@ --- group: rest-api title: Restricting access to anonymous web APIs +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/anonymous-api-security/ --- diff --git a/src/guides/v2.4/rest/asynchronous-web-endpoints.md b/src/guides/v2.4/rest/asynchronous-web-endpoints.md index 53e58957b8d..655d839dd83 100644 --- a/src/guides/v2.4/rest/asynchronous-web-endpoints.md +++ b/src/guides/v2.4/rest/asynchronous-web-endpoints.md @@ -6,6 +6,7 @@ contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ functional_areas: - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/asynchronous-web-endpoints/ --- An asynchronous web endpoint intercepts messages to a Web API and writes them to the message queue. Each time the system accepts such an API request, it generates a UUID identifier. Magento includes this UUID when it adds the message to the queue. Then, a consumer reads the messages from the queue and executes them one-by-one. diff --git a/src/guides/v2.4/rest/bulk-endpoints.md b/src/guides/v2.4/rest/bulk-endpoints.md index a3cb54768f9..b2bb0d77767 100644 --- a/src/guides/v2.4/rest/bulk-endpoints.md +++ b/src/guides/v2.4/rest/bulk-endpoints.md @@ -6,6 +6,7 @@ contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ functional_areas: - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/bulk-endpoints/ --- Bulk API endpoints differ from other REST endpoints in that they combine multiple calls of the same type into an array and execute them as a single request. The endpoint handler splits the array into individual entities and writes them as separate messages to the message queue. diff --git a/src/guides/v2.4/rest/modules/catalog-pricing.md b/src/guides/v2.4/rest/modules/catalog-pricing.md index 876f2047b99..7ce09edb346 100644 --- a/src/guides/v2.4/rest/modules/catalog-pricing.md +++ b/src/guides/v2.4/rest/modules/catalog-pricing.md @@ -1,7 +1,7 @@ --- group: rest-api title: Manage prices for multiple products - +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/catalog/catalog-pricing/ functional_areas: - Integration --- diff --git a/src/guides/v2.4/rest/modules/catalog.md b/src/guides/v2.4/rest/modules/catalog.md index 0835da832c7..de3721410ce 100644 --- a/src/guides/v2.4/rest/modules/catalog.md +++ b/src/guides/v2.4/rest/modules/catalog.md @@ -1,7 +1,7 @@ --- group: rest-api title: Catalog module - +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/catalog/ functional_areas: - Integration - Catalog diff --git a/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md b/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md index c6e38818c18..283dbe29d0c 100644 --- a/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md +++ b/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md @@ -1,6 +1,7 @@ --- group: rest-api title: Inventory mass actions +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/bulk-inventory/ --- diff --git a/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md b/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md index 996c25f6e12..ac539cf0f3b 100644 --- a/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md +++ b/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md @@ -1,7 +1,7 @@ --- group: rest-api title: Link and unlink stocks and sources - +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/link-stocks-sources/ --- diff --git a/src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md b/src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md index 582c561fea2..23ce6140c78 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md @@ -1,7 +1,7 @@ --- group: rest-api title: Manage low-quantity notifications - +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-low-quantity/ --- Low stock notification alert the merchant that the salable quantity of a stock has reached a critical threshold. The Admin allows the merchant to configure low-quantity notifications from several locations: diff --git a/src/guides/v2.4/rest/modules/inventory/manage-source-items.md b/src/guides/v2.4/rest/modules/inventory/manage-source-items.md index a6c8becfc87..cfa491d3b41 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-source-items.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-source-items.md @@ -1,7 +1,7 @@ --- group: rest-api title: Manage source items -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-source-items/ --- If Magento is configured to manage inventory, Magento assigns all existing products to the default source. Currently, Magento also assigns newly-created products to the default source. Single Source merchants do not need to manage source items, but Multi Source merchants may need to move products from the default source to a custom source, or move products from one custom source to another. diff --git a/src/guides/v2.4/rest/modules/inventory/manage-source-selection.md b/src/guides/v2.4/rest/modules/inventory/manage-source-selection.md index 001e6e00819..cf44eebe39c 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-source-selection.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-source-selection.md @@ -1,7 +1,7 @@ --- group: rest-api title: Manage source selection algorithms - +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-source-selection/ --- Inventory Management uses the Source Selection Algorithm (SSA) to track the salable quantities of product inventory across all sources and make recommendations for partial and full shipments. diff --git a/src/guides/v2.4/rest/modules/inventory/manage-sources.md b/src/guides/v2.4/rest/modules/inventory/manage-sources.md index 0a999d83558..4f5ceecf37d 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-sources.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-sources.md @@ -1,7 +1,7 @@ --- group: rest-api title: Manage sources -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-sources/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/ --- Sources represent locations storing and shipping available product stock. Any location with available stock and capable of order fulfillment can be added as a source. These locations can include warehouses, brick-and-mortar stores, distribution centers, and drop shippers. diff --git a/src/guides/v2.4/rest/modules/inventory/manage-stocks.md b/src/guides/v2.4/rest/modules/inventory/manage-stocks.md index fc5ded47f9f..52cc1185a5a 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-stocks.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-stocks.md @@ -1,7 +1,7 @@ --- group: rest-api title: Manage stocks - +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-stocks/ --- Stocks map your sources to sales channels, providing a direct link to salable quantities and inventories. diff --git a/src/guides/v2.4/rest/modules/sales/refunds.md b/src/guides/v2.4/rest/modules/sales/refunds.md index 44ee0d81952..9a21653531e 100644 --- a/src/guides/v2.4/rest/modules/sales/refunds.md +++ b/src/guides/v2.4/rest/modules/sales/refunds.md @@ -1,6 +1,7 @@ --- group: rest-api title: Refunds +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/sales/ functional_areas: - Integration diff --git a/src/guides/v2.4/rest/notes.md b/src/guides/v2.4/rest/notes.md index c83785dc329..85eced4ffc4 100644 --- a/src/guides/v2.4/rest/notes.md +++ b/src/guides/v2.4/rest/notes.md @@ -1,7 +1,7 @@ --- group: rest-api title: REST usage notes - +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/notes/ functional_areas: - Integration --- diff --git a/src/guides/v2.4/rest/operation-status-endpoints.md b/src/guides/v2.4/rest/operation-status-endpoints.md index 837e0797016..17263939f4d 100644 --- a/src/guides/v2.4/rest/operation-status-endpoints.md +++ b/src/guides/v2.4/rest/operation-status-endpoints.md @@ -1,7 +1,7 @@ --- group: rest-api title: Bulk operation status endpoints - +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/operation-status-endpoints/ contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com/ functional_areas: diff --git a/src/guides/v2.4/rest/operation-status-search.md b/src/guides/v2.4/rest/operation-status-search.md index c7c02a32fd9..d3472157bfd 100644 --- a/src/guides/v2.4/rest/operation-status-search.md +++ b/src/guides/v2.4/rest/operation-status-search.md @@ -1,7 +1,7 @@ --- group: rest-api title: Search for the status of a bulk operation - +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/operation-status-search contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com functional_areas: diff --git a/src/guides/v2.4/rest/performing-searches.md b/src/guides/v2.4/rest/performing-searches.md index b8ef346f6dc..28b3eda9894 100644 --- a/src/guides/v2.4/rest/performing-searches.md +++ b/src/guides/v2.4/rest/performing-searches.md @@ -1,7 +1,7 @@ --- group: rest-api title: Search using REST endpoints - +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/performing-searches/ --- POST, PUT, and DELETE requests to the REST Web [API](https://glossary.magento.com/api) require the service method parameters to be in the body of the request. For example, to create a Customer, you would specify a JSON array (or [XML](https://glossary.magento.com/xml) structure) in the body of the message. diff --git a/src/guides/v2.4/rest/retrieve-filtered-responses.md b/src/guides/v2.4/rest/retrieve-filtered-responses.md index fe142e676a7..8614cfb6ff3 100644 --- a/src/guides/v2.4/rest/retrieve-filtered-responses.md +++ b/src/guides/v2.4/rest/retrieve-filtered-responses.md @@ -1,7 +1,7 @@ --- group: rest-api title: Retrieve filtered responses for REST endpoints - +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/retrieve-filtered-responses/ --- Some REST calls return dozens or even hundreds of parameters, and parsing through all this data can be unwieldy. In addition, mobile app developers might find the bandwidth needed to process a request to be excessive. To resolve these problems, Magento provides a query parameter-based syntax for REST requests that return partial responses. diff --git a/src/guides/v2.4/rest/search-endpoint.md b/src/guides/v2.4/rest/search-endpoint.md index 4e754ec95cc..7f67d1e2008 100644 --- a/src/guides/v2.4/rest/search-endpoint.md +++ b/src/guides/v2.4/rest/search-endpoint.md @@ -1,7 +1,7 @@ --- group: rest-api title: Search for products with the /search endpoint - +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/search-endpoint/ contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com/ --- diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md index fb98e68dbdc..8d1b3f75f79 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md @@ -13,6 +13,7 @@ functional_areas: - Integration contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bulk-configurable-product/ --- A system integrator can use Magento REST bulk APIs to perform actions on a large scale; such as, creating multiple customers and products, changing prices across an inventory, and assigning large groups of products to a specific warehouse, all within a single call. diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md index 094da2885a5..66468cfbc3a 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md @@ -14,6 +14,7 @@ functional_areas: - Integration contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bulk-configurable-product/create-configurable-simple-products/ --- By providing configurable and simple product information, you can use the bulk API to create all necessary products with a single call. diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md index 5863f5f53ac..636479ae8dd 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md @@ -14,6 +14,7 @@ functional_areas: - Integration contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bulk-configurable-product/create-personalization-option/ --- Let's add a text box to the product page that allows the customer to add his name (up to 15 characters) to the back of the shirt. diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md index 2a8b31a4f86..7172f52009d 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md @@ -14,6 +14,7 @@ functional_areas: - Integration contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bulk-configurable-product/define-config-product-options/ --- Now that we've created all the Champ Tee products, we need to assign `size` as the configurable attribute and link the simple products to the configurable product. diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md index 14ddbd0d58f..8f398381ec8 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md @@ -14,6 +14,7 @@ functional_areas: - Integration contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bulk-configurable-product/plan-product/ --- To create a configurable product programmatically, you'll need to know the following: diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md b/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md index 2645b7ccba3..17edd8a80ad 100644 --- a/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md +++ b/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Create a bundle product tutorial +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/ contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md b/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md index c7054060f71..c0631437c14 100644 --- a/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md +++ b/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 3. Create the bundle product +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/create-bundle-product/ contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md b/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md index 57585c31d7b..20d75cf7b4c 100644 --- a/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md +++ b/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 2. Create the simple products +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/create-simple-products/ contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md b/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md index acd185007c9..9848fd9cdf2 100644 --- a/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md +++ b/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 1. Plan the product +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/plan-product/ contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md b/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md index 5f7a510e070..7fca3d5c579 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Create a configurable product tutorial +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/ menu_title: Initial tasks menu_order: 0 diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md b/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md index 068b4521c21..a16a2b6c143 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 2. Create the configurable product +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/create-configurable-product/ subtitle: Create a configurable product tutorial menu_title: Step 2. Create the configurable product diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md b/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md index e8d2c6a29e0..89ac3821df4 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 5. Create the personalization option +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/create-personalization-option/ subtitle: Create a configurable product tutorial menu_title: Step 5. Create the personalization option diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md b/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md index 646d83bbe6f..585d9a3345c 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 3. Create the simple products +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/create-simple-products/ subtitle: Create a configurable product tutorial menu_title: Step 3. Create the simple products diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md b/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md index b35c2e2575f..7654a7c67d9 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 4. Define configurable product options +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/define-config-product-options/ subtitle: Create a configurable product tutorial menu_title: Step 4. Define configurable product options diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md b/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md index b978d0d21e3..55f3ad7ef8d 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 1. Plan the product +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/plan-product/ subtitle: Create a configurable product tutorial menu_title: Step 1. Plan the product diff --git a/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md b/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md index 4d47f31c975..39d3e8f0677 100644 --- a/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md +++ b/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md @@ -1,6 +1,7 @@ --- group: rest-api title: Create and manage grouped products tutorial +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/grouped-product/ functional_areas: - Integration diff --git a/src/guides/v2.4/rest/tutorials/orders/order-add-items.md b/src/guides/v2.4/rest/tutorials/orders/order-add-items.md index d23ac7267c7..0d77637a74e 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-add-items.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-add-items.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 5. Add items to the cart +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-add-items/ subtitle: Order processing tutorial return_to: diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md b/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md index 68d02a66f8a..c3435c7747f 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 3. Create a customer +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-customer/ subtitle: Order processing tutorial return_to: diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md b/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md index a686f5ebe83..641a8792ec4 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 8. Create an invoice +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-invoice/ subtitle: Order processing tutorial return_to: diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-order.md b/src/guides/v2.4/rest/tutorials/orders/order-create-order.md index 069aa167524..082776399c3 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-order.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-order.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 7. Create an order +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-order/ subtitle: Order processing tutorial return_to: diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md b/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md index fc397b4d38c..84da17fe564 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 4. Create a quote +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-quote/ subtitle: Order processing tutorial return_to: diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md b/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md index 66e28902fc4..ccd82048e51 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md @@ -2,6 +2,7 @@ layout: tutorial group: rest-api title: Step 9. Create a shipment +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-shipment/ subtitle: Order processing tutorial return_to: diff --git a/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md b/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md index a48253a582c..26d6990efd8 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api subgroup: title: Step 6. Prepare for checkout +migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-prepare-checkout/ subtitle: Order Processing tutorial return_to: From 7444d1ec757689201fe403362df10399cdcdf498 Mon Sep 17 00:00:00 2001 From: Donald Booth Date: Tue, 28 Jun 2022 14:02:05 -0400 Subject: [PATCH 222/776] Updated old links --- src/release/availability.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/release/availability.md b/src/release/availability.md index 6c69fdf2cde..ca51d72f15d 100644 --- a/src/release/availability.md +++ b/src/release/availability.md @@ -5,15 +5,15 @@ group: release The following table describes the status of Adobe Commerce software availability and where to get it, particularly for software that is available outside the conventional {{site.data.var.ee}} Composer package. -| Product | Availability | How to get it | -|-------------------------------------------------|----------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **{{site.data.var.ee}} 2.4.4** | Available now | [Composer]({{ site.baseurl }}{{ site.gdeurl }}/install-gde/composer.html) | -| **{{site.data.var.ece}} Tools (aka ECE-Tools)** | Available now | [Composer]({{ site.baseurl }}/cloud/project/ece-tools-update.html) | -| **Live Search** | Available now | [Commerce Marketplace](https://marketplace.magento.com/magento-live-search.html) \| [Developer Documentation]({{ site.baseurl }}/live-search/overview.html) \| [Release Notes](https://docs.magento.com/user-guide/live-search/release-notes.html) \| [User Guide](https://docs.magento.com/user-guide/live-search/overview.html) | -| **Payment Services** | Available now | [Commerce Marketplace](https://marketplace.magento.com/magento-payment-services.html) \| [Release Notes](https://experienceleague.adobe.com/docs/commerce-merchant-services/payment-services/release-notes.html) \| [User Guide](https://experienceleague.adobe.com/docs/commerce-merchant-services/payment-services/guide-overview.html) | -| **Product Recommendations** | Available now | [Commerce Marketplace](https://marketplace.magento.com/magento-product-recommendations.html) \| [Developer Documentation]({{ site.baseurl }}/recommendations/product-recs.html) \| [Release Notes]({{ site.baseurl }}/recommendations/release-notes.html) \| [User Guide](https://docs.magento.com/m2/ee/user_guide/marketing/product-recommendations.html) | -| **PWA Studio** | Available now | [Documentation](http://pwastudio.io) and [GitHub](https://github.com/magento-research/pwa-studio) | -| **Amazon Sales Channel 4.4.1** | Available now for {{site.data.var.ee}} versions 2.4.x and 2.3.x (US, Canada, Mexico, and UK) | [Commerce Marketplace](https://marketplace.magento.com/magento-module-amazon.html) \| [Release Notes]({{ site.baseurl }}/extensions/amazon-sales/release-notes) \| [User Guide]({{ site.user_guide_url }}/sales-channels/asc/amazon-sales-channel.html) | +| Product | Availability | How to get it | +|-|-|-| +| **{{site.data.var.ee}} 2.4.4** | Available now | [Composer]({{ site.baseurl }}{{ site.gdeurl }}/install-gde/composer.html) | +| **{{site.data.var.ece}} Tools (aka ECE-Tools)** | Available now | [Composer]({{ site.baseurl }}/cloud/project/ece-tools-update.html) | +| **Live Search** | Available now | [Commerce Marketplace](https://marketplace.magento.com/magento-live-search.html) \| [Developer Documentation]({{ site.baseurl }}/live-search/overview.html) \| [Release Notes](https://docs.magento.com/user-guide/live-search/release-notes.html) \| [User Guide](https://docs.magento.com/user-guide/live-search/overview.html) | +| **Payment Services** | Available now | [Commerce Marketplace](https://marketplace.magento.com/magento-payment-services.html) \| [Release Notes](https://experienceleague.adobe.com/docs/commerce-merchant-services/payment-services/release-notes.html) \| [User Guide](https://experienceleague.adobe.com/docs/commerce-merchant-services/payment-services/guide-overview.html) | +| **Product Recommendations** | Available now | [Commerce Marketplace](https://marketplace.magento.com/magento-product-recommendations.html) \| [Developer Documentation]({{ site.baseurl }}/recommendations/product-recs.html) \| [Release Notes](https://experienceleague.adobe.com/docs/commerce-merchant-services/product-recommendations/release-notes.html) \| [User Guide](https://docs.magento.com/m2/ee/user_guide/marketing/product-recommendations.html) | +| **PWA Studio** | Available now | [Documentation](https://developer.adobe.com/commerce/pwa-studio/) and [GitHub](https://github.com/magento/pwa-studio) | +| **Amazon Sales Channel 4.4.1** | Available now for {{site.data.var.ee}} versions 2.4.x and 2.3.x (US, Canada, Mexico, and UK) | [Commerce Marketplace](https://marketplace.magento.com/magento-module-amazon.html) \| [Release Notes](https://experienceleague.adobe.com/docs/commerce-channels/amazon/release-notes.htmls) \| [User Guide]({{ site.user_guide_url }}/sales-channels/asc/amazon-sales-channel.html) | ## Compatibility From fcac9d34eec349b2b223948462b3a25bcfe65d40 Mon Sep 17 00:00:00 2001 From: Bohdan Korablov Date: Tue, 28 Jun 2022 13:15:41 -0500 Subject: [PATCH 223/776] MCLOUD-8879: Update docker options in Cloud guide --- src/cloud/docker/docker-containers-service.md | 34 +++++++++++++++++++ src/cloud/docker/docker-containers.md | 32 +++++++++-------- 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/src/cloud/docker/docker-containers-service.md b/src/cloud/docker/docker-containers-service.md index 7cb3b4781dc..461fc184818 100755 --- a/src/cloud/docker/docker-containers-service.md +++ b/src/cloud/docker/docker-containers-service.md @@ -117,6 +117,39 @@ To permanently update the system setting for `vm.max_map_count`: sysctl vm.max_map_count ``` +## Opensearch container + +**Container name**: opensearch
    +**Docker base image**: [magento/magento-cloud-docker-opensearch](https://hub.docker.com/r/magento/magento-cloud-docker-opensearch)
    +**Ports exposed**: `9200`, `9300`
    + +The Opensearch container for {{site.data.var.mcd-prod}} is a standard Opensearch container with required plugins and configurations for {{site.data.var.ee}}. + +Use the `--os-env-var` option to customize the Opensearch container when you generate the Docker Compose configuration file. You can set Opensearch options and specify the environment variables to apply when the container starts, such as the heap size for JVM. + +```bash +php vendor/bin/ece-docker build:compose --os-env-var=OPENSEARCH_JAVA_OPTS="-Xms512m -Xmx512m" --os-env-var=bootstrap.memory_lock=true +``` + +See [Important Opensearch configuration] in the Opensearch documentation for details about available configuration options. + +{:.bs-callout-info} +If your Cloud project uses {{site.data.var.ee}} version 2.4.4 or earlier with MySQL or Elasticsearch search, add the `--no-os` option to skip the Opensearch container configuration when you generate the Docker Compose configuration file: `ece-docker build:compose --no-os`. + +### Opensearch plugins + +There is a list of Opensearch plugins: https://opensearch.org/docs/latest/opensearch/install/plugins/ + +The following example adds the `opensearch-asynchronous-search` plugin to the Docker environment. + +```yaml +services: + opensearch: + environment: + - 'OS_PLUGINS=opensearch-asynchronous-search' +``` + + ## FPM container **Container name**: fpm
    @@ -337,6 +370,7 @@ The latest Zookeeper version is installed by default from Docker Hub. You can ad [Docker override file]: https://docs.docker.com/compose/extends/ [FPM]: https://php-fpm.org [Important Elasticsearch configuration]: https://www.elastic.co/guide/en/elasticsearch/reference/6.5/important-settings.html +[Important Opensearch configuration]: https://opensearch.org/docs/latest/opensearch/install/important-settings/ [mailhog]: https://hub.docker.com/u/mailhog [MailHog service]: https://github.com/mailhog/MailHog [Manage the database]: {{site.baseurl}}/cloud/docker/docker-manage-database.html diff --git a/src/cloud/docker/docker-containers.md b/src/cloud/docker/docker-containers.md index 14c29e24135..87b08e1f9a4 100644 --- a/src/cloud/docker/docker-containers.md +++ b/src/cloud/docker/docker-containers.md @@ -41,21 +41,22 @@ The following table shows the options to customize service container configurati {: .docker-service-versions-table} -| Name | Service | Key & options | Available Versions | Notes | -|------------------------------------|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [db] | MariaDB or MySQL
    | `--db`, `--db-image` (MySQL)
    `--expose-db-port`
    `--db-increment`
    `--db-offset`
    `--with-entrypoint`
    `--with-mariadb-config` | 10.0, 10.1, 10.2, 10.3, 10.4
    5.6, 5.7, 8.0 | Use the increment and offset options to customize the [auto-increment settings][Using AUTO_INCREMENT] for replication.

    Use the `--with-entrypoint` and `--with-mariadb-config` options to automatically configure database directories in the Docker environment

    *Example build commands:*
    `ece-docker build:compose --db `
    `ece-docker build:compose --db --db-image` | -| [elasticsearch] | Elasticsearch | `--es`
    `--es-env-var`
    `--no-es` | 5.2, 6.5, 6.8, 7.5, 7.6, 7.7, 7.9 | Use the options to specify the Elasticsearch version, customize Elasticsearch configuration options, or to build a Docker environment without Elasticsearch. | -| [fpm][fpm-container] | PHP FPM | `--php`
    `--with-xdebug` | 7.2, 7.3, 7.4, 8.0 | Used for all incoming requests. Optionally, install a specific php version or add Xdebug to debug PHP code in the Docker environment. | -| [fpm_xdebug][fpm_xdebug-container] | Xdebug | `--set-docker-host` | latest | Optional container for PHP debugging
    On Linux systems, `--set-docker-host` sets the `.host.docker.internal` value in the container `/etc/hosts` file. | -| [mailhog][mailhog-container] | MailHog | `--no-mailhog`
    `--mailhog-http-port`
    `--mailhog-smtp-port` | latest | Email service to replace Sendmail service, which can cause issues in Docker environment | -| [node][node-container] | Node | `--node` | 6, 8, 10, 11 | Node container to run gulp or other NPM based commands in the Docker environment. Use the `--node` option to install a specific node version. | -| [rabbitmq][rabbitmq-container] | RabbitMQ | `--rmq` | 3.5, 3.7, 3.8 | Use the `--rmq` option to install a specific RabbitMQ version. | -| [redis][redis-container] | Redis | `--redis` | 3.2, 5.0, 6.0 | Standard redis container | -| [selenium][selenium-container] | Selenium | `--with-selenium`
    `--selenium-version`
    `--selenium-image` | Any | Enables application testing using the Magento Functional Testing Framework (MFTF) | -| [test][test-container] | PHP CLI | `--with-test` | Any | Optional container with a writable file system for running tests | -| [tls][tls-container] | SSL Endpoint | `--tls-port`
    `--no-tls` | nginx 1.19 | Terminates SSL, can be configured to pass to varnish or nginx. Use the `--tls-port` option to change the default port (443).
    Use the `--no-tls` option to disable tls. | -| [varnish][varnish-container] | Varnish | `--no-varnish` | 4, 6.2, 6.6 | Varnish is provisioned by default. Use the `--no-varnish` option to skip Varnish service installation. | -| [zookeeper][zookeeper-container] | Zookeeper | `--with-zookeeper`
    `--zookeeper-version`
    `--zookeeper-image` | latest (default)
    User-specified version | Optional container for Zookeeper lock provider for projects not hosted on {{ site.data.var.ee }} on Cloud infrastructure.
    Use the `--zookeeper-version` option to install a specified version of Zookeeper from the Docker Hub or install a specified image by name with the `--zookeeper-image` option. | +| Name | Service | Key & options | Available Versions | Notes | +|------------------------------------|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [db] | MariaDB or MySQL
    | `--db`, `--db-image` (MySQL)
    `--expose-db-port`
    `--db-increment`
    `--db-offset`
    `--with-entrypoint`
    `--with-mariadb-config` | 10.0, 10.1, 10.2, 10.3, 10.4
    5.6, 5.7, 8.0 | Use the increment and offset options to customize the [auto-increment settings][Using AUTO_INCREMENT] for replication.

    Use the `--with-entrypoint` and `--with-mariadb-config` options to automatically configure database directories in the Docker environment

    *Example build commands:*
    `ece-docker build:compose --db `
    `ece-docker build:compose --db --db-image` | +| [elasticsearch] | Elasticsearch | `--es`
    `--es-env-var`
    `--no-es` | 5.2, 6.5, 6.8, 7.5, 7.6, 7.7, 7.9, 7.10, 7.11 | Use the options to specify the Elasticsearch version, customize Elasticsearch configuration options, or to build a Docker environment without Elasticsearch. | +| [opensearch] | Opensearch | `--os`
    `--os-env-var`
    `--no-os` | 1.1, 1.2 | Use the options to specify the Openseach version, customize Opensearch configuration options, or to build a Docker environment without Opensearch. | +| [fpm][fpm-container] | PHP FPM | `--php`
    `--with-xdebug` | 7.2, 7.3, 7.4, 8.0 | Used for all incoming requests. Optionally, install a specific php version or add Xdebug to debug PHP code in the Docker environment. | +| [fpm_xdebug][fpm_xdebug-container] | Xdebug | `--set-docker-host` | latest | Optional container for PHP debugging
    On Linux systems, `--set-docker-host` sets the `.host.docker.internal` value in the container `/etc/hosts` file. | +| [mailhog][mailhog-container] | MailHog | `--no-mailhog`
    `--mailhog-http-port`
    `--mailhog-smtp-port` | latest | Email service to replace Sendmail service, which can cause issues in Docker environment | +| [node][node-container] | Node | `--node` | 6, 8, 10, 11 | Node container to run gulp or other NPM based commands in the Docker environment. Use the `--node` option to install a specific node version. | +| [rabbitmq][rabbitmq-container] | RabbitMQ | `--rmq` | 3.5, 3.7, 3.8 | Use the `--rmq` option to install a specific RabbitMQ version. | +| [redis][redis-container] | Redis | `--redis` | 3.2, 5.0, 6.0 | Standard redis container | +| [selenium][selenium-container] | Selenium | `--with-selenium`
    `--selenium-version`
    `--selenium-image` | Any | Enables application testing using the Magento Functional Testing Framework (MFTF) | +| [test][test-container] | PHP CLI | `--with-test` | Any | Optional container with a writable file system for running tests | +| [tls][tls-container] | SSL Endpoint | `--tls-port`
    `--no-tls` | nginx 1.19 | Terminates SSL, can be configured to pass to varnish or nginx. Use the `--tls-port` option to change the default port (443).
    Use the `--no-tls` option to disable tls. | +| [varnish][varnish-container] | Varnish | `--no-varnish` | 4, 6.2, 6.6 | Varnish is provisioned by default. Use the `--no-varnish` option to skip Varnish service installation. | +| [zookeeper][zookeeper-container] | Zookeeper | `--with-zookeeper`
    `--zookeeper-version`
    `--zookeeper-image` | latest (default)
    User-specified version | Optional container for Zookeeper lock provider for projects not hosted on {{ site.data.var.ee }} on Cloud infrastructure.
    Use the `--zookeeper-version` option to install a specified version of Zookeeper from the Docker Hub or install a specified image by name with the `--zookeeper-image` option. | Use the following command to view all available options for the `ece-docker build:compose` command: @@ -148,6 +149,7 @@ Now you can see all requests that are passing through the TLS container and chec [deploy]: {{site.baseurl}}/cloud/docker/docker-containers-cli.html#deploy-container [db]: {{site.baseurl}}/cloud/docker/docker-containers-service.html#database-container [elasticsearch]: {{site.baseurl}}/cloud/docker/docker-containers-service.html#elasticsearch-container +[opensearch]: {{site.baseurl}}/cloud/docker/docker-containers-service.html#opensearch-container [Docker CLI containers]: {{site.baseurl}}/cloud/docker/docker-containers-cli.html [Docker service containers]: {{site.baseurl}}/cloud/docker/docker-containers-service.html [Using AUTO_INCREMENT]: https://dev.mysql.com/doc/refman/8.0/en/example-auto-increment.html From 75fc5d4de8f6398b89930145b93a58200c28fdc7 Mon Sep 17 00:00:00 2001 From: Bohdan Korablov Date: Tue, 28 Jun 2022 13:19:43 -0500 Subject: [PATCH 224/776] MCLOUD-8879: Update docker options in Cloud guide --- src/cloud/docker/docker-containers-service.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cloud/docker/docker-containers-service.md b/src/cloud/docker/docker-containers-service.md index 461fc184818..6cf1aebfebf 100755 --- a/src/cloud/docker/docker-containers-service.md +++ b/src/cloud/docker/docker-containers-service.md @@ -149,7 +149,6 @@ services: - 'OS_PLUGINS=opensearch-asynchronous-search' ``` - ## FPM container **Container name**: fpm
    From b402d5940c9804a248b6248778b7e06448546327 Mon Sep 17 00:00:00 2001 From: Donald Booth Date: Tue, 28 Jun 2022 14:23:56 -0400 Subject: [PATCH 225/776] Typo --- src/release/availability.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/release/availability.md b/src/release/availability.md index ca51d72f15d..bc5219827d1 100644 --- a/src/release/availability.md +++ b/src/release/availability.md @@ -13,7 +13,7 @@ The following table describes the status of Adobe Commerce software availability | **Payment Services** | Available now | [Commerce Marketplace](https://marketplace.magento.com/magento-payment-services.html) \| [Release Notes](https://experienceleague.adobe.com/docs/commerce-merchant-services/payment-services/release-notes.html) \| [User Guide](https://experienceleague.adobe.com/docs/commerce-merchant-services/payment-services/guide-overview.html) | | **Product Recommendations** | Available now | [Commerce Marketplace](https://marketplace.magento.com/magento-product-recommendations.html) \| [Developer Documentation]({{ site.baseurl }}/recommendations/product-recs.html) \| [Release Notes](https://experienceleague.adobe.com/docs/commerce-merchant-services/product-recommendations/release-notes.html) \| [User Guide](https://docs.magento.com/m2/ee/user_guide/marketing/product-recommendations.html) | | **PWA Studio** | Available now | [Documentation](https://developer.adobe.com/commerce/pwa-studio/) and [GitHub](https://github.com/magento/pwa-studio) | -| **Amazon Sales Channel 4.4.1** | Available now for {{site.data.var.ee}} versions 2.4.x and 2.3.x (US, Canada, Mexico, and UK) | [Commerce Marketplace](https://marketplace.magento.com/magento-module-amazon.html) \| [Release Notes](https://experienceleague.adobe.com/docs/commerce-channels/amazon/release-notes.htmls) \| [User Guide]({{ site.user_guide_url }}/sales-channels/asc/amazon-sales-channel.html) | +| **Amazon Sales Channel 4.4.1** | Available now for {{site.data.var.ee}} versions 2.4.x and 2.3.x (US, Canada, Mexico, and UK) | [Commerce Marketplace](https://marketplace.magento.com/magento-module-amazon.html) \| [Release Notes](https://experienceleague.adobe.com/docs/commerce-channels/amazon/release-notes.html) \| [User Guide]({{ site.user_guide_url }}/sales-channels/asc/amazon-sales-channel.html) | ## Compatibility From e8f9f73dd6974e8423c38d85261daf3e503b8274 Mon Sep 17 00:00:00 2001 From: jhadobe Date: Tue, 28 Jun 2022 15:26:47 -0400 Subject: [PATCH 226/776] Fixing links for directory structure change --- src/guides/v2.3/b2b/company-object.md | 2 +- src/guides/v2.3/b2b/company-structures.md | 2 +- src/guides/v2.3/b2b/credit-manage.md | 4 ++-- src/guides/v2.3/b2b/shared-cat-manage.md | 2 +- src/guides/v2.4/b2b/roles.md | 2 +- .../extension-dev-guide/searching-with-repositories.md | 2 +- src/guides/v2.4/extension-dev-guide/security/dos.md | 2 +- .../authentication/gs-authentication-token.md | 4 ++-- src/guides/v2.4/get-started/gs-web-api-request.md | 2 +- src/guides/v2.4/rest/anonymous-api-security.md | 2 +- src/guides/v2.4/rest/asynchronous-web-endpoints.md | 4 ++-- src/guides/v2.4/rest/bulk-endpoints.md | 2 +- src/guides/v2.4/rest/generate-local.md | 4 ++-- .../v2.4/rest/modules/inventory/in-store-pickup.md | 2 +- .../v2.4/rest/modules/inventory/link-stocks-sources.md | 2 +- .../v2.4/rest/modules/inventory/manage-source-items.md | 2 +- .../v2.4/rest/modules/inventory/manage-sources.md | 2 +- .../v2.4/rest/modules/inventory/manage-stocks.md | 2 +- src/guides/v2.4/rest/notes.md | 4 ++-- src/guides/v2.4/rest/operation-status-endpoints.md | 10 +++++----- src/guides/v2.4/rest/operation-status-search.md | 6 +++--- src/guides/v2.4/rest/performing-searches.md | 2 +- src/guides/v2.4/rest/protected-endpoints.md | 2 +- src/guides/v2.4/rest/retrieve-filtered-responses.md | 6 +++--- src/guides/v2.4/rest/search-endpoint.md | 6 +++--- .../bulk-configurable-product/config-product-intro.md | 4 ++-- .../create-configurable-simple-products.md | 2 +- .../define-config-product-options.md | 2 +- src/guides/v2.4/rest/tutorials/index.md | 2 +- src/guides/v2.4/rest/tutorials/inventory/index.md | 2 +- src/guides/v2.4/rest/tutorials/orders/order-intro.md | 2 +- 31 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/guides/v2.3/b2b/company-object.md b/src/guides/v2.3/b2b/company-object.md index 174ed3f82a5..56cb583e0d7 100644 --- a/src/guides/v2.3/b2b/company-object.md +++ b/src/guides/v2.3/b2b/company-object.md @@ -242,7 +242,7 @@ None The following call returns all companies that are located in California (`region_id` = `12`) -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/b2b/company-structures.md b/src/guides/v2.3/b2b/company-structures.md index 81e76c5939b..2686be3c739 100644 --- a/src/guides/v2.3/b2b/company-structures.md +++ b/src/guides/v2.3/b2b/company-structures.md @@ -123,7 +123,7 @@ An empty array The following query returns information about all teams (`team_id` ≥ `0`) -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/b2b/credit-manage.md b/src/guides/v2.3/b2b/credit-manage.md index 28bd610477f..68451b178f7 100644 --- a/src/guides/v2.3/b2b/credit-manage.md +++ b/src/guides/v2.3/b2b/credit-manage.md @@ -144,7 +144,7 @@ Not applicable The following call returns information for all companies whose credit balance is 0. -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** @@ -326,7 +326,7 @@ This call updates the credit history to specify a purchase order number. The following call returns a list instances in which the credit limit was set to a value higher than $500. -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/b2b/shared-cat-manage.md b/src/guides/v2.3/b2b/shared-cat-manage.md index 0c4a2929b7b..81dd6f3226b 100644 --- a/src/guides/v2.3/b2b/shared-cat-manage.md +++ b/src/guides/v2.3/b2b/shared-cat-manage.md @@ -137,7 +137,7 @@ Not applicable The following search returns all the custom shared catalogs (`type = 0`) in the system. -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.4/b2b/roles.md b/src/guides/v2.4/b2b/roles.md index 2c20d8b979f..004de050682 100644 --- a/src/guides/v2.4/b2b/roles.md +++ b/src/guides/v2.4/b2b/roles.md @@ -650,7 +650,7 @@ None The following call returns all roles that have been created for a company (`company_id` = `2`). -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.4/extension-dev-guide/searching-with-repositories.md b/src/guides/v2.4/extension-dev-guide/searching-with-repositories.md index 68642a37033..ed44dfe1102 100644 --- a/src/guides/v2.4/extension-dev-guide/searching-with-repositories.md +++ b/src/guides/v2.4/extension-dev-guide/searching-with-repositories.md @@ -44,7 +44,7 @@ $filter This filter will find all urls with the suffix of "magento.com". {:.bs-callout-info} -A full list of condition types can be found in the [Rest API Reference](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html). +A full list of condition types can be found in the [Rest API Reference](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html). ### Filter Group diff --git a/src/guides/v2.4/extension-dev-guide/security/dos.md b/src/guides/v2.4/extension-dev-guide/security/dos.md index 84f9b3a7ce7..76d228f8467 100644 --- a/src/guides/v2.4/extension-dev-guide/security/dos.md +++ b/src/guides/v2.4/extension-dev-guide/security/dos.md @@ -57,7 +57,7 @@ shopping. [Google ReCaptcha]({{ site.user_guide_url }}/stores/security-google-recaptcha.html) is an example of a challenge provider. One of the biggest advantages of ReCaptcha is that it avoids actually presenting -a user with a challenge, unless it detects suspicious behavior. [Protected endpoints](https://developer.adobe.com/commerce/webapi/rest/protected-endpoints.html) +a user with a challenge, unless it detects suspicious behavior. [Protected endpoints](https://developer.adobe.com/commerce/webapi/rest/use-rest/protected-endpoints.html) contains a list of forms/endpoints can be enabled for ReCaptcha out-of-the-box. You can extend the list by following the example on how to add coverage can be found in the [SecurityPackage](https://github.com/magento/security-package/tree/develop/ReCaptchaCustomer) repo. diff --git a/src/guides/v2.4/get-started/authentication/gs-authentication-token.md b/src/guides/v2.4/get-started/authentication/gs-authentication-token.md index 9a1cbb66948..8ad05280c08 100644 --- a/src/guides/v2.4/get-started/authentication/gs-authentication-token.md +++ b/src/guides/v2.4/get-started/authentication/gs-authentication-token.md @@ -159,7 +159,7 @@ echo send($request); Magento provides a separate token service for administrators and customers. When you request a token from one of these services, the service returns a unique access token in exchange for the username and password for a Magento account. -The Magento web API framework allows *guest users* to access resources that are configured with the permission level of anonymous. Guest users are users who the framework cannot authenticate through existing authentication mechanisms. As a guest user, you do not need to, but you can, specify a token in a web API call for a resource with anonymous permission. [Restricting access to anonymous web APIs](https://developer.adobe.com/commerce/webapi/rest/anonymous-api-security.html) contains a list of APIs that do not require a token. +The Magento web API framework allows *guest users* to access resources that are configured with the permission level of anonymous. Guest users are users who the framework cannot authenticate through existing authentication mechanisms. As a guest user, you do not need to, but you can, specify a token in a web API call for a resource with anonymous permission. [Restricting access to anonymous web APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/anonymous-api-security.html) contains a list of APIs that do not require a token. The following table lists endpoints and services that can be used to get an authentication token. Admin accounts must be authenticated with a [two factor authentication]({{page.baseurl}}/security/two-factor-authentication.html) provider. Some providers may require multiple calls. @@ -243,4 +243,4 @@ Related topics [Configure services as web APIs]({{ page.baseurl }}/extension-dev-guide/service-contracts/service-to-web-service.html) -[Restricting access to anonymous web APIs](https://developer.adobe.com/commerce/webapi/rest/anonymous-api-security.html) +[Restricting access to anonymous web APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/anonymous-api-security.html) diff --git a/src/guides/v2.4/get-started/gs-web-api-request.md b/src/guides/v2.4/get-started/gs-web-api-request.md index c01cf39c905..7fab6f3fb84 100644 --- a/src/guides/v2.4/get-started/gs-web-api-request.md +++ b/src/guides/v2.4/get-started/gs-web-api-request.md @@ -145,7 +145,7 @@ The following example builds a Customers Search request based on search criteria 1. Open the [Magento/Customer/etc/webapi.xml]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Customer/etc/webapi.xml) configuration file and find the [CustomerRepositoryInterface]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Customer/Api/CustomerRepositoryInterface.php) interface with the `getList` method. -1. Set the headers, URI and method to a request object. Use URI `/V1/customers/search` and method `GET` values. Use the `searchCriteria` parameter to complete the Customer Search query. See [searchCriteria usage](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html). +1. Set the headers, URI and method to a request object. Use URI `/V1/customers/search` and method `GET` values. Use the `searchCriteria` parameter to complete the Customer Search query. See [searchCriteria usage](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html). The following example finds customers whose first name contains "ver" or whose last name contains "Costello". diff --git a/src/guides/v2.4/rest/anonymous-api-security.md b/src/guides/v2.4/rest/anonymous-api-security.md index 03d624d8a0f..cd6ebea8632 100644 --- a/src/guides/v2.4/rest/anonymous-api-security.md +++ b/src/guides/v2.4/rest/anonymous-api-security.md @@ -1,7 +1,7 @@ --- group: rest-api title: Restricting access to anonymous web APIs -migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/anonymous-api-security/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/anonymous-api-security/ --- diff --git a/src/guides/v2.4/rest/asynchronous-web-endpoints.md b/src/guides/v2.4/rest/asynchronous-web-endpoints.md index 655d839dd83..a7003df75f5 100644 --- a/src/guides/v2.4/rest/asynchronous-web-endpoints.md +++ b/src/guides/v2.4/rest/asynchronous-web-endpoints.md @@ -6,7 +6,7 @@ contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ functional_areas: - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/asynchronous-web-endpoints/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/asynchronous-web-endpoints/ --- An asynchronous web endpoint intercepts messages to a Web API and writes them to the message queue. Each time the system accepts such an API request, it generates a UUID identifier. Magento includes this UUID when it adds the message to the queue. Then, a consumer reads the messages from the queue and executes them one-by-one. @@ -66,7 +66,7 @@ PUT /rest//async/V1/products/24-MB01 ## Response -Magento generates a `bulk_uuid` for each asynchronous request. Use the `bulk_uuid` to determine the [operation status](https://developer.adobe.com/commerce/webapi/rest/operation-status-endpoints.html) of your request. +Magento generates a `bulk_uuid` for each asynchronous request. Use the `bulk_uuid` to determine the [operation status](https://developer.adobe.com/commerce/webapi/rest/use-rest/operation-status-endpoints.html) of your request. ```json { diff --git a/src/guides/v2.4/rest/bulk-endpoints.md b/src/guides/v2.4/rest/bulk-endpoints.md index b2bb0d77767..2b37ab156c1 100644 --- a/src/guides/v2.4/rest/bulk-endpoints.md +++ b/src/guides/v2.4/rest/bulk-endpoints.md @@ -6,7 +6,7 @@ contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ functional_areas: - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/bulk-endpoints/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/bulk-endpoints/ --- Bulk API endpoints differ from other REST endpoints in that they combine multiple calls of the same type into an array and execute them as a single request. The endpoint handler splits the array into individual entities and writes them as separate messages to the message queue. diff --git a/src/guides/v2.4/rest/generate-local.md b/src/guides/v2.4/rest/generate-local.md index bad81892004..1a75b78d5d4 100644 --- a/src/guides/v2.4/rest/generate-local.md +++ b/src/guides/v2.4/rest/generate-local.md @@ -1,7 +1,7 @@ --- group: rest-api title: Generate a local REST reference -migrated_to: https://developer.adobe.com/commerce/webapi/quick_reference/rest/generate-local/ +migrated_to: https://developer.adobe.com/commerce/webapi/quick-reference/rest/generate-local/ functional_areas: - Integration --- @@ -85,5 +85,5 @@ You may also use web server rewrite rules to redirect users trying to access the {:.ref-header} Related topics -[Restricting access to anonymous web APIs](https://developer.adobe.com/commerce/webapi/rest/anonymous-api-security.html) +[Restricting access to anonymous web APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/anonymous-api-security.html) [Token-based authentication](https://developer.adobe.com/commerce/webapi/get-started/authentication/gs-authentication-token.html) diff --git a/src/guides/v2.4/rest/modules/inventory/in-store-pickup.md b/src/guides/v2.4/rest/modules/inventory/in-store-pickup.md index 172dec5d65d..8540c3bfe71 100644 --- a/src/guides/v2.4/rest/modules/inventory/in-store-pickup.md +++ b/src/guides/v2.4/rest/modules/inventory/in-store-pickup.md @@ -55,7 +55,7 @@ Name | Type | Description `[sort][0][field]=` | String | Specifies the field to sort on. `[sort][0][direction]=` | String | Specifies whether to return results in ascending (`ASC`) or descending (`DESC`) order. The default is `DESC`. -[Search using REST endpoints](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) provides a full list of supported condition types. +[Search using REST endpoints](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) provides a full list of supported condition types. **Sample Usage:** diff --git a/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md b/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md index ac539cf0f3b..60dd9ba5d00 100644 --- a/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md +++ b/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md @@ -98,7 +98,7 @@ Magento returns empty array. The following call returns the link information for `stock_id = 4`. -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.4/rest/modules/inventory/manage-source-items.md b/src/guides/v2.4/rest/modules/inventory/manage-source-items.md index cfa491d3b41..96368a1e9ba 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-source-items.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-source-items.md @@ -117,7 +117,7 @@ Magento returns an empty array. The following call returns all source items for `sku` = `new_product2`. -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.4/rest/modules/inventory/manage-sources.md b/src/guides/v2.4/rest/modules/inventory/manage-sources.md index 4f5ceecf37d..eefbd99f470 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-sources.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-sources.md @@ -175,7 +175,7 @@ None The following call returns all sources that are located in the United States (`country_id` = `US`) -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.4/rest/modules/inventory/manage-stocks.md b/src/guides/v2.4/rest/modules/inventory/manage-stocks.md index 52cc1185a5a..51aee9392f6 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-stocks.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-stocks.md @@ -150,7 +150,7 @@ Magento returns an empty array. The following call returns all stocks whose name contains the string `Stock`. -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.4/rest/notes.md b/src/guides/v2.4/rest/notes.md index 85eced4ffc4..3a8b18f65e9 100644 --- a/src/guides/v2.4/rest/notes.md +++ b/src/guides/v2.4/rest/notes.md @@ -1,7 +1,7 @@ --- group: rest-api title: REST usage notes -migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/notes/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/notes/ functional_areas: - Integration --- @@ -161,4 +161,4 @@ The following sample code creates a bundle product. The `price_type` attribute c {:.ref-header} Related topics -[Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) +[Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) diff --git a/src/guides/v2.4/rest/operation-status-endpoints.md b/src/guides/v2.4/rest/operation-status-endpoints.md index 17263939f4d..c8f0df813b2 100644 --- a/src/guides/v2.4/rest/operation-status-endpoints.md +++ b/src/guides/v2.4/rest/operation-status-endpoints.md @@ -1,14 +1,14 @@ --- group: rest-api title: Bulk operation status endpoints -migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/operation-status-endpoints/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/operation-status-endpoints/ contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com/ functional_areas: - Integration --- -Magento generates a `bulk_uuid` each time it executes an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html). You can track the status of an asynchronous operation with the following endpoints: +Magento generates a `bulk_uuid` each time it executes an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/use-rest/asynchronous-web-endpoints.html). You can track the status of an asynchronous operation with the following endpoints: * `GET /V1/bulk/:bulkUuid/status` * `GET /V1/bulk/:bulkUuid/operation-status/:status` @@ -26,7 +26,7 @@ Field name | Data type | Description `result_message` | String | Describes the result of the operation. If successful, the value contains the string `Service execution success` as well as the method that executed the operation. `error_code` | Integer | If applicable, an error code associated with the operation. `user_type` | Integer | Type of user who made this request. Possible values are:
    \* `1` = Integration
    \* `2` = Administrator
    \* `3` = Customer
    \* `4` = Guest User -`bulk_id` | String | UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html). +`bulk_id` | String | UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/use-rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/use-rest/bulk-endpoints.html). `description` | String | Contains the message queue topic. `start_time` | String | The time that a bulk or asynchronous operation started. `user_id` | Integer | The user ID that executed the request. @@ -83,7 +83,7 @@ Field name | Data type | Description --- | --- | --- `operations_list` | Object | An array containing information about each operation in a bulk or asynchronous request. `id` | Integer | Identifies the bulk or asynchronous request. -`bulk_uuid` | String | UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html). +`bulk_uuid` | String | UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/use-rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/use-rest/bulk-endpoints.html). `topic_name` | String | The name of the message queue topic, in the format `async..`. The service contract path is lowercase, and the method is either `post`, `put`, or `delete`. `serialized_data` | String | An array of serialized input data. It contains serialized JSON with the following keys: `entity_id` - `null`, `entity_link` - an empty string, `meta_info` - the body of the API request that was executed. `result_serialized_data` | String | Contains serialized output of the corresponding synchronous API call. For example, if you call `POST /async/V1/products`, this field contains serialized response from `POST /V1/products`. @@ -91,7 +91,7 @@ Field name | Data type | Description `result_message` | String | Describes the result of the operation. If successful, the value contains the string `Service execution success` as well as the method that executed the operation. `error_code` | Integer | If applicable, an error code associated with the operation. `user_type` | Integer | Type of user who made this request. Possible values are:
    \* `1` = Integration
    \* `2` = Administrator
    \* `3` = Customer
    \* `4` = Guest User -`bulk_id` | String | UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html). +`bulk_id` | String | UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/use-rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/use-rest/bulk-endpoints.html). `description` | String | Contains the message queue topic name. `start_time` | String | The time that a bulk or asynchronous operation started. `user_id` | Integer | The user ID that executed the request. diff --git a/src/guides/v2.4/rest/operation-status-search.md b/src/guides/v2.4/rest/operation-status-search.md index d3472157bfd..a027868e29b 100644 --- a/src/guides/v2.4/rest/operation-status-search.md +++ b/src/guides/v2.4/rest/operation-status-search.md @@ -1,7 +1,7 @@ --- group: rest-api title: Search for the status of a bulk operation -migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/operation-status-search +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/operation-status-search contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com functional_areas: @@ -19,7 +19,7 @@ You can specify any of the following fields to filter on operation statuses: * `3` = The operation failed. You must change something to retry it. * `4` = Open * `5` = Rejected -* `bulk_uuid` - UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html). +* `bulk_uuid` - UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/use-rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/use-rest/bulk-endpoints.html). * `topic_name` - Queue topic name **Sample usage:** @@ -33,7 +33,7 @@ searchCriteria[filter_groups][0][filters][0][value]=3& searchCriteria[filter_groups][0][filters][0][condition_type]=eq ``` -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for more information about the syntax of search requests. +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for more information about the syntax of search requests. **Response:** diff --git a/src/guides/v2.4/rest/performing-searches.md b/src/guides/v2.4/rest/performing-searches.md index 28b3eda9894..d6f0df7c9e5 100644 --- a/src/guides/v2.4/rest/performing-searches.md +++ b/src/guides/v2.4/rest/performing-searches.md @@ -1,7 +1,7 @@ --- group: rest-api title: Search using REST endpoints -migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/performing-searches/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches/ --- POST, PUT, and DELETE requests to the REST Web [API](https://glossary.magento.com/api) require the service method parameters to be in the body of the request. For example, to create a Customer, you would specify a JSON array (or [XML](https://glossary.magento.com/xml) structure) in the body of the message. diff --git a/src/guides/v2.4/rest/protected-endpoints.md b/src/guides/v2.4/rest/protected-endpoints.md index d5ea62e5437..45669e7624d 100644 --- a/src/guides/v2.4/rest/protected-endpoints.md +++ b/src/guides/v2.4/rest/protected-endpoints.md @@ -1,7 +1,7 @@ --- group: rest-api title: Protected endpoints -migrated_to: https://developer.adobe.com/commerce/webapi/rest/protected-endpoints/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/protected-endpoints/ functional_areas: - Integration --- diff --git a/src/guides/v2.4/rest/retrieve-filtered-responses.md b/src/guides/v2.4/rest/retrieve-filtered-responses.md index 8614cfb6ff3..d85d806e0ec 100644 --- a/src/guides/v2.4/rest/retrieve-filtered-responses.md +++ b/src/guides/v2.4/rest/retrieve-filtered-responses.md @@ -1,7 +1,7 @@ --- group: rest-api title: Retrieve filtered responses for REST endpoints -migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/retrieve-filtered-responses/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/retrieve-filtered-responses/ --- Some REST calls return dozens or even hundreds of parameters, and parsing through all this data can be unwieldy. In addition, mobile app developers might find the bandwidth needed to process a request to be excessive. To resolve these problems, Magento provides a query parameter-based syntax for REST requests that return partial responses. @@ -141,7 +141,7 @@ The following POST operation and payload creates a [catalog](https://glossary.ma ## Using with searchCriteria -The [`searchCriteria` query parameter](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) allows you to search across multiple objects in a collection. You can use the `fields` query parameter in conjunction with `searchCriteria` to limit the output. The question mark (?) that precedes `fields` in all the other examples in this document is replaced with an ampersand (&). +The [`searchCriteria` query parameter](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) allows you to search across multiple objects in a collection. You can use the `fields` query parameter in conjunction with `searchCriteria` to limit the output. The question mark (?) that precedes `fields` in all the other examples in this document is replaced with an ampersand (&). The following query returns only the `sku` and `name` parameters for product items whose `category_gear` attribute includes the value `86`. @@ -192,4 +192,4 @@ The following query returns only the `sku` and `name` parameters for product ite {:.ref-header} Related topics -* [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) +* [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) diff --git a/src/guides/v2.4/rest/search-endpoint.md b/src/guides/v2.4/rest/search-endpoint.md index 7f67d1e2008..067f66a6dfb 100644 --- a/src/guides/v2.4/rest/search-endpoint.md +++ b/src/guides/v2.4/rest/search-endpoint.md @@ -1,7 +1,7 @@ --- group: rest-api title: Search for products with the /search endpoint -migrated_to: https://developer.adobe.com/commerce/webapi/rest/use_rest/search-endpoint/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/search-endpoint/ contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com/ --- @@ -91,7 +91,7 @@ The default filters for advanced searches can use the following [field] value: The filter can also be any searchable attribute. To make an attribute searchable, set **Stores** > Attributes > **Product** > > **Storefront Properties** > **Use in Search** to **Yes**. The search query can include attributes such as the product name, SKU, or any other custom attribute. -Advanced searches can use any condition type to make comparisions, such as `like`, `eq`, or `finset`. See [Search using REST](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) describes condition types. +Advanced searches can use any condition type to make comparisions, such as `like`, `eq`, or `finset`. See [Search using REST](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) describes condition types. Advanced searches do not return aggregation data. @@ -140,4 +140,4 @@ searchCriteria[filter_groups][0][filters][0][condition_type]=eq ## Build queries for V1/products -[Search using REST](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) provides examples that can be used to search for products. +[Search using REST](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) provides examples that can be used to search for products. diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md index 8d1b3f75f79..a4074e9241a 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md @@ -34,5 +34,5 @@ A system integrator can use Magento REST bulk APIs to perform actions on a large ### Other resources * [REST Tutorials](https://developer.adobe.com/commerce/webapi/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. -* [Asynchronous web endpoints](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) provides information about how to use Magento Asynchronous API -* [Bulk endpoints](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html) provides information about how to use Magento Bulk API \ No newline at end of file +* [Asynchronous web endpoints](https://developer.adobe.com/commerce/webapi/rest/use-rest/asynchronous-web-endpoints.html) provides information about how to use Magento Asynchronous API +* [Bulk endpoints](https://developer.adobe.com/commerce/webapi/rest/use-rest/bulk-endpoints.html) provides information about how to use Magento Bulk API \ No newline at end of file diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md index 66468cfbc3a..7b09dbf44cb 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md @@ -309,7 +309,7 @@ The payload contains both the configurable product and the simple products. ``` {:.bs-callout-info} -For information about response fields, see the [Bulk API](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html) section. To check the status of operations, see the API for [Bulk operation status endpoints](https://developer.adobe.com/commerce/webapi/rest/operation-status-endpoints.html). +For information about response fields, see the [Bulk API](https://developer.adobe.com/commerce/webapi/rest/use-rest/bulk-endpoints.html) section. To check the status of operations, see the API for [Bulk operation status endpoints](https://developer.adobe.com/commerce/webapi/rest/use-rest/operation-status-endpoints.html). ## Verify this step diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md index 7172f52009d..4330c4f595d 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md @@ -74,7 +74,7 @@ Now that you have set the configurable attribute to be `sku`, you can link all s **Endpoint:** {:.bs-callout-info} -Bulk endpoint routes cannot contain input parameters, such as a `sku` value. You must replace input parameters with a string that begins with `by` and ends with the input parameter name, such as `bySku`. See [`bulk endpoints`](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html) for more information. +Bulk endpoint routes cannot contain input parameters, such as a `sku` value. You must replace input parameters with a string that begins with `by` and ends with the input parameter name, such as `bySku`. See [`bulk endpoints`](https://developer.adobe.com/commerce/webapi/rest/use-rest/bulk-endpoints.html) for more information. `POST /rest/default/async/bulk/V1/configurable-products/bySku/child` diff --git a/src/guides/v2.4/rest/tutorials/index.md b/src/guides/v2.4/rest/tutorials/index.md index 13ecabfc08b..51beaeef08f 100644 --- a/src/guides/v2.4/rest/tutorials/index.md +++ b/src/guides/v2.4/rest/tutorials/index.md @@ -32,7 +32,7 @@ Before you begin any tutorial, make sure you know the basics about {{site.data.v * Know how to construct a REST call in Magento. See [Construct a request](https://developer.adobe.com/commerce/webapi/get-started/gs-web-api-request.html) for details. -* Find the Magento REST API documentation. You can view the [static REST API documentation on devdocs]({{site.baseurl}}/redoc/{{page.guide_version}}/) or [generate a local API reference](https://developer.adobe.com/commerce/webapi/quick_reference/rest/generate-local.html). +* Find the Magento REST API documentation. You can view the [static REST API documentation on devdocs]({{site.baseurl}}/redoc/{{page.guide_version}}/) or [generate a local API reference](https://developer.adobe.com/commerce/webapi/quick-reference/rest/generate-local.html). * Find the Magento Merchant documentation. Refer to [Getting Started with {{site.data.var.ce}}]({{ site.user_guide_url }}/getting-started.html) for information about the Luma store that is created when you install Magento with the sample data. diff --git a/src/guides/v2.4/rest/tutorials/inventory/index.md b/src/guides/v2.4/rest/tutorials/inventory/index.md index 1d1a3fe1f8a..c4fec7cfa4e 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/index.md +++ b/src/guides/v2.4/rest/tutorials/inventory/index.md @@ -33,4 +33,4 @@ This **14-step tutorial** generally takes **1 hour**. ### Other resources -* Magento uses [Swagger](https://swagger.io) to provide REST API documentation on local instances of Magento. See [Generate a local API reference](https://developer.adobe.com/commerce/webapi/quick_reference/rest/generate-local.html) for more information. You can view the [static REST API documentation]({{site.baseurl}}/redoc/{{page.guide_version}}/), which displays reference information using ReDoc. +* Magento uses [Swagger](https://swagger.io) to provide REST API documentation on local instances of Magento. See [Generate a local API reference](https://developer.adobe.com/commerce/webapi/quick-reference/rest/generate-local.html) for more information. You can view the [static REST API documentation]({{site.baseurl}}/redoc/{{page.guide_version}}/), which displays reference information using ReDoc. diff --git a/src/guides/v2.4/rest/tutorials/orders/order-intro.md b/src/guides/v2.4/rest/tutorials/orders/order-intro.md index 5b6aa866019..54b08fafb2e 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-intro.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-intro.md @@ -33,7 +33,7 @@ Complete the following prerequisites: * Know how to construct a REST call in Magento. See [Construct a request](https://developer.adobe.com/commerce/webapi/get-started/gs-web-api-request.html) for details. -* Find the Magento REST API documentation. You can view the [static REST API documentation on devdocs]({{ site.baseurl }}/redoc/{{page.guide_version}}/) or [generate a local API reference](https://developer.adobe.com/commerce/webapi/quick_reference/rest/generate-local.html). +* Find the Magento REST API documentation. You can view the [static REST API documentation on devdocs]({{ site.baseurl }}/redoc/{{page.guide_version}}/) or [generate a local API reference](https://developer.adobe.com/commerce/webapi/quick-reference/rest/generate-local.html). * Find the Magento Merchant documentation. Refer to [Getting Started with {{site.data.var.ce}} 2.1]({{ site.user_guide_url }}/getting-started.html) for information about the Luma store that is created when you install Magento with the sample data. From f5a90524be489d57f1761317201d58150f8a22ad Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Thu, 26 May 2022 16:27:28 -0500 Subject: [PATCH 227/776] Update note-pro-using-yaml-support.md Fixes magento/devdocs#9445 --- src/_includes/cloud/note-pro-using-yaml-support.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/_includes/cloud/note-pro-using-yaml-support.md b/src/_includes/cloud/note-pro-using-yaml-support.md index 0c9d7b53cd6..e29d344349c 100644 --- a/src/_includes/cloud/note-pro-using-yaml-support.md +++ b/src/_includes/cloud/note-pro-using-yaml-support.md @@ -1,2 +1,3 @@ - {:.bs-callout-info} -For Pro projects, you must create a [Support ticket](http://support.magento.com) to install or update services in Staging and Production environments. Indicate the service changes needed and include your updated `.magento.app.yaml` and `services.yaml` files in the ticket. It can take up to 48 hours for the Cloud infrastructure team to update your project. \ No newline at end of file +{:.bs-callout-tip} +For Pro projects, you must create a [Support ticket](http://support.magento.com) to install or update services in Staging and Production environments. Indicate the service changes needed and include your updated `.magento.app.yaml` and `services.yaml` files in the ticket. It can take up to 48 hours for the Cloud infrastructure team to update your project. +PHP is **not** considered a service. Even though you can [upgrade PHP]({{ page.baseurl }}/cloud/project/magento-app-php-application.html) by updating the `.magento.app.yaml` file, it is important to mention your intent to upgrade PHP in the support ticket. This notifies the Cloud infrastructure team to upgrade PHP-specific extensions, such as the New Relic agent, to support the new version. \ No newline at end of file From 9fc4af9e178904d1843c0c43fbc9723e4e6a3046 Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Tue, 28 Jun 2022 17:16:56 -0500 Subject: [PATCH 228/776] mcloud-8901 update php extension --- src/cloud/project/magento-app-php-application.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cloud/project/magento-app-php-application.md b/src/cloud/project/magento-app-php-application.md index b89905eed97..ddccd6aa298 100644 --- a/src/cloud/project/magento-app-php-application.md +++ b/src/cloud/project/magento-app-php-application.md @@ -45,10 +45,19 @@ The following table shows the supported PHP extensions when deploying {{site.dat | Default extensions | Installed extensions
    that cannot be uninstalled | Extensions that can be installed
    and uninstalled as needed| |--------------------|---------------------|---------------------| -| `bcmath`
    `bz2`
    `calendar`
    `exif`
    `gd`
    `gettext`
    `intl`
    `mysqli`
    `pcntl`
    `pdo_mysql`
    `soap`
    `sockets`
    `sysvmsg`
    `sysvsem`
    `sysvshm`
    `opcache`
    `zip` |`ctype`
    `curl`
    `date`
    `dom`
    `fileinfo`
    `filter`
    `ftp`
    `hash`
    `iconv`
    `json`
    `mbstring`
    `mysqlnd`
    `openssl`
    `pcre`
    `pdo`
    `pdo_sqlite`
    `phar`
    `posix`
    `readline`
    `session`
    `sqlite3`
    `tokenizer`
    `xml`
    `xmlreader`
    `xmlwriter`
    |`geoip`
    `gmp`
    `igbinary`
    `imagick`
    `imap`
    `ioncube`
    `ldap`
    `mailparse`
    `mcrypt`
    `msgpack`
    `mysqli`
    `oauth`
    `pdo_mysql`
    `propro`
    `pspell`
    `raphf`
    `recode`
    `redis`
    `shmop` `sockets`
    `sodium`
    `ssh2`
    `tidy`
    `xdebug`
    `xmlrpc`
    `xsl`
    `yaml`| +| `bcmath`
    `bz2`
    `calendar`
    `exif`
    `gd`
    `gettext`
    `intl`
    `mysqli`
    `pcntl`
    `pdo_mysql`
    `soap`
    `sockets`
    `sysvmsg`
    `sysvsem`
    `sysvshm`
    `opcache`
    `zip` | `ctype`
    `curl`
    `date`
    `dom`
    `fileinfo`
    `filter`
    `ftp`
    `hash`
    `iconv`
    `json`
    `mbstring`
    `mysqlnd`
    `openssl`
    `pcre`
    `pdo`
    `pdo_sqlite`
    `phar`
    `posix`
    `readline`
    `session`
    `sqlite3`
    `tokenizer`
    `xml`
    `xmlreader`
    `xmlwriter`
    |`geoip`
    `gmp`
    `igbinary`
    `imagick`
    `imap`
    `ldap`
    `mailparse`
    `mcrypt`
    `msgpack`
    `mysqli`
    `oauth`
    `pdo_mysql`
    `propro`
    `pspell`
    `raphf`
    `recode`
    `redis`
    `shmop` `sockets`
    `sodium`
    `ssh2`
    `tidy`
    `xdebug`
    `xmlrpc`
    `xsl`
    `yaml` | PHP module requirements are tied to the {{site.data.var.ee}} version. See [PHP requirements]({{ site.baseurl }}{{ site.gdeurl }}/install-gde/prereq/php-settings.html). +### Extension support + +For Pro projects, the following extensions require additional support to install: + +- `ioncube` +- `sourceguardian` + +[Submit a support ticket](https://support.magento.com/hc/en-us/articles/360000913794#submit-ticket) to install these PHP extensions. + {:.bs-callout-warning} PHP compiled with debug is not supported and the Probe may conflict with XDebug or XHProf. Disable those extensions when enabling the Probe. The Probe conflicts with some PHP extensions like Pinba or IonCube. From 29762da6ae628afdd1cb17484a28899b9beca619 Mon Sep 17 00:00:00 2001 From: Donald Booth Date: Wed, 29 Jun 2022 11:15:02 -0400 Subject: [PATCH 229/776] Fixed nginx version number --- src/guides/v2.3/install-gde/prereq/nginx.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.3/install-gde/prereq/nginx.md b/src/guides/v2.3/install-gde/prereq/nginx.md index b22c1e5e22d..cf738b4e29f 100644 --- a/src/guides/v2.3/install-gde/prereq/nginx.md +++ b/src/guides/v2.3/install-gde/prereq/nginx.md @@ -6,7 +6,7 @@ functional_areas: - Setup --- -Magento supports nginx 1.8 (or the [latest mainline version](http://nginx.org/en/linux_packages.html#mainline)). You must also install the latest version of `php-fpm`. +Magento supports nginx 1.18 (or the [latest mainline version](http://nginx.org/en/linux_packages.html#mainline)). You must also install the latest version of `php-fpm`. Installation instructions vary based on which operating system you are using. See [PHP](php-settings.html) for information. From 89bc7c73d71bd752f96834b65626c2d17a4378d9 Mon Sep 17 00:00:00 2001 From: Bohdan Korablov Date: Wed, 29 Jun 2022 14:12:49 -0500 Subject: [PATCH 230/776] MCLOUD-8879: Update docker options in Cloud guide --- src/cloud/docker/docker-containers-service.md | 41 ++++++++++++++----- src/cloud/docker/docker-containers.md | 2 +- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/cloud/docker/docker-containers-service.md b/src/cloud/docker/docker-containers-service.md index 6cf1aebfebf..2b74871c638 100755 --- a/src/cloud/docker/docker-containers-service.md +++ b/src/cloud/docker/docker-containers-service.md @@ -117,28 +117,49 @@ To permanently update the system setting for `vm.max_map_count`: sysctl vm.max_map_count ``` -## Opensearch container +## OpenSearch container **Container name**: opensearch
    **Docker base image**: [magento/magento-cloud-docker-opensearch](https://hub.docker.com/r/magento/magento-cloud-docker-opensearch)
    **Ports exposed**: `9200`, `9300`
    -The Opensearch container for {{site.data.var.mcd-prod}} is a standard Opensearch container with required plugins and configurations for {{site.data.var.ee}}. +The OpenSearch container for {{site.data.var.mcd-prod}} is a standard OpenSearch container with required plugins and configurations for {{site.data.var.ee}}. -Use the `--os-env-var` option to customize the Opensearch container when you generate the Docker Compose configuration file. You can set Opensearch options and specify the environment variables to apply when the container starts, such as the heap size for JVM. +Use the `--os-env-var` option to customize the OpenSearch container when you generate the Docker Compose configuration file. You can set OpenSearch options and specify the environment variables to apply when the container starts, such as the heap size for JVM. ```bash php vendor/bin/ece-docker build:compose --os-env-var=OPENSEARCH_JAVA_OPTS="-Xms512m -Xmx512m" --os-env-var=bootstrap.memory_lock=true ``` -See [Important Opensearch configuration] in the Opensearch documentation for details about available configuration options. +See [Important OpenSearch configuration] in the OpenSearch documentation for details about available configuration options. {:.bs-callout-info} -If your Cloud project uses {{site.data.var.ee}} version 2.4.4 or earlier with MySQL or Elasticsearch search, add the `--no-os` option to skip the Opensearch container configuration when you generate the Docker Compose configuration file: `ece-docker build:compose --no-os`. - -### Opensearch plugins - -There is a list of Opensearch plugins: https://opensearch.org/docs/latest/opensearch/install/plugins/ +If your Cloud project uses {{site.data.var.ee}} version 2.4.4 or earlier with MySQL or Elasticsearch search, add the `--no-os` option to skip the OpenSearch container configuration when you generate the Docker Compose configuration file: `ece-docker build:compose --no-os` + +### OpenSearch plugins + +There is a list of OpenSearch plugins: https://opensearch.org/docs/latest/opensearch/install/plugins/ + +The following plugins are installed by default and can not be skipped: + +- OpenSearch 1.1: + - opensearch-notebooks +- OpenSearch 1.2: + - opensearch-observability +- OpenSearch 1.1 and 1.2: + - analysis-icu + - analysis-phonetic + - opensearch-alerting + - opensearch-anomaly-detection + - opensearch-asynchronous-search + - opensearch-cross-cluster-replication + - opensearch-index-management + - opensearch-job-scheduler + - opensearch-knn + - opensearch-performance-analyzer + - opensearch-reports-scheduler + - opensearch-security + - opensearch-sql The following example adds the `opensearch-asynchronous-search` plugin to the Docker environment. @@ -369,7 +390,7 @@ The latest Zookeeper version is installed by default from Docker Hub. You can ad [Docker override file]: https://docs.docker.com/compose/extends/ [FPM]: https://php-fpm.org [Important Elasticsearch configuration]: https://www.elastic.co/guide/en/elasticsearch/reference/6.5/important-settings.html -[Important Opensearch configuration]: https://opensearch.org/docs/latest/opensearch/install/important-settings/ +[Important OpenSearch configuration]: https://opensearch.org/docs/latest/opensearch/install/important-settings/ [mailhog]: https://hub.docker.com/u/mailhog [MailHog service]: https://github.com/mailhog/MailHog [Manage the database]: {{site.baseurl}}/cloud/docker/docker-manage-database.html diff --git a/src/cloud/docker/docker-containers.md b/src/cloud/docker/docker-containers.md index 87b08e1f9a4..0d11fbee9ad 100644 --- a/src/cloud/docker/docker-containers.md +++ b/src/cloud/docker/docker-containers.md @@ -45,7 +45,7 @@ The following table shows the options to customize service container configurati |------------------------------------|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | [db] | MariaDB or MySQL
    | `--db`, `--db-image` (MySQL)
    `--expose-db-port`
    `--db-increment`
    `--db-offset`
    `--with-entrypoint`
    `--with-mariadb-config` | 10.0, 10.1, 10.2, 10.3, 10.4
    5.6, 5.7, 8.0 | Use the increment and offset options to customize the [auto-increment settings][Using AUTO_INCREMENT] for replication.

    Use the `--with-entrypoint` and `--with-mariadb-config` options to automatically configure database directories in the Docker environment

    *Example build commands:*
    `ece-docker build:compose --db `
    `ece-docker build:compose --db --db-image` | | [elasticsearch] | Elasticsearch | `--es`
    `--es-env-var`
    `--no-es` | 5.2, 6.5, 6.8, 7.5, 7.6, 7.7, 7.9, 7.10, 7.11 | Use the options to specify the Elasticsearch version, customize Elasticsearch configuration options, or to build a Docker environment without Elasticsearch. | -| [opensearch] | Opensearch | `--os`
    `--os-env-var`
    `--no-os` | 1.1, 1.2 | Use the options to specify the Openseach version, customize Opensearch configuration options, or to build a Docker environment without Opensearch. | +| [opensearch] | OpenSearch | `--os`
    `--os-env-var`
    `--no-os` | 1.1, 1.2 | Use the options to specify the Openseach version, customize OpenSearch configuration options, or to build a Docker environment without OpenSearch. | | [fpm][fpm-container] | PHP FPM | `--php`
    `--with-xdebug` | 7.2, 7.3, 7.4, 8.0 | Used for all incoming requests. Optionally, install a specific php version or add Xdebug to debug PHP code in the Docker environment. | | [fpm_xdebug][fpm_xdebug-container] | Xdebug | `--set-docker-host` | latest | Optional container for PHP debugging
    On Linux systems, `--set-docker-host` sets the `.host.docker.internal` value in the container `/etc/hosts` file. | | [mailhog][mailhog-container] | MailHog | `--no-mailhog`
    `--mailhog-http-port`
    `--mailhog-smtp-port` | latest | Email service to replace Sendmail service, which can cause issues in Docker environment | From d87998870339b91d13231f048c6fe2a98a447364 Mon Sep 17 00:00:00 2001 From: hguthrie Date: Wed, 29 Jun 2022 14:27:20 -0500 Subject: [PATCH 231/776] fix bullet spacing --- src/cloud/docker/docker-containers-service.md | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/cloud/docker/docker-containers-service.md b/src/cloud/docker/docker-containers-service.md index 2b74871c638..6e2877d796d 100755 --- a/src/cloud/docker/docker-containers-service.md +++ b/src/cloud/docker/docker-containers-service.md @@ -140,26 +140,26 @@ If your Cloud project uses {{site.data.var.ee}} version 2.4.4 or earlier with My There is a list of OpenSearch plugins: https://opensearch.org/docs/latest/opensearch/install/plugins/ -The following plugins are installed by default and can not be skipped: - -- OpenSearch 1.1: - - opensearch-notebooks -- OpenSearch 1.2: - - opensearch-observability -- OpenSearch 1.1 and 1.2: - - analysis-icu - - analysis-phonetic - - opensearch-alerting - - opensearch-anomaly-detection - - opensearch-asynchronous-search - - opensearch-cross-cluster-replication - - opensearch-index-management - - opensearch-job-scheduler - - opensearch-knn - - opensearch-performance-analyzer - - opensearch-reports-scheduler - - opensearch-security - - opensearch-sql +The following plugins are installed by default and can **not** be skipped: + +- OpenSearch 1.1: + - opensearch-notebooks +- OpenSearch 1.2: + - opensearch-observability +- OpenSearch 1.1 and 1.2: + - analysis-icu + - analysis-phonetic + - opensearch-alerting + - opensearch-anomaly-detection + - opensearch-asynchronous-search + - opensearch-cross-cluster-replication + - opensearch-index-management + - opensearch-job-scheduler + - opensearch-knn + - opensearch-performance-analyzer + - opensearch-reports-scheduler + - opensearch-security + - opensearch-sql The following example adds the `opensearch-asynchronous-search` plugin to the Docker environment. @@ -408,4 +408,4 @@ The latest Zookeeper version is installed by default from Docker Hub. You can ad [varnish]: https://hub.docker.com/r/magento/magento-cloud-docker-varnish [varnish]: https://hub.docker.com/r/magento/magento-cloud-docker-varnish [web config]: https://github.com/magento/docker -[Configure the lock provider]: {{site.baseurl}}/guides/v2.4/install-gde/install/cli/install-cli-subcommands-lock.html#instgde-cli-lockconfig \ No newline at end of file +[Configure the lock provider]: {{site.baseurl}}/guides/v2.4/install-gde/install/cli/install-cli-subcommands-lock.html#instgde-cli-lockconfig From d1aa2a4b3919311c728758017cbddc3fa5f450c5 Mon Sep 17 00:00:00 2001 From: jhadobe Date: Wed, 29 Jun 2022 16:57:47 -0400 Subject: [PATCH 232/776] Breaking symlinks, updating links, removing blank metadata lines --- src/guides/v2.3/b2b/company-object.md | 2 +- src/guides/v2.3/b2b/company-structures.md | 2 +- src/guides/v2.3/b2b/company-users.md | 2 +- src/guides/v2.3/b2b/credit-manage.md | 4 +- src/guides/v2.3/b2b/shared-cat-manage.md | 2 +- src/guides/v2.3/b2b/shared-catalog.md | 2 +- .../v2.3/graphql/tutorials/checkout/index.md | 4 +- src/guides/v2.3/inventory/release-notes.md | 2 +- .../v2.3/rest/asynchronous-web-endpoints.md | 4 +- .../rest/modules/inventory/bulk-inventory.md | 2 +- .../modules/inventory/link-stocks-sources.md | 4 +- .../rest/modules/inventory/manage-stocks.md | 2 +- src/guides/v2.3/rest/notes.md | 2 +- .../v2.3/rest/operation-status-endpoints.md | 8 +- .../v2.3/rest/operation-status-search.md | 4 +- .../v2.3/rest/retrieve-filtered-responses.md | 4 +- src/guides/v2.3/rest/search-endpoint.md | 4 +- .../config-product-intro.md | 8 +- .../create-configurable-simple-products.md | 6 +- .../create-personalization-option.md | 6 +- .../define-config-product-options.md | 8 +- .../bundle-product/create-bundle-product.md | 6 +- .../bundle-product/create-simple-products.md | 4 +- .../config-product-intro.md | 4 +- .../create-configurable-product.md | 4 +- .../create-personalization-option.md | 6 +- .../create-simple-products.md | 4 +- .../define-config-product-options.md | 4 +- .../create-and-manage-grouped-products.md | 8 +- src/guides/v2.4/b2b/company-object.md | 345 ++++++++++++++- src/guides/v2.4/b2b/company-structures.md | 290 ++++++++++++- src/guides/v2.4/b2b/company-users.md | 176 +++++++- src/guides/v2.4/b2b/credit-manage.md | 400 +++++++++++++++++- src/guides/v2.4/b2b/shared-cat-manage.md | 189 ++++++++- src/guides/v2.4/b2b/shared-catalog.md | 30 +- .../v2.4/graphql/tutorials/checkout/index.md | 46 +- src/guides/v2.4/inventory/release-notes.md | 220 +++++++++- .../v2.4/rest/anonymous-api-security.md | 1 - .../v2.4/rest/asynchronous-web-endpoints.md | 1 - src/guides/v2.4/rest/bulk-endpoints.md | 1 - .../rest/modules/inventory/bulk-inventory.md | 1 - .../modules/inventory/link-stocks-sources.md | 1 - .../config-product-intro.md | 1 - .../create-configurable-simple-products.md | 1 - .../create-personalization-option.md | 1 - .../define-config-product-options.md | 1 - .../bulk-configurable-product/plan-product.md | 1 - .../bundle-product/bundle-product-intro.md | 1 - .../bundle-product/create-bundle-product.md | 1 - .../bundle-product/create-simple-products.md | 1 - .../tutorials/bundle-product/plan-product.md | 1 - .../config-product-intro.md | 1 - .../create-configurable-product.md | 1 - .../create-personalization-option.md | 1 - .../create-simple-products.md | 1 - .../define-config-product-options.md | 1 - .../configurable-product/plan-product.md | 1 - .../create-and-manage-grouped-products.md | 1 - .../rest/tutorials/orders/order-add-items.md | 1 - .../tutorials/orders/order-create-customer.md | 1 - .../tutorials/orders/order-create-invoice.md | 1 - .../tutorials/orders/order-create-order.md | 1 - .../tutorials/orders/order-create-quote.md | 1 - .../tutorials/orders/order-create-shipment.md | 1 - .../orders/order-prepare-checkout.md | 1 - 65 files changed, 1749 insertions(+), 97 deletions(-) mode change 120000 => 100644 src/guides/v2.4/b2b/company-object.md mode change 120000 => 100644 src/guides/v2.4/b2b/company-structures.md mode change 120000 => 100644 src/guides/v2.4/b2b/company-users.md mode change 120000 => 100644 src/guides/v2.4/b2b/credit-manage.md mode change 120000 => 100644 src/guides/v2.4/b2b/shared-cat-manage.md mode change 120000 => 100644 src/guides/v2.4/b2b/shared-catalog.md mode change 120000 => 100644 src/guides/v2.4/graphql/tutorials/checkout/index.md mode change 120000 => 100644 src/guides/v2.4/inventory/release-notes.md diff --git a/src/guides/v2.3/b2b/company-object.md b/src/guides/v2.3/b2b/company-object.md index 56cb583e0d7..42bfd38bd99 100644 --- a/src/guides/v2.3/b2b/company-object.md +++ b/src/guides/v2.3/b2b/company-object.md @@ -242,7 +242,7 @@ None The following call returns all companies that are located in California (`region_id` = `12`) -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs]({{ page.baseurl }}/rest/use-rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/b2b/company-structures.md b/src/guides/v2.3/b2b/company-structures.md index 2686be3c739..6d8b582d1c9 100644 --- a/src/guides/v2.3/b2b/company-structures.md +++ b/src/guides/v2.3/b2b/company-structures.md @@ -123,7 +123,7 @@ An empty array The following query returns information about all teams (`team_id` ≥ `0`) -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs]({{ page.baseurl }}/rest/use-rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/b2b/company-users.md b/src/guides/v2.3/b2b/company-users.md index 4bfd801ba06..7b4af08d349 100644 --- a/src/guides/v2.3/b2b/company-users.md +++ b/src/guides/v2.3/b2b/company-users.md @@ -10,7 +10,7 @@ functional_areas: A company user is a customer (buyer) that is assigned extended attributes that identify the company the user belongs to. Use the `POST /V1/customers` call, which is included with {{site.data.var.ce}} and {{site.data.var.ee}}, to create the user. After the user is created, you can use the `PUT /V1/customers/:customer_id` call to set their company data with the `company_attributes` extended attributes. {:.bs-callout-info} -This topic discusses only the features of the `customerCustomerRepositoryV1` service that are specific to B2B. See [Create a customer](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-customer.html) for an example of creating a standard customer. +This topic discusses only the features of the `customerCustomerRepositoryV1` service that are specific to B2B. See [Create a customer]({{ page.baseurl }}/rest/tutorials/orders/order-create-customer.html) for an example of creating a standard customer. ## Manage company users diff --git a/src/guides/v2.3/b2b/credit-manage.md b/src/guides/v2.3/b2b/credit-manage.md index 68451b178f7..4328e9e70db 100644 --- a/src/guides/v2.3/b2b/credit-manage.md +++ b/src/guides/v2.3/b2b/credit-manage.md @@ -144,7 +144,7 @@ Not applicable The following call returns information for all companies whose credit balance is 0. -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs]({{ page.baseurl }}/rest/use-rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** @@ -326,7 +326,7 @@ This call updates the credit history to specify a purchase order number. The following call returns a list instances in which the credit limit was set to a value higher than $500. -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs]({{ page.baseurl }}/rest/use-rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/b2b/shared-cat-manage.md b/src/guides/v2.3/b2b/shared-cat-manage.md index 81dd6f3226b..920f3fe012e 100644 --- a/src/guides/v2.3/b2b/shared-cat-manage.md +++ b/src/guides/v2.3/b2b/shared-cat-manage.md @@ -137,7 +137,7 @@ Not applicable The following search returns all the custom shared catalogs (`type = 0`) in the system. -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs]({{ page.baseurl }}/rest/use-rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/b2b/shared-catalog.md b/src/guides/v2.3/b2b/shared-catalog.md index ba46914c0ea..9a7027f91ba 100644 --- a/src/guides/v2.3/b2b/shared-catalog.md +++ b/src/guides/v2.3/b2b/shared-catalog.md @@ -26,4 +26,4 @@ Custom shared catalogs can be assigned to companies only. They cannot be set for * [Manage shared catalogs]({{ page.baseurl }}/b2b/shared-cat-manage.html) * [Assign categories and products]({{ page.baseurl }}/b2b/shared-cat-product-assign.html) * [Assign companies]({{ page.baseurl }}/b2b/shared-cat-company.html) -* [Manage prices for multiple products](https://developer.adobe.com/commerce/webapi/rest/modules/catalog/catalog-pricing) +* [Manage prices for multiple products]({{ page.baseurl }}/rest/modules/catalog/catalog-pricing) diff --git a/src/guides/v2.3/graphql/tutorials/checkout/index.md b/src/guides/v2.3/graphql/tutorials/checkout/index.md index a458935db14..8319d86d598 100644 --- a/src/guides/v2.3/graphql/tutorials/checkout/index.md +++ b/src/guides/v2.3/graphql/tutorials/checkout/index.md @@ -40,6 +40,6 @@ Complete the following prerequisites: ### Other resources -- [Order processing tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/) shows a system integrator how REST APIs are used in the lifecycle of an order, including configuring a store and creating a customer; creating quotes, orders, invoices, and shipments; preparing for checkout; and more order-related tasks. +- [Order processing tutorial]({{ page.baseurl }}/rest/tutorials/orders/) shows a system integrator how REST APIs are used in the lifecycle of an order, including configuring a store and creating a customer; creating quotes, orders, invoices, and shipments; preparing for checkout; and more order-related tasks. -- [REST Tutorials](https://developer.adobe.com/commerce/webapi/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. +- [REST Tutorials]({{ page.baseurl }}/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. diff --git a/src/guides/v2.3/inventory/release-notes.md b/src/guides/v2.3/inventory/release-notes.md index c41fe6a51f7..e08a1437df9 100644 --- a/src/guides/v2.3/inventory/release-notes.md +++ b/src/guides/v2.3/inventory/release-notes.md @@ -186,7 +186,7 @@ New modules for Inventory Management 1.1.2 Beta include: 'Magento_InventoryExportStockApi' => 0, ``` -- {:.new} **Added a Bulk Partial Stock Transfer Endpoint** - Current bulk transfer endpoints move all assigned quantity from an origin to a destination source. The new `/rest/V1/inventory/bulk-partial-source-transfer` endpoint allows merchants to transfer partial stock from source-to-source as a bulk operation. Enter a request to the endpoint with the `sku`, `qty`, `origin_source_code`, and `destination_source_code` to transfer a specific amount of quantity. Transfers verify the source is assigned to the `sku`, enough quantity exists to transfer, etc. See [Inventory Bulk Actions](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/bulk-inventory.html). +- {:.new} **Added a Bulk Partial Stock Transfer Endpoint** - Current bulk transfer endpoints move all assigned quantity from an origin to a destination source. The new `/rest/V1/inventory/bulk-partial-source-transfer` endpoint allows merchants to transfer partial stock from source-to-source as a bulk operation. Enter a request to the endpoint with the `sku`, `qty`, `origin_source_code`, and `destination_source_code` to transfer a specific amount of quantity. Transfers verify the source is assigned to the `sku`, enough quantity exists to transfer, etc. See [Inventory Bulk Actions]({{ page.baseurl }}/rest/modules/inventory/bulk-inventory.html). - {:.new} **Added Reservation CLI** - New commands give you options to detect and resolve reservation inconsistencies. As orders submit and change status, {{site.data.var.im}} generates initial reservations and updates through compensation reservations. These commands return a list of detected inconsistencies by Order ID, SKU, and Stock ID and create reservations to resolve. See [Inventory CLI reference]({{ page.baseurl }}/inventory/inventory-cli-reference.html). diff --git a/src/guides/v2.3/rest/asynchronous-web-endpoints.md b/src/guides/v2.3/rest/asynchronous-web-endpoints.md index 53e58957b8d..74c0ba85d3f 100644 --- a/src/guides/v2.3/rest/asynchronous-web-endpoints.md +++ b/src/guides/v2.3/rest/asynchronous-web-endpoints.md @@ -32,7 +32,7 @@ PUT /async/V1/products/:sku {{site.data.var.ce}} and {{site.data.var.ee}} installations support asynchronous web endpoints. -The [REST API documentation](https://developer.adobe.com/commerce/webapi/rest/) provides a list of all current synchronous Magento API routes. +The [REST API documentation]({{ page.baseurl }}/rest/) provides a list of all current synchronous Magento API routes. The response of an asynchronous request contains the following fields: @@ -65,7 +65,7 @@ PUT /rest//async/V1/products/24-MB01 ## Response -Magento generates a `bulk_uuid` for each asynchronous request. Use the `bulk_uuid` to determine the [operation status](https://developer.adobe.com/commerce/webapi/rest/operation-status-endpoints.html) of your request. +Magento generates a `bulk_uuid` for each asynchronous request. Use the `bulk_uuid` to determine the [operation status]({{ page.baseurl }}/rest/operation-status-endpoints.html) of your request. ```json { diff --git a/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md b/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md index c6e38818c18..ee4e46fa238 100644 --- a/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md +++ b/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md @@ -112,7 +112,7 @@ An empty array Use the `POST /V1/inventory/bulk-product-source-assign` endpoint to add one or more sources to your products. This endpoint helps when creating and assigning custom sources to your default or custom stocks and preparing new locations and inventory. -After adding new custom sources, you can add inventory quantities per product or for multiple products using the `POST V1/inventory/source-items` endpoint. [Assign products to a source](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-source-items) describes this endpoint. +After adding new custom sources, you can add inventory quantities per product or for multiple products using the `POST V1/inventory/source-items` endpoint. [Assign products to a source]({{ page.baseurl }}/rest/modules/inventory/manage-source-items) describes this endpoint. The sources are added to the products with an inventory quantity of 0. You can add inventory amounts as available per source. diff --git a/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md b/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md index 996c25f6e12..6bb9917189e 100644 --- a/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md +++ b/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md @@ -98,7 +98,7 @@ Magento returns empty array. The following call returns the link information for `stock_id = 4`. -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** @@ -147,7 +147,7 @@ None ## Get sources assigned to a stock -The `GET /V1/inventory/get-sources-assigned-to-stock-ordered-by-priority/:stock_id` endpoint returns details about each source that is assigned to the specified stock. [Manage sources](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/) provides definitions for each attribute returned. +The `GET /V1/inventory/get-sources-assigned-to-stock-ordered-by-priority/:stock_id` endpoint returns details about each source that is assigned to the specified stock. [Manage sources]({{ page.baseurl }}/rest/modules/inventory/) provides definitions for each attribute returned. **Sample Usage:** diff --git a/src/guides/v2.3/rest/modules/inventory/manage-stocks.md b/src/guides/v2.3/rest/modules/inventory/manage-stocks.md index fc5ded47f9f..41bb349378b 100644 --- a/src/guides/v2.3/rest/modules/inventory/manage-stocks.md +++ b/src/guides/v2.3/rest/modules/inventory/manage-stocks.md @@ -150,7 +150,7 @@ Magento returns an empty array. The following call returns all stocks whose name contains the string `Stock`. -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/rest/notes.md b/src/guides/v2.3/rest/notes.md index c83785dc329..c21e4a9581c 100644 --- a/src/guides/v2.3/rest/notes.md +++ b/src/guides/v2.3/rest/notes.md @@ -161,4 +161,4 @@ The following sample code creates a bundle product. The `price_type` attribute c {:.ref-header} Related topics -[Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) +[Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) diff --git a/src/guides/v2.3/rest/operation-status-endpoints.md b/src/guides/v2.3/rest/operation-status-endpoints.md index 837e0797016..5243f85688b 100644 --- a/src/guides/v2.3/rest/operation-status-endpoints.md +++ b/src/guides/v2.3/rest/operation-status-endpoints.md @@ -8,7 +8,7 @@ functional_areas: - Integration --- -Magento generates a `bulk_uuid` each time it executes an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html). You can track the status of an asynchronous operation with the following endpoints: +Magento generates a `bulk_uuid` each time it executes an [asynchronous API request]({{ page.baseurl }}/rest/asynchronous-web-endpoints.html). You can track the status of an asynchronous operation with the following endpoints: * `GET /V1/bulk/:bulkUuid/status` * `GET /V1/bulk/:bulkUuid/operation-status/:status` @@ -26,7 +26,7 @@ Field name | Data type | Description `result_message` | String | Describes the result of the operation. If successful, the value contains the string `Service execution success` as well as the method that executed the operation. `error_code` | Integer | If applicable, an error code associated with the operation. `user_type` | Integer | Type of user who made this request. Possible values are:
    \* `1` = Integration
    \* `2` = Administrator
    \* `3` = Customer
    \* `4` = Guest User -`bulk_id` | String | UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html). +`bulk_id` | String | UUID generated by an [asynchronous API request]({{ page.baseurl }}/rest/asynchronous-web-endpoints.html) or [Bulk API request]({{ page.baseurl }}/rest/bulk-endpoints.html). `description` | String | Contains the message queue topic. `start_time` | String | The time that a bulk or asynchronous operation started. `user_id` | Integer | The user ID that executed the request. @@ -83,7 +83,7 @@ Field name | Data type | Description --- | --- | --- `operations_list` | Object | An array containing information about each operation in a bulk or asynchronous request. `id` | Integer | Identifies the bulk or asynchronous request. -`bulk_uuid` | String | UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html). +`bulk_uuid` | String | UUID generated by an [asynchronous API request]({{ page.baseurl }}/rest/asynchronous-web-endpoints.html) or [Bulk API request]({{ page.baseurl }}/rest/bulk-endpoints.html). `topic_name` | String | The name of the message queue topic, in the format `async..`. The service contract path is lowercase, and the method is either `post`, `put`, or `delete`. `serialized_data` | String | An array of serialized input data. It contains serialized JSON with the following keys: `entity_id` - `null`, `entity_link` - an empty string, `meta_info` - the body of the API request that was executed. `result_serialized_data` | String | Contains serialized output of the corresponding synchronous API call. For example, if you call `POST /async/V1/products`, this field contains serialized response from `POST /V1/products`. @@ -91,7 +91,7 @@ Field name | Data type | Description `result_message` | String | Describes the result of the operation. If successful, the value contains the string `Service execution success` as well as the method that executed the operation. `error_code` | Integer | If applicable, an error code associated with the operation. `user_type` | Integer | Type of user who made this request. Possible values are:
    \* `1` = Integration
    \* `2` = Administrator
    \* `3` = Customer
    \* `4` = Guest User -`bulk_id` | String | UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html). +`bulk_id` | String | UUID generated by an [asynchronous API request]({{ page.baseurl }}/rest/asynchronous-web-endpoints.html) or [Bulk API request]({{ page.baseurl }}/rest/bulk-endpoints.html). `description` | String | Contains the message queue topic name. `start_time` | String | The time that a bulk or asynchronous operation started. `user_id` | Integer | The user ID that executed the request. diff --git a/src/guides/v2.3/rest/operation-status-search.md b/src/guides/v2.3/rest/operation-status-search.md index c7c02a32fd9..b93877d0954 100644 --- a/src/guides/v2.3/rest/operation-status-search.md +++ b/src/guides/v2.3/rest/operation-status-search.md @@ -19,7 +19,7 @@ You can specify any of the following fields to filter on operation statuses: * `3` = The operation failed. You must change something to retry it. * `4` = Open * `5` = Rejected -* `bulk_uuid` - UUID generated by an [asynchronous API request](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) or [Bulk API request](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html). +* `bulk_uuid` - UUID generated by an [asynchronous API request]({{ page.baseurl }}/rest/asynchronous-web-endpoints.html) or [Bulk API request]({{ page.baseurl }}/rest/bulk-endpoints.html). * `topic_name` - Queue topic name **Sample usage:** @@ -33,7 +33,7 @@ searchCriteria[filter_groups][0][filters][0][value]=3& searchCriteria[filter_groups][0][filters][0][condition_type]=eq ``` -See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) for more information about the syntax of search requests. +See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for more information about the syntax of search requests. **Response:** diff --git a/src/guides/v2.3/rest/retrieve-filtered-responses.md b/src/guides/v2.3/rest/retrieve-filtered-responses.md index fe142e676a7..20302f4732a 100644 --- a/src/guides/v2.3/rest/retrieve-filtered-responses.md +++ b/src/guides/v2.3/rest/retrieve-filtered-responses.md @@ -141,7 +141,7 @@ The following POST operation and payload creates a [catalog](https://glossary.ma ## Using with searchCriteria -The [`searchCriteria` query parameter](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) allows you to search across multiple objects in a collection. You can use the `fields` query parameter in conjunction with `searchCriteria` to limit the output. The question mark (?) that precedes `fields` in all the other examples in this document is replaced with an ampersand (&). +The [`searchCriteria` query parameter]({{ page.baseurl }}/rest/performing-searches.html) allows you to search across multiple objects in a collection. You can use the `fields` query parameter in conjunction with `searchCriteria` to limit the output. The question mark (?) that precedes `fields` in all the other examples in this document is replaced with an ampersand (&). The following query returns only the `sku` and `name` parameters for product items whose `category_gear` attribute includes the value `86`. @@ -192,4 +192,4 @@ The following query returns only the `sku` and `name` parameters for product ite {:.ref-header} Related topics -* [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) +* [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) diff --git a/src/guides/v2.3/rest/search-endpoint.md b/src/guides/v2.3/rest/search-endpoint.md index 4e754ec95cc..18f295dfbd4 100644 --- a/src/guides/v2.3/rest/search-endpoint.md +++ b/src/guides/v2.3/rest/search-endpoint.md @@ -91,7 +91,7 @@ The default filters for advanced searches can use the following [field] value: The filter can also be any searchable attribute. To make an attribute searchable, set **Stores** > Attributes > **Product** > > **Storefront Properties** > **Use in Search** to **Yes**. The search query can include attributes such as the product name, SKU, or any other custom attribute. -Advanced searches can use any condition type to make comparisions, such as `like`, `eq`, or `finset`. See [Search using REST](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) describes condition types. +Advanced searches can use any condition type to make comparisions, such as `like`, `eq`, or `finset`. See [Search using REST]({{ page.baseurl }}/rest/performing-searches.html) describes condition types. Advanced searches do not return aggregation data. @@ -140,4 +140,4 @@ searchCriteria[filter_groups][0][filters][0][condition_type]=eq ## Build queries for V1/products -[Search using REST](https://developer.adobe.com/commerce/webapi/rest/performing-searches.html) provides examples that can be used to search for products. +[Search using REST]({{ page.baseurl }}/rest/performing-searches.html) provides examples that can be used to search for products. diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md index fb98e68dbdc..98f9a85d8cd 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md @@ -27,11 +27,11 @@ A system integrator can use Magento REST bulk APIs to perform actions on a large * Install a Magento 2.3 (or later) instance with sample data. The sample data defines a functional store, called Luma, that sells fitness clothing and accessories. * Install a REST client. You can use any REST client to send calls to Magento. [Postman](https://www.getpostman.com/) is recommended. -* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/) for more information. +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token]({{ page.baseurl }}/rest/tutorials/prerequisite-tasks/) for more information. * Use the `bin/magento queue:consumers:start async.operations.all` command to enable bulk endpoint processing. ### Other resources -* [REST Tutorials](https://developer.adobe.com/commerce/webapi/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. -* [Asynchronous web endpoints](https://developer.adobe.com/commerce/webapi/rest/asynchronous-web-endpoints.html) provides information about how to use Magento Asynchronous API -* [Bulk endpoints](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html) provides information about how to use Magento Bulk API \ No newline at end of file +* [REST Tutorials]({{ page.baseurl }}/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. +* [Asynchronous web endpoints]({{ page.baseurl }}/rest/asynchronous-web-endpoints.html) provides information about how to use Magento Asynchronous API +* [Bulk endpoints]({{ page.baseurl }}/rest/bulk-endpoints.html) provides information about how to use Magento Bulk API \ No newline at end of file diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md index 094da2885a5..1d59edfbac3 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md @@ -39,7 +39,7 @@ Some notes about the configurable product payload example: Although it's not required, the simple product payload also includes `stock_item` information. By default, the Luma store hides out-of-stock items, so adding stock will make the Champ Tee visible on the website. {:.bs-callout-info} -Before you use this code sample, verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute searchCriteria](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. +Before you use this code sample, verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute searchCriteria]({{ page.baseurl }}/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. {:.bs-callout-info} The payload contains both the configurable product and the simple products. @@ -308,12 +308,12 @@ The payload contains both the configurable product and the simple products. ``` {:.bs-callout-info} -For information about response fields, see the [Bulk API](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html) section. To check the status of operations, see the API for [Bulk operation status endpoints](https://developer.adobe.com/commerce/webapi/rest/operation-status-endpoints.html). +For information about response fields, see the [Bulk API]({{ page.baseurl }}/rest/bulk-endpoints.html) section. To check the status of operations, see the API for [Bulk operation status endpoints]({{ page.baseurl }}/rest/operation-status-endpoints.html). ## Verify this step * Log in to the Luma website and select **Catalog > Products**. The product appears in the grid. - ![Product page with configurable product](https://developer.adobe.com/commerce/webapi/rest/images/products-page.png) + ![Product page with configurable product]({{ page.baseurl }}/rest/images/products-page.png) * On the Luma storefront page, search for `Champ`. No results are returned. diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md index 5863f5f53ac..62f2ea24e9b 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md @@ -62,11 +62,11 @@ The `product_sku` is the `sku` of the configurable product. The `sku` specified * Log in to the Luma website and select **Catalog > Products**. Click on the **Champ Tee** configurable product and expand the **Customizable Options** section. - ![Product page with configurable and simple products](https://developer.adobe.com/commerce/webapi/rest/images/options-section.png) + ![Product page with configurable and simple products]({{ page.baseurl }}/rest/images/options-section.png) * On the Luma storefront page, search for `Champ`. Then click on the Champ Tee product. - ![Search results](https://developer.adobe.com/commerce/webapi/rest/images/add-your-name.png) + ![Search results]({{ page.baseurl }}/rest/images/add-your-name.png) {:.bs-callout-info} If the personalization option is not displayed, go to the **Champ Tee** configuration product page in Admin and set **Stock Status** to **In Stock**. @@ -77,4 +77,4 @@ The `product_sku` is the `sku` of the configurable product. The `sku` specified {:.ref-header} Related topic -[Order Processing with REST APIs Tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/) +[Order Processing with REST APIs Tutorial]({{ page.baseurl }}/rest/tutorials/orders/) diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md index 2a8b31a4f86..d592653fce5 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md @@ -23,7 +23,7 @@ contributor_link: http://comwrap.com/ The `POST async/bulk/V1/configurable-products/bySku/options` call assigns the specified `attribute_id` to be the configurable attribute. {:.bs-callout-warning} - The `attribute_id` and its value may be different on your installation. Check the values carefully before using them in your calls. To get the correct `attribute_id`, see [Get the list of attributes defined in an attribute searchCriteria](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. + The `attribute_id` and its value may be different on your installation. Check the values carefully before using them in your calls. To get the correct `attribute_id`, see [Get the list of attributes defined in an attribute searchCriteria]({{ page.baseurl }}/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. The value assigned to the `value_index` must be unique within the system. @@ -73,7 +73,7 @@ Now that you have set the configurable attribute to be `sku`, you can link all s **Endpoint:** {:.bs-callout-info} -Bulk endpoint routes cannot contain input parameters, such as a `sku` value. You must replace input parameters with a string that begins with `by` and ends with the input parameter name, such as `bySku`. See [`bulk endpoints`](https://developer.adobe.com/commerce/webapi/rest/bulk-endpoints.html) for more information. +Bulk endpoint routes cannot contain input parameters, such as a `sku` value. You must replace input parameters with a string that begins with `by` and ends with the input parameter name, such as `bySku`. See [`bulk endpoints`]({{ page.baseurl }}/rest/bulk-endpoints.html) for more information. `POST /rest/default/async/bulk/V1/configurable-products/bySku/child` @@ -127,11 +127,11 @@ Bulk endpoint routes cannot contain input parameters, such as a `sku` value. Yo * Log in to the Luma website and select **Catalog > Products**. Click on the **Champ Tee** configurable product and expand the **Configurations** section. - ![Product page with configurable and simple products](https://developer.adobe.com/commerce/webapi/rest/images/configurations-section.png) + ![Product page with configurable and simple products]({{ page.baseurl }}/rest/images/configurations-section.png) * On the Luma storefront page, search for `Champ`. - ![Search results](https://developer.adobe.com/commerce/webapi/rest/images/search-results.png) + ![Search results]({{ page.baseurl }}/rest/images/search-results.png) * Call `GET /rest/default/V1/products/MS-Champ`. The response includes the `configurable_product_options` and `configurable_product_links` arrays. diff --git a/src/guides/v2.3/rest/tutorials/bundle-product/create-bundle-product.md b/src/guides/v2.3/rest/tutorials/bundle-product/create-bundle-product.md index c7054060f71..382f1abb670 100644 --- a/src/guides/v2.3/rest/tutorials/bundle-product/create-bundle-product.md +++ b/src/guides/v2.3/rest/tutorials/bundle-product/create-bundle-product.md @@ -297,15 +297,15 @@ POST http://domain.com/rest/default/V1/products 1. On the Luma storefront page, search for `Desktop Computer`. There should be one result. - ![Search](https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/images/search-desktop-computer.png) + ![Search]({{ page.baseurl }}/rest/tutorials/bundle-product/images/search-desktop-computer.png) 1. Click on the Desktop Computer product. - ![Product](https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/images/site-desktop-computer.png) + ![Product]({{ page.baseurl }}/rest/tutorials/bundle-product/images/site-desktop-computer.png) 1. Customize Desktop Computer and add it to the shopping cart. - ![Shopping Cart](https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/images/shopping-cart-desktop-computer.png) + ![Shopping Cart]({{ page.baseurl }}/rest/tutorials/bundle-product/images/shopping-cart-desktop-computer.png) {:.bs-callout-info} If you do not see the bundle product on the frontend, you can try reindexing and clearing the cache. diff --git a/src/guides/v2.3/rest/tutorials/bundle-product/create-simple-products.md b/src/guides/v2.3/rest/tutorials/bundle-product/create-simple-products.md index 57585c31d7b..b1d90a0849d 100644 --- a/src/guides/v2.3/rest/tutorials/bundle-product/create-simple-products.md +++ b/src/guides/v2.3/rest/tutorials/bundle-product/create-simple-products.md @@ -8,7 +8,7 @@ contributor_link: https://www.goivvy.com/magento-optimization-service --- {:.bs-callout-info} -Before you run the code, please verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute set](https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/plan-product.html#get-attributes) for more information. +Before you run the code, please verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute set]({{ page.baseurl }}/rest/tutorials/bundle-product/plan-product.html#get-attributes) for more information. We will create four simple products: `RAM 12GB`, `RAM 24GB`, `Monitor 15"` and `Monitor 17"`. @@ -570,7 +570,7 @@ POST http://domain.com/rest/default/V1/products * Log in to the Adobe Commerce Admin Panel and select Catalog > Products and confirm that your products appear in the grid. - ![Simple products](https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/images/simple-products-admin-grid.png) + ![Simple products]({{ page.baseurl }}/rest/tutorials/bundle-product/images/simple-products-admin-grid.png) {:.bs-callout-info} If you do not see your products in the catalog, you can try reindexing and clearing the cache. diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md b/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md index 5f7a510e070..ea05bbc4b59 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md @@ -27,8 +27,8 @@ This **5-step tutorial** generally takes **45 minutes**. * [Install and configure RabbitMQ]({{ page.baseurl }}/install-gde/prereq/install-rabbitmq.html), which is the default message broker for bulk API endpoints. -* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/) for more information. +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token]({{ page.baseurl }}/rest/tutorials/prerequisite-tasks/) for more information. ### Other resources -* [REST Tutorials](https://developer.adobe.com/commerce/webapi/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. +* [REST Tutorials]({{ page.baseurl }}/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/create-configurable-product.md b/src/guides/v2.3/rest/tutorials/configurable-product/create-configurable-product.md index 068b4521c21..7dff2fcada2 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/create-configurable-product.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/create-configurable-product.md @@ -30,7 +30,7 @@ Visibility | Code `Catalog, Search` | 4 {:.bs-callout-info} -Before you using this code sample, verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute searchCriteria](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. +Before you using this code sample, verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute searchCriteria]({{ page.baseurl }}/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. **Endpoint:** @@ -217,6 +217,6 @@ Before you using this code sample, verify that the attribute values are the same * Log in to the Luma website and select **Catalog > Products**. The product appears in the grid. - ![Product page with configurable product](https://developer.adobe.com/commerce/webapi/rest/images/products-page.png) + ![Product page with configurable product]({{ page.baseurl }}/rest/images/products-page.png) * On the Luma storefront page, search for `Champ`. No results are returned. diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md b/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md index e8d2c6a29e0..7161e353d72 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md @@ -61,11 +61,11 @@ The `product_sku` is the `sku` of the configurable product. The `sku` specified * Log in to the Luma website and select **Catalog > Products**. Click on the **Champ Tee** configurable product and expand the **Customizable Options** section. - ![Product page with configurable and simple products](https://developer.adobe.com/commerce/webapi/rest/images/options-section.png) + ![Product page with configurable and simple products]({{ page.baseurl }}/rest/images/options-section.png) * On the Luma storefront page, search for `Champ`. Then click on the Champ Tee product. - ![Search results](https://developer.adobe.com/commerce/webapi/rest/images/add-your-name.png) + ![Search results]({{ page.baseurl }}/rest/images/add-your-name.png) {:.bs-callout-info} If the personalization option is not displayed, go to the **Champ Tee** configuration product page in Admin and set **Stock Status** to **In Stock**. @@ -76,4 +76,4 @@ The `product_sku` is the `sku` of the configurable product. The `sku` specified {:.ref-header} Related topic -[Order Processing with REST APIs Tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/) +[Order Processing with REST APIs Tutorial]({{ page.baseurl }}/rest/tutorials/orders/) diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/create-simple-products.md b/src/guides/v2.3/rest/tutorials/configurable-product/create-simple-products.md index 646d83bbe6f..2047d31972f 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/create-simple-products.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/create-simple-products.md @@ -27,7 +27,7 @@ Although it's not required, the simple product payload also includes `stock_item ## Create the first simple product {:.bs-callout-info} -Before you using this code sample, verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute searchCriteria](https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. +Before you using this code sample, verify that the attribute values are the same in your installation. See [Get the list of attributes defined in an attribute searchCriteria]({{ page.baseurl }}/rest/tutorials/configurable-product/plan-product.html#get-attributes) for more information. **Endpoint:** @@ -233,6 +233,6 @@ Attribute | Medium Value | Large Value * Log in to the Luma website and select Catalog > Products. The product appears in the grid. - ![Product page with configurable and simple products](https://developer.adobe.com/commerce/webapi/rest/images/products-page-all.png) + ![Product page with configurable and simple products]({{ page.baseurl }}/rest/images/products-page-all.png) * On the Luma storefront page, search for `Champ`. No results are returned. diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/define-config-product-options.md b/src/guides/v2.3/rest/tutorials/configurable-product/define-config-product-options.md index b35c2e2575f..cef6468e095 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/define-config-product-options.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/define-config-product-options.md @@ -72,11 +72,11 @@ The call to link a simple (child) product to the configurable product accepts on * Log in to the Luma website and select **Catalog > Products**. Click on the **Champ Tee** configurable product and expand the **Configurations** section. -![Product page with configurable and simple products](https://developer.adobe.com/commerce/webapi/rest/images/configurations-section.png) +![Product page with configurable and simple products]({{ page.baseurl }}/rest/images/configurations-section.png) * On the Luma storefront page, search for `Champ`. -![Search results](https://developer.adobe.com/commerce/webapi/rest/images/search-results.png) +![Search results]({{ page.baseurl }}/rest/images/search-results.png) * Call `GET /V1/products/MS-Champ`. The response includes the `configurable_product_options` and `configurable_product_links` arrays. diff --git a/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md b/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md index 4d47f31c975..b19930230ce 100644 --- a/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md +++ b/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md @@ -16,11 +16,11 @@ This tutorial describes how you can use the Magento REST API to create and manag * Install a REST client. You can use any REST client to send calls to Magento. [Postman](https://www.getpostman.com/) is recommended. -* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token](https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/) for more information. +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token]({{ page.baseurl }}/rest/tutorials/prerequisite-tasks/) for more information. ### Other resources -* [REST Tutorials](https://developer.adobe.com/commerce/webapi/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. +* [REST Tutorials]({{ page.baseurl }}/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. ## 1. Create an empty grouped product @@ -211,13 +211,13 @@ You also can use the `DELETE` endpoint to delete a simple product from the group 1. Select **Catalog > Products**. 1. Click on the **New Grouped Product** grouped product and expand the **Grouped Products** section. - ![New grouped product](https://developer.adobe.com/commerce/webapi/rest/images/new-grouped-product.png) + ![New grouped product]({{ page.baseurl }}/rest/images/new-grouped-product.png) ## Add a grouped product to a cart Customers can now add this grouped products to their carts, as shown below. -Refer to the [Order processing tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/) for more information about how to add items to a cart with REST. +Refer to the [Order processing tutorial]({{ page.baseurl }}/rest/tutorials/orders/) for more information about how to add items to a cart with REST. ### Endpoint diff --git a/src/guides/v2.4/b2b/company-object.md b/src/guides/v2.4/b2b/company-object.md deleted file mode 120000 index f7fa3cb53c8..00000000000 --- a/src/guides/v2.4/b2b/company-object.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/b2b/company-object.md \ No newline at end of file diff --git a/src/guides/v2.4/b2b/company-object.md b/src/guides/v2.4/b2b/company-object.md new file mode 100644 index 00000000000..56cb583e0d7 --- /dev/null +++ b/src/guides/v2.4/b2b/company-object.md @@ -0,0 +1,344 @@ +--- +group: b2b-developer-guide +subgroup: 10_REST +title: Manage company objects +menu_title: Manage company objects +menu_order: 12 +ee_only: True +level3_menu_node: level3child +level3_subgroup: company +functional_areas: + - B2B + - Integration +--- + +## Manage company objects + +This section describes the REST endpoints used to manage `Company` objects. + +**Service Name:** + +`companyCompanyRepositoryV1` + +**REST Endpoints:** + +```json +POST /V1/company/ +PUT /V1/company/:companyId +GET /V1/company/:companyId +DELETE /V1/company/:companyId +GET /V1/company/ +``` + +**CompanyInterface Parameters:** + +The following table lists the parameters defined in `CompanyInterface`. + +Name | Description | Format | Requirements +--- | --- | --- | --- +`id` | System-generated company ID | integer | Required for updates and deletes. +`status` | 0 - Pending approval
    1 - Approved
    2 - Rejected
    3 - Blocked | integer | Optional +`company_name` | Company name | string | Required to create or update a company. +`legal_name` | Legal name | string | Optional +`company_email` | Official e-mail address of the company. It does not have to be unique. | string | Required to create or update a company. +`vat_tax_id` | The company's Value Added Tax ID | string | Optional +`reseller_id` | Unique ID of the company reseller | string | Optional +`comment` | Additional details about the company | string | Optional +`street` | Street address where the company is registered. The array can contain one or two lines. | Array[string] | Required to create or update a company. +`city` | The company's city | string | Required to create or update a company. +`country_id` | The country where the company is registered. | string | Required to create or update a company. +`region` | State or province | string | Required to create or update a company. +`region_id` | An ID assigned to a state or province | string | Optional +`postcode` | The company's ZIP or postal code | string | Required to create or update a company. +`telephone` | The company contact's phone number | string | Required to create or update a company. +`customer_group_id` | Defines the company's shared catalog. A value of `1` assigns the default shared catalog. | integer | Required to create or update a company. +`sales_representative_id` | User ID of the Sales Representative for the company | integer | Optional +`reject_reason` | Specifies why a company's request to be a B2B customer is rejected | string | Optional +`rejected_at` | A timestamp indicating when the company was rejected. | string | Optional +`super_user_id` | The `customer_id` of the company administrator. When creating a company, the `customer_id` must already exist. | integer | Required to create or update a company. + +### Create a company + +The following example creates a company and assigns the default shared catalog (`customer_group_id`). The company admin (`super_user_id`) must be a previously-defined `customer_id`. + +**Sample Usage:** + +`POST /rest//V1/company/` + +**Payload:** + +```json +{ + "company": { + "company_name": "Test company", + "company_email": "newemail@example.com", + "street":[ + "100 Big Tree Avenue" + ], + "city": "San Francisco", + "country_id": "US", + "region": "CA", + "region_id": "12", + "postcode": "99999", + "telephone": "4155551212", + "super_user_id": 5, + "customer_group_id": 1 + } +} +``` + +**Response:** + +```json +{ + "id": 2, + "company_name": "Test company", + "company_email": "newemail@example.com", + "street": [ + "100 Big Tree Avenue" + ], + "city": "San Francisco", + "country_id": "US", + "region": "California", + "region_id": "12", + "postcode": "99999", + "telephone": "4155551212", + "customer_group_id": 1, + "sales_representative_id": 1, + "reject_reason": null, + "rejected_at": null, + "super_user_id": 5, + "extension_attributes": { + "quote_config": { + "company_id": "2", + "is_quote_enabled": false + } + } +} +``` + +### Update the company + +The following call changes the company status to Rejected (`2`) and explains why. + +**Sample Usage:** + +`PUT /rest//V1/company/2` + +**Payload:** + +```json +{ + "company": { + "id": 2, + "company_name": "Test company", + "company_email": "newemail@example.com", + "customer_group_id": 1, + "street":[ + "100 Big Tree Avenue" + ], + "city": "San Francisco", + "country_id": "US", + "region": "CA", + "region_id": "12", + "postcode": "99999", + "telephone": "4155551212", + "super_user_id": 5, + "status": 2, + "reject_reason": "Failed background check." + } +} +``` + +**Response:** + +```json +{ + "id": 2, + "company_name": "Test company", + "company_email": "newemail@example.com", + "street": [ + "100 Big Tree Avenue" + ], + "city": "San Francisco", + "country_id": "US", + "region": "California", + "region_id": "12", + "postcode": "99999", + "telephone": "4155551212", + "customer_group_id": 1, + "sales_representative_id": 1, + "reject_reason": null, + "rejected_at": null, + "super_user_id": 5, + "extension_attributes": { + "quote_config": { + "company_id": "2", + "is_quote_enabled": true + } + } +} +``` + +### Return all information about a company + +This call returns detailed information about the specified company. +**Sample Usage:** + +`GET /rest//V1/company/2` + +**Payload:** + +None + +**Response:** + +```json +{ + "id": 2, + "status": 0, + "company_name": "Test company", + "company_email": "newemail@example.com", + "street": [ + "100 Big Tree Avenue" + ], + "city": "San Francisco", + "country_id": "US", + "region": "California", + "region_id": "12", + "postcode": "99999", + "telephone": "4155551212", + "customer_group_id": 1, + "sales_representative_id": 1, + "reject_reason": null, + "rejected_at": null, + "super_user_id": 5, + "extension_attributes": { + "quote_config": { + "company_id": "2", + "is_quote_enabled": true + } + } +} +``` + +### Delete a company + +When you delete a company, Magento assigns the "Inactive" status to all company members. The system also removes company ID from the customer profile of all company members. + +**Sample Usage:** + +`DELETE /rest//V1/company/2` + +**Payload:** + +None + +**Response:** + +`true`, indicating the request was successful + +### Search for companies + +The following call returns all companies that are located in California (`region_id` = `12`) + +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. + +**Sample Usage:** + +`GET /rest//V1/company?searchCriteria[filter_groups][0][filters][0][field]=region_id&searchCriteria[filter_groups][0][filters][0][value]=12&searchCriteria[filter_groups][0][filters][0][condition_type]=eq` + +**Payload:** + +None + +**Response:** + +{% collapsible Show code sample %} +```json +{ + "items": [ + { + "id": 2, + "status": 1, + "company_name": "Test Company", + "legal_name": "Test Company", + "company_email": "newemail@example.com", + "street": [ + "100 Big Tree Avenue" + ], + "city": "San Francisco", + "country_id": "US", + "region": "California", + "region_id": "12", + "postcode": "99999", + "telephone": "4155551212", + "customer_group_id": 1, + "sales_representative_id": 1, + "reject_reason": null, + "rejected_at": null, + "super_user_id": 3, + "extension_attributes": { + "applicable_payment_method": 0, + "available_payment_methods": "banktransfer,cashondelivery,checkmo,payflowpro,payflow_advanced,payflow_link,braintree,cybersource,eway,authorizenet_directpost,free,braintree_paypal,paypal_billing_agreement,payflow_express_bml,paypal_express_bml,paypal_express,payflow_express,hosted_pro,worldpay,companycredit,purchaseorder,braintree_paypal_vault,braintree_cc_vault,payflowpro_cc_vault", + "use_config_settings": 1, + "quote_config": { + "is_quote_enabled": true + } + } + }, + { + "id": 3, + "status": 1, + "company_name": "Widgets, Inc", + "legal_name": "Widgets, Inc", + "company_email": "widgetsinc@example.com", + "street": [ + "8383 Wilshire Blvd", + "Ste 1500" + ], + "city": "Beverly Hills", + "country_id": "US", + "region": "California", + "region_id": "12", + "postcode": "90211", + "telephone": "(310) 555-0000", + "customer_group_id": 1, + "sales_representative_id": 1, + "reject_reason": null, + "rejected_at": null, + "super_user_id": 10, + "extension_attributes": { + "applicable_payment_method": 0, + "available_payment_methods": "banktransfer,cashondelivery,checkmo,payflowpro,payflow_advanced,payflow_link,braintree,cybersource,eway,authorizenet_directpost,free,braintree_paypal,paypal_billing_agreement,payflow_express_bml,paypal_express_bml,paypal_express,payflow_express,hosted_pro,worldpay,companycredit,purchaseorder,braintree_paypal_vault,braintree_cc_vault,payflowpro_cc_vault", + "use_config_settings": 1, + "quote_config": { + "is_quote_enabled": true + } + } + } + ], + "search_criteria": { + "filter_groups": [ + { + "filters": [ + { + "field": "region_id", + "value": "12", + "condition_type": "eq" + } + ] + } + ] + }, + "total_count": 2 +} +``` +{% endcollapsible %} + +## Related information + +* [Integrate with the Company module]({{ page.baseurl }}/b2b/company.html) +* [Manage company users]({{ page.baseurl }}/b2b/company-users.html) +* [Manage company roles]({{ page.baseurl }}/b2b/roles.html) +* [Manage company structures]({{ page.baseurl }}/b2b/company-structures.html) diff --git a/src/guides/v2.4/b2b/company-structures.md b/src/guides/v2.4/b2b/company-structures.md deleted file mode 120000 index 5e1eae9643f..00000000000 --- a/src/guides/v2.4/b2b/company-structures.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/b2b/company-structures.md \ No newline at end of file diff --git a/src/guides/v2.4/b2b/company-structures.md b/src/guides/v2.4/b2b/company-structures.md new file mode 100644 index 00000000000..2686be3c739 --- /dev/null +++ b/src/guides/v2.4/b2b/company-structures.md @@ -0,0 +1,289 @@ +--- +group: b2b-developer-guide +title: Manage company structures +ee_only: true +functional_areas: + - B2B + - Integration +--- + +{{site.data.var.b2b}} allows company users to be assigned to company teams and hierarchies. + +## Manage company teams + +Company teams allow you to group company users by location, job responsibilities, or any criteria you choose. You can assign individual company users to a team with the company hierarchy endpoints. + +**Service name:** + +`companyTeamRepositoryV1` + +**REST Endpoints:** + +```terminal +POST /V1/team/:companyId +PUT /V1/team/:teamId +GET /V1/team/:teamId +DELETE /V1/team/:teamId +GET /V1/team/ +``` + +**Company team parameters:** + +Name | Description | Format | Requirements +--- | --- | --- | --- +id | System-generated team ID | integer | Not applicable for create operations. +name | The displayed name of the team | string | Required to create or update a team. +description | An optional description of the team. | string | Optional + +### Create a team + +A newly-created team is placed under Company Admin in the company hierarchy. + +**Sample Usage:** + +`POST /rest//V1/team/2` + +**Payload:** + +```json +{ + "team": { + "name": "Western District", + "description": "Buyers from the California office" + } +} +``` + +**Response:** + +The team ID, such as `4`. + +### Update a team + +You can only change the name or description of a team. + +**Sample Usage:** + +`PUT /rest//V1/team/4` + +**Payload:** + +```json +{ + "team": { + "id": 4, + "name": "Western Region" + } +} +``` + +**Response:** + +`true`, indicating the request was successful + +### Return all information about a team + +The `GET` call returns the team `id`, `name`, and `description`. + +**Sample Usage:** + +`GET /rest//V1/team/4` + +**Payload:** + +Not applicable + +**Response:** + +```json +{ + "id": 4, + "name": "Western Region", + "description": "Buyers from the California office" +} +``` + +### Delete a team + +You cannot delete a team if members are assigned to it. + +**Sample Usage:** + +`DELETE /rest//V1/team/4` + +**Payload:** + +Not applicable + +**Response:** + +An empty array + +### Search for a team + +The following query returns information about all teams (`team_id` ≥ `0`) + +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. + +**Sample Usage:** + +`GET /rest//V1/team?searchCriteria[filter_groups][0][filters][0][field]=team_id&searchCriteria[filter_groups][0][filters][0][value]=0&searchCriteria[filter_groups][0][filters][0][condition_type]=gteq` + +**Payload:** + +Not applicable + +**Response:** +{% collapsible Show code sample %} + +```json +{ + "items": [ + { + "id": 1, + "name": "West", + "description": "California office" + }, + { + "id": 2, + "name": "East", + "description": "New York office" + } + ], + "search_criteria": { + "filter_groups": [ + { + "filters": [ + { + "field": "team_id", + "value": "0", + "condition_type": "gteq" + } + ] + } + ] + }, + "total_count": 2 +} +``` + +{% endcollapsible %} + +## Company hierarchies + +In the B2B storefront, a buyer can view the company structure represented as a hierarchy tree. The tree can display multiple levels of company subdivisions (teams) as well as company users. The company hierarchy can have any number of items and levels. + +You can use REST endpoints to retrieve the current structure and move teams and buyers within the hierarchy. You cannot delete teams or buyers. + +**Service name:** + +`companyHierarchyV1` + +**REST Endpoints:** + +```terminal +GET /V1/hierarchy/:id +PUT /V1/hierarchy/move/:id +``` + +### Return all information about the company hierarchy + +In the following example, the following company hierarchy has already been established: + +```terminal +Admin (structure_id = 2) +|-- East (team, structure_id = 8) +| |-- Bryce Martin (customer, structure_id = 4) +| |-- Melanie Shaw (customer, structure_id = 3) +| +|-- West (team, structure_id = 7) +| |-- Marcus Thomas (customer, structure_id = 6) +| |-- Teresa Gomez (customer, structure_id = 5) +``` + +**Sample Usage:** + +`GET /rest//V1/hierarchy/2` + +**Payload:** + +Not applicable + +**Response:** + +{% collapsible Show code sample %} + +```json +[ + { + "structure_id": 6, + "entity_id": 7, + "entity_type": "customer", + "structure_parent_id": 7 + }, + { + "structure_id": 5, + "entity_id": 6, + "entity_type": "customer", + "structure_parent_id": 7 + }, + { + "structure_id": 7, + "entity_id": 1, + "entity_type": "team", + "structure_parent_id": 2 + }, + { + "structure_id": 3, + "entity_id": 4, + "entity_type": "customer", + "structure_parent_id": 8 + }, + { + "structure_id": 4, + "entity_id": 5, + "entity_type": "customer", + "structure_parent_id": 8 + }, + { + "structure_id": 8, + "entity_id": 2, + "entity_type": "team", + "structure_parent_id": 2 + }, + { + "structure_id": 2, + "entity_id": 3, + "entity_type": "customer", + "structure_parent_id": 0 + } +``` + +{% endcollapsible %} + +### Assign a new parent to teams and company users + +The following example moves Bryce Martin (`structure_id = 4`) to the West team (`structure_id = 7`) + +**Sample Usage:** + +`PUT /rest//V1/hierarchy/move/5` + +**Payload:** + +```json +{ + "newParentId": 7 +} +``` + +**Response:** + +`[]` (an empty array) + +## Related information + +* [Integrate with the Company module]({{ page.baseurl }}/b2b/company.html) +* [Manage company objects]({{ page.baseurl }}/b2b/company-object.html) +* [Manage company users]({{ page.baseurl }}/b2b/company-users.html) +* [Manage company roles]({{ page.baseurl }}/b2b/roles.html) diff --git a/src/guides/v2.4/b2b/company-users.md b/src/guides/v2.4/b2b/company-users.md deleted file mode 120000 index aee69b383ec..00000000000 --- a/src/guides/v2.4/b2b/company-users.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/b2b/company-users.md \ No newline at end of file diff --git a/src/guides/v2.4/b2b/company-users.md b/src/guides/v2.4/b2b/company-users.md new file mode 100644 index 00000000000..4bfd801ba06 --- /dev/null +++ b/src/guides/v2.4/b2b/company-users.md @@ -0,0 +1,175 @@ +--- +group: b2b-developer-guide +title: Manage company users +ee_only: true +functional_areas: + - B2B + - Integration +--- + +A company user is a customer (buyer) that is assigned extended attributes that identify the company the user belongs to. Use the `POST /V1/customers` call, which is included with {{site.data.var.ce}} and {{site.data.var.ee}}, to create the user. After the user is created, you can use the `PUT /V1/customers/:customer_id` call to set their company data with the `company_attributes` extended attributes. + + {:.bs-callout-info} +This topic discusses only the features of the `customerCustomerRepositoryV1` service that are specific to B2B. See [Create a customer](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-customer.html) for an example of creating a standard customer. + +## Manage company users + +This section describes the REST endpoints used to manage company users. + +**Service Name:** + +`customerCustomerRepositoryV1` + +**REST Endpoints:** + +```terminal +POST /V1/customers/ +PUT /V1/customers/:customerId +``` + +**Company user parameters:** + +The following table lists the parameters that can be used to set company data for a user. + +Name | Description | Format | Requirements +--- | --- | --- | --- +`customer_id` | System-generated customer ID. | integer | Not applicable for create operations. +`company_id` | System-generated company ID. | integer | Required to create or update a company user. +`job_title` | A string that describes the company user's responsibilities. | string | Required to create or update a company. +`status` | Indicates whether the company user is active or inactive | integer | `0` - inactive; `1` - active +`telephone` | Telephone number | string | Required to create a company user. + +### Create a company user + +The `POST /V1/customers` call creates a Magento customer. B2B extends the `customerAccountManagementV1` service so that you can create a company user. + +**Sample Usage:** + +`POST /rest//V1/customers` + +**Payload:** + +First, create the standard customer. Their `company_id` will initially be set to `0`. + +```json +{ + "customer": { + "email": "mshaw@example.com", + "firstname": "Melanie", + "lastname": "Shaw" + } +} +``` + +**Response:** + +```json +{ + "id": 13, + "group_id": 1, + "created_at": "2017-05-18 16:47:44", + "updated_at": "2017-05-18 16:47:44", + "created_in": "Default Store View", + "email": "mshaw@example.com", + "firstname": "Melanie", + "lastname": "Shaw", + "store_id": 1, + "website_id": 1, + "addresses": [], + "disable_auto_group_change": 0, + "extension_attributes": { + "company_attributes": { + "customer_id": 13, + "company_id": 0 + } + } +} +``` + +If you create a user from the admin dashboard, you can also set their company data at the same time. + +### Modify a company user + +The following example assigns the user to a company, sets their status to inactive and also sets their `job_title` and `telephone`. + +If you change the `status` to inactive, the account is locked. If the company user has child users, the system re-assigns the child users to the parent of the deactivated user. + +**Sample Usage:** + +`PUT /rest//V1/customers/13` + +**Payload:** + +```json +{ + "customer": { + "id": 13, + "email": "mshaw@example.com", + "firstname": "Melanie", + "lastname": "Shaw", + "website_id": 1, + "extension_attributes": { + "company_attributes": { + "company_id": 2, + "status": 0, + "job_title": "Sales Rep", + "telephone": "512-555-3322" + } + } + } +} +``` + +**Response:** + +```json +{ + "id": 13, + "group_id": 1, + "created_at": "2017-05-18 16:47:44", + "updated_at": "2017-05-18 18:50:58", + "created_in": "Default Store View", + "email": "mshaw@example.com", + "firstname": "Melanie", + "lastname": "Shaw", + "store_id": 1, + "website_id": 1, + "addresses": [], + "disable_auto_group_change": 0, + "extension_attributes": { + "company_attributes": { + "customer_id": 13, + "company_id": 2, + "status": 0, + "job_title": "Sales Rep", + "telephone": "512-555-3322" + }, + "is_subscribed": false + } +} +``` + +### Delete a company user + +If the specified company user has child users, the system re-assigns the child users to the parent of the deleted user. The user account is deleted from Magento with all of its content, except quotes and orders. The user's orders and quotes remain visible to the seller. + +Magento locks the deleted user's quotes and changes their status to Closed. The system does not allow to make changes on such quotes. + +**Sample Usage:** + +`DELETE /rest//V1/customers/13` + +**Payload:** + +Not applicable + +**Response:** + +`true`, indicating the request was successful + +## Related information + +* [Integrate with the Company module]({{ page.baseurl }}/b2b/company.html) +* [Manage company objects]({{ page.baseurl }}/b2b/company-object.html) +* [Manage company roles]({{ page.baseurl }}/b2b/roles.html) +* [Manage company structures]({{ page.baseurl }}/b2b/company-structures.html) diff --git a/src/guides/v2.4/b2b/credit-manage.md b/src/guides/v2.4/b2b/credit-manage.md deleted file mode 120000 index 95d6e8f2700..00000000000 --- a/src/guides/v2.4/b2b/credit-manage.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/b2b/credit-manage.md \ No newline at end of file diff --git a/src/guides/v2.4/b2b/credit-manage.md b/src/guides/v2.4/b2b/credit-manage.md new file mode 100644 index 00000000000..68451b178f7 --- /dev/null +++ b/src/guides/v2.4/b2b/credit-manage.md @@ -0,0 +1,399 @@ +--- +group: b2b-developer-guide +title: Manage company credit +ee_only: true +functional_areas: + - B2B + - Integration +--- + +The company credit entity operates with the following attributes: + +* Credit limit +* Available credit +* Outstanding balance + +The credit limit is allocated by seller, while available credit and outstanding balance are automatically calculated by the system based on the buyer transactions (place an order, return) and seller's transactions (refund, reimburse, update credit limit, cancel order). + +## Manage company credit limits + +When you create a company, the credit limit is set to 0. Use the `PUT /V1/companyCredits/:id` call to change this value and perform other updates to the company's credit settings. + +**REST Endpoints:** + +```terminal +PUT /V1/companyCredits/:id +GET /V1/companyCredits/:creditId +GET /V1/companyCredits/company/:companyId +GET /V1/companyCredits/ +``` + +**Company credit parameters:** + +Name | Description | Format | Requirements +--- | --- | --- | --- +`id` | The credit ID generated by the system | Integer | Required +`company_id` | Company ID | Integer | Required +`credit_limit` | The amount of credit granted to the company | Float | Required +`balance` | The amount the company currently owes the seller | Float | Optional +`currency_code` | The currency code for the company's credit, such as USD | String | Required +`exceed_limit` | Indicates whether the company can exceed their credit limit | Boolean | Optional +`available_limit` | The amount of credit currently available to the company | Float | Optional +`credit_comment` | Describes the change being made | String | Optional + +### Update a company credit limit + +This call changes the company's credit limit to $1000. The `available_limit` parameter is calculated, so you cannot specify the value. + +**Service Name:** + +`companyCreditCreditLimitRepositoryV1` + +**Sample Usage:** + +`PUT /rest//V1/companyCredits/2` + +**Payload:** + +```json +{ + "creditLimit": { + "id": 2, + "company_id": 2, + "credit_limit": 1000, + "currency_code": "USD" + } +} +``` + +**Response:** + +```json +{ + "id": 2, + "company_id": 2, + "credit_limit": 1000, + "balance": 0, + "currency_code": "USD", + "exceed_limit": false, + "available_limit": 1000 +} +``` + +### Get details about a company's credit limit using credit ID + +This call returns data on the credit limit for the specified credit ID. + +**Service Name:** + +`companyCreditCreditLimitRepositoryV1` + +**Sample Usage:** + +`GET /rest//V1/companyCredits/2` + +**Payload:** + +Not applicable + +**Response:** + +```json +{ + "id": 2, + "company_id": 2, + "credit_limit": 500, + "balance": 0, + "currency_code": "USD", + "exceed_limit": false, + "available_limit": 500 +} +``` + +### Get details about a company's credit limit using company ID + +This call returns information about the credit limit for a specified company. + +**Service Name:** + +`companyCreditCreditLimitManagementV1` + +**Sample Usage:** + +`GET /rest//V1/companyCredits/company/2` + +**Payload:** + +Not applicable + +**Response:** + +```json +{ + "id": 2, + "company_id": 2, + "credit_limit": 500, + "balance": 0, + "currency_code": "USD", + "exceed_limit": false, + "available_limit": 500 +} +``` + +### Search credit IDs + +The following call returns information for all companies whose credit balance is 0. + +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. + +**Sample Usage:** + +`GET /rest//V1/companyCredits?searchCriteria[filter_groups][0][filters][0][field]=balance&searchCriteria[filter_groups][0][filters][0][value]=0&searchCriteria[filter_groups][0][filters][0][condition_type]=eq` + +**Payload:** + +Not applicable + +**Response:** + +{% collapsible Show code sample %} + +```json +{ + "items": [ + { + "id": 2, + "company_id": 2, + "credit_limit": 1000, + "balance": 0, + "currency_code": "USD", + "exceed_limit": false, + "available_limit": 1000 + }, + { + "id": 3, + "company_id": 3, + "balance": 0, + "currency_code": "USD", + "exceed_limit": false, + "available_limit": 0 + }, + { + "id": 4, + "company_id": 4, + "credit_limit": 2000, + "balance": 0, + "currency_code": "USD", + "exceed_limit": false, + "available_limit": 2000 + } + ], + "search_criteria": { + "filter_groups": [ + { + "filters": [ + { + "field": "balance", + "value": "0", + "condition_type": "eq" + } + ] + } + ] + }, + "total_count": 3 +} +``` + +{% endcollapsible %} + +## Balance operations + +The company's outstanding balance can be updated as the buyer makes payments, purchases, and other transactions. + +**Service Name:** + +`companyCreditCreditBalanceManagementV1` + +**REST Endpoints:** + +```terminal +POST /V1/companyCredits/:creditId/decreaseBalance +POST /V1/companyCredits/:creditId/increaseBalance +``` + +**Balance Parameters:** + +Name | Description | Format | Requirements +--- | --- | --- | --- +`value` | Indicates how much money is involved in this company credit balance operation. | Number | Required +`currency` | The currency of the transaction, such as USD | String | Required +`operationType` | Must be one of the following: 1 - Allocated; 2 - Updated; 3 - Purchased; 4 - Reimbursed; 5 - Refunded; 6 - Reverted | Integer | Required +`comment` | Describers the operation | String | Optional +`options` | An object that provides additional information for increasing or decreasing the credit balance | Object | Optional + +**`options` parameters:** + +Name | Description | Format | Requirements +--- | --- | --- | --- +`purchase_order` | The company's purchase order number | String | Optional +`order_increment` | Order increment | String | Optional +`currency_display` | Currency code for displaying the operation | String | Optional +`currency_base` | The base currency | String | Optional + +### Increase the company credit balance + +This call increases the company credit with an Allocate, Update, Refund, Revert, or Reimburse transaction. (You cannot specify the Purchased (3) operation type.) This call also decreases the company's outstanding balance. + +**Sample Usage:** + +`POST /rest//V1/companyCredits/2/increaseBalance` + +**Payload:** + +```json +{ + "value": 250, + "currency": "USD", + "operationType": 2, + "comment": "update limit" +} +``` + +**Response:** + +`true`, indicating the increase to the company credit balance succeeded + +### Decrease the balance + +This call decreases the company credit with an Update (operation type = 2), Purchased (3), or Reimbursed (4) transaction. (You cannot specify the other operation types.) This call also increases company's outstanding balance. + +**Sample Usage:** + +`POST /rest//V1/companyCredits/2/decreaseBalance` + +**Payload:** + +```json +{ + "value": 250, + "currency": "USD", + "operationType": 4, + "comment": "issue refund" +} +``` + +**Response:** + +`true`, indicating the decrease to the company credit balance succeeded + +## Credit history + +A Reimburse transaction can be updated to include a purchase order and comment. + +**Service Name:** +`companyCreditCreditHistoryManagementV1` + +**REST Endpoints:** + +```text +GET /V1/companyCredits/history +PUT /V1/companyCredits/history/:historyId +``` + +### Save the credit history + +This call updates the credit history to specify a purchase order number. + +**Sample Usage:** + +`PUT /rest//V1/companyCredits/history/6` + +**Payload:** + +```json +{ + "purchaseOrder": "A12345", + "comment": "Adding PO info" +} +``` + +**Response:** + +`true`, indicating the call was successful + +### Search credit history IDs + +The following call returns a list instances in which the credit limit was set to a value higher than $500. + +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. + +**Sample Usage:** + +`GET /rest//V1/companyCredits/history?searchCriteria[filter_groups][0][filters][0][field]=credit_limit&searchCriteria[filter_groups][0][filters][0][value]=500&searchCriteria[filter_groups][0][filters][0][condition_type]=gt` + +**Payload:** + +Not applicable + +**Response:** + +```json +{ + "items": [ + { + "id": 6, + "company_credit_id": 2, + "user_id": 1, + "user_type": 2, + "currency_credit": "USD", + "currency_operation": "USD", + "rate": 1, + "rate_credit": 0, + "amount": -250, + "balance": 0, + "credit_limit": 1000, + "available_limit": 1000, + "type": 4, + "datetime": "2017-06-12 02:26:28", + "purchase_order": "A12345", + "comment": "{\"custom\":\"Adding PO info\"}" + }, + { + "id": 7, + "company_credit_id": 4, + "user_id": 1, + "user_type": 2, + "currency_credit": "USD", + "currency_operation": "USD", + "rate": 1, + "rate_credit": 0, + "amount": 0, + "balance": 0, + "credit_limit": 2000, + "available_limit": 2000, + "type": 1, + "datetime": "2017-07-20 21:28:35", + "comment": "" + } + ], + "search_criteria": { + "filter_groups": [ + { + "filters": [ + { + "field": "credit_limit", + "value": "500", + "condition_type": "gt" + } + ] + } + ] + }, + "total_count": 2 +} +``` + +## Related information + +[Integrate with the CompanyCredit module]({{ page.baseurl }}/b2b/company-credit.html) diff --git a/src/guides/v2.4/b2b/shared-cat-manage.md b/src/guides/v2.4/b2b/shared-cat-manage.md deleted file mode 120000 index f9e57d72353..00000000000 --- a/src/guides/v2.4/b2b/shared-cat-manage.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/b2b/shared-cat-manage.md \ No newline at end of file diff --git a/src/guides/v2.4/b2b/shared-cat-manage.md b/src/guides/v2.4/b2b/shared-cat-manage.md new file mode 100644 index 00000000000..81dd6f3226b --- /dev/null +++ b/src/guides/v2.4/b2b/shared-cat-manage.md @@ -0,0 +1,188 @@ +--- +group: b2b-developer-guide +title: Manage shared catalogs +ee_only: true +functional_areas: + - B2B + - Catalog + - Integration +--- + +## Manage custom shared catalogs + +{{site.data.var.b2b}} provides two types of shared catalog: public and custom. A public catalog is the default shared catalog. It is automatically displayed to all guest customers and to logged-in customers that are not company users. The seller assigns a custom shared catalog to specific companies as configured by admin. There can only be one public catalog, and it cannot be deleted. + +**Service name:** + +`sharedCatalogSharedCatalogRepositoryV1` + +**REST Endpoints:** + +```terminal +POST /V1/sharedCatalog +PUT /V1/sharedCatalog/:id +GET /V1/sharedCatalog/:sharedCatalogId +DELETE /V1/sharedCatalog/:sharedCatalogId +GET /V1/sharedCatalog/ +``` + +**Shared catalog parameters:** + +Name | Description | Format | Requirements +--- | --- | --- | --- +`id` | The system-generated shared catalog ID number | integer | Required to update a shared catalog. Not applicable for create operations. +`name` | The display name of the shared catalog. Must be unique | string | Required to create or update a shared catalog. +`description` | Describes the shared catalog | string | Optional +`customer_group_id` | A system-generated ID. It cannot be changed. | integer | 0 - Not logged in; 1 - General; 2 - Wholesale; 3 - Retailer +`type` | Indicates whether this is a custom or public shared catalog. | integer | Required to create or update a shared catalog. 0 - Custom; 1 - Public +`created_by` | The user ID of the admin who created the shared catalog | integer | Optional +`store_id` | The store ID the shared catalog is assigned to | integer | Required to create or update a shared catalog. +`tax_class_id` | | integer | Required to create a shared catalog. 2 - Taxable goods; 3 - Retail Customer + +### Create a custom shared catalog + +When B2B is enabled, the system creates a public shared catalog named `Default (General)`. Magento allows only one public shared catalog at a time. You can create an unlimited number of custom shared catalogs. + +**Sample Usage:** + +`POST /rest//V1/sharedCatalog` + +**Payload:** + +```json +{ + "sharedCatalog": { + "name": "Test", + "type": 0, + "store_id": 0, + "tax_class_id": 3 + } +} +``` + +**Response:** + +The shared catalog `id`, such as `2`. + +### Update a characteristics of a shared catalog + +You cannot change the `type` from public (`1`) to custom (`0`). If you need to replace the public shared catalog, create a custom catalog and change its type to public. + +**Sample Usage:** + +`PUT /rest//V1/sharedCatalog/2` + +```json +{ + "sharedCatalog": { + "id": 2, + "name": "Custom shared catalog", + "description": "Just a sample custom shared catalog.", + "type": 0, + "store_id": 0, + "tax_class_id": 3 + } +} +``` + +**Response:** + +The shared catalog `id`, such as `2`. + +### Retrieve general information about a shared catalog + +This call returns information about the specified shared catalog. + +**Sample Usage:** + +`GET /rest//V1/sharedCatalog/2` + +**Payload:** + +Not applicable + +**Response:** + +```json +{ + "id": 2, + "name": "Custom shared catalog", + "description": "Just a sample custom shared catalog.", + "customer_group_id": 4, + "type": 0, + "created_at": "2017-07-21 15:39:40", + "created_by": 1, + "store_id": 0, + "tax_class_id": 3 +} +``` + +### Delete a shared catalog + +Only custom shared catalogs can be deleted. When a custom catalog is deleted, the assigned companies are re-assigned to the default public catalog. + +**Sample Usage:** + +`DELETE /rest//V1/sharedCatalog/2` + +**Payload:** + +Not applicable + +**Response:** + +`true`, indicating the request was successful + +### Search for a shared catalog + +The following search returns all the custom shared catalogs (`type = 0`) in the system. + +See [Search using REST APIs](https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches.html) for information about constructing a search query. + +**Sample Usage:** + +`GET /rest//V1/sharedCatalog?searchCriteria[filter_groups][0][filters][0][field]=type&searchCriteria[filter_groups][0][filters][0][value]=0&searchCriteria[filter_groups][0][filters][0][condition_type]=eq` + +**Payload:** + +Not applicable + +**Response:** + +```json +{ + "items": [ + { + "id": 2, + "name": "Custom shared catalog", + "description": "Just a sample custom shared catalog.", + "customer_group_id": 4, + "type": 0, + "created_at": "2017-07-21 15:39:40", + "created_by": 1, + "store_id": 0, + "tax_class_id": 3 + } + ], + "search_criteria": { + "filter_groups": [ + { + "filters": [ + { + "field": "type", + "value": "0", + "condition_type": "eq" + } + ] + } + ] + }, + "total_count": 1 +} +``` + +## Related information + +* [Integrate with the SharedCatalog module]({{ page.baseurl }}/b2b/shared-catalog.html) +* [Assign categories and products]({{ page.baseurl }}/b2b/shared-cat-product-assign.html) +* [Assign companies]({{ page.baseurl }}/b2b/shared-cat-company.html) diff --git a/src/guides/v2.4/b2b/shared-catalog.md b/src/guides/v2.4/b2b/shared-catalog.md deleted file mode 120000 index 05a3a2ac762..00000000000 --- a/src/guides/v2.4/b2b/shared-catalog.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/b2b/shared-catalog.md \ No newline at end of file diff --git a/src/guides/v2.4/b2b/shared-catalog.md b/src/guides/v2.4/b2b/shared-catalog.md new file mode 100644 index 00000000000..ba46914c0ea --- /dev/null +++ b/src/guides/v2.4/b2b/shared-catalog.md @@ -0,0 +1,29 @@ +--- +group: b2b-developer-guide +subgroup: 10_REST +title: Integrate with the SharedCatalog module +menu_title: Integrate with the SharedCatalog module +menu_order: 21 +ee_only: True +level3_menu_node: level3child +level3_subgroup: shared +functional_areas: + - B2B + - Catalog + - Integration +--- + +A shared catalog is an entity that allows a seller to set special rules for the products that company users (buyers) can purchase. By using shared catalogs, a seller can apply different pricing levels for different companies. Also, shared catalogs allow a seller to configure the visibility of categories and products specifically for different companies. + +Products and categories are not created or stored within a shared catalog. The products are defined in the master catalog. (The master catalog is the Magento standard product catalog and is visible to the seller only.) The categories are created within the Categories page, and the seller determines whether a category should be displayed in each shared catalog. + +Custom shared catalogs can be assigned to companies only. They cannot be set for individual users. A company can be assigned only one shared catalog. + +{{site.data.var.b2b}} provides two types of shared catalog: public and custom. A public catalog is the default shared catalog. It is automatically displayed to all guest customers and to logged-in customers that are not company users, though a company can be assigned the public catalog. The seller assigns a custom shared catalog to specific companies. There can only be one public catalog, and it cannot be deleted. + +## Related information + +* [Manage shared catalogs]({{ page.baseurl }}/b2b/shared-cat-manage.html) +* [Assign categories and products]({{ page.baseurl }}/b2b/shared-cat-product-assign.html) +* [Assign companies]({{ page.baseurl }}/b2b/shared-cat-company.html) +* [Manage prices for multiple products](https://developer.adobe.com/commerce/webapi/rest/modules/catalog/catalog-pricing) diff --git a/src/guides/v2.4/graphql/tutorials/checkout/index.md b/src/guides/v2.4/graphql/tutorials/checkout/index.md deleted file mode 120000 index 46380a2f0ac..00000000000 --- a/src/guides/v2.4/graphql/tutorials/checkout/index.md +++ /dev/null @@ -1 +0,0 @@ -../../../../v2.3/graphql/tutorials/checkout/index.md \ No newline at end of file diff --git a/src/guides/v2.4/graphql/tutorials/checkout/index.md b/src/guides/v2.4/graphql/tutorials/checkout/index.md new file mode 100644 index 00000000000..a458935db14 --- /dev/null +++ b/src/guides/v2.4/graphql/tutorials/checkout/index.md @@ -0,0 +1,45 @@ +--- +layout: tutorial +group: graphql +title: GraphQL checkout tutorial +menu_title: Initial tasks +menu_order: 0 +level3_subgroup: graphql-checkout +return_to: + title: GraphQL Overview + url: graphql/index.html +functional_areas: + - Integration +contributor_name: Atwix +contributor_link: https://www.atwix.com/ +--- + +This tutorial describes how to place an order through GraphQl. Customers can make purchases in two ways: + +- As a logged-in user +- As a guest user who does not create an account + +The **10-step tutorial** generally takes **30 minutes**. + +Magento GraphQL is designed to run queries and perform actions on behalf of a customer. Magento GraphQL does not perform backend tasks, such as manage invoices or shipments. + +### Before you begin + +Complete the following prerequisites: + +- Install a Magento 2 instance with sample data. + The sample data defines a functional store, called Luma, that sells fitness clothing and accessories. The store does not provide any sandbox accounts for testing credit card payments, so transactions will be simulated using an offline [payment method](https://glossary.magento.com/payment-method). + +- Install a GraphQl client. You can use any GraphQl client to send calls to Magento. [Altair](https://altair.sirmuel.design/) is a good example. + +- Learn about GraphQL, how it works, and how to use it. See [Introduction to GraphQL](https://graphql.org/learn/) for details. + +- Know how to generate a customer token. See [Authorization tokens]({{page.baseurl}}/graphql/authorization-tokens.html) for details. + +- In the Magento admin, create a [coupon]({{ site.user_guide_url }}/marketing/price-rules-cart-coupon-code-configure.html) that will be used in [Step 7. Apply a coupon]({{page.baseurl}}/graphql/tutorials/checkout/checkout-coupon.html). + +### Other resources + +- [Order processing tutorial](https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/) shows a system integrator how REST APIs are used in the lifecycle of an order, including configuring a store and creating a customer; creating quotes, orders, invoices, and shipments; preparing for checkout; and more order-related tasks. + +- [REST Tutorials](https://developer.adobe.com/commerce/webapi/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. diff --git a/src/guides/v2.4/inventory/release-notes.md b/src/guides/v2.4/inventory/release-notes.md deleted file mode 120000 index 4396905adfa..00000000000 --- a/src/guides/v2.4/inventory/release-notes.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/inventory/release-notes.md \ No newline at end of file diff --git a/src/guides/v2.4/inventory/release-notes.md b/src/guides/v2.4/inventory/release-notes.md new file mode 100644 index 00000000000..c41fe6a51f7 --- /dev/null +++ b/src/guides/v2.4/inventory/release-notes.md @@ -0,0 +1,219 @@ +--- +group: inventory +title: Release Notes +migrated_to: https://experienceleague.adobe.com/docs/commerce-admin/inventory/release-notes.html +layout: migrated +--- + +**{{site.data.var.im}} (provided by the [Magento Inventory (was MSI)](https://github.com/magento/inventory) project)** is available with {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}} 2.3.x. Merchants can use {{site.data.var.im}} to manage inventory for all product types in a single warehouse and across complex shipping networks. Manage these locations as sources, tracking on-hand inventory quantities per product. Stocks connect these sources with sales channels (websites) to provide an accurate salable quantity, calculating available on-hand products, pending orders (reservations), and configured thresholds. {{site.data.var.im}} also updates order and shipment options, giving you full control over your inventory and deductions at the source level. + +{{site.data.var.im}} is a Magento Community Engineering special project open to contributors. To take part and contribute, see the [MSI GitHub](https://github.com/magento/inventory) repository and [wiki](https://github.com/magento/inventory/wiki) to get started. Join us in our [Slack](https://magentocommeng.slack.com/archives/C5FU5E2HY) channel ([self signup](https://opensource.magento.com/slack)) to discuss the project. + +See the following documentation: + +- [{{site.data.var.im}} overview]({{ page.baseurl }}/inventory/index.html) for developer documentation +- [Managing Inventory](https://docs.magento.com/m2/ce/user_guide/catalog/inventory-management.html) for merchant information and instructions +- [Install {{site.data.var.im}}]({{site.baseurl}}/extensions/inventory-management/) for module maintenance, updates, and upgrades +- [Upcoming releases]({{site.baseurl}}/release/) for supported and compatible releases + +The release notes include: + +- {:.new}New features +- {:.fix}Fixes and improvements +- {:.bug}Known issues + +### v1.2.4 + +{{site.data.var.im}} 1.2.4 (module version: `magento/inventory-metapackage = 1.2.4`) is supported with version 2.4.4 and compatible with version 2.4.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. + +- {:.fix} {{ site.data.var.ce }} now displays an accurate salable quantity value for all products in the Admin product list view. Previously, {{ site.data.var.ce }} displayed a blank value for salable quantity of in-stock products with SKUs that contained special characters. + +- {:.fix} Performance has improved for cart-and-checkout actions such as adding products to the cart in deployments with many (approximately 10,000) inventory sources. + +- {:.fix} The `bin/magento inventory:reservation:list-inconsistencies` command now handles orders with partial shipments correctly even if the reservations are missed from the database and the cache has been cleared. Previously, when this command was executed with a pre-cleared cache, Magento displayed this error: `Area code is not set`. + +- {:.fix} The `bin/magento inventory:reservation:list-inconsistencies` command no longer returns an undefined index error. + +- {:.fix} Incremental indexing of grouped product child products no longer causes other grouped products to be incorrectly indexed when children are shared. + +- {:.fix} The storefront category page now displays the correct product count after removing a product from a category by API. Previously, the category page product count was incorrect until re-indexing occurred. + +- {:.fix} Configurable products can now be returned to stock when creating a credit memo when the **Manage Stock** option is disabled. Previously, {{ site.data.var.ce }} did not display the **Return to stock** checkbox on the credit memo creation page when this option was disabled. + +- {:.fix} Management of Inventory stock that exceeds 10,000 items has improved. Previously, performance issues sometimes prevented merchants from editing stock in the Admin before launching their website. + +- {:.fix} The Admin **SYSTEM** > **Permissions** > **User Roles** page has been changed to provide administrators with restricted permissions access to delivery methods configuration. The Shipping methods section has been renamed to Delivery methods, and In-Store Pickup has been moved under Delivery methods section. [GitHub-30053](https://github.com/magento/magento2/issues/30053) + +- {:.fix} {{site.data.var.ce}} no longer creates a duplicate product reservation after a credit memo is updated by API. + +- {:.fix} Switching from the Pick in Store tab to the Shipping tab in the checkout workflow no longer triggers a JavaScript error when only In-Store Pickup Delivery is available. + +- {:.fix} Saleable product quantity and in-stock product quantity are now synced correctly. Previously, inventory reservation compensation was not recreated for canceled orders. + +- {:.fix} We’ve optimized the performance of the validator that prevents adding new source to a bundled product’s child product with shipment type `Ship Together`. + +- {:.fix} The `Allocated sources` column is now included as expected in order export CSV files. Previously, this column was omitted. + +- {:.fix} Product stock update through import now takes into account back orders and `Out-of-Stock Threshold` configuration settings when determining product stock status. Product stock status is now automatically set to out-of-stock if the product does not meet the stock requirements. If product stock does meet the threshold, the user-defined stock status `is_in_stock` is used. + +- {:.fix} Shoppers now receive a message when they try to order a product quantity that exceeds the salable quantity. Previously, {{site.data.var.ee}} did not display an error message. + +- {:.fix} Merchants can now successfully save a Company account that contains a custom `company_name` attribute. Previously, {{ site.data.var.ce }} threw an error when you tried to save the Company account. + +- {:.fix} Products no longer go out of stock after being imported with zero (0) quantity when back orders are enabled. + +- {:.fix} Stock status for a configurable product with multiple sources during import no longer changes when child products are assigned to the non-default stock. They are listed as in-stock because the other source has quantity greater than 0. Previously, the configurable product was listed as out of stock. + +### v1.2.3 + +{{site.data.var.im}} 1.2.3 (module version: `magento/inventory-metapackage = 1.2.3`) is supported with version 2.4.3 and compatible with version 2.4.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. + +- {:.fix} Fixed several issues related to the composite product visibility on the frontend. + +- {:.fix} Improved cart page management performance with the minimum required quantity. + +- {:.fix} Several bug fixes targeted to resolve issues with source creation, out of stock items, stock sourcing, sorting allocated sources, in-store delivery, and inventory commands. + +- {:.fix} Magento now supports three-digit Canadian postal codes for in-store delivery. Six-digit codes are not supported due to limitations set by `geonames.org`. + +- {:.fix} The Admin now displays the correct quantity of default stock for disabled products on the **Products** grid and the **Edit Product** page for multi-store deployments. + +- {:.fix} Magento now refreshes the category product cache when a bundle product comes back in stock. + +### v1.2.2 + +{{site.data.var.im}} 1.2.2 (module version: `magento/inventory-metapackage = 1.2.2`) is supported with version 2.4.2 and compatible with version 2.4.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. + +- {:.fix} Fixed several issues related to the composite product visibility on the frontend. + +- {:.fix} Improved cart page performance during quantity update on B2B. + +- {:.fix} Several bug fixes targeted to resolve issues with in-store pickup, mass updates, and inventory threshold. + +- {:.new} **Functional tests.** Introduced new functional tests and provided fixes for existing tests to make them more stable. + +### v1.2.1 + +{{site.data.var.im}} 1.2.1 (module version: `magento/inventory-metapackage = 1.2.1`) is supported with version 2.4.1 and compatible with version 2.4.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. + +- {:.fix} Fixed known issue related to `inventory_cleanup_reservations` cron job, addressed issue related to In-Store Pickup functionality for bundle products, general improvements to stock calculation, bundle product support and backorders functionality. + +- {:.new} **Functional tests.** Introduced new functional tests to provide additional coverage for In-Store Pickup functionality. + +### v1.2.0 + +{{site.data.var.im}} 1.2.0 (module version: `magento/inventory-metapackage = 1.2.0`) is supported with version 2.4.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. + +- {:.fix} Numerous bug fixes to resolve issues with source assignment, scalable environment feature support, and compatibility with PHP 7.4, MySQL 8, and PHPUNIT 9. + +- {:.new} **In-store delivery method.** Added a new option for users to select a source to be used as a pickup location during checkout. See [In-store Delivery]({{ site.user_guide_url }}/shipping/shipping-in-store-delivery.html). + +- {:.new} **Bundle product support for multi source mode.** Inventory supports all product types with multiple sources. + +- {:.new} **Asynchronous stock re-indexing.** Added the ability to asynchronously re-index stock and improved the performance of several critical scenarios. + +- {:.new} **Bulk interfaces.** Introduced new bulk interfaces for salability check: `\Magento\InventorySalesApi\Api\AreProductsSalableInterface`, `\Magento\InventorySalesApi\Api\AreProductsSalableForRequestedQtyInterface`. + +- {:.new} **Increased test coverage.** New functionality covered with automated tests, extended coverage for discovered and fixed issues. + +- {:.bug} **Known issue.** The absence of the `object_id` field in the reservations metadata is preventing the `inventory_cleanup_reservations` cron job from working properly. This issue was introduced in [magento/inventory#3046](https://github.com/magento/inventory/pull/3046). + + **Workaround:** Execute the following MySQL queries to manually cleanup reservations: + + ```sql + SELECT GROUP_CONCAT(reservation_id) FROM inventory_reservation GROUP BY stock_id, sku HAVING SUM(quantity) = 0; + DELETE FROM inventory_reservation where reservation_id IN (result_of_the_first_query); + ``` + +### v1.1.6 + +{{site.data.var.im}} 1.1.6 (module version: `inventory-composer-metapackage = 1.1.6`) is supported with version 2.3.6 and compatible with version 2.3.5, 2.3.4, 2.3.3, 2.3.2, 2.3.1, and 2.3.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. + +- {:.fix} Bug fixes to resolve issues related to backorders, credit memos, low stock report grid, fixes connected to "resolve inconsistencies" CLI tool and general improvements. + +- {:.new} **Asynchronous stock re-indexing.** Added the ability to asynchronously re-index stock and improved the performance of several critical scenarios. + +### v1.1.5 +{{site.data.var.im}} 1.1.5 (module version: `inventory-composer-metapackage = 1.1.5`) is supported with version 2.3.5 and compatible with version 2.3.4, 2.3.3, 2.3.2, 2.3.1, and 2.3.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. + +- {:.new} **Update inventory once product SKU is changed.** Introduced a new configuration setting to switch to the new behavior: "Synchronize with Catalog". + +- {:.new} **Functional tests.** Introduced new functional tests to eliminate the test coverage gap. Fixed several issues to make tests more stable and reliable). + +- {:.bug} Bug fixes to prevent product oversell, "Out of stock" products visibility on the storefront, numerous fixes for scalable environment support and user interface improvements. + +### v1.1.4 + +{{site.data.var.im}} 1.1.4 (module version: `inventory-composer-metapackage = 1.1.4`) is supported with version 2.3.4 and compatible with version 2.3.3, 2.3.2, 2.3.1, and 2.3.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. + +- {:.fix}**Increased performance.** Introduced bunching logic for Inventory Reservations CLI command to reduce memory usage and avoid cases when the process is stuck without any response. + +- {:.new}**Increased test coverage.** Introduced many new Functional tests. Almost all manual Inventory scenarios are covered with automated tests. + +- {:.bug} Numerous bug fixes targeted to resolve issues with credit memos, grouped products, source and stock mass actions. + +### v1.1.3 + +{{site.data.var.im}} 1.1.3 (module version: `inventory-composer-metapackage = 1.1.3`) is supported with version 2.3.3 and compatible with version 2.3.2, 2.3.1, and 2.3.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. + +- {:.fix}**Better integration with {{site.data.var.ee}} and {{site.data.var.b2b}} features.** {{site.data.var.im}} now works correctly with the following features for websites using non-default inventory sources and stocks: + - Order by SKU ({{site.data.var.ee}}) + - Quick order ({{site.data.var.b2b}}) + - Requisition lists ({{site.data.var.b2b}}) + +- {:.new}**Increased performance.** Storefront catalog browsing performance has significantly improved for websites running the default inventory stock and source. + +- {:.new}**Increased test coverage.** The automated Functional and Integration test coverage has increased significantly. + +### v1.1.2 + +{{site.data.var.im}} 1.1.2 (module version: `inventory-composer-metapackage = 1.1.2`) is supported with version 2.3.2 and compatible with version 2.3.1, and 2.3.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. + +- {:.fix} Added `source_code` to the response for the GET `/V1/shipments` REST endpoint. + +- {:.fix} Resolved issue to correctly clear reservations and update product quantities after issuing a credit memo for an unshipped order. When you select the option to + +- {:.fix} Resolved issue to correctly save quantity for configurable product children when entering quantities during product creation. + +New modules for Inventory Management 1.1.2 Beta include: + +```php + 'Magento_InventoryGraphQl' => 1, + 'Magento_InventoryReservations' => 1, + 'Magento_InventoryReservationsApi' => 1, + 'Magento_InventoryReservationCli' => 1, + 'Magento_InventoryExportStock' => 0, + 'Magento_InventoryExportStockApi' => 0, +``` + +- {:.new} **Added a Bulk Partial Stock Transfer Endpoint** - Current bulk transfer endpoints move all assigned quantity from an origin to a destination source. The new `/rest/V1/inventory/bulk-partial-source-transfer` endpoint allows merchants to transfer partial stock from source-to-source as a bulk operation. Enter a request to the endpoint with the `sku`, `qty`, `origin_source_code`, and `destination_source_code` to transfer a specific amount of quantity. Transfers verify the source is assigned to the `sku`, enough quantity exists to transfer, etc. See [Inventory Bulk Actions](https://developer.adobe.com/commerce/webapi/rest/modules/inventory/bulk-inventory.html). + +- {:.new} **Added Reservation CLI** - New commands give you options to detect and resolve reservation inconsistencies. As orders submit and change status, {{site.data.var.im}} generates initial reservations and updates through compensation reservations. These commands return a list of detected inconsistencies by Order ID, SKU, and Stock ID and create reservations to resolve. See [Inventory CLI reference]({{ page.baseurl }}/inventory/inventory-cli-reference.html). + +- {:.new} **Performance improvements for sources and SSA options** - Sorting and selecting sources during shipment caused performance degradation for stocks with high numbers of sources. This release provides significant performance improvements to list and sort available sources when reviewing and selecting SSA options in shipments. + +- {:.new} **Added GraphQL support for {{site.data.var.im}}** - This release installs a new `magento/module-inventory-graph-ql` module. The GraphQL [Products endpoint]({{ page.baseurl }}/graphql/queries/products.html) now includes the `only_x_left_in_stock` and `stock_status` attributes for {{site.data.var.im}} support. + +- {:.new} **Simplified UI for Assigned Sources** - The Assigned Sources table in product pages has simplified content for easier updates and increased performance when displaying many sources. All sources list by source name (hover over for `source_code`). + +- {:.new} **Export Aggregated Stock Service** - This release provides a new export aggregated stock service (retaining reservations in the system) to support external Sales Channels like Amazon, eBay, Google Shopping ads, etc. + +### v1.1.0 + +{{site.data.var.im}} 1.1.0 (module version: `inventory-composer-metapackage = 1.1.0`) is supported and compatible with version 2.3.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. {{site.data.var.im}} 1.1.1 released only as a package name update, supported with version 2.3.1 and compatible with version 2.3.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. + +- {:.fix} **Added support for Elasticsearch for single and multi sources modes** — You can now configure and use Elasticsearch with custom stocks. This resolves a [known issue]({{ page.baseurl }}/release-notes/ReleaseNotes2.3.0OpenSource.html#known-issues) in version 2.3.0 of {{site.data.var.ce}} and {{site.data.var.ee}}. See [Set up the search engine]({{ page.baseurl }}/config-guide/elasticsearch/es-overview.html) for installation information and [Elasticsearch](https://docs.magento.com/m2/ce/user_guide/catalog/search-elasticsearch.html) to configure through the Admin. + +- {:.fix} Resolved performance issues with Default Stock to drastically increase performance with numerous operations. Improvements increase performance for Single Source mode, Transfer Inventory to Source, Storefront Category pages, and Salable Quantity calculations. This resolves a [known issue]({{ page.baseurl }}/release-notes/ReleaseNotes2.3.0OpenSource.html#known-issues) requiring custom stocks creation for Single Source merchants in version 2.3.0 of {{site.data.var.ce}} and {{site.data.var.ee}}. + + + +- {:.fix} Resolved issues with Out of Stock status and bulk Inventory Transfer to Stock for configurable and grouped products. Selecting the parent products and performing bulk actions does not affect the product status. If the parent product was In Stock, it remains In Stock. + + + +- {:.new} **Distance Priority Algorithm** — The Distance Priority Algorithm is a new, out-of-the-box Source Selection Algorithm for distance-based shipping recommendations. This algorithm compares the location of the shipping destination address with source locations to determine the closest source to fulfill shipments. The distance may be determined by either physical distance or the time spent traveling from one location to another, using imported geocode location data or Google directions (driving, walking, or bicycling). See [Configuring Distance Priority Algorithm](https://docs.magento.com/m2/ce/user_guide/catalog/inventory-configure-distance-priority.html) in the _User Guide_. + +- {:.new} **Expanded source quantity list** — Merchants with a high number of sources can easily hover and view all sources per product through the Product Grid. Each product displays a minimum of five sources and matching quantities. When hovering over the sources, you can scroll through the entire list of sources and current quantities. See [Managing Inventory Quantities](https://docs.magento.com/m2/ce/user_guide/catalog/inventory-manage-inventory-quantities.html). + +- {:.bug} Known issue with Magento v2.3.1 - Asynchronous migration of data between sources will encounter issues due to changes in Asynchronous APIs with topic names reflecting PHP class and method names. We recommend using synchronous operations, setting **Run asynchronously** to "No". To configure, see [Configure Global Options](https://docs.magento.com/m2/ee/user_guide/catalog/inventory-options-global.html) in the Magento User Guide. diff --git a/src/guides/v2.4/rest/anonymous-api-security.md b/src/guides/v2.4/rest/anonymous-api-security.md index cd6ebea8632..eeaa477f3ce 100644 --- a/src/guides/v2.4/rest/anonymous-api-security.md +++ b/src/guides/v2.4/rest/anonymous-api-security.md @@ -2,7 +2,6 @@ group: rest-api title: Restricting access to anonymous web APIs migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/anonymous-api-security/ - --- Magento 2 allows some web APIs to be accessed by unauthenticated (anonymous) users. Many of these APIs allow a customer to have a robust shopping experience on the [website](https://glossary.magento.com/website) without having to log in. diff --git a/src/guides/v2.4/rest/asynchronous-web-endpoints.md b/src/guides/v2.4/rest/asynchronous-web-endpoints.md index a7003df75f5..82a850c5917 100644 --- a/src/guides/v2.4/rest/asynchronous-web-endpoints.md +++ b/src/guides/v2.4/rest/asynchronous-web-endpoints.md @@ -1,7 +1,6 @@ --- group: rest-api title: Asynchronous web endpoints - contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ functional_areas: diff --git a/src/guides/v2.4/rest/bulk-endpoints.md b/src/guides/v2.4/rest/bulk-endpoints.md index 2b37ab156c1..92f14550f9d 100644 --- a/src/guides/v2.4/rest/bulk-endpoints.md +++ b/src/guides/v2.4/rest/bulk-endpoints.md @@ -1,7 +1,6 @@ --- group: rest-api title: Bulk endpoints - contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ functional_areas: diff --git a/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md b/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md index 283dbe29d0c..42ed73e897f 100644 --- a/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md +++ b/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md @@ -2,7 +2,6 @@ group: rest-api title: Inventory mass actions migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/bulk-inventory/ - --- Magento provides several endpoints that allow Multi Source merchants to make quick updates across multiple products. This is helpful for transferring inventory between sources and removing a source without editing each product individually. diff --git a/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md b/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md index 60dd9ba5d00..18004a12157 100644 --- a/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md +++ b/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md @@ -2,7 +2,6 @@ group: rest-api title: Link and unlink stocks and sources migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/link-stocks-sources/ - --- In Admin, you can assign (link) sources to a stock when you create the stock. In REST, creating a stock and assigning sources to it are separate steps. diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md index a4074e9241a..eb1caadae94 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Create a configurable product using bulk APIs - menu_title: Initial tasks menu_order: 0 level3_subgroup: bulk-configurable-product-tutorial diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md index 7b09dbf44cb..5cfa070ebf3 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 2. Create the configurable and simple products - subtitle: Create a configurable product using bulk APIs menu_title: Step 2. Create the configurable and simple products menu_order: 20 diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md index 636479ae8dd..33642594c77 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 4. Create the personalization option - subtitle: Create a configurable product using bulk APIs menu_title: Step 4. Create the personalization option menu_order: 40 diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md index 4330c4f595d..0ffe1de378d 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 3. Define configurable product options - subtitle: Create a configurable product using bulk APIs menu_title: Step 3. Define configurable product options menu_order: 30 diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md index 8f398381ec8..eb1132ed0ce 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 1. Plan the product - subtitle: Create a configurable product using bulk APIs menu_title: Step 1. Plan the product menu_order: 10 diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md b/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md index 17edd8a80ad..3cc9150515f 100644 --- a/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md +++ b/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api title: Create a bundle product tutorial migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/ - contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md b/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md index c0631437c14..b4b1907215c 100644 --- a/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md +++ b/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api title: Step 3. Create the bundle product migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/create-bundle-product/ - contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md b/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md index 20d75cf7b4c..e57f8396686 100644 --- a/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md +++ b/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api title: Step 2. Create the simple products migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/create-simple-products/ - contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md b/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md index 9848fd9cdf2..c0ded6836a0 100644 --- a/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md +++ b/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api title: Step 1. Plan the product migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/plan-product/ - contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md b/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md index 7fca3d5c579..970de23b7b2 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api title: Create a configurable product tutorial migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/ - menu_title: Initial tasks menu_order: 0 level3_subgroup: configurable-product-tutorial diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md b/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md index a16a2b6c143..161a553825d 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api title: Step 2. Create the configurable product migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/create-configurable-product/ - subtitle: Create a configurable product tutorial menu_title: Step 2. Create the configurable product menu_order: 20 diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md b/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md index 89ac3821df4..d9aaeb1195f 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api title: Step 5. Create the personalization option migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/create-personalization-option/ - subtitle: Create a configurable product tutorial menu_title: Step 5. Create the personalization option menu_order: 50 diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md b/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md index 585d9a3345c..6bb323d659b 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api title: Step 3. Create the simple products migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/create-simple-products/ - subtitle: Create a configurable product tutorial menu_title: Step 3. Create the simple products menu_order: 30 diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md b/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md index 7654a7c67d9..6096e09f732 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api title: Step 4. Define configurable product options migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/define-config-product-options/ - subtitle: Create a configurable product tutorial menu_title: Step 4. Define configurable product options menu_order: 40 diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md b/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md index 55f3ad7ef8d..65204276051 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api title: Step 1. Plan the product migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/plan-product/ - subtitle: Create a configurable product tutorial menu_title: Step 1. Plan the product menu_order: 10 diff --git a/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md b/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md index 39d3e8f0677..b76596d7edf 100644 --- a/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md +++ b/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md @@ -2,7 +2,6 @@ group: rest-api title: Create and manage grouped products tutorial migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/grouped-product/ - functional_areas: - Integration --- diff --git a/src/guides/v2.4/rest/tutorials/orders/order-add-items.md b/src/guides/v2.4/rest/tutorials/orders/order-add-items.md index 0d77637a74e..44e5998c6ef 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-add-items.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-add-items.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api title: Step 5. Add items to the cart migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-add-items/ - subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md b/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md index c3435c7747f..c5b302547b4 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api title: Step 3. Create a customer migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-customer/ - subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md b/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md index 641a8792ec4..1b1e7dd571f 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api title: Step 8. Create an invoice migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-invoice/ - subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-order.md b/src/guides/v2.4/rest/tutorials/orders/order-create-order.md index 082776399c3..60f946c3e1e 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-order.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-order.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api title: Step 7. Create an order migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-order/ - subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md b/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md index 84da17fe564..479f4d98c71 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api title: Step 4. Create a quote migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-quote/ - subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md b/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md index ccd82048e51..522303eddf1 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api title: Step 9. Create a shipment migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-shipment/ - subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md b/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md index 26d6990efd8..03fe685e813 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md @@ -4,7 +4,6 @@ group: rest-api subgroup: title: Step 6. Prepare for checkout migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-prepare-checkout/ - subtitle: Order Processing tutorial return_to: title: REST tutorials From 09a32613555d6850881223caa863678a02fecce7 Mon Sep 17 00:00:00 2001 From: jhadobe Date: Wed, 29 Jun 2022 17:04:09 -0400 Subject: [PATCH 233/776] Removing blank metadata lines in 2.3, cleaning links --- src/guides/v2.3/b2b/company-object.md | 2 +- src/guides/v2.3/b2b/company-structures.md | 2 +- src/guides/v2.3/b2b/credit-manage.md | 4 ++-- src/guides/v2.3/b2b/shared-cat-manage.md | 2 +- src/guides/v2.3/rest/anonymous-api-security.md | 1 - src/guides/v2.3/rest/asynchronous-web-endpoints.md | 1 - src/guides/v2.3/rest/bulk-endpoints.md | 1 - src/guides/v2.3/rest/modules/catalog-pricing.md | 1 - src/guides/v2.3/rest/modules/catalog.md | 1 - src/guides/v2.3/rest/modules/inventory/bulk-inventory.md | 1 - src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md | 2 -- src/guides/v2.3/rest/modules/inventory/manage-low-quantity.md | 1 - src/guides/v2.3/rest/modules/inventory/manage-source-items.md | 1 - .../v2.3/rest/modules/inventory/manage-source-selection.md | 1 - src/guides/v2.3/rest/modules/inventory/manage-stocks.md | 1 - src/guides/v2.3/rest/modules/sales/refunds.md | 1 - src/guides/v2.3/rest/notes.md | 1 - src/guides/v2.3/rest/operation-status-endpoints.md | 1 - src/guides/v2.3/rest/operation-status-search.md | 1 - src/guides/v2.3/rest/performing-searches.md | 1 - src/guides/v2.3/rest/retrieve-filtered-responses.md | 1 - src/guides/v2.3/rest/search-endpoint.md | 1 - .../bulk-configurable-product/config-product-intro.md | 1 - .../create-configurable-simple-products.md | 1 - .../create-personalization-option.md | 1 - .../define-config-product-options.md | 1 - .../rest/tutorials/bulk-configurable-product/plan-product.md | 1 - .../rest/tutorials/bundle-product/bundle-product-intro.md | 1 - .../rest/tutorials/bundle-product/create-bundle-product.md | 1 - .../rest/tutorials/bundle-product/create-simple-products.md | 1 - src/guides/v2.3/rest/tutorials/bundle-product/plan-product.md | 1 - .../tutorials/configurable-product/config-product-intro.md | 1 - .../configurable-product/create-configurable-product.md | 1 - .../configurable-product/create-personalization-option.md | 1 - .../tutorials/configurable-product/create-simple-products.md | 1 - .../configurable-product/define-config-product-options.md | 1 - .../v2.3/rest/tutorials/configurable-product/plan-product.md | 1 - .../grouped-product/create-and-manage-grouped-products.md | 1 - src/guides/v2.3/rest/tutorials/orders/order-add-items.md | 1 - .../v2.3/rest/tutorials/orders/order-create-customer.md | 1 - src/guides/v2.3/rest/tutorials/orders/order-create-invoice.md | 1 - src/guides/v2.3/rest/tutorials/orders/order-create-order.md | 1 - src/guides/v2.3/rest/tutorials/orders/order-create-quote.md | 1 - .../v2.3/rest/tutorials/orders/order-create-shipment.md | 1 - .../v2.3/rest/tutorials/orders/order-prepare-checkout.md | 1 - 45 files changed, 5 insertions(+), 47 deletions(-) diff --git a/src/guides/v2.3/b2b/company-object.md b/src/guides/v2.3/b2b/company-object.md index 42bfd38bd99..ac8c7389f1d 100644 --- a/src/guides/v2.3/b2b/company-object.md +++ b/src/guides/v2.3/b2b/company-object.md @@ -242,7 +242,7 @@ None The following call returns all companies that are located in California (`region_id` = `12`) -See [Search using REST APIs]({{ page.baseurl }}/rest/use-rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/b2b/company-structures.md b/src/guides/v2.3/b2b/company-structures.md index 6d8b582d1c9..99c7bfb6fe2 100644 --- a/src/guides/v2.3/b2b/company-structures.md +++ b/src/guides/v2.3/b2b/company-structures.md @@ -123,7 +123,7 @@ An empty array The following query returns information about all teams (`team_id` ≥ `0`) -See [Search using REST APIs]({{ page.baseurl }}/rest/use-rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/b2b/credit-manage.md b/src/guides/v2.3/b2b/credit-manage.md index 4328e9e70db..8af2bbc11c2 100644 --- a/src/guides/v2.3/b2b/credit-manage.md +++ b/src/guides/v2.3/b2b/credit-manage.md @@ -144,7 +144,7 @@ Not applicable The following call returns information for all companies whose credit balance is 0. -See [Search using REST APIs]({{ page.baseurl }}/rest/use-rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** @@ -326,7 +326,7 @@ This call updates the credit history to specify a purchase order number. The following call returns a list instances in which the credit limit was set to a value higher than $500. -See [Search using REST APIs]({{ page.baseurl }}/rest/use-rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/b2b/shared-cat-manage.md b/src/guides/v2.3/b2b/shared-cat-manage.md index 920f3fe012e..0c72f1a1011 100644 --- a/src/guides/v2.3/b2b/shared-cat-manage.md +++ b/src/guides/v2.3/b2b/shared-cat-manage.md @@ -137,7 +137,7 @@ Not applicable The following search returns all the custom shared catalogs (`type = 0`) in the system. -See [Search using REST APIs]({{ page.baseurl }}/rest/use-rest/performing-searches.html) for information about constructing a search query. +See [Search using REST APIs]({{ page.baseurl }}/rest/performing-searches.html) for information about constructing a search query. **Sample Usage:** diff --git a/src/guides/v2.3/rest/anonymous-api-security.md b/src/guides/v2.3/rest/anonymous-api-security.md index 970ce3a2541..8e4c2f2df2b 100644 --- a/src/guides/v2.3/rest/anonymous-api-security.md +++ b/src/guides/v2.3/rest/anonymous-api-security.md @@ -1,7 +1,6 @@ --- group: rest-api title: Restricting access to anonymous web APIs - --- Magento 2 allows some web APIs to be accessed by unauthenticated (anonymous) users. Many of these APIs allow a customer to have a robust shopping experience on the [website](https://glossary.magento.com/website) without having to log in. diff --git a/src/guides/v2.3/rest/asynchronous-web-endpoints.md b/src/guides/v2.3/rest/asynchronous-web-endpoints.md index 74c0ba85d3f..048263770c8 100644 --- a/src/guides/v2.3/rest/asynchronous-web-endpoints.md +++ b/src/guides/v2.3/rest/asynchronous-web-endpoints.md @@ -1,7 +1,6 @@ --- group: rest-api title: Asynchronous web endpoints - contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ functional_areas: diff --git a/src/guides/v2.3/rest/bulk-endpoints.md b/src/guides/v2.3/rest/bulk-endpoints.md index a3cb54768f9..bc0194ca324 100644 --- a/src/guides/v2.3/rest/bulk-endpoints.md +++ b/src/guides/v2.3/rest/bulk-endpoints.md @@ -1,7 +1,6 @@ --- group: rest-api title: Bulk endpoints - contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ functional_areas: diff --git a/src/guides/v2.3/rest/modules/catalog-pricing.md b/src/guides/v2.3/rest/modules/catalog-pricing.md index 876f2047b99..f1e125f69b1 100644 --- a/src/guides/v2.3/rest/modules/catalog-pricing.md +++ b/src/guides/v2.3/rest/modules/catalog-pricing.md @@ -1,7 +1,6 @@ --- group: rest-api title: Manage prices for multiple products - functional_areas: - Integration --- diff --git a/src/guides/v2.3/rest/modules/catalog.md b/src/guides/v2.3/rest/modules/catalog.md index 0835da832c7..da62103b7c5 100644 --- a/src/guides/v2.3/rest/modules/catalog.md +++ b/src/guides/v2.3/rest/modules/catalog.md @@ -1,7 +1,6 @@ --- group: rest-api title: Catalog module - functional_areas: - Integration - Catalog diff --git a/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md b/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md index ee4e46fa238..02a97b71c0a 100644 --- a/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md +++ b/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md @@ -1,7 +1,6 @@ --- group: rest-api title: Inventory mass actions - --- Magento provides several endpoints that allow Multi Source merchants to make quick updates across multiple products. This is helpful for transferring inventory between sources and removing a source without editing each product individually. diff --git a/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md b/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md index 6bb9917189e..f98174aabda 100644 --- a/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md +++ b/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md @@ -1,8 +1,6 @@ --- group: rest-api title: Link and unlink stocks and sources - - --- In Admin, you can assign (link) sources to a stock when you create the stock. In REST, creating a stock and assigning sources to it are separate steps. diff --git a/src/guides/v2.3/rest/modules/inventory/manage-low-quantity.md b/src/guides/v2.3/rest/modules/inventory/manage-low-quantity.md index 582c561fea2..a6f8b4d56b2 100644 --- a/src/guides/v2.3/rest/modules/inventory/manage-low-quantity.md +++ b/src/guides/v2.3/rest/modules/inventory/manage-low-quantity.md @@ -1,7 +1,6 @@ --- group: rest-api title: Manage low-quantity notifications - --- Low stock notification alert the merchant that the salable quantity of a stock has reached a critical threshold. The Admin allows the merchant to configure low-quantity notifications from several locations: diff --git a/src/guides/v2.3/rest/modules/inventory/manage-source-items.md b/src/guides/v2.3/rest/modules/inventory/manage-source-items.md index a0fc57b33eb..b22ea5b4c22 100644 --- a/src/guides/v2.3/rest/modules/inventory/manage-source-items.md +++ b/src/guides/v2.3/rest/modules/inventory/manage-source-items.md @@ -1,7 +1,6 @@ --- group: rest-api title: Manage source items - --- If Magento is configured to manage inventory, when you upgrade to version 2.3, Magento assigns all existing products to the default source. Currently, Magento also assigns newly-created products to the default source. Single Source merchants do not need to manage source items, but Multi Source merchants may need to move products from the default source to a custom source, or move products from one custom source to another. diff --git a/src/guides/v2.3/rest/modules/inventory/manage-source-selection.md b/src/guides/v2.3/rest/modules/inventory/manage-source-selection.md index 001e6e00819..69932af7f02 100644 --- a/src/guides/v2.3/rest/modules/inventory/manage-source-selection.md +++ b/src/guides/v2.3/rest/modules/inventory/manage-source-selection.md @@ -1,7 +1,6 @@ --- group: rest-api title: Manage source selection algorithms - --- Inventory Management uses the Source Selection Algorithm (SSA) to track the salable quantities of product inventory across all sources and make recommendations for partial and full shipments. diff --git a/src/guides/v2.3/rest/modules/inventory/manage-stocks.md b/src/guides/v2.3/rest/modules/inventory/manage-stocks.md index 41bb349378b..64f659bae8e 100644 --- a/src/guides/v2.3/rest/modules/inventory/manage-stocks.md +++ b/src/guides/v2.3/rest/modules/inventory/manage-stocks.md @@ -1,7 +1,6 @@ --- group: rest-api title: Manage stocks - --- Stocks map your sources to sales channels, providing a direct link to salable quantities and inventories. diff --git a/src/guides/v2.3/rest/modules/sales/refunds.md b/src/guides/v2.3/rest/modules/sales/refunds.md index 44ee0d81952..bc7cd67f522 100644 --- a/src/guides/v2.3/rest/modules/sales/refunds.md +++ b/src/guides/v2.3/rest/modules/sales/refunds.md @@ -1,7 +1,6 @@ --- group: rest-api title: Refunds - functional_areas: - Integration - Catalog diff --git a/src/guides/v2.3/rest/notes.md b/src/guides/v2.3/rest/notes.md index c21e4a9581c..c324e11d9f3 100644 --- a/src/guides/v2.3/rest/notes.md +++ b/src/guides/v2.3/rest/notes.md @@ -1,7 +1,6 @@ --- group: rest-api title: REST usage notes - functional_areas: - Integration --- diff --git a/src/guides/v2.3/rest/operation-status-endpoints.md b/src/guides/v2.3/rest/operation-status-endpoints.md index 5243f85688b..b9f7a54de90 100644 --- a/src/guides/v2.3/rest/operation-status-endpoints.md +++ b/src/guides/v2.3/rest/operation-status-endpoints.md @@ -1,7 +1,6 @@ --- group: rest-api title: Bulk operation status endpoints - contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com/ functional_areas: diff --git a/src/guides/v2.3/rest/operation-status-search.md b/src/guides/v2.3/rest/operation-status-search.md index b93877d0954..63241cbcb47 100644 --- a/src/guides/v2.3/rest/operation-status-search.md +++ b/src/guides/v2.3/rest/operation-status-search.md @@ -1,7 +1,6 @@ --- group: rest-api title: Search for the status of a bulk operation - contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com functional_areas: diff --git a/src/guides/v2.3/rest/performing-searches.md b/src/guides/v2.3/rest/performing-searches.md index b8ef346f6dc..edc38fdc694 100644 --- a/src/guides/v2.3/rest/performing-searches.md +++ b/src/guides/v2.3/rest/performing-searches.md @@ -1,7 +1,6 @@ --- group: rest-api title: Search using REST endpoints - --- POST, PUT, and DELETE requests to the REST Web [API](https://glossary.magento.com/api) require the service method parameters to be in the body of the request. For example, to create a Customer, you would specify a JSON array (or [XML](https://glossary.magento.com/xml) structure) in the body of the message. diff --git a/src/guides/v2.3/rest/retrieve-filtered-responses.md b/src/guides/v2.3/rest/retrieve-filtered-responses.md index 20302f4732a..87325dfbd4b 100644 --- a/src/guides/v2.3/rest/retrieve-filtered-responses.md +++ b/src/guides/v2.3/rest/retrieve-filtered-responses.md @@ -1,7 +1,6 @@ --- group: rest-api title: Retrieve filtered responses for REST endpoints - --- Some REST calls return dozens or even hundreds of parameters, and parsing through all this data can be unwieldy. In addition, mobile app developers might find the bandwidth needed to process a request to be excessive. To resolve these problems, Magento provides a query parameter-based syntax for REST requests that return partial responses. diff --git a/src/guides/v2.3/rest/search-endpoint.md b/src/guides/v2.3/rest/search-endpoint.md index 18f295dfbd4..051c8719e4f 100644 --- a/src/guides/v2.3/rest/search-endpoint.md +++ b/src/guides/v2.3/rest/search-endpoint.md @@ -1,7 +1,6 @@ --- group: rest-api title: Search for products with the /search endpoint - contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com/ --- diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md index 98f9a85d8cd..b3fd0aa24f0 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Create a configurable product using bulk APIs - menu_title: Initial tasks menu_order: 0 level3_subgroup: bulk-configurable-product-tutorial diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md index 1d59edfbac3..5c8e627d5e7 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 2. Create the configurable and simple products - subtitle: Create a configurable product using bulk APIs menu_title: Step 2. Create the configurable and simple products menu_order: 20 diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md index 62f2ea24e9b..5a5b2a2c1b4 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 4. Create the personalization option - subtitle: Create a configurable product using bulk APIs menu_title: Step 4. Create the personalization option menu_order: 40 diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md index d592653fce5..b0a16c57244 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/define-config-product-options.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 3. Define configurable product options - subtitle: Create a configurable product using bulk APIs menu_title: Step 3. Define configurable product options menu_order: 30 diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/plan-product.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/plan-product.md index 14ddbd0d58f..5eef0a030fc 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/plan-product.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/plan-product.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 1. Plan the product - subtitle: Create a configurable product using bulk APIs menu_title: Step 1. Plan the product menu_order: 10 diff --git a/src/guides/v2.3/rest/tutorials/bundle-product/bundle-product-intro.md b/src/guides/v2.3/rest/tutorials/bundle-product/bundle-product-intro.md index 2645b7ccba3..49f48c491b1 100644 --- a/src/guides/v2.3/rest/tutorials/bundle-product/bundle-product-intro.md +++ b/src/guides/v2.3/rest/tutorials/bundle-product/bundle-product-intro.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Create a bundle product tutorial - contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.3/rest/tutorials/bundle-product/create-bundle-product.md b/src/guides/v2.3/rest/tutorials/bundle-product/create-bundle-product.md index 382f1abb670..60508e3cc9f 100644 --- a/src/guides/v2.3/rest/tutorials/bundle-product/create-bundle-product.md +++ b/src/guides/v2.3/rest/tutorials/bundle-product/create-bundle-product.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 3. Create the bundle product - contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.3/rest/tutorials/bundle-product/create-simple-products.md b/src/guides/v2.3/rest/tutorials/bundle-product/create-simple-products.md index b1d90a0849d..1a7b9f570ed 100644 --- a/src/guides/v2.3/rest/tutorials/bundle-product/create-simple-products.md +++ b/src/guides/v2.3/rest/tutorials/bundle-product/create-simple-products.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 2. Create the simple products - contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.3/rest/tutorials/bundle-product/plan-product.md b/src/guides/v2.3/rest/tutorials/bundle-product/plan-product.md index acd185007c9..140f21cc671 100644 --- a/src/guides/v2.3/rest/tutorials/bundle-product/plan-product.md +++ b/src/guides/v2.3/rest/tutorials/bundle-product/plan-product.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 1. Plan the product - contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md b/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md index ea05bbc4b59..63c378f8930 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Create a configurable product tutorial - menu_title: Initial tasks menu_order: 0 level3_subgroup: configurable-product-tutorial diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/create-configurable-product.md b/src/guides/v2.3/rest/tutorials/configurable-product/create-configurable-product.md index 7dff2fcada2..c4de68d6be5 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/create-configurable-product.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/create-configurable-product.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 2. Create the configurable product - subtitle: Create a configurable product tutorial menu_title: Step 2. Create the configurable product menu_order: 20 diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md b/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md index 7161e353d72..949ea55ddab 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 5. Create the personalization option - subtitle: Create a configurable product tutorial menu_title: Step 5. Create the personalization option menu_order: 50 diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/create-simple-products.md b/src/guides/v2.3/rest/tutorials/configurable-product/create-simple-products.md index 2047d31972f..7438ac46489 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/create-simple-products.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/create-simple-products.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 3. Create the simple products - subtitle: Create a configurable product tutorial menu_title: Step 3. Create the simple products menu_order: 30 diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/define-config-product-options.md b/src/guides/v2.3/rest/tutorials/configurable-product/define-config-product-options.md index cef6468e095..94eb8d22324 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/define-config-product-options.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/define-config-product-options.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 4. Define configurable product options - subtitle: Create a configurable product tutorial menu_title: Step 4. Define configurable product options menu_order: 40 diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/plan-product.md b/src/guides/v2.3/rest/tutorials/configurable-product/plan-product.md index b978d0d21e3..d6cd8912193 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/plan-product.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/plan-product.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 1. Plan the product - subtitle: Create a configurable product tutorial menu_title: Step 1. Plan the product menu_order: 10 diff --git a/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md b/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md index b19930230ce..535f971decf 100644 --- a/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md +++ b/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md @@ -1,7 +1,6 @@ --- group: rest-api title: Create and manage grouped products tutorial - functional_areas: - Integration --- diff --git a/src/guides/v2.3/rest/tutorials/orders/order-add-items.md b/src/guides/v2.3/rest/tutorials/orders/order-add-items.md index d23ac7267c7..d83e091c944 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-add-items.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-add-items.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 5. Add items to the cart - subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-create-customer.md b/src/guides/v2.3/rest/tutorials/orders/order-create-customer.md index 68d02a66f8a..faa64e1c0af 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-create-customer.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-create-customer.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 3. Create a customer - subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-create-invoice.md b/src/guides/v2.3/rest/tutorials/orders/order-create-invoice.md index a686f5ebe83..1e3f480a65d 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-create-invoice.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-create-invoice.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 8. Create an invoice - subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-create-order.md b/src/guides/v2.3/rest/tutorials/orders/order-create-order.md index 069aa167524..8e647b2f576 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-create-order.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-create-order.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 7. Create an order - subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-create-quote.md b/src/guides/v2.3/rest/tutorials/orders/order-create-quote.md index fc397b4d38c..e74079e53b4 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-create-quote.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-create-quote.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 4. Create a quote - subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-create-shipment.md b/src/guides/v2.3/rest/tutorials/orders/order-create-shipment.md index 66e28902fc4..babdcc78778 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-create-shipment.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-create-shipment.md @@ -2,7 +2,6 @@ layout: tutorial group: rest-api title: Step 9. Create a shipment - subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.3/rest/tutorials/orders/order-prepare-checkout.md b/src/guides/v2.3/rest/tutorials/orders/order-prepare-checkout.md index a48253a582c..74a9580d712 100644 --- a/src/guides/v2.3/rest/tutorials/orders/order-prepare-checkout.md +++ b/src/guides/v2.3/rest/tutorials/orders/order-prepare-checkout.md @@ -3,7 +3,6 @@ layout: tutorial group: rest-api subgroup: title: Step 6. Prepare for checkout - subtitle: Order Processing tutorial return_to: title: REST tutorials From 076d869c6d0f2cc4dc7862fed115e7c5c998a9ba Mon Sep 17 00:00:00 2001 From: jhadobe Date: Wed, 29 Jun 2022 17:16:37 -0400 Subject: [PATCH 234/776] Reverting changes to 2.3 --- src/guides/v2.3/graphql/tutorials/checkout/index.md | 2 +- src/guides/v2.3/rest/asynchronous-web-endpoints.md | 2 +- .../bulk-configurable-product/config-product-intro.md | 2 +- .../create-personalization-option.md | 2 +- .../tutorials/configurable-product/config-product-intro.md | 2 +- .../configurable-product/create-personalization-option.md | 2 +- .../grouped-product/create-and-manage-grouped-products.md | 4 ++-- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/guides/v2.3/graphql/tutorials/checkout/index.md b/src/guides/v2.3/graphql/tutorials/checkout/index.md index 8319d86d598..8556e41646c 100644 --- a/src/guides/v2.3/graphql/tutorials/checkout/index.md +++ b/src/guides/v2.3/graphql/tutorials/checkout/index.md @@ -40,6 +40,6 @@ Complete the following prerequisites: ### Other resources -- [Order processing tutorial]({{ page.baseurl }}/rest/tutorials/orders/) shows a system integrator how REST APIs are used in the lifecycle of an order, including configuring a store and creating a customer; creating quotes, orders, invoices, and shipments; preparing for checkout; and more order-related tasks. +- [Order processing tutorial]({{ page.baseurl }}/rest/tutorials/orders/order-intro.html) shows a system integrator how REST APIs are used in the lifecycle of an order, including configuring a store and creating a customer; creating quotes, orders, invoices, and shipments; preparing for checkout; and more order-related tasks. - [REST Tutorials]({{ page.baseurl }}/rest/tutorials/index.html) provides additional information about completing any Magento REST tutorial. diff --git a/src/guides/v2.3/rest/asynchronous-web-endpoints.md b/src/guides/v2.3/rest/asynchronous-web-endpoints.md index 048263770c8..610be0f311d 100644 --- a/src/guides/v2.3/rest/asynchronous-web-endpoints.md +++ b/src/guides/v2.3/rest/asynchronous-web-endpoints.md @@ -31,7 +31,7 @@ PUT /async/V1/products/:sku {{site.data.var.ce}} and {{site.data.var.ee}} installations support asynchronous web endpoints. -The [REST API documentation]({{ page.baseurl }}/rest/) provides a list of all current synchronous Magento API routes. +The [REST API documentation]({{ page.baseurl }}/rest/bk-rest.html) provides a list of all current synchronous Magento API routes. The response of an asynchronous request contains the following fields: diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md index b3fd0aa24f0..0895efec3ae 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/config-product-intro.md @@ -26,7 +26,7 @@ A system integrator can use Magento REST bulk APIs to perform actions on a large * Install a Magento 2.3 (or later) instance with sample data. The sample data defines a functional store, called Luma, that sells fitness clothing and accessories. * Install a REST client. You can use any REST client to send calls to Magento. [Postman](https://www.getpostman.com/) is recommended. -* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token]({{ page.baseurl }}/rest/tutorials/prerequisite-tasks/) for more information. +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token]({{ page.baseurl }}/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. * Use the `bin/magento queue:consumers:start async.operations.all` command to enable bulk endpoint processing. ### Other resources diff --git a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md index 5a5b2a2c1b4..5f0d4e6cae2 100644 --- a/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md +++ b/src/guides/v2.3/rest/tutorials/bulk-configurable-product/create-personalization-option.md @@ -76,4 +76,4 @@ The `product_sku` is the `sku` of the configurable product. The `sku` specified {:.ref-header} Related topic -[Order Processing with REST APIs Tutorial]({{ page.baseurl }}/rest/tutorials/orders/) +[Order Processing with REST APIs Tutorial]({{ page.baseurl }}/rest/tutorials/orders/order-intro.html) diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md b/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md index 63c378f8930..0a357acf0cb 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/config-product-intro.md @@ -26,7 +26,7 @@ This **5-step tutorial** generally takes **45 minutes**. * [Install and configure RabbitMQ]({{ page.baseurl }}/install-gde/prereq/install-rabbitmq.html), which is the default message broker for bulk API endpoints. -* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token]({{ page.baseurl }}/rest/tutorials/prerequisite-tasks/) for more information. +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token]({{ page.baseurl }}/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. ### Other resources diff --git a/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md b/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md index 949ea55ddab..512c6ec6a5c 100644 --- a/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md +++ b/src/guides/v2.3/rest/tutorials/configurable-product/create-personalization-option.md @@ -75,4 +75,4 @@ The `product_sku` is the `sku` of the configurable product. The `sku` specified {:.ref-header} Related topic -[Order Processing with REST APIs Tutorial]({{ page.baseurl }}/rest/tutorials/orders/) +[Order Processing with REST APIs Tutorial]({{ page.baseurl }}/rest/tutorials/orders/order-intro.html) diff --git a/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md b/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md index 535f971decf..6ae331597db 100644 --- a/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md +++ b/src/guides/v2.3/rest/tutorials/grouped-product/create-and-manage-grouped-products.md @@ -15,7 +15,7 @@ This tutorial describes how you can use the Magento REST API to create and manag * Install a REST client. You can use any REST client to send calls to Magento. [Postman](https://www.getpostman.com/) is recommended. -* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token]({{ page.baseurl }}/rest/tutorials/prerequisite-tasks/) for more information. +* Obtain an admin authorization token. All calls in this tutorial require administrator privileges. See [Generate the admin token]({{ page.baseurl }}/rest/tutorials/prerequisite-tasks/create-admin-token.html) for more information. ### Other resources @@ -216,7 +216,7 @@ You also can use the `DELETE` endpoint to delete a simple product from the group Customers can now add this grouped products to their carts, as shown below. -Refer to the [Order processing tutorial]({{ page.baseurl }}/rest/tutorials/orders/) for more information about how to add items to a cart with REST. +Refer to the [Order processing tutorial]({{ page.baseurl }}/rest/tutorials/orders/order-intro.html) for more information about how to add items to a cart with REST. ### Endpoint From cbc0deca2af521b3fb455cbf2d7793f59dc26aae Mon Sep 17 00:00:00 2001 From: jhadobe Date: Wed, 29 Jun 2022 17:17:48 -0400 Subject: [PATCH 235/776] Adding 2.3 reversions --- src/guides/v2.3/b2b/shared-catalog.md | 2 +- src/guides/v2.3/rest/modules/inventory/bulk-inventory.md | 2 +- src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md | 2 +- src/guides/v2.3/rest/search-endpoint.md | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/guides/v2.3/b2b/shared-catalog.md b/src/guides/v2.3/b2b/shared-catalog.md index 9a7027f91ba..b1bb0e282e0 100644 --- a/src/guides/v2.3/b2b/shared-catalog.md +++ b/src/guides/v2.3/b2b/shared-catalog.md @@ -26,4 +26,4 @@ Custom shared catalogs can be assigned to companies only. They cannot be set for * [Manage shared catalogs]({{ page.baseurl }}/b2b/shared-cat-manage.html) * [Assign categories and products]({{ page.baseurl }}/b2b/shared-cat-product-assign.html) * [Assign companies]({{ page.baseurl }}/b2b/shared-cat-company.html) -* [Manage prices for multiple products]({{ page.baseurl }}/rest/modules/catalog/catalog-pricing) +* [Manage prices for multiple products]({{ page.baseurl }}/rest/modules/catalog-pricing) diff --git a/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md b/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md index 02a97b71c0a..e87eb9b3493 100644 --- a/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md +++ b/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md @@ -111,7 +111,7 @@ An empty array Use the `POST /V1/inventory/bulk-product-source-assign` endpoint to add one or more sources to your products. This endpoint helps when creating and assigning custom sources to your default or custom stocks and preparing new locations and inventory. -After adding new custom sources, you can add inventory quantities per product or for multiple products using the `POST V1/inventory/source-items` endpoint. [Assign products to a source]({{ page.baseurl }}/rest/modules/inventory/manage-source-items) describes this endpoint. +After adding new custom sources, you can add inventory quantities per product or for multiple products using the `POST V1/inventory/source-items` endpoint. [Assign products to a source]({{ page.baseurl }}/rest/modules/inventory/#assign) describes this endpoint. The sources are added to the products with an inventory quantity of 0. You can add inventory amounts as available per source. diff --git a/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md b/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md index f98174aabda..a0aa7e6dcc2 100644 --- a/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md +++ b/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md @@ -145,7 +145,7 @@ None ## Get sources assigned to a stock -The `GET /V1/inventory/get-sources-assigned-to-stock-ordered-by-priority/:stock_id` endpoint returns details about each source that is assigned to the specified stock. [Manage sources]({{ page.baseurl }}/rest/modules/inventory/) provides definitions for each attribute returned. +The `GET /V1/inventory/get-sources-assigned-to-stock-ordered-by-priority/:stock_id` endpoint returns details about each source that is assigned to the specified stock. [Manage sources]({{ page.baseurl }}/rest/modules/inventory/manage-sources.html) provides definitions for each attribute returned. **Sample Usage:** diff --git a/src/guides/v2.3/rest/search-endpoint.md b/src/guides/v2.3/rest/search-endpoint.md index 051c8719e4f..a478d79ce4c 100644 --- a/src/guides/v2.3/rest/search-endpoint.md +++ b/src/guides/v2.3/rest/search-endpoint.md @@ -90,7 +90,7 @@ The default filters for advanced searches can use the following [field] value: The filter can also be any searchable attribute. To make an attribute searchable, set **Stores** > Attributes > **Product** > > **Storefront Properties** > **Use in Search** to **Yes**. The search query can include attributes such as the product name, SKU, or any other custom attribute. -Advanced searches can use any condition type to make comparisions, such as `like`, `eq`, or `finset`. See [Search using REST]({{ page.baseurl }}/rest/performing-searches.html) describes condition types. +Advanced searches can use any condition type to make comparisions, such as `like`, `eq`, or `finset`. See [Search using REST]({{page.baseurl}}/rest/performing-searches.html) describes condition types. Advanced searches do not return aggregation data. @@ -139,4 +139,4 @@ searchCriteria[filter_groups][0][filters][0][condition_type]=eq ## Build queries for V1/products -[Search using REST]({{ page.baseurl }}/rest/performing-searches.html) provides examples that can be used to search for products. +[Search using REST]({{page.baseurl}}/rest/performing-searches.html) provides examples that can be used to search for products. From 1602109d9221c1a5765c192e5b48f7ec9667d121 Mon Sep 17 00:00:00 2001 From: jhadobe Date: Wed, 29 Jun 2022 17:22:53 -0400 Subject: [PATCH 236/776] Reversions --- src/guides/v2.3/b2b/shared-catalog.md | 2 +- src/guides/v2.3/rest/asynchronous-web-endpoints.md | 2 +- src/guides/v2.3/rest/modules/inventory/bulk-inventory.md | 2 +- src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md | 1 + src/guides/v2.3/rest/modules/inventory/manage-sources.md | 1 + 5 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/guides/v2.3/b2b/shared-catalog.md b/src/guides/v2.3/b2b/shared-catalog.md index b1bb0e282e0..c18d542fa7a 100644 --- a/src/guides/v2.3/b2b/shared-catalog.md +++ b/src/guides/v2.3/b2b/shared-catalog.md @@ -26,4 +26,4 @@ Custom shared catalogs can be assigned to companies only. They cannot be set for * [Manage shared catalogs]({{ page.baseurl }}/b2b/shared-cat-manage.html) * [Assign categories and products]({{ page.baseurl }}/b2b/shared-cat-product-assign.html) * [Assign companies]({{ page.baseurl }}/b2b/shared-cat-company.html) -* [Manage prices for multiple products]({{ page.baseurl }}/rest/modules/catalog-pricing) +* [Manage prices for multiple products]({{ page.baseurl }}/rest/modules/catalog-pricing.html) diff --git a/src/guides/v2.3/rest/asynchronous-web-endpoints.md b/src/guides/v2.3/rest/asynchronous-web-endpoints.md index 610be0f311d..bff4533f8fe 100644 --- a/src/guides/v2.3/rest/asynchronous-web-endpoints.md +++ b/src/guides/v2.3/rest/asynchronous-web-endpoints.md @@ -31,7 +31,7 @@ PUT /async/V1/products/:sku {{site.data.var.ce}} and {{site.data.var.ee}} installations support asynchronous web endpoints. -The [REST API documentation]({{ page.baseurl }}/rest/bk-rest.html) provides a list of all current synchronous Magento API routes. +The [REST API documentation]({{page.baseurl}}/rest/bk-rest.html) provides a list of all current synchronous Magento API routes. The response of an asynchronous request contains the following fields: diff --git a/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md b/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md index e87eb9b3493..e5ca4b58c0d 100644 --- a/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md +++ b/src/guides/v2.3/rest/modules/inventory/bulk-inventory.md @@ -111,7 +111,7 @@ An empty array Use the `POST /V1/inventory/bulk-product-source-assign` endpoint to add one or more sources to your products. This endpoint helps when creating and assigning custom sources to your default or custom stocks and preparing new locations and inventory. -After adding new custom sources, you can add inventory quantities per product or for multiple products using the `POST V1/inventory/source-items` endpoint. [Assign products to a source]({{ page.baseurl }}/rest/modules/inventory/#assign) describes this endpoint. +After adding new custom sources, you can add inventory quantities per product or for multiple products using the `POST V1/inventory/source-items` endpoint. [Assign products to a source]({{ page.baseurl }}/rest/modules/inventory/manage-source-items.html#assign) describes this endpoint. The sources are added to the products with an inventory quantity of 0. You can add inventory amounts as available per source. diff --git a/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md b/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md index a0aa7e6dcc2..136040f8fab 100644 --- a/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md +++ b/src/guides/v2.3/rest/modules/inventory/link-stocks-sources.md @@ -1,6 +1,7 @@ --- group: rest-api title: Link and unlink stocks and sources + --- In Admin, you can assign (link) sources to a stock when you create the stock. In REST, creating a stock and assigning sources to it are separate steps. diff --git a/src/guides/v2.3/rest/modules/inventory/manage-sources.md b/src/guides/v2.3/rest/modules/inventory/manage-sources.md index 28f30130c66..40de2ef4c85 100644 --- a/src/guides/v2.3/rest/modules/inventory/manage-sources.md +++ b/src/guides/v2.3/rest/modules/inventory/manage-sources.md @@ -1,6 +1,7 @@ --- group: rest-api title: Manage sources + --- Sources represent locations storing and shipping available product stock. Any location with available stock and capable of order fulfillment can be added as a source. These locations can include warehouses, brick-and-mortar stores, distribution centers, and drop shippers. From 0ffcf753f172876484e65d3f0ba9a41e76519a46 Mon Sep 17 00:00:00 2001 From: jhadobe Date: Wed, 29 Jun 2022 17:23:56 -0400 Subject: [PATCH 237/776] Reversions --- src/guides/v2.3/rest/modules/inventory/manage-source-items.md | 1 + src/guides/v2.3/rest/modules/inventory/manage-sources.md | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.3/rest/modules/inventory/manage-source-items.md b/src/guides/v2.3/rest/modules/inventory/manage-source-items.md index b22ea5b4c22..a0fc57b33eb 100644 --- a/src/guides/v2.3/rest/modules/inventory/manage-source-items.md +++ b/src/guides/v2.3/rest/modules/inventory/manage-source-items.md @@ -1,6 +1,7 @@ --- group: rest-api title: Manage source items + --- If Magento is configured to manage inventory, when you upgrade to version 2.3, Magento assigns all existing products to the default source. Currently, Magento also assigns newly-created products to the default source. Single Source merchants do not need to manage source items, but Multi Source merchants may need to move products from the default source to a custom source, or move products from one custom source to another. diff --git a/src/guides/v2.3/rest/modules/inventory/manage-sources.md b/src/guides/v2.3/rest/modules/inventory/manage-sources.md index 40de2ef4c85..28f30130c66 100644 --- a/src/guides/v2.3/rest/modules/inventory/manage-sources.md +++ b/src/guides/v2.3/rest/modules/inventory/manage-sources.md @@ -1,7 +1,6 @@ --- group: rest-api title: Manage sources - --- Sources represent locations storing and shipping available product stock. Any location with available stock and capable of order fulfillment can be added as a source. These locations can include warehouses, brick-and-mortar stores, distribution centers, and drop shippers. From a56adf778fc8ec46d4ac100c3c0eb8b83a4a8720 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Thu, 30 Jun 2022 11:15:14 -0500 Subject: [PATCH 238/776] ACP2E-993: [Documentation] user_errors is a field u can select to get error for addProductsToCart GraphQL Mutation --- .../graphql/cart-user-input-errors.md | 6 +++ .../graphql/mutations/add-products-to-cart.md | 50 ++++++++++++++++--- 2 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 src/_includes/graphql/cart-user-input-errors.md diff --git a/src/_includes/graphql/cart-user-input-errors.md b/src/_includes/graphql/cart-user-input-errors.md new file mode 100644 index 00000000000..50b2283f0a0 --- /dev/null +++ b/src/_includes/graphql/cart-user-input-errors.md @@ -0,0 +1,6 @@ +The `CartUserInputError` object contains information about errors that are specific to carts. + +| Attribute | Data Type | Description | +|-----------|-------------------------|------------------------------------------------------------------------------------------------------------------------------| +| `code` | CartUserInputErrorType! | A cart-specific error code. Possible values include `PRODUCT_NOT_FOUND`, `NOT_SALABLE`, `INSUFFICIENT_STOCK` and `UNDEFINED` | +| `message` | String! | A localized error message | diff --git a/src/guides/v2.4/graphql/mutations/add-products-to-cart.md b/src/guides/v2.4/graphql/mutations/add-products-to-cart.md index f0a5c8ea6be..68145d5601c 100644 --- a/src/guides/v2.4/graphql/mutations/add-products-to-cart.md +++ b/src/guides/v2.4/graphql/mutations/add-products-to-cart.md @@ -76,6 +76,10 @@ mutation { quantity } } + user_errors { + code + message + } } } ``` @@ -96,7 +100,8 @@ mutation { "quantity": 1 } ] - } + }, + "user_errors": [] } } } @@ -134,6 +139,10 @@ mutation { quantity } } + user_errors { + code + message + } } } ``` @@ -163,7 +172,8 @@ mutation { "quantity": 1 } ] - } + }, + "user_errors": [] } } } @@ -204,6 +214,10 @@ mutation { quantity } } + user_errors { + code + message + } } } ``` @@ -238,7 +252,8 @@ mutation { "quantity": 1 } ] - } + }, + "user_errors": [] } } } @@ -287,6 +302,10 @@ mutation { quantity } } + user_errors { + code + message + } } } ``` @@ -320,7 +339,8 @@ mutation { "quantity": 1 } ] - } + }, + "user_errors": [] } } } @@ -385,6 +405,10 @@ mutation { } } } + user_errors { + code + message + } } } ``` @@ -460,7 +484,8 @@ mutation { ] } ] - } + }, + "user_errors": [] } } } @@ -516,6 +541,10 @@ mutation { } } } + user_errors { + code + message + } } } ``` @@ -543,9 +572,10 @@ The `CartItemInput` object must contain the following attributes: The `AddProductsToCartOutput` object contains the `Cart` object. -Attribute | Data Type | Description ---- | --- | --- -`cart` |[Cart!](#CartObject) | Describes the contents of the specified shopping cart +| Attribute | Data Type | Description | +|---------------|--------------------------------------------|----------------------------------------------------------------| +| `user_errors` | [CartUserInputError!](#CartUserInputError) | An array of errors encountered while adding products to a cart | +| `cart` | [Cart!](#CartObject) | Describes the contents of the specified shopping cart | ### Cart object {#CartObject} @@ -553,6 +583,10 @@ Attribute | Data Type | Description [Cart query output]({{page.baseurl}}/graphql/queries/cart.html#cart-output) provides more information about the `Cart` object. +### CartUserInputError attributes {#CartUserInputError} + +{% include graphql/cart-user-input-errors.md %} + ## Errors Code | Error | Description From 7b23e6d2f291a07bcde3eb41ac282080c8c23030 Mon Sep 17 00:00:00 2001 From: Erik Marr Date: Thu, 30 Jun 2022 11:17:01 -0500 Subject: [PATCH 239/776] Renaming the MSE SDK in devdocs --- src/_data/toc/shared-services.yml | 6 +++--- src/live-search/events.md | 2 +- src/recommendations/events.md | 2 +- src/shared-services/storefront-event-collector.md | 4 ++-- src/shared-services/storefront-events-api-ref-context.md | 2 +- src/shared-services/storefront-events-api-ref-publish.md | 2 +- src/shared-services/storefront-events-api-ref-subscribe.md | 2 +- .../storefront-events-api-ref-unsubscribe.md | 2 +- src/shared-services/storefront-events-api-reference.md | 4 ++-- src/shared-services/storefront-events-sdk.md | 4 ++-- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/_data/toc/shared-services.yml b/src/_data/toc/shared-services.yml index 9db984df1fb..015f73cf60c 100644 --- a/src/_data/toc/shared-services.yml +++ b/src/_data/toc/shared-services.yml @@ -1,12 +1,12 @@ label: Shared Services pages: -- label: Storefront Events +- label: Adobe Commerce Storefront Events children: - - label: Storefront Events SDK + - label: Adobe Commerce Storefront Event SDK url: /shared-services/storefront-events-sdk.html versionless: true - - label: Storefront Event Collector + - label: Adobe Commerce Storefront Event Collector url: /shared-services/storefront-event-collector.html versionless: true diff --git a/src/live-search/events.md b/src/live-search/events.md index 6b3991e20c9..617827b115d 100644 --- a/src/live-search/events.md +++ b/src/live-search/events.md @@ -4,7 +4,7 @@ title: Events ee_only: True --- -The [_Storefront Events SDK_]({{ site.baseurl }}/shared-services/storefront-events-sdk.html) provides access to a common data layer, with event publishing and subscription services. The [_Storefront Event Collector_]({{ site.baseurl }}/shared-services/storefront-event-collector.html) package listens for events and includes the following search-related functions: +The [_Adobe Commerce Event SDK_]({{ site.baseurl }}/shared-services/storefront-events-sdk.html) provides access to a common data layer, with event publishing and subscription services. The [_Adobe Commerce Event Collector_]({{ site.baseurl }}/shared-services/storefront-event-collector.html) package listens for events and includes the following search-related functions: |Function|Description| |---|---| diff --git a/src/recommendations/events.md b/src/recommendations/events.md index 5952feec407..53c65c3f513 100644 --- a/src/recommendations/events.md +++ b/src/recommendations/events.md @@ -15,7 +15,7 @@ The following events are not specific to Product Recommendations, but are requir - `add-to-cart` - `place-order` -The [Storefront Events Collector]({{ site.baseurl }}/shared-services/storefront-event-collector.html#quick-start) lists all the events deployed to your storefront. From that list, however, there is a subset of events specific to Product Recommendations. These events collect data when shoppers interact with recommendation units on the storefront and power the metrics used to help you analyze how well your recommendations are performing. +The [Adobe Commerce Storefront Event Collector]({{ site.baseurl }}/shared-services/storefront-event-collector.html#quick-start) lists all the events deployed to your storefront. From that list, however, there is a subset of events specific to Product Recommendations. These events collect data when shoppers interact with recommendation units on the storefront and power the metrics used to help you analyze how well your recommendations are performing. Event | Description | [Used for metrics?]({{ site.user_guide_url }}/recommendations/workspace.html) --- | --- | --- diff --git a/src/shared-services/storefront-event-collector.md b/src/shared-services/storefront-event-collector.md index bf0c8e0f089..3c4a17cf090 100644 --- a/src/shared-services/storefront-event-collector.md +++ b/src/shared-services/storefront-event-collector.md @@ -1,10 +1,10 @@ --- group: shared-services -title: Storefront Event Collector +title: Adobe Commerce Event Collector ee_only: True --- -This package listens for and handles events sent from the [{{site.data.var.ee}} Storefront Events SDK]({{ site.baseurl }}/shared-services/storefront-events-sdk.html). It runs as a side effect and is meant to be a convenience for users who want to send events to {{site.data.var.ee}} for processing. +This package listens for and handles events sent from the [{{site.data.var.ee}} Adobe Commerce Event SDK]({{ site.baseurl }}/shared-services/storefront-events-sdk.html). It runs as a side effect and is meant to be a convenience for users who want to send events to {{site.data.var.ee}} for processing. ## Installation diff --git a/src/shared-services/storefront-events-api-ref-context.md b/src/shared-services/storefront-events-api-ref-context.md index d6374731df5..cbcdd8dab71 100644 --- a/src/shared-services/storefront-events-api-ref-context.md +++ b/src/shared-services/storefront-events-api-ref-context.md @@ -1,6 +1,6 @@ --- group: shared-services -title: Context - Events SDK Reference +title: Context - Adobe Commerce Event SDK Reference ee_only: True --- diff --git a/src/shared-services/storefront-events-api-ref-publish.md b/src/shared-services/storefront-events-api-ref-publish.md index 81511119dcf..1678ad5620d 100644 --- a/src/shared-services/storefront-events-api-ref-publish.md +++ b/src/shared-services/storefront-events-api-ref-publish.md @@ -1,6 +1,6 @@ --- group: shared-services -title: Publish - Events SDK Reference +title: Publish - Adobe Commerce Event SDK Reference ee_only: True --- diff --git a/src/shared-services/storefront-events-api-ref-subscribe.md b/src/shared-services/storefront-events-api-ref-subscribe.md index a92f8f16545..f30604e282a 100644 --- a/src/shared-services/storefront-events-api-ref-subscribe.md +++ b/src/shared-services/storefront-events-api-ref-subscribe.md @@ -1,6 +1,6 @@ --- group: shared-services -title: Subscribe - Events SDK Reference +title: Subscribe - Adobe Commerce Event SDK Reference ee_only: True --- ## Functions diff --git a/src/shared-services/storefront-events-api-ref-unsubscribe.md b/src/shared-services/storefront-events-api-ref-unsubscribe.md index b725d141b7e..772e51dd6bf 100644 --- a/src/shared-services/storefront-events-api-ref-unsubscribe.md +++ b/src/shared-services/storefront-events-api-ref-unsubscribe.md @@ -1,6 +1,6 @@ --- group: shared-services -title: Unsubscribe - Events SDK Reference +title: Unsubscribe - Adobe Commerce Event SDK Reference ee_only: True --- diff --git a/src/shared-services/storefront-events-api-reference.md b/src/shared-services/storefront-events-api-reference.md index 23ec9c3b37e..92a3fe1374a 100644 --- a/src/shared-services/storefront-events-api-reference.md +++ b/src/shared-services/storefront-events-api-reference.md @@ -1,10 +1,10 @@ --- group: shared-services -title: Events SDK Reference +title: Adobe Commerce Event SDK Reference ee_only: True --- -The Storefront Events SDK functions are organized into the following sections: +The Adobe Commerce Event SDK functions are organized into the following sections: - [Context]({{ site.baseurl }}/shared-services/storefront-events-api-ref-context.html) - [Publish]({{ site.baseurl }}/shared-services/storefront-events-api-ref-publish.html) diff --git a/src/shared-services/storefront-events-sdk.md b/src/shared-services/storefront-events-sdk.md index 94cb4ed47c1..4c2753ebd43 100644 --- a/src/shared-services/storefront-events-sdk.md +++ b/src/shared-services/storefront-events-sdk.md @@ -1,10 +1,10 @@ --- group: shared-services -title: Storefront Events SDK +title: Adobe Commerce Event SDK ee_only: True --- -This package serves as the foundation for eventing on an [{{site.data.var.ee}}](https://business.adobe.com/products/magento/magento-commerce.html) storefront. It provides access to a common data layer, and an event publishing and subscription service. Handling these events is up to you, but we provide the [Storefront Event Collector]({{ site.baseurl }}/shared-services/storefront-event-collector.html) package that can listen for events and send them to {{site.data.var.ee}} for processing. +This package serves as the foundation for eventing on an [{{site.data.var.ee}}](https://business.adobe.com/products/magento/magento-commerce.html) storefront. It provides access to a common data layer, and an event publishing and subscription service. Handling these events is up to you, but we provide the [Adobe Commerce Event Collector]({{ site.baseurl }}/shared-services/storefront-event-collector.html) package that can listen for events and send them to {{site.data.var.ee}} for processing. ## Installation From 8ae2d3380bc869fa6abff4a7943340dcae5bc7a7 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Thu, 30 Jun 2022 11:20:52 -0500 Subject: [PATCH 240/776] ACP2E-993: [Documentation] user_errors is a field u can select to get error for addProductsToCart GraphQL Mutation --- .../v2.4/graphql/mutations/add-products-to-cart.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/guides/v2.4/graphql/mutations/add-products-to-cart.md b/src/guides/v2.4/graphql/mutations/add-products-to-cart.md index 68145d5601c..37ff250f3bd 100644 --- a/src/guides/v2.4/graphql/mutations/add-products-to-cart.md +++ b/src/guides/v2.4/graphql/mutations/add-products-to-cart.md @@ -142,7 +142,7 @@ mutation { user_errors { code message - } + } } } ``` @@ -217,7 +217,7 @@ mutation { user_errors { code message - } + } } } ``` @@ -305,7 +305,7 @@ mutation { user_errors { code message - } + } } } ``` @@ -408,7 +408,7 @@ mutation { user_errors { code message - } + } } } ``` @@ -544,7 +544,7 @@ mutation { user_errors { code message - } + } } } ``` From ff89f94d6752b974cd0086e5978937338e1fac76 Mon Sep 17 00:00:00 2001 From: jhadobe Date: Thu, 30 Jun 2022 13:01:20 -0400 Subject: [PATCH 241/776] Adding layout: migrated metadata --- src/guides/v2.4/rest/anonymous-api-security.md | 1 + src/guides/v2.4/rest/asynchronous-web-endpoints.md | 1 + src/guides/v2.4/rest/bk-rest.md | 1 + src/guides/v2.4/rest/bulk-endpoints.md | 1 + src/guides/v2.4/rest/generate-local.md | 1 + src/guides/v2.4/rest/modules/catalog-pricing.md | 1 + src/guides/v2.4/rest/modules/catalog.md | 1 + src/guides/v2.4/rest/modules/inventory/bulk-inventory.md | 1 + src/guides/v2.4/rest/modules/inventory/check-salable-quantity.md | 1 + src/guides/v2.4/rest/modules/inventory/in-store-pickup.md | 1 + src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md | 1 + src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md | 1 + src/guides/v2.4/rest/modules/inventory/manage-source-items.md | 1 + .../v2.4/rest/modules/inventory/manage-source-selection.md | 1 + src/guides/v2.4/rest/modules/inventory/manage-sources.md | 1 + src/guides/v2.4/rest/modules/inventory/manage-stocks.md | 1 + src/guides/v2.4/rest/modules/sales/refunds.md | 1 + src/guides/v2.4/rest/notes.md | 1 + src/guides/v2.4/rest/operation-status-endpoints.md | 1 + src/guides/v2.4/rest/operation-status-search.md | 1 + src/guides/v2.4/rest/performing-searches.md | 1 + src/guides/v2.4/rest/protected-endpoints.md | 1 + src/guides/v2.4/rest/retrieve-filtered-responses.md | 1 + src/guides/v2.4/rest/search-endpoint.md | 1 + .../tutorials/bulk-configurable-product/config-product-intro.md | 1 + .../create-configurable-simple-products.md | 1 + .../bulk-configurable-product/create-personalization-option.md | 1 + .../bulk-configurable-product/define-config-product-options.md | 1 + .../rest/tutorials/bulk-configurable-product/plan-product.md | 1 + .../v2.4/rest/tutorials/bundle-product/bundle-product-intro.md | 1 + .../v2.4/rest/tutorials/bundle-product/create-bundle-product.md | 1 + .../v2.4/rest/tutorials/bundle-product/create-simple-products.md | 1 + src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md | 1 + .../rest/tutorials/configurable-product/config-product-intro.md | 1 + .../configurable-product/create-configurable-product.md | 1 + .../configurable-product/create-personalization-option.md | 1 + .../tutorials/configurable-product/create-simple-products.md | 1 + .../configurable-product/define-config-product-options.md | 1 + .../v2.4/rest/tutorials/configurable-product/plan-product.md | 1 + .../grouped-product/create-and-manage-grouped-products.md | 1 + src/guides/v2.4/rest/tutorials/index.md | 1 + .../v2.4/rest/tutorials/inventory/assign-source-to-stock.md | 1 + .../v2.4/rest/tutorials/inventory/bulk-transfer-products.md | 1 + .../v2.4/rest/tutorials/inventory/configure-environment.md | 1 + .../v2.4/rest/tutorials/inventory/create-cart-add-products.md | 1 + src/guides/v2.4/rest/tutorials/inventory/create-customer.md | 1 + src/guides/v2.4/rest/tutorials/inventory/create-invoice.md | 1 + src/guides/v2.4/rest/tutorials/inventory/create-order.md | 1 + src/guides/v2.4/rest/tutorials/inventory/create-shipment.md | 1 + src/guides/v2.4/rest/tutorials/inventory/create-sources.md | 1 + src/guides/v2.4/rest/tutorials/inventory/create-stock.md | 1 + src/guides/v2.4/rest/tutorials/inventory/in-store-pickup.md | 1 + src/guides/v2.4/rest/tutorials/inventory/index.md | 1 + src/guides/v2.4/rest/tutorials/inventory/prepare-for-checkout.md | 1 + .../tutorials/inventory/reassign-products-to-another-source.md | 1 + src/guides/v2.4/rest/tutorials/inventory/run-ssa.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-add-items.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-admin-token.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-config-store.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-create-customer.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-create-order.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-create-quote.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-intro.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md | 1 + src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md | 1 + .../v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md | 1 + 68 files changed, 68 insertions(+) diff --git a/src/guides/v2.4/rest/anonymous-api-security.md b/src/guides/v2.4/rest/anonymous-api-security.md index eeaa477f3ce..ea0e85a75ca 100644 --- a/src/guides/v2.4/rest/anonymous-api-security.md +++ b/src/guides/v2.4/rest/anonymous-api-security.md @@ -2,6 +2,7 @@ group: rest-api title: Restricting access to anonymous web APIs migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/anonymous-api-security/ +layout: migrated --- Magento 2 allows some web APIs to be accessed by unauthenticated (anonymous) users. Many of these APIs allow a customer to have a robust shopping experience on the [website](https://glossary.magento.com/website) without having to log in. diff --git a/src/guides/v2.4/rest/asynchronous-web-endpoints.md b/src/guides/v2.4/rest/asynchronous-web-endpoints.md index 82a850c5917..c36c064b2f9 100644 --- a/src/guides/v2.4/rest/asynchronous-web-endpoints.md +++ b/src/guides/v2.4/rest/asynchronous-web-endpoints.md @@ -6,6 +6,7 @@ contributor_link: http://comwrap.com/ functional_areas: - Integration migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/asynchronous-web-endpoints/ +layout: migrated --- An asynchronous web endpoint intercepts messages to a Web API and writes them to the message queue. Each time the system accepts such an API request, it generates a UUID identifier. Magento includes this UUID when it adds the message to the queue. Then, a consumer reads the messages from the queue and executes them one-by-one. diff --git a/src/guides/v2.4/rest/bk-rest.md b/src/guides/v2.4/rest/bk-rest.md index ca79c27bd02..7fc0736660e 100644 --- a/src/guides/v2.4/rest/bk-rest.md +++ b/src/guides/v2.4/rest/bk-rest.md @@ -2,6 +2,7 @@ group: rest-api title: REST API Overview migrated_to: https://developer.adobe.com/commerce/webapi/rest/ +layout: migrated functional_areas: - Integration --- diff --git a/src/guides/v2.4/rest/bulk-endpoints.md b/src/guides/v2.4/rest/bulk-endpoints.md index 92f14550f9d..631c30fa5bb 100644 --- a/src/guides/v2.4/rest/bulk-endpoints.md +++ b/src/guides/v2.4/rest/bulk-endpoints.md @@ -6,6 +6,7 @@ contributor_link: http://comwrap.com/ functional_areas: - Integration migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/bulk-endpoints/ +layout: migrated --- Bulk API endpoints differ from other REST endpoints in that they combine multiple calls of the same type into an array and execute them as a single request. The endpoint handler splits the array into individual entities and writes them as separate messages to the message queue. diff --git a/src/guides/v2.4/rest/generate-local.md b/src/guides/v2.4/rest/generate-local.md index 1a75b78d5d4..7eeacea1c1d 100644 --- a/src/guides/v2.4/rest/generate-local.md +++ b/src/guides/v2.4/rest/generate-local.md @@ -2,6 +2,7 @@ group: rest-api title: Generate a local REST reference migrated_to: https://developer.adobe.com/commerce/webapi/quick-reference/rest/generate-local/ +layout: migrated functional_areas: - Integration --- diff --git a/src/guides/v2.4/rest/modules/catalog-pricing.md b/src/guides/v2.4/rest/modules/catalog-pricing.md index 7ce09edb346..c0218404205 100644 --- a/src/guides/v2.4/rest/modules/catalog-pricing.md +++ b/src/guides/v2.4/rest/modules/catalog-pricing.md @@ -2,6 +2,7 @@ group: rest-api title: Manage prices for multiple products migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/catalog/catalog-pricing/ +layout: migrated functional_areas: - Integration --- diff --git a/src/guides/v2.4/rest/modules/catalog.md b/src/guides/v2.4/rest/modules/catalog.md index de3721410ce..8f1d787d324 100644 --- a/src/guides/v2.4/rest/modules/catalog.md +++ b/src/guides/v2.4/rest/modules/catalog.md @@ -2,6 +2,7 @@ group: rest-api title: Catalog module migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/catalog/ +layout: migrated functional_areas: - Integration - Catalog diff --git a/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md b/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md index 42ed73e897f..d0c9ed8d145 100644 --- a/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md +++ b/src/guides/v2.4/rest/modules/inventory/bulk-inventory.md @@ -2,6 +2,7 @@ group: rest-api title: Inventory mass actions migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/bulk-inventory/ +layout: migrated --- Magento provides several endpoints that allow Multi Source merchants to make quick updates across multiple products. This is helpful for transferring inventory between sources and removing a source without editing each product individually. diff --git a/src/guides/v2.4/rest/modules/inventory/check-salable-quantity.md b/src/guides/v2.4/rest/modules/inventory/check-salable-quantity.md index d6017214c96..b78022a4578 100644 --- a/src/guides/v2.4/rest/modules/inventory/check-salable-quantity.md +++ b/src/guides/v2.4/rest/modules/inventory/check-salable-quantity.md @@ -2,6 +2,7 @@ group: rest-api title: Check salable quantities migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/check-salable-quantity/ +layout: migrated --- Magento provides several endpoints that allow you to check whether a product from a specified stock is salable and the available quantity. diff --git a/src/guides/v2.4/rest/modules/inventory/in-store-pickup.md b/src/guides/v2.4/rest/modules/inventory/in-store-pickup.md index 8540c3bfe71..965bcf0defc 100644 --- a/src/guides/v2.4/rest/modules/inventory/in-store-pickup.md +++ b/src/guides/v2.4/rest/modules/inventory/in-store-pickup.md @@ -2,6 +2,7 @@ group: rest-api title: In-Store Pickup migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/in-store-pickup/ +layout: migrated contributor_name: Oleksandr Kravchuk contributor_link: https://github.com/swnsma --- diff --git a/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md b/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md index 18004a12157..351258860c9 100644 --- a/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md +++ b/src/guides/v2.4/rest/modules/inventory/link-stocks-sources.md @@ -2,6 +2,7 @@ group: rest-api title: Link and unlink stocks and sources migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/link-stocks-sources/ +layout: migrated --- In Admin, you can assign (link) sources to a stock when you create the stock. In REST, creating a stock and assigning sources to it are separate steps. diff --git a/src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md b/src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md index 23ce6140c78..713af3ed8ec 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-low-quantity.md @@ -2,6 +2,7 @@ group: rest-api title: Manage low-quantity notifications migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-low-quantity/ +layout: migrated --- Low stock notification alert the merchant that the salable quantity of a stock has reached a critical threshold. The Admin allows the merchant to configure low-quantity notifications from several locations: diff --git a/src/guides/v2.4/rest/modules/inventory/manage-source-items.md b/src/guides/v2.4/rest/modules/inventory/manage-source-items.md index 96368a1e9ba..3d7a377751e 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-source-items.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-source-items.md @@ -2,6 +2,7 @@ group: rest-api title: Manage source items migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-source-items/ +layout: migrated --- If Magento is configured to manage inventory, Magento assigns all existing products to the default source. Currently, Magento also assigns newly-created products to the default source. Single Source merchants do not need to manage source items, but Multi Source merchants may need to move products from the default source to a custom source, or move products from one custom source to another. diff --git a/src/guides/v2.4/rest/modules/inventory/manage-source-selection.md b/src/guides/v2.4/rest/modules/inventory/manage-source-selection.md index cf44eebe39c..c9e1e1ee3fe 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-source-selection.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-source-selection.md @@ -2,6 +2,7 @@ group: rest-api title: Manage source selection algorithms migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-source-selection/ +layout: migrated --- Inventory Management uses the Source Selection Algorithm (SSA) to track the salable quantities of product inventory across all sources and make recommendations for partial and full shipments. diff --git a/src/guides/v2.4/rest/modules/inventory/manage-sources.md b/src/guides/v2.4/rest/modules/inventory/manage-sources.md index eefbd99f470..f20cc317c18 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-sources.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-sources.md @@ -2,6 +2,7 @@ group: rest-api title: Manage sources migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/ +layout: migrated --- Sources represent locations storing and shipping available product stock. Any location with available stock and capable of order fulfillment can be added as a source. These locations can include warehouses, brick-and-mortar stores, distribution centers, and drop shippers. diff --git a/src/guides/v2.4/rest/modules/inventory/manage-stocks.md b/src/guides/v2.4/rest/modules/inventory/manage-stocks.md index 51aee9392f6..ee70e38d479 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-stocks.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-stocks.md @@ -2,6 +2,7 @@ group: rest-api title: Manage stocks migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-stocks/ +layout: migrated --- Stocks map your sources to sales channels, providing a direct link to salable quantities and inventories. diff --git a/src/guides/v2.4/rest/modules/sales/refunds.md b/src/guides/v2.4/rest/modules/sales/refunds.md index 9a21653531e..6e9c61b8f8a 100644 --- a/src/guides/v2.4/rest/modules/sales/refunds.md +++ b/src/guides/v2.4/rest/modules/sales/refunds.md @@ -2,6 +2,7 @@ group: rest-api title: Refunds migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/sales/ +layout: migrated functional_areas: - Integration diff --git a/src/guides/v2.4/rest/notes.md b/src/guides/v2.4/rest/notes.md index 3a8b18f65e9..925a8f6efd8 100644 --- a/src/guides/v2.4/rest/notes.md +++ b/src/guides/v2.4/rest/notes.md @@ -2,6 +2,7 @@ group: rest-api title: REST usage notes migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/notes/ +layout: migrated functional_areas: - Integration --- diff --git a/src/guides/v2.4/rest/operation-status-endpoints.md b/src/guides/v2.4/rest/operation-status-endpoints.md index c8f0df813b2..29d68bfa68c 100644 --- a/src/guides/v2.4/rest/operation-status-endpoints.md +++ b/src/guides/v2.4/rest/operation-status-endpoints.md @@ -2,6 +2,7 @@ group: rest-api title: Bulk operation status endpoints migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/operation-status-endpoints/ +layout: migrated contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com/ functional_areas: diff --git a/src/guides/v2.4/rest/operation-status-search.md b/src/guides/v2.4/rest/operation-status-search.md index a027868e29b..1ff8302cbb3 100644 --- a/src/guides/v2.4/rest/operation-status-search.md +++ b/src/guides/v2.4/rest/operation-status-search.md @@ -2,6 +2,7 @@ group: rest-api title: Search for the status of a bulk operation migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/operation-status-search +layout: migrated contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com functional_areas: diff --git a/src/guides/v2.4/rest/performing-searches.md b/src/guides/v2.4/rest/performing-searches.md index d6f0df7c9e5..70f6bddaa75 100644 --- a/src/guides/v2.4/rest/performing-searches.md +++ b/src/guides/v2.4/rest/performing-searches.md @@ -2,6 +2,7 @@ group: rest-api title: Search using REST endpoints migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/performing-searches/ +layout: migrated --- POST, PUT, and DELETE requests to the REST Web [API](https://glossary.magento.com/api) require the service method parameters to be in the body of the request. For example, to create a Customer, you would specify a JSON array (or [XML](https://glossary.magento.com/xml) structure) in the body of the message. diff --git a/src/guides/v2.4/rest/protected-endpoints.md b/src/guides/v2.4/rest/protected-endpoints.md index 45669e7624d..f38924afcab 100644 --- a/src/guides/v2.4/rest/protected-endpoints.md +++ b/src/guides/v2.4/rest/protected-endpoints.md @@ -2,6 +2,7 @@ group: rest-api title: Protected endpoints migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/protected-endpoints/ +layout: migrated functional_areas: - Integration --- diff --git a/src/guides/v2.4/rest/retrieve-filtered-responses.md b/src/guides/v2.4/rest/retrieve-filtered-responses.md index d85d806e0ec..ab34efdf930 100644 --- a/src/guides/v2.4/rest/retrieve-filtered-responses.md +++ b/src/guides/v2.4/rest/retrieve-filtered-responses.md @@ -2,6 +2,7 @@ group: rest-api title: Retrieve filtered responses for REST endpoints migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/retrieve-filtered-responses/ +layout: migrated --- Some REST calls return dozens or even hundreds of parameters, and parsing through all this data can be unwieldy. In addition, mobile app developers might find the bandwidth needed to process a request to be excessive. To resolve these problems, Magento provides a query parameter-based syntax for REST requests that return partial responses. diff --git a/src/guides/v2.4/rest/search-endpoint.md b/src/guides/v2.4/rest/search-endpoint.md index 067f66a6dfb..61a7b88b16f 100644 --- a/src/guides/v2.4/rest/search-endpoint.md +++ b/src/guides/v2.4/rest/search-endpoint.md @@ -2,6 +2,7 @@ group: rest-api title: Search for products with the /search endpoint migrated_to: https://developer.adobe.com/commerce/webapi/rest/use-rest/search-endpoint/ +layout: migrated contributor_name: comwrap GmbH contributor_link: https://www.comwrap.com/ --- diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md index eb1caadae94..16cecc2ccaa 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/config-product-intro.md @@ -13,6 +13,7 @@ functional_areas: contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bulk-configurable-product/ +layout: migrated --- A system integrator can use Magento REST bulk APIs to perform actions on a large scale; such as, creating multiple customers and products, changing prices across an inventory, and assigning large groups of products to a specific warehouse, all within a single call. diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md index 5cfa070ebf3..e900cd61d82 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-configurable-simple-products.md @@ -14,6 +14,7 @@ functional_areas: contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bulk-configurable-product/create-configurable-simple-products/ +layout: migrated --- By providing configurable and simple product information, you can use the bulk API to create all necessary products with a single call. diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md index 33642594c77..eaf2a2a9e53 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/create-personalization-option.md @@ -14,6 +14,7 @@ functional_areas: contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bulk-configurable-product/create-personalization-option/ +layout: migrated --- Let's add a text box to the product page that allows the customer to add his name (up to 15 characters) to the back of the shirt. diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md index 0ffe1de378d..67dcb9428de 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/define-config-product-options.md @@ -14,6 +14,7 @@ functional_areas: contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bulk-configurable-product/define-config-product-options/ +layout: migrated --- Now that we've created all the Champ Tee products, we need to assign `size` as the configurable attribute and link the simple products to the configurable product. diff --git a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md index eb1132ed0ce..8d40d2b1fbe 100644 --- a/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md +++ b/src/guides/v2.4/rest/tutorials/bulk-configurable-product/plan-product.md @@ -14,6 +14,7 @@ functional_areas: contributor_name: comwrap GmbH contributor_link: http://comwrap.com/ migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bulk-configurable-product/plan-product/ +layout: migrated --- To create a configurable product programmatically, you'll need to know the following: diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md b/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md index 3cc9150515f..566634c6b78 100644 --- a/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md +++ b/src/guides/v2.4/rest/tutorials/bundle-product/bundle-product-intro.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Create a bundle product tutorial migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/ +layout: migrated contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md b/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md index b4b1907215c..d9ab1f1dcaf 100644 --- a/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md +++ b/src/guides/v2.4/rest/tutorials/bundle-product/create-bundle-product.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 3. Create the bundle product migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/create-bundle-product/ +layout: migrated contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md b/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md index e57f8396686..c6c470da956 100644 --- a/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md +++ b/src/guides/v2.4/rest/tutorials/bundle-product/create-simple-products.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 2. Create the simple products migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/create-simple-products/ +layout: migrated contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md b/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md index c0ded6836a0..cebb6d7faf8 100644 --- a/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md +++ b/src/guides/v2.4/rest/tutorials/bundle-product/plan-product.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 1. Plan the product migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/bundle-product/plan-product/ +layout: migrated contributor_name: Goivvy LLC contributor_link: https://www.goivvy.com/magento-optimization-service --- diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md b/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md index 970de23b7b2..d674446d72a 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/config-product-intro.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Create a configurable product tutorial migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/ +layout: migrated menu_title: Initial tasks menu_order: 0 level3_subgroup: configurable-product-tutorial diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md b/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md index 161a553825d..30c4a93362e 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/create-configurable-product.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 2. Create the configurable product migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/create-configurable-product/ +layout: migrated subtitle: Create a configurable product tutorial menu_title: Step 2. Create the configurable product menu_order: 20 diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md b/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md index d9aaeb1195f..27be40fe7d3 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/create-personalization-option.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 5. Create the personalization option migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/create-personalization-option/ +layout: migrated subtitle: Create a configurable product tutorial menu_title: Step 5. Create the personalization option menu_order: 50 diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md b/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md index 6bb323d659b..9ef46691203 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/create-simple-products.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 3. Create the simple products migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/create-simple-products/ +layout: migrated subtitle: Create a configurable product tutorial menu_title: Step 3. Create the simple products menu_order: 30 diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md b/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md index 6096e09f732..9b70b9ebda5 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/define-config-product-options.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 4. Define configurable product options migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/define-config-product-options/ +layout: migrated subtitle: Create a configurable product tutorial menu_title: Step 4. Define configurable product options menu_order: 40 diff --git a/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md b/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md index 65204276051..ca43d432e45 100644 --- a/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md +++ b/src/guides/v2.4/rest/tutorials/configurable-product/plan-product.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 1. Plan the product migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/configurable-product/plan-product/ +layout: migrated subtitle: Create a configurable product tutorial menu_title: Step 1. Plan the product menu_order: 10 diff --git a/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md b/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md index b76596d7edf..47a84b8f352 100644 --- a/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md +++ b/src/guides/v2.4/rest/tutorials/grouped-product/create-and-manage-grouped-products.md @@ -2,6 +2,7 @@ group: rest-api title: Create and manage grouped products tutorial migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/grouped-product/ +layout: migrated functional_areas: - Integration --- diff --git a/src/guides/v2.4/rest/tutorials/index.md b/src/guides/v2.4/rest/tutorials/index.md index 51beaeef08f..0d657e041ca 100644 --- a/src/guides/v2.4/rest/tutorials/index.md +++ b/src/guides/v2.4/rest/tutorials/index.md @@ -2,6 +2,7 @@ group: rest-api title: REST tutorials migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/ +layout: migrated functional_areas: - Integration - Orders diff --git a/src/guides/v2.4/rest/tutorials/inventory/assign-source-to-stock.md b/src/guides/v2.4/rest/tutorials/inventory/assign-source-to-stock.md index 0066124b021..b4b02c9f9cf 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/assign-source-to-stock.md +++ b/src/guides/v2.4/rest/tutorials/inventory/assign-source-to-stock.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 4. Link stocks and sources migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/assign-source-to-stock/ +layout: migrated subtitle: Order processing with Inventory Management menu_title: Step 4. Link stocks and sources menu_order: 40 diff --git a/src/guides/v2.4/rest/tutorials/inventory/bulk-transfer-products.md b/src/guides/v2.4/rest/tutorials/inventory/bulk-transfer-products.md index 00abc207499..40812c17dda 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/bulk-transfer-products.md +++ b/src/guides/v2.4/rest/tutorials/inventory/bulk-transfer-products.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 13. Bulk transfer products migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/bulk-transfer-products/ +layout: migrated subtitle: Order processing with Inventory Management menu_title: Step 13. Bulk transfer products menu_order: 130 diff --git a/src/guides/v2.4/rest/tutorials/inventory/configure-environment.md b/src/guides/v2.4/rest/tutorials/inventory/configure-environment.md index 9435f8504a9..6cefb6407f1 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/configure-environment.md +++ b/src/guides/v2.4/rest/tutorials/inventory/configure-environment.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 1. Configure your environment migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/configure-environment/ +layout: migrated subtitle: Order processing with Inventory Management menu_title: Step 1. Configure your environment menu_order: 10 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-cart-add-products.md b/src/guides/v2.4/rest/tutorials/inventory/create-cart-add-products.md index 05abb0a792e..86c81c2946a 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-cart-add-products.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-cart-add-products.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 7. Create a cart and add products to it migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-cart-add-products/ +layout: migrated subtitle: Order processing with Inventory Management menu_title: Step 7. Create a cart and add products to it menu_order: 70 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-customer.md b/src/guides/v2.4/rest/tutorials/inventory/create-customer.md index 4352be90229..da7030b6380 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-customer.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-customer.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 6. Create a customer and generate a customer token migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-customer/ +layout: migrated subtitle: Order processing with Inventory Management menu_title: Step 6. Create a customer and generate a customer token menu_order: 60 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-invoice.md b/src/guides/v2.4/rest/tutorials/inventory/create-invoice.md index 0d700ac7cde..82715592c00 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-invoice.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-invoice.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 10. Create an invoice migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-invoice/ +layout: migrated subtitle: Order processing with Inventory Management menu_title: Step 10. Create an invoice menu_order: 100 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-order.md b/src/guides/v2.4/rest/tutorials/inventory/create-order.md index 2da3ced38b3..b6b86cb4c24 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-order.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-order.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 9. Create an order migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-order/ +layout: migrated subtitle: Order processing with Inventory Management menu_title: Step 9. Create an order menu_order: 90 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-shipment.md b/src/guides/v2.4/rest/tutorials/inventory/create-shipment.md index 71ead0971e4..31977f6bc94 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-shipment.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-shipment.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 12. Create a shipment migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-shipment/ +layout: migrated menu_title: Step 12. Create a shipment subtitle: Order processing with Inventory Management menu_order: 120 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-sources.md b/src/guides/v2.4/rest/tutorials/inventory/create-sources.md index 5a12be59239..4dc9c4c23bd 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-sources.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-sources.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 2. Create sources migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-sources/ +layout: migrated subtitle: Order processing with Inventory Management menu_title: Step 2. Create sources menu_order: 20 diff --git a/src/guides/v2.4/rest/tutorials/inventory/create-stock.md b/src/guides/v2.4/rest/tutorials/inventory/create-stock.md index 8dd3399ef24..4cd78263726 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/create-stock.md +++ b/src/guides/v2.4/rest/tutorials/inventory/create-stock.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 3. Create stocks migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-stock/ +layout: migrated subtitle: Order processing with Inventory Management menu_title: Step 3. Create stocks menu_order: 30 diff --git a/src/guides/v2.4/rest/tutorials/inventory/in-store-pickup.md b/src/guides/v2.4/rest/tutorials/inventory/in-store-pickup.md index eeefae79265..9ef0c2baada 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/in-store-pickup.md +++ b/src/guides/v2.4/rest/tutorials/inventory/in-store-pickup.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 14. Create an order for in-store pickup (optional) migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/in-store-pickup/ +layout: migrated subtitle: Order processing with Inventory Management menu_title: Step 14. Bulk transfer products menu_order: 140 diff --git a/src/guides/v2.4/rest/tutorials/inventory/index.md b/src/guides/v2.4/rest/tutorials/inventory/index.md index c4fec7cfa4e..2a0171eb914 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/index.md +++ b/src/guides/v2.4/rest/tutorials/inventory/index.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Order Processing with Inventory Management migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/ +layout: migrated menu_title: Initial tasks menu_order: 0 level3_subgroup: msi-tutorial diff --git a/src/guides/v2.4/rest/tutorials/inventory/prepare-for-checkout.md b/src/guides/v2.4/rest/tutorials/inventory/prepare-for-checkout.md index 6c07fb5b47d..10ae3e49e7b 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/prepare-for-checkout.md +++ b/src/guides/v2.4/rest/tutorials/inventory/prepare-for-checkout.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 8. Prepare for checkout migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/prepare-for-checkout/ +layout: migrated subtitle: Order processing with Inventory Management menu_title: Step 8. Prepare for checkout menu_order: 80 diff --git a/src/guides/v2.4/rest/tutorials/inventory/reassign-products-to-another-source.md b/src/guides/v2.4/rest/tutorials/inventory/reassign-products-to-another-source.md index e27a06eb9ce..7d3b3af32a2 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/reassign-products-to-another-source.md +++ b/src/guides/v2.4/rest/tutorials/inventory/reassign-products-to-another-source.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 5. Reassign products to custom sources migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/reassign-products-to-another-source/ +layout: migrated subtitle: Order processing with Inventory Management menu_title: Step 5. Reassign products to custom sources menu_order: 50 diff --git a/src/guides/v2.4/rest/tutorials/inventory/run-ssa.md b/src/guides/v2.4/rest/tutorials/inventory/run-ssa.md index 3d27858f0a0..e4d1a1816d9 100644 --- a/src/guides/v2.4/rest/tutorials/inventory/run-ssa.md +++ b/src/guides/v2.4/rest/tutorials/inventory/run-ssa.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 11. Run the Source Selection Algorithms migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/run-ssa/ +layout: migrated subtitle: Order processing with Inventory Management menu_title: Step 11. Run the Source Selection Algorithms menu_order: 110 diff --git a/src/guides/v2.4/rest/tutorials/orders/order-add-items.md b/src/guides/v2.4/rest/tutorials/orders/order-add-items.md index 44e5998c6ef..d5520bc783c 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-add-items.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-add-items.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 5. Add items to the cart migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-add-items/ +layout: migrated subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-admin-token.md b/src/guides/v2.4/rest/tutorials/orders/order-admin-token.md index 8c05170bd7f..1fe32256ce0 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-admin-token.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-admin-token.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 2. Get the admin token migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-admin-token/ +layout: migrated subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-config-store.md b/src/guides/v2.4/rest/tutorials/orders/order-config-store.md index f3bd17e74a9..5a8700c6070 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-config-store.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-config-store.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 1. Configure the store migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-config-store/ +layout: migrated subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md b/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md index c5b302547b4..a64b4a80f55 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-customer.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 3. Create a customer migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-customer/ +layout: migrated subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md b/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md index 1b1e7dd571f..82f5aa547b5 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-invoice.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 8. Create an invoice migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-invoice/ +layout: migrated subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-order.md b/src/guides/v2.4/rest/tutorials/orders/order-create-order.md index 60f946c3e1e..f2299f13f51 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-order.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-order.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 7. Create an order migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-order/ +layout: migrated subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md b/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md index 479f4d98c71..225b43afab9 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-quote.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 4. Create a quote migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-quote/ +layout: migrated subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md b/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md index 522303eddf1..2aa755af0a9 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-create-shipment.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 9. Create a shipment migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-create-shipment/ +layout: migrated subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-intro.md b/src/guides/v2.4/rest/tutorials/orders/order-intro.md index 54b08fafb2e..060b0b903b6 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-intro.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-intro.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Order processing tutorial migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/ +layout: migrated menu_title: Initial tasks return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md b/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md index 594a58027a0..4c6b32deaea 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-issue-refund.md @@ -3,6 +3,7 @@ layout: tutorial group: rest-api title: Step 10. Issue a partial refund migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-issue-refund/ +layout: migrated subtitle: Order processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md b/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md index 03fe685e813..fed294fe0b3 100644 --- a/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md +++ b/src/guides/v2.4/rest/tutorials/orders/order-prepare-checkout.md @@ -4,6 +4,7 @@ group: rest-api subgroup: title: Step 6. Prepare for checkout migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/orders/order-prepare-checkout/ +layout: migrated subtitle: Order Processing tutorial return_to: title: REST tutorials diff --git a/src/guides/v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md b/src/guides/v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md index d379d1d4c50..46931b69399 100644 --- a/src/guides/v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md +++ b/src/guides/v2.4/rest/tutorials/prerequisite-tasks/create-admin-token.md @@ -2,6 +2,7 @@ group: rest-api title: Generate the admin token migrated_to: https://developer.adobe.com/commerce/webapi/rest/tutorials/prerequisite-tasks/ +layout: migrated functional_areas: - Integration - Orders From 9b7fb14d0bbac86ba7c521d265bf60403690ec6d Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Thu, 30 Jun 2022 12:31:48 -0500 Subject: [PATCH 242/776] revert note and add mention of PHP version to add to ticket info --- src/_includes/cloud/note-pro-using-yaml-support.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/_includes/cloud/note-pro-using-yaml-support.md b/src/_includes/cloud/note-pro-using-yaml-support.md index e29d344349c..11862db945a 100644 --- a/src/_includes/cloud/note-pro-using-yaml-support.md +++ b/src/_includes/cloud/note-pro-using-yaml-support.md @@ -1,3 +1,2 @@ {:.bs-callout-tip} -For Pro projects, you must create a [Support ticket](http://support.magento.com) to install or update services in Staging and Production environments. Indicate the service changes needed and include your updated `.magento.app.yaml` and `services.yaml` files in the ticket. It can take up to 48 hours for the Cloud infrastructure team to update your project. -PHP is **not** considered a service. Even though you can [upgrade PHP]({{ page.baseurl }}/cloud/project/magento-app-php-application.html) by updating the `.magento.app.yaml` file, it is important to mention your intent to upgrade PHP in the support ticket. This notifies the Cloud infrastructure team to upgrade PHP-specific extensions, such as the New Relic agent, to support the new version. \ No newline at end of file +For Pro projects, you must create a [Support ticket](http://support.magento.com) to install or update services in Staging and Production environments. Indicate the service changes needed and include your updated `.magento.app.yaml` and `services.yaml` files and PHP version in the ticket. It can take up to 48 hours for the Cloud infrastructure team to update your project. \ No newline at end of file From 0066a0b6902872de96e8f118c7cbe94d7e6db22f Mon Sep 17 00:00:00 2001 From: Thiaramus Date: Thu, 30 Jun 2022 12:44:02 -0500 Subject: [PATCH 243/776] Apply suggestions from code review Co-authored-by: Jeff Matthews --- src/guides/v2.4/graphql/mutations/add-products-to-cart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/graphql/mutations/add-products-to-cart.md b/src/guides/v2.4/graphql/mutations/add-products-to-cart.md index 37ff250f3bd..69dc35ba0e8 100644 --- a/src/guides/v2.4/graphql/mutations/add-products-to-cart.md +++ b/src/guides/v2.4/graphql/mutations/add-products-to-cart.md @@ -574,8 +574,8 @@ The `AddProductsToCartOutput` object contains the `Cart` object. | Attribute | Data Type | Description | |---------------|--------------------------------------------|----------------------------------------------------------------| -| `user_errors` | [CartUserInputError!](#CartUserInputError) | An array of errors encountered while adding products to a cart | | `cart` | [Cart!](#CartObject) | Describes the contents of the specified shopping cart | +| `user_errors` | [CartUserInputError!](#CartUserInputError) | An array of errors encountered while adding products to a cart | ### Cart object {#CartObject} From fa5bd0465f9952a5f48f2bb686b42214ab4cf2ea Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Thu, 30 Jun 2022 13:31:25 -0500 Subject: [PATCH 244/776] Update services-redis.md --- src/cloud/project/services-redis.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cloud/project/services-redis.md b/src/cloud/project/services-redis.md index 855a8b12eaf..927d96dae07 100644 --- a/src/cloud/project/services-redis.md +++ b/src/cloud/project/services-redis.md @@ -93,7 +93,7 @@ See the following {{site.data.var.ee}} Support articles for help troubleshooting - [Redis issue delay Admin login or checkout](https://support.magento.com/hc/en-us/articles/360000448493) - [Extended Redis cache implementation Magento Commerce and Cloud 2.3.5+](https://support.magento.com/hc/en-us/articles/360049292532-Extended-Redis-cache-implementation-Magento-Commerce-and-Cloud-2-3-5-) -- [MDVA-30102 Magento patch: Redis cache getting full](https://support.magento.com/hc/en-us/articles/360050393371)] +- [MDVA-30102 Magento patch: Redis cache getting full](https://support.magento.com/hc/en-us/articles/360050393371) - [Managed alerts on Magento Commerce: Redis memory warning alert](https://support.magento.com/hc/en-us/articles/360049928852) - [Managed alerts on Magento Commerce: Redis memory critical alert](https://support.magento.com/hc/en-us/articles/360049936112) - [Redis troubleshooter](https://support.magento.com/hc/en-us/articles/360046673932-Redis-troubleshooter) From db46f956d116163fbca6b3be150dd93c6e9d47d9 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Thu, 30 Jun 2022 16:14:15 -0500 Subject: [PATCH 245/776] Added comment for migration --- src/_includes/graphql/cart-user-input-errors.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/_includes/graphql/cart-user-input-errors.md b/src/_includes/graphql/cart-user-input-errors.md index 50b2283f0a0..cffe6f39365 100644 --- a/src/_includes/graphql/cart-user-input-errors.md +++ b/src/_includes/graphql/cart-user-input-errors.md @@ -1,3 +1,11 @@ + + The `CartUserInputError` object contains information about errors that are specific to carts. | Attribute | Data Type | Description | From 31a7466a2246d5c407b2f03940455fb026c21fb9 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Thu, 30 Jun 2022 16:21:11 -0500 Subject: [PATCH 246/776] Fixed linting error --- src/_includes/graphql/cart-user-input-errors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_includes/graphql/cart-user-input-errors.md b/src/_includes/graphql/cart-user-input-errors.md index cffe6f39365..cae8d362cd7 100644 --- a/src/_includes/graphql/cart-user-input-errors.md +++ b/src/_includes/graphql/cart-user-input-errors.md @@ -1,4 +1,4 @@ - +## v1.1.16 + +- **MDVA-44703** _(for Adobe Commerce and Magento Open Source `>=2.4.3 <2.4.4`)_-Fixes the issue where order totals in the Orders report are miscalculated for the restricted admin user. +- **MDVA-44940** _(for Adobe Commerce and Magento Open Source `>=2.4.3 <2.4.4`)_-Fixes the SQL error that occurs while saving the category from admin. +- **MDVA-44562** _(for Adobe Commerce and Magento Open Source `>=2.4.0 <2.4.2-p2`)_-Fixes the issue where the non-default store id for quote items is overridden by the default store id, despite the GraphQL request originating from the non-default store view. +- **MDVA-43167** _(for Adobe Commerce and Magento Open Source `>=2.4.2 <2.4.4`)_-Fixes the issue where admin order grid mass action doesn't apply for multi-page when admin user selects all orders. +- **MDVA-44044** _(for Adobe Commerce and Magento Open Source `>=2.3.0 <2.4.2-p2`)_-Fixes the issue where a product is not displayed on the category page after it is assigned to a new website. +- **MDVA-42509** _(for Adobe Commerce and Magento Open Source `>=2.3.3 <2.4.4`)_-Fixes the issue where a CSV could not be uploaded for a quick order resulting in an 'Unable to send the cookie' error. +- Updated patches: MDVA-41061, MDVA-42584. +- The prefix for the new QPT patches will be changed from "MDVA" to "ACSD" due to internal process changes. + ## v1.1.15 - **MDVA-40961** _(for Adobe Commerce and Magento Open Source `>=2.4.3 <2.4.4`)_-Fixes the issue where an additional item can't be added to the cart when the minimum qty of the item is already in the cart. From 6a737a0c7a87fca8a5029575a4b3119d443336bb Mon Sep 17 00:00:00 2001 From: Oleksandr Gorbivskyi Date: Fri, 1 Jul 2022 12:02:29 -0700 Subject: [PATCH 248/776] Update src/quality-patches/release-notes.md Co-authored-by: Jeff Matthews --- src/quality-patches/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quality-patches/release-notes.md b/src/quality-patches/release-notes.md index 8fe30f38c5e..8bb7e9b7890 100644 --- a/src/quality-patches/release-notes.md +++ b/src/quality-patches/release-notes.md @@ -30,7 +30,7 @@ For information about quality patches created by the Community for {{site.data.v - **MDVA-44044** _(for Adobe Commerce and Magento Open Source `>=2.3.0 <2.4.2-p2`)_-Fixes the issue where a product is not displayed on the category page after it is assigned to a new website. - **MDVA-42509** _(for Adobe Commerce and Magento Open Source `>=2.3.3 <2.4.4`)_-Fixes the issue where a CSV could not be uploaded for a quick order resulting in an 'Unable to send the cookie' error. - Updated patches: MDVA-41061, MDVA-42584. -- The prefix for the new QPT patches will be changed from "MDVA" to "ACSD" due to internal process changes. +- The prefix for the new Quality Patches Tool patches will be changed from "MDVA" to "ACSD" due to internal process changes. ## v1.1.15 From aa17428a5ff7b83e7a4ef51502fa301dbeaff6e0 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorbivskyi Date: Fri, 1 Jul 2022 12:13:44 -0700 Subject: [PATCH 249/776] Update src/quality-patches/release-notes.md Co-authored-by: Jeff Matthews --- src/quality-patches/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quality-patches/release-notes.md b/src/quality-patches/release-notes.md index 8bb7e9b7890..5db91cd2496 100644 --- a/src/quality-patches/release-notes.md +++ b/src/quality-patches/release-notes.md @@ -23,7 +23,7 @@ For information about quality patches created by the Community for {{site.data.v ## v1.1.16 -- **MDVA-44703** _(for Adobe Commerce and Magento Open Source `>=2.4.3 <2.4.4`)_-Fixes the issue where order totals in the Orders report are miscalculated for the restricted admin user. +- **MDVA-44703** _(for Adobe Commerce and Magento Open Source `>=2.4.3 <2.4.4`)_-Fixes the issue where order totals in the Orders report are miscalculated for the restricted admin user. - **MDVA-44940** _(for Adobe Commerce and Magento Open Source `>=2.4.3 <2.4.4`)_-Fixes the SQL error that occurs while saving the category from admin. - **MDVA-44562** _(for Adobe Commerce and Magento Open Source `>=2.4.0 <2.4.2-p2`)_-Fixes the issue where the non-default store id for quote items is overridden by the default store id, despite the GraphQL request originating from the non-default store view. - **MDVA-43167** _(for Adobe Commerce and Magento Open Source `>=2.4.2 <2.4.4`)_-Fixes the issue where admin order grid mass action doesn't apply for multi-page when admin user selects all orders. From 0e81872d914535403a32b40b1a9a34c6d458ecc7 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorbivskyi Date: Fri, 1 Jul 2022 12:13:49 -0700 Subject: [PATCH 250/776] Update src/quality-patches/release-notes.md Co-authored-by: Jeff Matthews --- src/quality-patches/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quality-patches/release-notes.md b/src/quality-patches/release-notes.md index 5db91cd2496..56ba974200d 100644 --- a/src/quality-patches/release-notes.md +++ b/src/quality-patches/release-notes.md @@ -24,7 +24,7 @@ For information about quality patches created by the Community for {{site.data.v ## v1.1.16 - **MDVA-44703** _(for Adobe Commerce and Magento Open Source `>=2.4.3 <2.4.4`)_-Fixes the issue where order totals in the Orders report are miscalculated for the restricted admin user. -- **MDVA-44940** _(for Adobe Commerce and Magento Open Source `>=2.4.3 <2.4.4`)_-Fixes the SQL error that occurs while saving the category from admin. +- **MDVA-44940** _(for Adobe Commerce and Magento Open Source `>=2.4.3 <2.4.4`)_-Fixes the SQL error that occurs while saving the category from admin. - **MDVA-44562** _(for Adobe Commerce and Magento Open Source `>=2.4.0 <2.4.2-p2`)_-Fixes the issue where the non-default store id for quote items is overridden by the default store id, despite the GraphQL request originating from the non-default store view. - **MDVA-43167** _(for Adobe Commerce and Magento Open Source `>=2.4.2 <2.4.4`)_-Fixes the issue where admin order grid mass action doesn't apply for multi-page when admin user selects all orders. - **MDVA-44044** _(for Adobe Commerce and Magento Open Source `>=2.3.0 <2.4.2-p2`)_-Fixes the issue where a product is not displayed on the category page after it is assigned to a new website. From 3d72e91fe18767261852099bdad69248558c12d0 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorbivskyi Date: Fri, 1 Jul 2022 12:14:02 -0700 Subject: [PATCH 251/776] Update src/quality-patches/release-notes.md Co-authored-by: Jeff Matthews --- src/quality-patches/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quality-patches/release-notes.md b/src/quality-patches/release-notes.md index 56ba974200d..a0c3f21dde0 100644 --- a/src/quality-patches/release-notes.md +++ b/src/quality-patches/release-notes.md @@ -25,7 +25,7 @@ For information about quality patches created by the Community for {{site.data.v - **MDVA-44703** _(for Adobe Commerce and Magento Open Source `>=2.4.3 <2.4.4`)_-Fixes the issue where order totals in the Orders report are miscalculated for the restricted admin user. - **MDVA-44940** _(for Adobe Commerce and Magento Open Source `>=2.4.3 <2.4.4`)_-Fixes the SQL error that occurs while saving the category from admin. -- **MDVA-44562** _(for Adobe Commerce and Magento Open Source `>=2.4.0 <2.4.2-p2`)_-Fixes the issue where the non-default store id for quote items is overridden by the default store id, despite the GraphQL request originating from the non-default store view. +- **MDVA-44562** _(for Adobe Commerce and Magento Open Source `>=2.4.0 <2.4.2-p2`)_-Fixes the issue where the non-default store id for quote items is overridden by the default store id, despite the GraphQL request originating from the non-default store view. - **MDVA-43167** _(for Adobe Commerce and Magento Open Source `>=2.4.2 <2.4.4`)_-Fixes the issue where admin order grid mass action doesn't apply for multi-page when admin user selects all orders. - **MDVA-44044** _(for Adobe Commerce and Magento Open Source `>=2.3.0 <2.4.2-p2`)_-Fixes the issue where a product is not displayed on the category page after it is assigned to a new website. - **MDVA-42509** _(for Adobe Commerce and Magento Open Source `>=2.3.3 <2.4.4`)_-Fixes the issue where a CSV could not be uploaded for a quick order resulting in an 'Unable to send the cookie' error. From 0715b85450aefef6eb6d91703a20184e9b0208a0 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorbivskyi Date: Fri, 1 Jul 2022 12:14:18 -0700 Subject: [PATCH 252/776] Update src/quality-patches/release-notes.md Co-authored-by: Jeff Matthews --- src/quality-patches/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quality-patches/release-notes.md b/src/quality-patches/release-notes.md index a0c3f21dde0..0557f0324af 100644 --- a/src/quality-patches/release-notes.md +++ b/src/quality-patches/release-notes.md @@ -26,7 +26,7 @@ For information about quality patches created by the Community for {{site.data.v - **MDVA-44703** _(for Adobe Commerce and Magento Open Source `>=2.4.3 <2.4.4`)_-Fixes the issue where order totals in the Orders report are miscalculated for the restricted admin user. - **MDVA-44940** _(for Adobe Commerce and Magento Open Source `>=2.4.3 <2.4.4`)_-Fixes the SQL error that occurs while saving the category from admin. - **MDVA-44562** _(for Adobe Commerce and Magento Open Source `>=2.4.0 <2.4.2-p2`)_-Fixes the issue where the non-default store id for quote items is overridden by the default store id, despite the GraphQL request originating from the non-default store view. -- **MDVA-43167** _(for Adobe Commerce and Magento Open Source `>=2.4.2 <2.4.4`)_-Fixes the issue where admin order grid mass action doesn't apply for multi-page when admin user selects all orders. +- **MDVA-43167** _(for Adobe Commerce and Magento Open Source `>=2.4.2 <2.4.4`)_-Fixes the issue where admin order grid mass action doesn't apply for multi-page when admin user selects all orders. - **MDVA-44044** _(for Adobe Commerce and Magento Open Source `>=2.3.0 <2.4.2-p2`)_-Fixes the issue where a product is not displayed on the category page after it is assigned to a new website. - **MDVA-42509** _(for Adobe Commerce and Magento Open Source `>=2.3.3 <2.4.4`)_-Fixes the issue where a CSV could not be uploaded for a quick order resulting in an 'Unable to send the cookie' error. - Updated patches: MDVA-41061, MDVA-42584. From 4101594af2b1bf4778d8f5da0f0cfca1edab7728 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorbivskyi Date: Fri, 1 Jul 2022 12:14:28 -0700 Subject: [PATCH 253/776] Update src/quality-patches/release-notes.md Co-authored-by: Jeff Matthews --- src/quality-patches/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quality-patches/release-notes.md b/src/quality-patches/release-notes.md index 0557f0324af..99c37824ea8 100644 --- a/src/quality-patches/release-notes.md +++ b/src/quality-patches/release-notes.md @@ -27,7 +27,7 @@ For information about quality patches created by the Community for {{site.data.v - **MDVA-44940** _(for Adobe Commerce and Magento Open Source `>=2.4.3 <2.4.4`)_-Fixes the SQL error that occurs while saving the category from admin. - **MDVA-44562** _(for Adobe Commerce and Magento Open Source `>=2.4.0 <2.4.2-p2`)_-Fixes the issue where the non-default store id for quote items is overridden by the default store id, despite the GraphQL request originating from the non-default store view. - **MDVA-43167** _(for Adobe Commerce and Magento Open Source `>=2.4.2 <2.4.4`)_-Fixes the issue where admin order grid mass action doesn't apply for multi-page when admin user selects all orders. -- **MDVA-44044** _(for Adobe Commerce and Magento Open Source `>=2.3.0 <2.4.2-p2`)_-Fixes the issue where a product is not displayed on the category page after it is assigned to a new website. +- **MDVA-44044** _(for Adobe Commerce and Magento Open Source `>=2.3.0 <2.4.2-p2`)_-Fixes the issue where a product is not displayed on the category page after it is assigned to a new website. - **MDVA-42509** _(for Adobe Commerce and Magento Open Source `>=2.3.3 <2.4.4`)_-Fixes the issue where a CSV could not be uploaded for a quick order resulting in an 'Unable to send the cookie' error. - Updated patches: MDVA-41061, MDVA-42584. - The prefix for the new Quality Patches Tool patches will be changed from "MDVA" to "ACSD" due to internal process changes. From 929cf2b792e97ccf859bb40047605b6c87d4fa2a Mon Sep 17 00:00:00 2001 From: Oleksandr Gorbivskyi Date: Fri, 1 Jul 2022 12:14:36 -0700 Subject: [PATCH 254/776] Update src/quality-patches/release-notes.md Co-authored-by: Jeff Matthews --- src/quality-patches/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quality-patches/release-notes.md b/src/quality-patches/release-notes.md index 99c37824ea8..c2916194eb1 100644 --- a/src/quality-patches/release-notes.md +++ b/src/quality-patches/release-notes.md @@ -28,7 +28,7 @@ For information about quality patches created by the Community for {{site.data.v - **MDVA-44562** _(for Adobe Commerce and Magento Open Source `>=2.4.0 <2.4.2-p2`)_-Fixes the issue where the non-default store id for quote items is overridden by the default store id, despite the GraphQL request originating from the non-default store view. - **MDVA-43167** _(for Adobe Commerce and Magento Open Source `>=2.4.2 <2.4.4`)_-Fixes the issue where admin order grid mass action doesn't apply for multi-page when admin user selects all orders. - **MDVA-44044** _(for Adobe Commerce and Magento Open Source `>=2.3.0 <2.4.2-p2`)_-Fixes the issue where a product is not displayed on the category page after it is assigned to a new website. -- **MDVA-42509** _(for Adobe Commerce and Magento Open Source `>=2.3.3 <2.4.4`)_-Fixes the issue where a CSV could not be uploaded for a quick order resulting in an 'Unable to send the cookie' error. +- **MDVA-42509** _(for Adobe Commerce and Magento Open Source `>=2.3.3 <2.4.4`)_-Fixes the issue where a CSV could not be uploaded for a quick order resulting in an 'Unable to send the cookie' error. - Updated patches: MDVA-41061, MDVA-42584. - The prefix for the new Quality Patches Tool patches will be changed from "MDVA" to "ACSD" due to internal process changes. From d6ed02aaa47d7d0b02416daeeb6aa84c2f5c9941 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorbivskyi Date: Fri, 1 Jul 2022 12:14:45 -0700 Subject: [PATCH 255/776] Update src/quality-patches/release-notes.md Co-authored-by: Jeff Matthews --- src/quality-patches/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quality-patches/release-notes.md b/src/quality-patches/release-notes.md index c2916194eb1..129a3b3c84f 100644 --- a/src/quality-patches/release-notes.md +++ b/src/quality-patches/release-notes.md @@ -29,7 +29,7 @@ For information about quality patches created by the Community for {{site.data.v - **MDVA-43167** _(for Adobe Commerce and Magento Open Source `>=2.4.2 <2.4.4`)_-Fixes the issue where admin order grid mass action doesn't apply for multi-page when admin user selects all orders. - **MDVA-44044** _(for Adobe Commerce and Magento Open Source `>=2.3.0 <2.4.2-p2`)_-Fixes the issue where a product is not displayed on the category page after it is assigned to a new website. - **MDVA-42509** _(for Adobe Commerce and Magento Open Source `>=2.3.3 <2.4.4`)_-Fixes the issue where a CSV could not be uploaded for a quick order resulting in an 'Unable to send the cookie' error. -- Updated patches: MDVA-41061, MDVA-42584. +- Updated patches: MDVA-41061, MDVA-42584. - The prefix for the new Quality Patches Tool patches will be changed from "MDVA" to "ACSD" due to internal process changes. ## v1.1.15 From 36aa654b19e0b8961dfdef5b511fae4d80b3fd29 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorbivskyi Date: Fri, 1 Jul 2022 12:14:52 -0700 Subject: [PATCH 256/776] Update src/quality-patches/release-notes.md Co-authored-by: Jeff Matthews --- src/quality-patches/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quality-patches/release-notes.md b/src/quality-patches/release-notes.md index 129a3b3c84f..27cc1b20564 100644 --- a/src/quality-patches/release-notes.md +++ b/src/quality-patches/release-notes.md @@ -30,7 +30,7 @@ For information about quality patches created by the Community for {{site.data.v - **MDVA-44044** _(for Adobe Commerce and Magento Open Source `>=2.3.0 <2.4.2-p2`)_-Fixes the issue where a product is not displayed on the category page after it is assigned to a new website. - **MDVA-42509** _(for Adobe Commerce and Magento Open Source `>=2.3.3 <2.4.4`)_-Fixes the issue where a CSV could not be uploaded for a quick order resulting in an 'Unable to send the cookie' error. - Updated patches: MDVA-41061, MDVA-42584. -- The prefix for the new Quality Patches Tool patches will be changed from "MDVA" to "ACSD" due to internal process changes. +- The prefix for the new Quality Patches Tool patches will be changed from "MDVA" to "ACSD" due to internal process changes. ## v1.1.15 From ce435473c891998397ea6f09cba5388bc3afbbb2 Mon Sep 17 00:00:00 2001 From: jfrontain Date: Fri, 1 Jul 2022 16:20:19 -0500 Subject: [PATCH 257/776] entered keharper's and hgutherie's review comments --- src/guides/v2.3/inventory/release-notes.md | 6 +- src/guides/v2.3/release-notes/2-3-7-p4.md | 2 +- src/guides/v2.4/release-notes/2-4-3-p3.md | 2 +- src/guides/v2.4/release-notes/2-4-4-p1.md | 2 +- .../v2.4/release-notes/b2b-release-notes.md | 16 +- .../v2.4/release-notes/commerce-2-4-5.md | 193 +++++++++++------- 6 files changed, 134 insertions(+), 87 deletions(-) diff --git a/src/guides/v2.3/inventory/release-notes.md b/src/guides/v2.3/inventory/release-notes.md index aa60a4affcd..4111e2a17d7 100644 --- a/src/guides/v2.3/inventory/release-notes.md +++ b/src/guides/v2.3/inventory/release-notes.md @@ -26,11 +26,11 @@ The release notes include: - {:.fix} The default inventory stock status of bundle and grouped products is now updated as expected when a merchant creates a shipment from the Admin. Previously, the status of these products remained unchanged after a shipment was created. -- {:.fix} Configurable products are now returned back to stock when one of these conditions is met: the parent product has at least one saved child in stock, or the configurable product itself was updated and set as **in stock** and had at least one child in stock +- {:.fix} Configurable products are now returned back to stock when one of these conditions is met: the parent product has at least one saved child in stock, or the configurable product itself was updated and set as **in stock** and had at least one child in stock. - {:.fix} Inventory changes implemented through the REST API are now reflected as expected on product detail pages. The cache for catalog products is now cleaned after comparing the last and current stock statuses. Previously, omitting the callback function resulted in the incorrect evaluation of stock status changes, which did not trigger the necessary cache cleaning. As a result, the storefront did not reflect the inventory changes. -- {:.fix} Products that are assigned to default stock and that were previously out of stock are now visible on the storefront after updating the source item using `V1/inventory/source-items’. Previously, this REST API endpoint set the wrong 'stock_status`. +- {:.fix} Products that are assigned to default stock and that were previously out of stock are now visible on the storefront after updating the source item using `V1/inventory/source-items`. Previously, this REST API endpoint set the wrong 'stock_status`. - {:.fix} Unassigning inventory sources through bulk action (**Catalog** > **Products** > **Select Products** > **Actions - Unassign Inventory Source**) now works as expected when sources include SKUs that are duplicates with the exception of a leading zero (for example, `01234` and `1234`). Previously, Magento did not unassign inventory sources and threw an error. @@ -50,7 +50,7 @@ The release notes include: - {:.fix} The performance of save operations that include bundle products that contain many options (several hundred) has been improved. Previously, saving these large bundle products took several minutes and sometimes resulted in timeouts in deployments with Inventory services enabled. [GitHub-34732](https://github.com/magento/magento2/issues/34732) -- {:.fix} The product bulk action tool (**Catalog** > **Products** > **Select Products** > **Actions** > **Assign Inventory Source**) now works as expected when assigning inventory source to multiple products when SKUs are duplicate with the exception of a leading 0 (for example, 01234 and 1234). Previously, only one product was assigned an Inventory source. [GitHub-35171](https://github.com/magento/magento2/issues/35171) +- {:.fix} The product bulk action tool (**Catalog** > **Products** > **Select Products** > **Actions** > **Assign Inventory Source**) now works as expected when assigning inventory source to multiple products when SKUs are duplicated with the exception of a leading 0 (for example, 01234 and 1234). Previously, only one product was assigned an Inventory source. [GitHub-35171](https://github.com/magento/magento2/issues/35171) ### v1.2.4 diff --git a/src/guides/v2.3/release-notes/2-3-7-p4.md b/src/guides/v2.3/release-notes/2-3-7-p4.md index 53cbdbc5f27..1361e87dcdf 100644 --- a/src/guides/v2.3/release-notes/2-3-7-p4.md +++ b/src/guides/v2.3/release-notes/2-3-7-p4.md @@ -16,7 +16,7 @@ Releases may contain backward-incompatible changes (BIC). To review minor backwa This security patch includes: * Security enhancements -* security bug fixes. See Adobe Security Bulletin for the latest discussion of these fixed issues. +* Security bug fixes. See Adobe Security Bulletin for the latest discussion of these fixed issues. ### Security highlights diff --git a/src/guides/v2.4/release-notes/2-4-3-p3.md b/src/guides/v2.4/release-notes/2-4-3-p3.md index ce431ce7f52..4e998a63333 100644 --- a/src/guides/v2.4/release-notes/2-4-3-p3.md +++ b/src/guides/v2.4/release-notes/2-4-3-p3.md @@ -13,7 +13,7 @@ Releases may contain backward-incompatible changes (BIC). To review minor backwa This security patch includes: * Security enhancements -* security bug fixes. See Adobe Security Bulletin for the latest discussion of these fixed issues. +* Security bug fixes. See Adobe Security Bulletin for the latest discussion of these fixed issues. ### Security highlights diff --git a/src/guides/v2.4/release-notes/2-4-4-p1.md b/src/guides/v2.4/release-notes/2-4-4-p1.md index e52577597f3..d837c0cf612 100644 --- a/src/guides/v2.4/release-notes/2-4-4-p1.md +++ b/src/guides/v2.4/release-notes/2-4-4-p1.md @@ -13,7 +13,7 @@ Releases may contain backward-incompatible changes (BIC). To review minor backwa This security patch includes: * Security enhancements -* security bug fixes. See Adobe Security Bulletin for the latest discussion of these fixed issues. +* Security bug fixes. See Adobe Security Bulletin for the latest discussion of these fixed issues. ### Security highlights diff --git a/src/guides/v2.4/release-notes/b2b-release-notes.md b/src/guides/v2.4/release-notes/b2b-release-notes.md index fe4746b0c12..37eec7e0e23 100644 --- a/src/guides/v2.4/release-notes/b2b-release-notes.md +++ b/src/guides/v2.4/release-notes/b2b-release-notes.md @@ -9,13 +9,13 @@ These release notes can include: - {:.new} New features - {:.fix} Fixes and improvements -## {{ site.data.var.ee }} B2B - Adobe Commerce 2.4.5 +## {{ site.data.var.ee }} B2B 1.3.4 - Adobe Commerce 2.4.5 - {:.fix} {{ site.data.var.ee }} no longer sends email notifications each time an existing Company is updated by an API call. Emails are now sent only when a company is created. - {:.fix} {{ site.data.var.ee }} now correctly calculates a negotiable quote grand total when the **Enable Cross Border Trade** tax calculation setting is enabled. -- {:.fix} Configurable products are now moved to the last position in the product listing after stock is updated when the **Move out of stock to the bottom** setting is enabled. A new custom database query has been implemented to negate Elasticsearch index sort order, which disregards Admin-enabled sort order. Previously, configurable products and their child products were not moved to the bottom of the list when this setting was enabled. +- {:.fix} Configurable products are now moved to the last position in the product listing after stock is updated when the **Move out of stock to the bottom** setting is enabled. A new custom database query has been implemented to ensure Elasticsearch index sort order now honors the Admin-enabled sort order. Previously, configurable products and their child products were not moved to the bottom of the list when this setting was enabled. - {:.fix} Purchase Order email now honors the email sending setting of each website in a multi-site deployment. A check for the **Disable Email Communications** setting has been added to the custom logic for email queues. Previously, {{ site.data.var.ee }} did not honor the email sending setting of the secondary website. @@ -25,9 +25,9 @@ These release notes can include: - {:.fix} The **Account Created in** field for a company administrator now retains its value as expected after you save the company. -- {:.fix} customer queries to retrieve customer requisition lists that are filtered by `uid` no longer return empty results. +- {:.fix} The `customer` query no longer returns empty results when it retrieves requisition lists that are filtered by `uid`. -- {:.fix} Added a plugin before the `collectQuoteTotals` call to ensure that store credits are applied only once. +- {:.fix} Added a plugin before the `collectQuoteTotals` call to ensure that store credits are applied only once. - {:.fix} Customers are now redirected to the login page when their account is deleted by an administrator from the Admin. Previously, {{ site.data.var.ee }} threw an error. The plugin (`SessionPlugin`) code block is now inside the `try…catch` block. Previously, this code was not wrapped inside the generic exception handling block. @@ -141,7 +141,7 @@ These release notes can include: ### Requisition lists -- {:.fix} Merchants can now use the POST `rest/all/V1/requisition_lists` endpoint to create a requisition list for a customer. Previously, {{ site.data.var.ee }} threw this 400 error when you tried to create a requisition list: `Could not save Requisition List`. +- {:.fix} Merchants can now use the POST `/all/V1/requisition_lists` endpoint to create a requisition list for a customer. Previously, {{ site.data.var.ee }} threw this 400 error when you tried to create a requisition list: `Could not save Requisition List`. - {:.fix} The **Add to Requisition List** button now appears for a shopping cart’s in-stock products when the cart also contains out-of-stock products. Previously, if a cart contained two products, one of which was out-of-stock, the **Add to Requisition List** button did not appear for either products. @@ -209,7 +209,7 @@ These release notes can include: - {:.fix} Custom customer address attribute fields that are associated with a shopper’s non-default address are now saved as expected in the storefront checkout workflow. -- {:.fix} Orders for products that belong to a store’s default shared catalog can now be placed for shoppers through the Admin REST API (`rest/V1/carts/{{CART_ID}}/items`) as expected. {{ site.data.var.ee }} now checks if the product was assigned to a public catalog before shared catalog permissions validation in `\Magento\SharedCatalog\Plugin\Quote\Api\ValidateAddProductToCartPlugin::beforeSave`. Previously, {{ site.data.var.ee }} did not add the product to the shopper’s cart and threw this error: `No such shared catalog entity`. +- {:.fix} Orders for products that belong to a store’s default shared catalog can now be placed for shoppers through the Admin REST API (`POST /V1/carts/{{CART_ID}}/items`) as expected. {{ site.data.var.ee }} now checks if the product was assigned to a public catalog before shared catalog permissions validation in `\Magento\SharedCatalog\Plugin\Quote\Api\ValidateAddProductToCartPlugin::beforeSave`. Previously, {{ site.data.var.ee }} did not add the product to the shopper’s cart and threw this error: `No such shared catalog entity`. - {:.fix} {{ site.data.var.ee }} now sends new company user registration emails from the {{ site.data.var.ee }} store's address. Previously, this email was sent from the company administrator’s address. @@ -273,13 +273,13 @@ This release includes improvements to order approvals, shipping methods, shoppin - {:.fix} A company can now be updated using the REST API PUT `/V1/company/:companyId` request without specifying the `region_id` when state is configured as **not required**. Previously, even though `region_id` was not required, {{ site.data.var.ee }} threw an error if it was not specified. -- {:.fix} When you create or update a B2B Company using the REST API (`http://magento.local/rest/V1/company/2`, where `2` represents the company ID), the response now includes the settings for `applicable_payment_method` or `available_payment_methods` as expected. +- {:.fix} When you create or update a B2B Company using the REST API (`POST or PUT /V1/company/2`, where `2` represents the company ID), the response now includes the settings for `applicable_payment_method` or `available_payment_methods` as expected. - {:.fix} {{ site.data.var.ee }} no longer displays a 404 page when a merchant uses the **Enter** button instead of clicking the **Save** button when creating a requisition list on the storefront. - {:.fix} Category permissions no longer change when a new product is assigned to a public shared catalog. Previously, category permissions were duplicated. -- {:.fix} The REST API endpoint PUT `rest/default/V1/company/{id}`, which is used to update Company email, is no longer case-sensitive. +- {:.fix} The REST API endpoint `PUT /V1/company/{id}`, which is used to update Company email, is no longer case-sensitive. - {:.fix} Disabling reward modules no longer affects B2B features on customer accounts. Previously, when reward modules were disabled, the following B2B-related tabs were not displayed: Company Profile, Company Users, and Roles and Permissions. diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md index 1a6c6ebca21..548581ce575 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-5.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -5,7 +5,7 @@ title: Adobe Commerce 2.4.5 Release Notes {{ site.data.var.ee }} 2.4.5 introduces support for -This release includes almost quality fixes and enhancements. +This release includes almost 240 quality fixes and enhancements. {:.bs-callout-info} Releases may contain backward-incompatible changes (BIC). {{ site.data.var.ee }} 2.4.5 contains backward-incompatible changes. To review these backward-incompatible changes, see [BIC reference]({{page.baseurl}}/release-notes/backward-incompatible-changes/reference.html). (Major backward-incompatible issues are described in [BIC highlights]({{page.baseurl}}/release-notes/backward-incompatible-changes/index.html). Not all releases introduce major BICs.) @@ -29,10 +29,10 @@ This release includes 20 security fix and platform security improvements. This s No confirmed attacks related to these issues have occurred to date. However, certain vulnerabilities can potentially be exploited to access customer information or take over administrator sessions. Most of these issues require that an attacker first obtains access to the Admin. As a result, we remind you to take all necessary steps to protect your Admin, including but not limited to these efforts: * IP allowlisting -* [two-factor authentication]({{page.baseurl}}/security/two-factor-authentication.html) -* use of a VPN -* use of a unique location rather than `/admin` -* good password hygiene +* [Two-factor authentication]({{page.baseurl}}/security/two-factor-authentication.html) +* Use of a VPN +* Use of a unique location rather than `/admin` +* Good password hygiene See Adobe Security Bulletin for the latest discussion of these fixed issues. @@ -64,7 +64,7 @@ Security improvements for this release improve compliance with the latest securi * `PHPStan` (^1.5.7 with constraint) [GitHub-35315](https://github.com/magento/magento2/issues/35315) -* DHL Integration schema has been updated from v6.0 to v6.2. DHL is deprecated v6.0 +* DHL Integration schema has been updated from v6.0 to v6.2. DHL has deprecated v6.0 Outdated JavaScript libraries have been updated to their latest versions, and outdated dependencies have been removed. These changes are backward compatible. @@ -74,11 +74,11 @@ Outdated JavaScript libraries have been updated to their latest versions, and ou The following Composer dependencies have been updated to the latest versions with constraint: -* `colinmollenhour/credis` (1.13.0 or 1.12.2)? +* `colinmollenhour/credis` (1.13.0)? * `guzzlehttp/guzzle` (^7.4.2) * `laminas/laminas-captcha` (updated with a constraint ^2.12) * `laminas/laminas-db` (^2.15.0) -* `laminas/laminas-di` (^3.4.0) +* `laminas/laminas-di` (^3.7.0) * `laminas/laminas-escaper` (~2.10.0) * `laminas/laminas-eventmanager` (^3.5.0) * `laminas/laminas-feed` (^2.17.0) @@ -86,14 +86,12 @@ The following Composer dependencies have been updated to the latest versions wit * `laminas/laminas-mvc` (^3.3.3) * `laminas/laminas-server` (^2.11.1) * `laminas/laminas-servicemanager` (^3.11.0) -* `laminas/laminas-session` (^2.12.1) * `laminas/laminas-validator` (^2.17.0) * `league/fly` (2.4.3) * `monolog/monolog` (^2.5) * `phpmd/phpmd` (^2.12.0) * `phpstan/phpstan` (^1.5.7) * `phpunit/phpunit` (~9.5.20) -* `phpunit/phpunit` (^9.4) * `php-cs-fixer` (^3.4.0) * `webonyx/graphql-php` (14.11.6) @@ -139,10 +137,6 @@ Primary index performance has been improved by reducing the number of primary in This release includes these GraphQL enhancements: -#### New mutations - -* **Performance improvements**: - See the [GraphQL Developer Guide]({{page.baseurl}}/graphql/) for details on these enhancements. ### Adobe Sign Extension @@ -229,6 +223,10 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. + + +* The path to Magento Analytics is no longer hardcoded. Previously, this hardcoded path resulted in conflicts when multiple Magento instances were installed on one server. [GitHub-29373](https://github.com/magento/magento2/issues/29373) + ### Accessibility @@ -273,7 +271,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* You can now use the REST API to update product price attributes for a specific website. Previously, if some product attributes were overridden for a specific store view, you could not update a price attribute for that product in that same store view. +* You can now use the `PUT /V1/products` endpoint to update product price attributes for a specific website. Previously, if some product attributes were overridden for a specific store view, you could not update a price attribute for that product in that same store view. @@ -285,6 +283,10 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * Full page cache is no longer shown as disabled in the Admin when the Magento cache is flushed and `use_stale_cache` is enabled. + + +* New Relic deployment markers now work as expected when cache is flushed. [GitHub-32649](https://github.com/magento/magento2/issues/32649) + ### Cart and checkout @@ -309,7 +311,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* The update SQL query that update affected quotes after disabling cart price rule has been optimized to avoid locking the entire quote table. +* The SQL query that updates affected quotes after disabling a cart price rule has been optimized to avoid locking the entire quote table. @@ -321,7 +323,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* `cart` query responses no longer return null responses when a product is out of stock, and a new `errors` element containing the error message was introduced to the response. Previously, when you ran a query with an out-of-stock product, Magento displayed a `null` value under the `items` section in the response. See [cart query](https://devdocs.magento.com/guides/v2.4/graphql/queries/cart.html). +* The `cart` query no longer return null responses when a product is out of stock. A new `errors` element containing the error message was introduced to the response. Previously, when you ran a query with an out-of-stock product, Magento displayed a `null` value under the `items` section in the response. See [cart query](https://devdocs.magento.com/guides/v2.4/graphql/queries/cart.html). @@ -333,7 +335,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* Cart contents and login status are now reloaded as expected after a session times out when **Enable Persistence** is set to **yes**. [GitHub-35182](https://github.com/magento/magento2/issues/35182) +* Cart contents and login status are now reloaded as expected after a session times out when **Enable Persistence** is set to **Yes**. [GitHub-35182](https://github.com/magento/magento2/issues/35182) @@ -343,10 +345,6 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * The mini cart now displays previously added products after a session timeout when **Enable Persistence** is enabled . [GitHub-35183](https://github.com/magento/magento2/issues/35183) - - -* Unassigning inventory sources through bulk action (**Catalog** > **Products** > **Select Products** > **Actions - Unassign Inventory Source**) now works as expected when sources include SKUs that are duplicate with the exception of a leading zero (for example, `01234` and `1234`). Previously, {{ site.data.var.ee }} did not unassign inventory sources and threw an error. - * Store credit is now unavailable when the Zero Subtotal Checkout payment method is disabled. Previously, the Store Credit checkbox was not functional during order placement from Admin. {{ site.data.var.ee }} did not place the order with the store credit and displayed this error: `The requested Payment Method is not available`. @@ -369,7 +367,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* Product URL keys now remain unchanged when updating product name via `/rest/default/V1/products/` for a store view. Previously, a new URL key was generated based on the new product name and assigned to the product, which overrode the URL key in that store view. +* Product URL keys now remain unchanged when updating product name via `PUT /V1/products/` for a store view. Previously, a new URL key was generated based on the new product name and assigned to the product, which overrode the URL key in that store view. @@ -425,11 +423,11 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* The same error message is now displayed by the API and on the storefront when trying to retrieve the tier prices of a product with duplicate records. Previously, `PUT rest/all/V1/products/tier-prices` returned an incorrect error message. +* The same error message is now displayed by the API and on the storefront when trying to retrieve the tier prices of a product with duplicate records. Previously, `PUT /V1/products/tier-prices` returned an incorrect error message. -* {{ site.data.var.ee }}now provides validation error messages when you try to add a product URL key with a trailing hyphen. Informative tooltip text is also available. +* {{ site.data.var.ee }} now provides validation error messages when you try to add a product URL key with a trailing hyphen. Informative tooltip text is also available. @@ -445,7 +443,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* When the `Synchronize widget products with backend storage` setting is enabled, {{ site.data.var.ee }}adds recently view product data into the `catalog_product_frontend_action` database table. It includes the customer or visitor ID when adding records. The `recently_viewed_product` section in the response is now empty if customer ID and visitor ID are null. As a result, when the `customer/section/load` Ajax request is sent, {{ site.data.var.ee }} can correctly filter recently viewed products based on customer or visitor ID. Previously, the response included all the data available in the `catalog_product_frontend_action` database table because there was no check for an empty customer or visitor ID. +* When the `Synchronize widget products with backend storage` setting is enabled, {{ site.data.var.ee }} adds recently view product data into the `catalog_product_frontend_action` database table. It includes the customer or visitor ID when adding records. The `recently_viewed_product` section in the response is now empty if customer ID and visitor ID are null. As a result, when the `customer/section/load` Ajax request is sent, {{ site.data.var.ee }} can correctly filter recently viewed products based on customer or visitor ID. Previously, the response included all the data available in the `catalog_product_frontend_action` database table because there was no check for an empty customer or visitor ID. @@ -487,6 +485,16 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. +* A new product cache is now successfully generated after you add a new image with a name that contains '.' to a product, then save the product and clean the image cache. [GitHub-32699](https://github.com/magento/magento2/issues/32699) + + + + + +* {{ site.data.var.ee }} now displays an error message as expected when you try to create an attribute from the product page without completing the Admin field. [GitHub-33099](https://github.com/magento/magento2/issues/33099) + +* Product ratings are now correct on all catalog product lists when the home page contains multiple catalog lists. [GitHub-33867](https://github.com/magento/magento2/issues/33867) + ### Catalog rule ### CMS content @@ -511,7 +519,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* Configurable options are now linked to configurable products that are created in the Admin using `POST /rest/default/V1/configurable-products/configurable1/child`. +* Configurable options are now linked to configurable products that are created in the Admin using `POST /V1/configurable-products/configurable1/child`. @@ -523,7 +531,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* `addConfigurableProductsToCart` queries can now be used to add configurable products with custom options. Previously, {{ site.data.var.ee }} threw this error: `Magento 2.3.4 graphql Notice: Undefined index: option_value in /var/www/html/mg234/vendor/magento/module-configurable-product-graph-ql/Model/Resolver/ConfigurableCartItemOptions.php on line 62`. [GitHub-28860](https://github.com/magento/magento2/issues/28860) +* The `addConfigurableProductsToCart` mutation can now be used to add configurable products with custom options. Previously, {{ site.data.var.ee }} threw this error: `Magento 2.3.4 graphql Notice: Undefined index: option_value in /var/www/html/mg234/vendor/magento/module-configurable-product-graph-ql/Model/Resolver/ConfigurableCartItemOptions.php on line 62`. [GitHub-28860](https://github.com/magento/magento2/issues/28860) @@ -533,6 +541,8 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * {{ site.data.var.ee }} now correctly displays a configurable product’s stock status, available configurations, and displayed price when the availability of one of the configurable product’s child product is changed by a scheduled update. Previously, when a configurable product had two children and the availability of one child product was disabled with a scheduled update, the parent product’s stock status was incorrectly displayed as **Out of Stock** when the update was active, After the update completed, the displayed price and the availability of its configurations was miscalculated. +* You can now re-order configurable products with optional custom options. Previously, re-order attempts failed, and meant displayed this error: `Some of the selected options are not currently available`. [GitHub-35409](https://github.com/magento/magento2/issues/35409) + ### Customer @@ -559,7 +569,11 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* Shoppers now get email reminders about their abandoned carts on the correct schedule. The new `TIMESTAMPDIFF(DAY, ,)` SQL function has replaced the `TO_DAYS()` function and calculates the difference in the timestamps on the basis of date and time. Previously, email reminders were not sent per schedule because of the incorrect calculation of two date-time values of cart abandonment (any timezone) and server time (UTC). +* Customers now get email reminders about their abandoned carts on the correct schedule. The new `TIMESTAMPDIFF(DAY, ,)` SQL function has replaced the `TO_DAYS()` function and calculates the difference in the timestamps on the basis of date and time. Previously, email reminders were not sent per schedule because of the incorrect calculation of two date-time values of cart abandonment (any timezone) and server time (UTC). + + + +* {{ site.data.var.ee }} now displays an error message on the Shipping page when a shopper enters an invalid email format after the shopper clicks **Place Order**. Previously, the error message was displayed on the Payment page. [GitHub-33590](https://github.com/magento/magento2/issues/33590 ### Frameworks @@ -569,7 +583,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* `setup:static-content:deploy -s compact` now includes styles from child themes as expected. Previously, theme CSS files were not present on the storefront after deployment. +* The `bin/magento setup:static-content:deploy -s compact` command now includes styles from child themes as expected. Previously, theme CSS files were not present on the storefront after deployment. @@ -601,7 +615,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* {{ site.data.var.ee }} no longer throws the following error when you create a plugin for any method of class `vendor/magento/module-backend/Model/Menu.php`: `Error: Call to undefined method ReflectionUnionType::getName(). [GitHub-35292](https://github.com/magento/magento2/issues/35292) +* {{ site.data.var.ee }} no longer throws the following error when you create a plugin for any method of class `vendor/magento/module-backend/Model/Menu.php`: `Error: Call to undefined method ReflectionUnionType::getName(). [GitHub-35292](https://github.com/magento/magento2/issues/35292) @@ -613,22 +627,35 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. +* Corrected the `longblog` database definition to `long blob`. [GitHub-35108](https://github.com/magento/magento2/issues/35108) + +* Knockout text containing single quotes are now translatable. [GitHub-34319](https://github.com/magento/magento2/issues/34319) + +* A `TypeError` in `magento2/app/code/Magento/Security/Model/AdminSessionsManager.php` has been corrected from int to string. [GitHub-34415](https://github.com/magento/magento2/issues/34415) + - +* Merchants can now successfully upgrade from an {{ site.data.var.ee }} 2.4.2 deployment with Klarna to {{ site.data.var.ee }} 2.4.3. [GitHub-33760](https://github.com/magento/magento2/issues/33760) +* [GitHub-35150](https://github.com/magento/magento2/issues/35150) + +* Load time of category product list pages have been improved by adding `Magento_Ui/js/core/app` as a `deps` to `app/code/Magento/Ui/view/frontend/requirejs-config.js`. [GitHub-34847](https://github.com/magento/magento2/issues/34847) + +Added an error message to a new exception that was created in the exception handler for cron jobs. +[GitHub-34941](https://github.com/magento/magento2/issues/34941) + @@ -705,7 +732,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* Magento no longer throws the following error during the creation of a catalog rule in the Admin after upgrade: `A technical problem with the server created an error. Try again to continue what you were doing. If the problem persists, try again later`. +* {{ site.data.var.ee }} no longer throws the following error during the creation of a catalog rule in the Admin after upgrade: `A technical problem with the server created an error. Try again to continue what you were doing. If the problem persists, try again later`. @@ -715,21 +742,21 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -### Gift cards + - +* Updated the labels and comment descriptions in `app/code/Magento/NewRelicReporting/etc/adminhtml/system.xml`. [GitHub-31947](https://github.com/magento/magento2/issues/31947) -* `products` queries now correctly returns product data that contains gift card products with a `gift-card` URL key. + -### GraphQL +* Removed unneeded csp_whitelist.xml files. [GitHub-30607](https://github.com/magento/magento2/issues/30607) - +### Gift cards -* `addConfigurableProductsToCart` queries can now be used to add configurable products with custom options. Previously, {{ site.data.var.ee }} threw this error: `Magento 2.3.4 graphql Notice: Undefined index: option_value in /var/www/html/mg234/vendor/magento/module-configurable-product-graph-ql/Model/Resolver/ConfigurableCartItemOptions.php on line 62`. [GitHub-28860](https://github.com/magento/magento2/issues/28860) + - +* `products` queries now correctly returns product data that contains gift card products with a `gift-card` URL key. -* `CartItemInterface` now includes `customizable_options`. [GitHub-31180](https://github.com/magento/magento2/issues/31180) +### GraphQL @@ -739,10 +766,6 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * The `products` query no longer returns attributes as an aggregation when the **Use in Search Results** Layered Navigation setting is disabled. [GitHub-33318](https://github.com/magento/magento2/issues/33318) - - -* The `updateCartCurrency` function now sets string instead of an object inside the cart object. Previously, {{ site.data.var.ee }} did not load a quote using `getQuote` because the `updateCartCurrency` function set an object instead of a string inside the cart object. [GitHub-34199](https://github.com/magento/magento2/issues/34199) - * A `price_including_tax` field has been added to `CartItemPrices`. [GitHub-29057](https://github.com/magento/magento2/issues/29057) @@ -757,11 +780,11 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* The `GetLines` query no longer throws an exception when fetching a list of categories one of which contains an image that can’t be found on the filesystem. Previously, {{ site.data.var.ee }} threw this exception: Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) +* The `categories` query no longer throws an exception when fetching a list of categories one of which contains an image that can’t be found on the filesystem. Previously, {{ site.data.var.ee }} threw this exception: Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) -* The `GetProductsInCategory` query now returns `category_uid` as an aggregation as expected. [GitHub-32557](https://github.com/magento/magento2/issues/32557) +* The `products` query now returns `category_uid` as an aggregation as expected. [GitHub-32557](https://github.com/magento/magento2/issues/32557) @@ -769,7 +792,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* The `urlresolver` query now resolves the path delimiter (/) correctly when multiple homepages have the same identifier. Previously, the query did not resolve the delimiter and returned null. [GitHub-33615](https://github.com/magento/magento2/issues/33615) +* The `urlResolver` query now resolves the path delimiter (/) correctly when multiple homepages have the same identifier. Previously, the query did not resolve the delimiter and returned null. [GitHub-33615](https://github.com/magento/magento2/issues/33615) @@ -781,7 +804,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* `products` queries no longer returns price_range values for configurable products that are affected by disabled variants. [GitHub-33629](https://github.com/magento/magento2/issues/33629) +* The `products` query no longer returns price_range values for configurable products that are affected by disabled variants. [GitHub-33629](https://github.com/magento/magento2/issues/33629) @@ -805,7 +828,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* The `searchProducts` query no longer returns attributes as an aggregation when the **Use in Search Results Layered Navigation** setting is disabled. [GitHub-33318](https://github.com/magento/magento2/issues/33318) +* The `products` query no longer returns attributes as an aggregation when the **Use in Search Results Layered Navigation** setting is disabled. [GitHub-33318](https://github.com/magento/magento2/issues/33318) @@ -825,11 +848,11 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* The `getCartDetails` query now returns only one payment methods for free orders. Previously, all active payment methods were returned in the query response. [GitHub-34036](https://github.com/magento/magento2/issues/34036) +* The `cart` query now returns only one payment methods for free orders. Previously, all active payment methods were returned in the query response. [GitHub-34036](https://github.com/magento/magento2/issues/34036) -* The `GetLines` query no longer throws an exception when fetching a list of categories one of which contains an image that can’t be found on the filesystem. Previously, {{ site.data.var.ee }} threw this exception: Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) +* The `categories` query no longer throws an exception when fetching a list of categories one of which contains an image that can’t be found on the filesystem. Previously, {{ site.data.var.ee }} threw this exception: Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) @@ -839,10 +862,6 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * The `updateCartItems` query now removes products as expected when the product stock has reached the maximum stock amount. [GitHub-30220](https://github.com/magento/magento2/issues/30220) - - -* The `urlresolver` query now resolves the path delimiter (/) correctly when multiple homepages have the same identifier. Previously, the query did not resolve the delimiter and returned null. [GitHub-33615](https://github.com/magento/magento2/issues/33615) - * `customer` queries now fetch bundle product multi-select options as expected when querying orders. [GitHub-34717](https://github.com/magento/magento2/issues/34717) @@ -861,7 +880,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* The `generateCustomerTokenAsAdmin` request now retrieves customer tokens as expected. Previously, tokens were not returned, and this error was returned: `Customer email provided does not exist`. +* The `generateCustomerTokenAsAdmin` mutation now retrieves customer tokens as expected. Previously, tokens were not returned, and this error was returned: `Customer email provided does not exist`. @@ -869,27 +888,31 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* Customers added through the `createCustomer/createCustomerV2/updateCustomer/updateCustomerV2` mutation are now added with active newsletter subscriptions. Previously, customers were unsubscribed from newsletters even when the request contained proper input parameters. [GitHub-33599](https://github.com/magento/magento2/issues/33599) +* Customers added or updates with the `createCustomer`, `createCustomerV2`, `updateCustomer`, or `updateCustomerV2` mutation are now added with active newsletter subscriptions. Previously, customers were unsubscribed from newsletters even when the request contained proper input parameters. [GitHub-33599](https://github.com/magento/magento2/issues/33599) -* The `productDetail` query for a specific store view now returns only categories that are in the specific website's root category in multi-site deployment. Previously, the query returned categories from the root categories of other websites. [GitHub-34570](https://github.com/magento/magento2/issues/34570) +* The `products` query for a specific store view now returns only categories that are in the specific website's root category in multi-site deployment. Previously, the query returned categories from the root categories of other websites. [GitHub-34570](https://github.com/magento/magento2/issues/34570) -* The `getProductFiltersByCategory` query now returns only the sub category of provided category ID. Previously, it returned all categories. [GitHub-35220](https://github.com/magento/magento2/issues/35220) +* The `products` query now returns only the sub category of provided category ID. Previously, it returned all categories. [GitHub-35220](https://github.com/magento/magento2/issues/35220) -* The `customerOrders` query now responds as expected when the `gift_message` object is specified in the response but no gift message exists. Previously, the query returned this message: `Can't load gift message for order is returned`. +* The `customerOrders` query now responds as expected when the `gift_message` object is specified in the response but no gift message exists. Previously, the query returned this message: `Can't load gift message for order is returned`. [GitHub-28957](https://github.com/magento/magento2/issues/28957) -* Fixed a bug with the `catalog_category_product` indexer that caused the `products` query to return categories from another store. +* Fixed a bug with the `catalog_category_product` indexer that caused the `products` query to return categories from another store. [GitHub-31253](https://github.com/magento/magento2/issues/31253) - + -* `productDetail` queries for a specific store view now returns only categories that are in the specific website's root category. Previously, this query returned categories in every root category. [GitHub-34570](https://github.com/magento/magento2/issues/34570) +* The `generateCustomerToken` mutation now creates an entry in the `customer_log` as expected after generating a customer token. [GitHub-33378](https://github.com/magento/magento2/issues/33378) + + + +* The `V1/products/base-prices` endpoint now works as expected with **Catalog Price Mode - Website**. [GitHub-30132](https://github.com/magento/magento2/issues/30132) ### Image @@ -943,6 +966,18 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. +* Race conditions no longer interrupt the creation of the `contentUpdated` event listener. [GitHub-32068](https://github.com/magento/magento2/issues/32068) + + + +* The `getTypeID` function now returns product type ID not product ID. [GitHub-35458](https://github.com/magento/magento2/issues/35458) + + + +* jQuery UI slider and `SelectMenu` mapping has been corrected in `vendor/magento/module-theme/view/base/requirejs-config.js`. + +* Observers placed on `sales_order_state_change_before` now support the retrieval of data from the order object. The `sales_order_state_change_before` `event` argument has been updated. [GitHub-26789](https://github.com/magento/magento2/issues/26789) + #### Library removals and deprecations #### Library upgrades @@ -987,10 +1022,6 @@ Repetitive actions have been replaced with action groups in these tests: * The newsletter subscription confirmation email now has the correct, store-specific email address in the **From** field if the customer is assigned to a non-default store and subscribed or unsubscribed from the Admin. Previously, the customer received an email with default email in **From** header. [GitHub-34963](https://github.com/magento/magento2/issues/34963) - - -* Customers added through the `createCustomer/createCustomerV2/updateCustomer/updateCustomerV2` mutation are now added with active newsletter subscriptions. Previously, customers were unsubscribed from newsletters even when the request contained proper input parameters. [GitHub-33599](https://github.com/magento/magento2/issues/33599) - ### Order @@ -1073,6 +1104,10 @@ Repetitive actions have been replaced with action groups in these tests: + + +* Fixed issue with `array_merge` in loops. [GitHub-33929](https://github.com/magento/magento2/issues/33929) + ### Pricing @@ -1113,7 +1148,7 @@ Repetitive actions have been replaced with action groups in these tests: -* The `/rest/default/V1/returnsAttributeMetadata` endpoint now works correctly when the `rma_item` entity default attribute set ID differs from the default installation ID. Previously, this endpoint returned an empty result if these IDs differed. +* The `GET /V1/returnsAttributeMetadata` endpoint now works correctly when the `rma_item` entity default attribute set ID differs from the default installation ID. Previously, this endpoint returned an empty result if these IDs differed. @@ -1135,6 +1170,10 @@ Repetitive actions have been replaced with action groups in these tests: * Credit memos for guest orders no longer check for `customer_id`, which skips querying the `magento_reward_history' database table table for reward points. This change has improved performance. +### Roles + +* The **Store** > **Configuration** > **Services** page now displays Magento Web API information as expected when Resource Access is set to **Custom** on the Role Resources tab. [GitHub-35506](https://github.com/magento/magento2/issues/35506) + ### Sales ### Sales Rule @@ -1263,11 +1302,11 @@ Repetitive actions have been replaced with action groups in these tests: -* The `getCartDetails` query no longer includes tax when returning `subtotal_with_discount_excluding_tax`. [GitHub-33905](https://github.com/magento/magento2/issues/33905) +* The `cart` query no longer includes tax when returning `subtotal_with_discount_excluding_tax`. [GitHub-33905](https://github.com/magento/magento2/issues/33905) -* Web API requests for order data (`rest/V1/orders/`) no longer returns negative values for row totals. +* Web API requests for order data (`GET/V1/orders/`) no longer returns negative values for row totals. @@ -1281,6 +1320,8 @@ Repetitive actions have been replaced with action groups in these tests: * The `testCreateProductOnStoreLevel` integration test no longer causes a nested transaction on the database. +* The following exception no longer occurs when running WebAPI tests for the Send Friend feature when product image has not set on PHP 8.1: `exception main.ERROR: /var/www/html/lib/internal/Magento/Framework/DataObject.php:131 strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated`. [GitHub-34864](https://github.com/magento/magento2/issues/34864) + #### Unit tests ### Theme @@ -1377,10 +1418,16 @@ Repetitive actions have been replaced with action groups in these tests: +* The favicon icon upload form now supports `.ico` file types. Previously, when you tried to upload a favicon file with this extension type in the Admin, Magento displayed this error: `Warning: imagecreatefromstring(): one parameter to a memory allocation multiplication is negative or zero, failing operation gracefully in /var/www/html/vendor/magento/module-media-storage/Model/File/Validator/Image.php on line 64`. [GitHub-34858](https://github.com/magento/magento2/issues/34858) + + + +* Corrected display issues with the drop-down Select menu in the Admin grid. [GitHub-35386](https://github.com/magento/magento2/issues/35386) + ### URL rewrites @@ -1417,11 +1464,11 @@ Repetitive actions have been replaced with action groups in these tests: -* Cart price rules created through the `/rest/V1/salesRules/` endpoint now retain existing coupon code values after changing status from disabled to enabled. [GitHub-35298](https://github.com/magento/magento2/issues/35298) +* Cart price rules created through the `POST /V1/salesRules/` endpoint now retain existing coupon code values after changing status from disabled to enabled. [GitHub-35298](https://github.com/magento/magento2/issues/35298) -* Cart price rules created through the `/rest/V1/salesRules/` endpoint now contain valid `from_date` and `to_date` values. [GitHub-35265](https://github.com/magento/magento2/issues/35265) +* Cart price rules created through the `POST /V1/salesRules/` endpoint now contain valid `from_date` and `to_date` values. [GitHub-35265](https://github.com/magento/magento2/issues/35265) From ec81cf4db49eb82bb55f9edc6d071ebad685d409 Mon Sep 17 00:00:00 2001 From: vkolesny Date: Fri, 1 Jul 2022 16:23:48 -0500 Subject: [PATCH 258/776] ACP2E-994: [Documentation] Add notice that Admin, Bearer and other types of tokens are not supported to skip providing of HTTP X-Captcha header. --- src/guides/v2.4/graphql/protected-mutations.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/guides/v2.4/graphql/protected-mutations.md b/src/guides/v2.4/graphql/protected-mutations.md index ccad4fae168..7500a0a1dec 100644 --- a/src/guides/v2.4/graphql/protected-mutations.md +++ b/src/guides/v2.4/graphql/protected-mutations.md @@ -5,6 +5,10 @@ title: Protected mutations If CAPTCHA or reCAPTCHA is enabled on pages requiring shopper input, then in most cases, the corresponding mutations that send requests to the Magento server must include an HTTP header that contains a value entered by the shopper (for CAPTCHA) or generated by the Google API (for reCAPTCHA). However, if you specify an integration authorization token in the header of the mutation, then you do not supply a header specific to CAPTCHA or reCAPTCHA. +HTTP `X-Captcha` header: +- Cannot be received by automated script or non-UI API call. It is captured and returned by UI Web form only. +- Is optional in protected mutation API calls with providing **_integration authorization_** tokens only. It cannot be skipped with Admin and Bearer tokens. + ## CAPTCHA The following table lists the forms that can be configured to require CAPTCHA. Go to **Stores** > **Configuration** > **Customers** > **Customer Configuration** > **CAPTCHA** > **Forms** to enable or disable CAPTCHA on these forms. From b8f4bfbf607b97c2094c038c5d5506ae5f7c4735 Mon Sep 17 00:00:00 2001 From: vkolesny Date: Fri, 1 Jul 2022 16:48:56 -0500 Subject: [PATCH 259/776] ACP2E-994: [Documentation] Add notice that Admin, Bearer and other types of tokens are not supported to skip providing of HTTP X-Captcha header. --- src/guides/v2.4/graphql/protected-mutations.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/guides/v2.4/graphql/protected-mutations.md b/src/guides/v2.4/graphql/protected-mutations.md index 7500a0a1dec..7c85a817405 100644 --- a/src/guides/v2.4/graphql/protected-mutations.md +++ b/src/guides/v2.4/graphql/protected-mutations.md @@ -6,6 +6,7 @@ title: Protected mutations If CAPTCHA or reCAPTCHA is enabled on pages requiring shopper input, then in most cases, the corresponding mutations that send requests to the Magento server must include an HTTP header that contains a value entered by the shopper (for CAPTCHA) or generated by the Google API (for reCAPTCHA). However, if you specify an integration authorization token in the header of the mutation, then you do not supply a header specific to CAPTCHA or reCAPTCHA. HTTP `X-Captcha` header: + - Cannot be received by automated script or non-UI API call. It is captured and returned by UI Web form only. - Is optional in protected mutation API calls with providing **_integration authorization_** tokens only. It cannot be skipped with Admin and Bearer tokens. From d4d90af3b4334e3ebde081693f4c1b295d7bce4b Mon Sep 17 00:00:00 2001 From: vkolesny Date: Fri, 1 Jul 2022 16:54:42 -0500 Subject: [PATCH 260/776] ACP2E-994: [Documentation] Add notice that Admin, Bearer and other types of tokens are not supported to skip providing of HTTP X-Captcha header. --- src/guides/v2.4/graphql/protected-mutations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/guides/v2.4/graphql/protected-mutations.md b/src/guides/v2.4/graphql/protected-mutations.md index 7c85a817405..815d5134ddf 100644 --- a/src/guides/v2.4/graphql/protected-mutations.md +++ b/src/guides/v2.4/graphql/protected-mutations.md @@ -7,8 +7,8 @@ If CAPTCHA or reCAPTCHA is enabled on pages requiring shopper input, then in mos HTTP `X-Captcha` header: -- Cannot be received by automated script or non-UI API call. It is captured and returned by UI Web form only. -- Is optional in protected mutation API calls with providing **_integration authorization_** tokens only. It cannot be skipped with Admin and Bearer tokens. +* Cannot be received by automated script or non-UI API call. It is captured and returned by UI Web form only. +* Is optional in protected mutation API calls with providing **_integration authorization_** tokens only. It cannot be skipped with Admin and Bearer tokens. ## CAPTCHA From 9ee64dc22c0bc7a0b51f7275ae4c5e044948b518 Mon Sep 17 00:00:00 2001 From: vkolesny Date: Fri, 1 Jul 2022 16:59:10 -0500 Subject: [PATCH 261/776] ACP2E-994: [Documentation] Add notice that Admin, Bearer and other types of tokens are not supported to skip providing of HTTP X-Captcha header. --- src/guides/v2.4/graphql/protected-mutations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/graphql/protected-mutations.md b/src/guides/v2.4/graphql/protected-mutations.md index 815d5134ddf..e8977d8ce73 100644 --- a/src/guides/v2.4/graphql/protected-mutations.md +++ b/src/guides/v2.4/graphql/protected-mutations.md @@ -8,7 +8,7 @@ If CAPTCHA or reCAPTCHA is enabled on pages requiring shopper input, then in mos HTTP `X-Captcha` header: * Cannot be received by automated script or non-UI API call. It is captured and returned by UI Web form only. -* Is optional in protected mutation API calls with providing **_integration authorization_** tokens only. It cannot be skipped with Admin and Bearer tokens. +* Is optional in protected mutation API calls with providing **_integration authorization_** tokens only. It cannot be skipped with Admin and Bearer tokens. ## CAPTCHA From 9467dd590a0e63b29faa5d9082855727fcbd9624 Mon Sep 17 00:00:00 2001 From: magedocs Date: Mon, 4 Jul 2022 14:38:47 +0000 Subject: [PATCH 262/776] Update News data --- src/_data/whats-new.yml | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/_data/whats-new.yml b/src/_data/whats-new.yml index 62398ff43a3..911026fb232 100644 --- a/src/_data/whats-new.yml +++ b/src/_data/whats-new.yml @@ -4,8 +4,46 @@ description: This page contains recent changes that we think you'd like to know We exclude from this list proofreading, spelling checks, and all minor updates. link: "/whats-new.html" thread: "/whatsnew-feed.xml" -updated: Mon Jun 27 14:38:49 2022 +updated: Mon Jul 4 14:38:45 2022 entries: +- description: Published [release notes](https://devdocs.magento.com/quality-patches/release-notes.html) + for the 1.1.16 Quality Patches Tool (QPT) package release. + versions: 2.3.x, 2.4.x + type: Major Update + date: July 1, 2022 + link: https://github.com/magento-commerce/devdocs/pull/3041 + merge_commit: 9fdcefcaf5218e84070e90bc1aae5a0fdb13f6ea + contributor: agorbivskyi + membership: true + labels: + - Major Update + - 2.3.x + - 2.4.x +- description: The [REST API Guide](https://devdocs.magento.com/guides/v2.4/rest/bk-rest.html) + topics moved to the [Adobe Developer documentation](https://developer.adobe.com/commerce/webapi/rest/) + and will be redirected soon. + versions: '' + type: Major Update + date: June 30, 2022 + link: https://github.com/magento-commerce/devdocs/pull/3030 + merge_commit: 49967163918d0696e5a680e52a2093ef443d4207 + contributor: jhadobe + membership: true + labels: + - Major Update + - migration +- description: Added the `user_outputs` output attribute to the [`addProductsToCart`](https://devdocs.magento.com/guides/v2.4/graphql/mutations/add-products-to-cart.html) + GraphQL mutation. + versions: 2.4.x + type: Major Update + date: June 30, 2022 + link: https://github.com/magento-commerce/devdocs/pull/3038 + merge_commit: 035e85978f73c140f5b119f63cb415547ef5c7d6 + contributor: thiaramus + membership: true + labels: + - Major Update + - 2.4.x - description: The [Frontend Developer Guide](https://devdocs.magento.com/guides/v2.4/frontend-dev-guide/bk-frontend-dev-guide.html) topics moved to the [Adobe Developer documentation](https://developer.adobe.com/commerce/frontend-core/guide/) and will be redirected soon. From 2feb4b013f964e15426e4912bbd84d4c1c43e478 Mon Sep 17 00:00:00 2001 From: Taoufiq Ait Ali Date: Mon, 4 Jul 2022 21:08:44 +0200 Subject: [PATCH 263/776] fix typo group instead of field fix typo in field section --- src/guides/v2.4/config-guide/prod/config-reference-systemxml.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/config-guide/prod/config-reference-systemxml.md b/src/guides/v2.4/config-guide/prod/config-reference-systemxml.md index 70806337f1d..7da3633834c 100644 --- a/src/guides/v2.4/config-guide/prod/config-reference-systemxml.md +++ b/src/guides/v2.4/config-guide/prod/config-reference-systemxml.md @@ -273,7 +273,7 @@ A ``-Tag can have the following children: | Node | Description | Type | |-----------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------| | `label` | Defines the label that is displayed in the frontend. | `string` | -| `comment` | Adds a comment below the group label. By using `` HTML can be applied. | `string` | +| `comment` | Adds a comment below the field label. By using `` HTML can be applied. | `string` | | `tooltip` | Another possible frontend element that also can be used to describe the meaning of this field. Will be displayed as a small icon beside the field. | `string` | | `hint` | Displays additional information. Only available with specific `frontend_model`. | `string` | | `frontend_class` | Adds a defined CSS class to the rendered section HTML element. | `string` | From 44677be1dc5467690421d9055cc332e2539203b8 Mon Sep 17 00:00:00 2001 From: Ravi Chandra Date: Wed, 6 Jul 2022 10:58:08 +0530 Subject: [PATCH 264/776] Update apply patch in cloud docs --- src/cloud/project/project-patch.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cloud/project/project-patch.md b/src/cloud/project/project-patch.md index feb48846137..11c53dba964 100644 --- a/src/cloud/project/project-patch.md +++ b/src/cloud/project/project-patch.md @@ -156,7 +156,11 @@ To apply patches in a Cloud environment: {:.bs-callout-info} After upgrading to a new version of {{site.data.var.ee}}, you must re-apply patches if the patches are not included in the new version. -1. Commit and push the updated `.magento.env.yaml` file. +1. Add, commit and push the updated `.magento.env.yaml` file. + + ```bash + git add .magento.env.yaml + ``` ```bash git commit -m "Apply patch" @@ -187,7 +191,7 @@ To apply and test a custom patch on a Cloud environment: 1. Add, commit, and push code changes. ```bash - git add -A + git add m2-hotfixes/ ``` ```bash From 167390e1a7954758103ff9016cd2c87e4c88f7f2 Mon Sep 17 00:00:00 2001 From: jfrontain Date: Thu, 7 Jul 2022 15:03:58 -0500 Subject: [PATCH 265/776] added final descriptions for community fixes --- src/guides/v2.3/inventory/release-notes.md | 2 + .../v2.4/release-notes/commerce-2-4-5.md | 162 ++++++++---------- 2 files changed, 71 insertions(+), 93 deletions(-) diff --git a/src/guides/v2.3/inventory/release-notes.md b/src/guides/v2.3/inventory/release-notes.md index 4111e2a17d7..b5b06e484b0 100644 --- a/src/guides/v2.3/inventory/release-notes.md +++ b/src/guides/v2.3/inventory/release-notes.md @@ -52,6 +52,8 @@ The release notes include: - {:.fix} The product bulk action tool (**Catalog** > **Products** > **Select Products** > **Actions** > **Assign Inventory Source**) now works as expected when assigning inventory source to multiple products when SKUs are duplicated with the exception of a leading 0 (for example, 01234 and 1234). Previously, only one product was assigned an Inventory source. [GitHub-35171](https://github.com/magento/magento2/issues/35171) +- {:.fix} `only_x_left_in_stock` now returns 0 if inventory is 0. Previously, it returned null. [GitHub-29932](https://github.com/magento/magento2/issues/29932) + ### v1.2.4 {{site.data.var.im}} 1.2.4 (module version: `magento/inventory-metapackage = 1.2.4`) is supported with version 2.4.4 and compatible with version 2.4.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md index 548581ce575..0b133b16b9d 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-5.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -217,15 +217,9 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * Merchants can now successfully upgrade from an {{ site.data.var.ee }} 2.4.2 deployment with Klarna to {{ site.data.var.ee }} 2.4.3. [GitHub-33760](https://github.com/magento/magento2/issues/33760) - - - - - - -* The path to Magento Analytics is no longer hardcoded. Previously, this hardcoded path resulted in conflicts when multiple Magento instances were installed on one server. [GitHub-29373](https://github.com/magento/magento2/issues/29373) +* The path to {{ site.data.var.ee }} Analytics is no longer hardcoded. Previously, this hardcoded path resulted in conflicts when multiple {{ site.data.var.ee }} instances were installed on one server. [GitHub-29373](https://github.com/magento/magento2/issues/29373) ### Accessibility @@ -257,16 +251,12 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * Screen reader users are informed when a new page view is rendered. Previously, when a page title changed, the title change was not announced. -### AdminGWS - ### Adobe Stock * Users can now successfully sign out of Adobe Stock. -### Backend - ### Bundle products @@ -281,7 +271,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* Full page cache is no longer shown as disabled in the Admin when the Magento cache is flushed and `use_stale_cache` is enabled. +* Full page cache is no longer shown as disabled in the Admin when the {{ site.data.var.ee }} cache is flushed and `use_stale_cache` is enabled. @@ -323,7 +313,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* The `cart` query no longer return null responses when a product is out of stock. A new `errors` element containing the error message was introduced to the response. Previously, when you ran a query with an out-of-stock product, Magento displayed a `null` value under the `items` section in the response. See [cart query](https://devdocs.magento.com/guides/v2.4/graphql/queries/cart.html). +* The `cart` query no longer return null responses when a product is out of stock. A new `errors` element containing the error message was introduced to the response. Previously, when you ran a query with an out-of-stock product, {{ site.data.var.ee }} displayed a `null` value under the `items` section in the response. See [cart query](https://devdocs.magento.com/guides/v2.4/graphql/queries/cart.html). @@ -353,10 +343,10 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * Merchants can now create a credit memo in which **Refund Shipping (Incl. Tax)** is set to -0.01 and can now set this amount to 0. Previously, the credit memo could not be created under these conditions. - - +* Coupons that are set for one-time use can now be redeemed only once as expected. [GitHub-35077](https://github.com/magento/magento2/issues/35077) + ### Cart price rule @@ -477,26 +467,16 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * The EAV indexer now processes product IDs as type `int` to prevent possible performance issues. - - - - - - * A new product cache is now successfully generated after you add a new image with a name that contains '.' to a product, then save the product and clean the image cache. [GitHub-32699](https://github.com/magento/magento2/issues/32699) - - * {{ site.data.var.ee }} now displays an error message as expected when you try to create an attribute from the product page without completing the Admin field. [GitHub-33099](https://github.com/magento/magento2/issues/33099) * Product ratings are now correct on all catalog product lists when the home page contains multiple catalog lists. [GitHub-33867](https://github.com/magento/magento2/issues/33867) -### Catalog rule - ### CMS content @@ -543,6 +523,10 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * You can now re-order configurable products with optional custom options. Previously, re-order attempts failed, and meant displayed this error: `Some of the selected options are not currently available`. [GitHub-35409](https://github.com/magento/magento2/issues/35409) + + +* The addConfigurableProductsToCart mutation now works as expected with multiple products. Previously, incorrect product information was returned, or an invalid error message was returned. [GitHub-30948](https://github.com/magento/magento2/issues/30948) + ### Customer @@ -623,7 +607,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* Magento no longer triggers a `trim(): Passing null to parameter #1 ($string) of type string is deprecated` error when the AMPQ connection is configured without SSL configuration. +* {{ site.data.var.ee }} no longer triggers a `trim(): Passing null to parameter #1 ($string) of type string is deprecated` error when the AMPQ connection is configured without SSL configuration. @@ -643,7 +627,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* [GitHub-35150](https://github.com/magento/magento2/issues/35150) +* `.htpasswd` has been added to banned locations in the `nginx` configuration file. [GitHub-35150](https://github.com/magento/magento2/issues/35150) @@ -651,19 +635,24 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. - +* The `ProductRepository.php:get` method now returns cache keys once. Previously, they were returned twice. [GitHub-34958](https://github.com/magento/magento2/issues/34958) -Added an error message to a new exception that was created in the exception handler for cron jobs. -[GitHub-34941](https://github.com/magento/magento2/issues/34941) + - +* Added an error message to a new exception that was created in the exception handler for cron jobs. [GitHub-34941](https://github.com/magento/magento2/issues/34941) +* The ReadMe files for the GraphQl-GroupedProductGraphQl modules have been updated. [GitHub-34951](https://github.com/magento/magento2/issues/34951) + +* [GitHub-34430](https://github.com/magento/magento2/issues/34430) + +* The storefront print order/invoice/credit memo pages no longer display the default Luma logo instead of the logo that has been specified for display on the website. [GitHub-34942](https://github.com/magento/magento2/issues/34942) + ### General fixes @@ -736,11 +725,11 @@ Added an error message to a new exception that was created in the exception hand - +* {{ site.data.var.ee }} no longer throws an error when you activate the **Check here to link an RSS feed to your Wish List** checkbox before clicking on **Share Wish list**. [GitHub-34998](https://github.com/magento/magento2/issues/34998) - +* The title of the **Show Password** checkbox (Customer Login, Customer Registration, Customer Edit (Change Password section), and Customer Set New Password forms) is now translatable. [GitHub-34857](https://github.com/magento/magento2/issues/34857) @@ -778,7 +767,7 @@ Added an error message to a new exception that was created in the exception hand * The `getCartDetails` query now returns only one payment methods for free orders. Previously, all active payment methods were returned in the query response. [GitHub-34036](https://github.com/magento/magento2/issues/34036) - + * The `categories` query no longer throws an exception when fetching a list of categories one of which contains an image that can’t be found on the filesystem. Previously, {{ site.data.var.ee }} threw this exception: Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) @@ -790,7 +779,7 @@ Added an error message to a new exception that was created in the exception hand * The `updateCartItems` query now removes products as expected when the product stock has reached the maximum stock amount. [GitHub-30220](https://github.com/magento/magento2/issues/30220) - + * The `urlResolver` query now resolves the path delimiter (/) correctly when multiple homepages have the same identifier. Previously, the query did not resolve the delimiter and returned null. [GitHub-33615](https://github.com/magento/magento2/issues/33615) @@ -912,7 +901,13 @@ Added an error message to a new exception that was created in the exception hand -* The `V1/products/base-prices` endpoint now works as expected with **Catalog Price Mode - Website**. [GitHub-30132](https://github.com/magento/magento2/issues/30132) +* The `V1/products/base-prices` endpoint now works as expected with **Catalog Price Mode - Website**. [GitHub-30132](https://github.com/magento/magento2/issues/30132) + +### Google Analytics + + + +* The Google Tag module has been added to the codebase, which supports the transition to Google Analytics 4 in July 2023. You can currently use and collect new data in your Google Universal Analytics properties, but Google Universal will reach end-of-life in July 2023. [GitHub-35204](https://github.com/magento/magento2/issues/35204), [GitHub-35376](https://github.com/magento/magento2/issues/35376) ### Image @@ -948,7 +943,7 @@ Added an error message to a new exception that was created in the exception hand -### Index +* Existing records in the `catalog_url_rewrite_product_category` table are now deleted before inserting new ones. Previously, the following error occurred during multi-store product import: `SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '74583' for key 'PRIMARY', query was: INSERT INTO catalog_url_rewrite_product_category (url_rewrite_id,category_id,product_id) VALUES (?, ?, ?)`. [GitHub-34210](https://github.com/magento/magento2/issues/34210) ### Infrastructure @@ -978,12 +973,14 @@ Added an error message to a new exception that was created in the exception hand * Observers placed on `sales_order_state_change_before` now support the retrieval of data from the order object. The `sales_order_state_change_before` `event` argument has been updated. [GitHub-26789](https://github.com/magento/magento2/issues/26789) + + +* `indexer:reset` has been refactored to call `$indexer->invalidate()`. [GitHub-34988](https://github.com/magento/magento2/issues/34988) + #### Library removals and deprecations #### Library upgrades -### Invoice - ### Logging @@ -992,8 +989,6 @@ Added an error message to a new exception that was created in the exception hand ### {{ site.data.var.ee }} coding standard -### Media Gallery - ### MFTF #### New action groups @@ -1007,7 +1002,10 @@ Repetitive actions have been replaced with action groups in these tests: #### New tests +`AdminUnlockAdminUserEntityTest` [GitHub-34836](https://github.com/magento/magento2/issues/34836) + `StorefrontNewsletterSubscriptionWithEnabledNeedToConfirmConfigTest` [GitHub-33344](https://github.com/magento/magento2/issues/33344) + #### Refactored tests `AdminCancelTheCreatedOrderWithCashOnDeliveryPaymentMethodTest` [GitHub-33692](https://github.com/magento/magento2/issues/33692) @@ -1022,6 +1020,10 @@ Repetitive actions have been replaced with action groups in these tests: * The newsletter subscription confirmation email now has the correct, store-specific email address in the **From** field if the customer is assigned to a non-default store and subscribed or unsubscribed from the Admin. Previously, the customer received an email with default email in **From** header. [GitHub-34963](https://github.com/magento/magento2/issues/34963) + + +* The unsubscribe URL in the newsletter email template now works as expected. [GitHub-33310](https://github.com/magento/magento2/issues/33310) + ### Order @@ -1062,12 +1064,12 @@ Repetitive actions have been replaced with action groups in these tests: -* Magento now displays correct order status during checkout when customer store credit is used. - - +* {{ site.data.var.ee }} now displays correct order status during checkout when customer store credit is used. +* The `increment_id` column in the `sales_order` table has been increased. Previously, third-party modules that assumed that `sales_order.increment_id` had a length of 50 characters saved only the first 32 characters of an `increment_id`. [GitHub-34521](https://github.com/magento/magento2/issues/34521) + ### Payment methods @@ -1078,16 +1080,20 @@ Repetitive actions have been replaced with action groups in these tests: * Payment Review page in the checkout workflow now displays the correct payment method name when payment is made with Venmo, PayPal Later, or PayPal. - - +* The `getCartDetails` query no longer returns all active payment methods for free orders. [GitHub-34036](https://github.com/magento/magento2/issues/34036) + #### PayPal * {{ site.data.var.ee }} now shows the correct customer name in a guest order paid for with PayPal. Previously, the customer name was displayed as Guest. + + +* The PaypalExpressToken resolver has been updated to use correct input from the GraphQL schema. Previously, adding the `use_paypal_credit` input that is defined in `etc/schema.graphqls` to `createPaypalExpressToken` requests has no effect because the code was incorrectly checking for the presence of `paypal_credit` rather than `use_paypal_credit`. [GitHub-35180](https://github.com/magento/magento2/issues/35180) + ### Performance @@ -1104,6 +1110,8 @@ Repetitive actions have been replaced with action groups in these tests: +* The Catalog Search fulltext indexer has been relocated outside the stores loop, which streamlines re-indexing. [GitHub-33984](https://github.com/magento/magento2/issues/33984) + * Fixed issue with `array_merge` in loops. [GitHub-33929](https://github.com/magento/magento2/issues/33929) @@ -1118,32 +1126,16 @@ Repetitive actions have been replaced with action groups in these tests: * The price listed on the product detail page is now the same as the price listed in the checkout workflow for tier prices that differ by quantity selected (for example, a product priced differently based on buying 2 items versus 5 items). Previously, the checkout price reflected the price for the lowest product quantity. -### Product - - - - - -### ProductAlert - -### Product video - ### Promotions * The **Times Used** value for a discount is no longer incremented twice when a guest customer places an order with a discount and subsequently registers an account. - - ### ReCAPTCHA * The **Submit** button on the Login and Create an Account pages is now inactive until ReCaptcha is fully loaded. -### Reports - - - ### Return Merchandise Authorizations (RMA) @@ -1154,8 +1146,6 @@ Repetitive actions have been replaced with action groups in these tests: * The **Use Default** checkbox, which is used to enable RMA on the product edit page, now works as expected for Default Store. Previously, the checkbox was cleared immediately after the product was saved. -### Reviews - ### Rewards @@ -1172,11 +1162,7 @@ Repetitive actions have been replaced with action groups in these tests: ### Roles -* The **Store** > **Configuration** > **Services** page now displays Magento Web API information as expected when Resource Access is set to **Custom** on the Role Resources tab. [GitHub-35506](https://github.com/magento/magento2/issues/35506) - -### Sales - -### Sales Rule +* The **Store** > **Configuration** > **Services** page now displays {{ site.data.var.ee }} Web API information as expected when Resource Access is set to **Custom** on the Role Resources tab. [GitHub-35506](https://github.com/magento/magento2/issues/35506) ### Search @@ -1206,6 +1192,8 @@ Repetitive actions have been replaced with action groups in these tests: +* Fixed PHP errors on the `catalogsearch/advanced/result` and  `catalogsearch/advanced/index` pages. Previously, {{ site.data.var.ee }} displayed this error when an array was passed in any advanced search string : `Warning: trim() expects parameter 1 to be string, array given | magento/module-catalog-search`. [GitHub-33586](https://github.com/magento/magento2/issues/33586) + ### Shipping @@ -1220,8 +1208,6 @@ Repetitive actions have been replaced with action groups in these tests: * Table rate shipping rates with zero price are now displayed correctly in the checkout workflow Order Summary block for orders that have had a discount coupon applied. Previously, the shipping method was not displayed. - - ### Staging @@ -1272,8 +1258,6 @@ Repetitive actions have been replaced with action groups in these tests: * Problems with DHL domestic shipping in deployments running PHP 8.1 have been resolved by requiring dutiable tags for international shipments only. -### Store - ### Tax @@ -1308,8 +1292,6 @@ Repetitive actions have been replaced with action groups in these tests: * Web API requests for order data (`GET/V1/orders/`) no longer returns negative values for row totals. - - ### Test @@ -1322,10 +1304,6 @@ Repetitive actions have been replaced with action groups in these tests: * The following exception no longer occurs when running WebAPI tests for the Send Friend feature when product image has not set on PHP 8.1: `exception main.ERROR: /var/www/html/lib/internal/Magento/Framework/DataObject.php:131 strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated`. [GitHub-34864](https://github.com/magento/magento2/issues/34864) -#### Unit tests - -### Theme - ### Translations and locales @@ -1352,6 +1330,10 @@ Repetitive actions have been replaced with action groups in these tests: * Search Synonyms now respect their assigned store scope. Previously, a synonym assigned to a specific store was searchable on any other store. + + +* Problems with the Filipino (Philippines) locale has been resolved. [GitHub-33996](https://github.com/magento/magento2/issues/33996) + ### UI @@ -1414,20 +1396,18 @@ Repetitive actions have been replaced with action groups in these tests: * You can now switch between store views when website restrictions are enabled. Previously, problems with the store view switcher prevented switching store views. - - -* The favicon icon upload form now supports `.ico` file types. Previously, when you tried to upload a favicon file with this extension type in the Admin, Magento displayed this error: `Warning: imagecreatefromstring(): one parameter to a memory allocation multiplication is negative or zero, failing operation gracefully in /var/www/html/vendor/magento/module-media-storage/Model/File/Validator/Image.php on line 64`. [GitHub-34858](https://github.com/magento/magento2/issues/34858) - - - - +* The favicon icon upload form now supports `.ico` file types. Previously, when you tried to upload a favicon file with this extension type in the Admin, {{ site.data.var.ee }} displayed this error: `Warning: imagecreatefromstring(): one parameter to a memory allocation multiplication is negative or zero, failing operation gracefully in /var/www/html/vendor/magento/module-media-storage/Model/File/Validator/Image.php on line 64`. [GitHub-34858](https://github.com/magento/magento2/issues/34858) * Corrected display issues with the drop-down Select menu in the Admin grid. [GitHub-35386](https://github.com/magento/magento2/issues/35386) + + +* [GitHub-34430](https://github.com/magento/magento2/issues/34430) + ### URL rewrites @@ -1482,20 +1462,16 @@ Repetitive actions have been replaced with action groups in these tests: * The Bulk Rest API now works with the `bySku` option for configurable products. Previously, it returned a 500 error. - - - - - - ### Wish list -* Updating an item quantity from the wishlist page now updates the quantity on the product detail page as expected. {{ site.data.var.ee }} now picks up the updated value from the product URL and populates the `qty` field of product detail page from the wishlist itself. +* Updating an item quantity from the wish list page now updates the quantity on the product detail page as expected. {{ site.data.var.ee }} now picks up the updated value from the product URL and populates the `qty` field of product detail page from the wishlist itself. ## Known issues +**Issue**: {{ site.data.var.ee }} displays the following message when an administrator logs in: `Invalid security or form key. Please refresh the page`. **Workaround**: Refresh the page. To permanent remove this error occurrence, you can lengthen the session lifetime from the command line ( for example, `bin/magento config:set admin/security/session_lifetime 10800`). [GitHub-33749](https://github.com/magento/magento2/issues/33749) + ## Community contributions We are grateful to the wider Magento community and would like to acknowledge their contributions to this release. From a5d2321a10eb56f7e663af7e1e0de55f86c74384 Mon Sep 17 00:00:00 2001 From: jfrontain Date: Thu, 7 Jul 2022 21:04:06 -0500 Subject: [PATCH 266/776] entered keharper's review comments --- src/guides/v2.3/inventory/release-notes.md | 4 +- .../v2.4/release-notes/b2b-release-notes.md | 2 +- .../v2.4/release-notes/commerce-2-4-5.md | 22 +- .../v2.4/release-notes/open-source-2-4-5.md | 1214 ++++++++++++++++- 4 files changed, 1201 insertions(+), 41 deletions(-) diff --git a/src/guides/v2.3/inventory/release-notes.md b/src/guides/v2.3/inventory/release-notes.md index b5b06e484b0..d53f0d2b620 100644 --- a/src/guides/v2.3/inventory/release-notes.md +++ b/src/guides/v2.3/inventory/release-notes.md @@ -30,7 +30,7 @@ The release notes include: - {:.fix} Inventory changes implemented through the REST API are now reflected as expected on product detail pages. The cache for catalog products is now cleaned after comparing the last and current stock statuses. Previously, omitting the callback function resulted in the incorrect evaluation of stock status changes, which did not trigger the necessary cache cleaning. As a result, the storefront did not reflect the inventory changes. -- {:.fix} Products that are assigned to default stock and that were previously out of stock are now visible on the storefront after updating the source item using `V1/inventory/source-items`. Previously, this REST API endpoint set the wrong 'stock_status`. +- {:.fix} Products that are assigned to default stock and that were previously out of stock are now visible on the storefront after updating the source item using `/V1/inventory/source-items`. Previously, this REST API endpoint set the wrong `stock_status`. - {:.fix} Unassigning inventory sources through bulk action (**Catalog** > **Products** > **Select Products** > **Actions - Unassign Inventory Source**) now works as expected when sources include SKUs that are duplicates with the exception of a leading zero (for example, `01234` and `1234`). Previously, Magento did not unassign inventory sources and threw an error. @@ -52,7 +52,7 @@ The release notes include: - {:.fix} The product bulk action tool (**Catalog** > **Products** > **Select Products** > **Actions** > **Assign Inventory Source**) now works as expected when assigning inventory source to multiple products when SKUs are duplicated with the exception of a leading 0 (for example, 01234 and 1234). Previously, only one product was assigned an Inventory source. [GitHub-35171](https://github.com/magento/magento2/issues/35171) -- {:.fix} `only_x_left_in_stock` now returns 0 if inventory is 0. Previously, it returned null. [GitHub-29932](https://github.com/magento/magento2/issues/29932) +- {:.fix} The `ProductInterface.only_x_left_in_stock` field now returns 0 if inventory is 0. Previously, it returned null. [GitHub-29932](https://github.com/magento/magento2/issues/29932) ### v1.2.4 diff --git a/src/guides/v2.4/release-notes/b2b-release-notes.md b/src/guides/v2.4/release-notes/b2b-release-notes.md index 37eec7e0e23..0662b280d27 100644 --- a/src/guides/v2.4/release-notes/b2b-release-notes.md +++ b/src/guides/v2.4/release-notes/b2b-release-notes.md @@ -141,7 +141,7 @@ These release notes can include: ### Requisition lists -- {:.fix} Merchants can now use the POST `/all/V1/requisition_lists` endpoint to create a requisition list for a customer. Previously, {{ site.data.var.ee }} threw this 400 error when you tried to create a requisition list: `Could not save Requisition List`. +- {:.fix} Merchants can now use the POST `/V1/requisition_lists` endpoint to create a requisition list for a customer. Previously, {{ site.data.var.ee }} threw this 400 error when you tried to create a requisition list: `Could not save Requisition List`. - {:.fix} The **Add to Requisition List** button now appears for a shopping cart’s in-stock products when the cart also contains out-of-stock products. Previously, if a cart contained two products, one of which was out-of-stock, the **Add to Requisition List** button did not appear for either products. diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md index 0b133b16b9d..af9e70bd7af 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-5.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -99,7 +99,7 @@ The `laminas/laminas-session`, `laminas/laminas-text`, and `laminas/laminas-view #### Other upgrades and replacements -* DHL Integration schema has been updated from v6.0 to v6.2. (DHL is deprecating the v6.0 schema mid-2022.) +* DHL Integration schema has been updated from v6.0 to v6.2. (DHL will deprecate the v6.0 schema mid-2022.) * The default Gateway URL for USPS shipping has been updated to use `https` instead of `http`. @@ -525,7 +525,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* The addConfigurableProductsToCart mutation now works as expected with multiple products. Previously, incorrect product information was returned, or an invalid error message was returned. [GitHub-30948](https://github.com/magento/magento2/issues/30948) +* The `addConfigurableProductsToCart` mutation now works as expected with multiple products. Previously, incorrect product information was returned, or an invalid error message was returned. [GitHub-30948](https://github.com/magento/magento2/issues/30948) ### Customer @@ -599,7 +599,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* {{ site.data.var.ee }} no longer throws the following error when you create a plugin for any method of class `vendor/magento/module-backend/Model/Menu.php`: `Error: Call to undefined method ReflectionUnionType::getName(). [GitHub-35292](https://github.com/magento/magento2/issues/35292) +* {{ site.data.var.ee }} no longer throws the following error when you create a plugin for any method of class `vendor/magento/module-backend/Model/Menu.php`: `Error: Call to undefined method ReflectionUnionType::getName()`. [GitHub-35292](https://github.com/magento/magento2/issues/35292) @@ -737,7 +737,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* Removed unneeded csp_whitelist.xml files. [GitHub-30607](https://github.com/magento/magento2/issues/30607) +* Removed unneeded `csp_whitelist.xml` files. [GitHub-30607](https://github.com/magento/magento2/issues/30607) ### Gift cards @@ -877,7 +877,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* Customers added or updates with the `createCustomer`, `createCustomerV2`, `updateCustomer`, or `updateCustomerV2` mutation are now added with active newsletter subscriptions. Previously, customers were unsubscribed from newsletters even when the request contained proper input parameters. [GitHub-33599](https://github.com/magento/magento2/issues/33599) +* Customers added or updated with the `createCustomer`, `createCustomerV2`, `updateCustomer`, or `updateCustomerV2` mutation are now added with active newsletter subscriptions. Previously, customers were unsubscribed from newsletters even when the request contained proper input parameters. [GitHub-33599](https://github.com/magento/magento2/issues/33599) @@ -901,7 +901,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* The `V1/products/base-prices` endpoint now works as expected with **Catalog Price Mode - Website**. [GitHub-30132](https://github.com/magento/magento2/issues/30132) +* The `/V1/products/base-prices` endpoint now works as expected with **Catalog Price Mode - Website**. [GitHub-30132](https://github.com/magento/magento2/issues/30132) ### Google Analytics @@ -943,7 +943,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* Existing records in the `catalog_url_rewrite_product_category` table are now deleted before inserting new ones. Previously, the following error occurred during multi-store product import: `SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '74583' for key 'PRIMARY', query was: INSERT INTO catalog_url_rewrite_product_category (url_rewrite_id,category_id,product_id) VALUES (?, ?, ?)`. [GitHub-34210](https://github.com/magento/magento2/issues/34210) +* Existing records in the `catalog_url_rewrite_product_category` table are now deleted before inserting new ones. Previously, the following error occurred during multi-store product import: `SQLSTATE[23000]: Integrity constraint violation`. [GitHub-34210](https://github.com/magento/magento2/issues/34210) ### Infrastructure @@ -1082,7 +1082,7 @@ Repetitive actions have been replaced with action groups in these tests: -* The `getCartDetails` query no longer returns all active payment methods for free orders. [GitHub-34036](https://github.com/magento/magento2/issues/34036) +* The `cart` query no longer returns all active payment methods for free orders. [GitHub-34036](https://github.com/magento/magento2/issues/34036) #### PayPal @@ -1092,7 +1092,7 @@ Repetitive actions have been replaced with action groups in these tests: -* The PaypalExpressToken resolver has been updated to use correct input from the GraphQL schema. Previously, adding the `use_paypal_credit` input that is defined in `etc/schema.graphqls` to `createPaypalExpressToken` requests has no effect because the code was incorrectly checking for the presence of `paypal_credit` rather than `use_paypal_credit`. [GitHub-35180](https://github.com/magento/magento2/issues/35180) +* The resolver for the createPaypalExpressToken mutation has been updated to correctly use the value specified in the use_paypal_credit input field. Previously, it attempted to use an invalid `paypal_credit` field. [GitHub-35180](https://github.com/magento/magento2/issues/35180) ### Performance @@ -1290,7 +1290,7 @@ Repetitive actions have been replaced with action groups in these tests: -* Web API requests for order data (`GET/V1/orders/`) no longer returns negative values for row totals. +* Web API requests for order data (`GET /V1/orders/`) no longer returns negative values for row totals. ### Test @@ -1470,7 +1470,7 @@ Repetitive actions have been replaced with action groups in these tests: ## Known issues -**Issue**: {{ site.data.var.ee }} displays the following message when an administrator logs in: `Invalid security or form key. Please refresh the page`. **Workaround**: Refresh the page. To permanent remove this error occurrence, you can lengthen the session lifetime from the command line ( for example, `bin/magento config:set admin/security/session_lifetime 10800`). [GitHub-33749](https://github.com/magento/magento2/issues/33749) +**Issue**: {{ site.data.var.ee }} displays the following message when an administrator logs in: `Invalid security or form key. Please refresh the page`. **Workaround**: Refresh the page. To permanently remove this error occurrence, you can lengthen the session lifetime from the command line (for example, `bin/magento config:set admin/security/session_lifetime 10800`). [GitHub-33749](https://github.com/magento/magento2/issues/33749) ## Community contributions diff --git a/src/guides/v2.4/release-notes/open-source-2-4-5.md b/src/guides/v2.4/release-notes/open-source-2-4-5.md index 68b8d680242..a21f5d8d5aa 100644 --- a/src/guides/v2.4/release-notes/open-source-2-4-5.md +++ b/src/guides/v2.4/release-notes/open-source-2-4-5.md @@ -65,54 +65,791 @@ This release brings enhanced conformance to standard accessibility guidelines. We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. - ### Installation, upgrade, deployment -### Accessibility + + +* You can now rename a data patch and add the old class name as an alias in the `patch_list` database table. {{ site.data.var.ee }} now checks whether data patch aliases already existed in the database before applying the patch. Previously, {{ site.data.var.ee }} threw an error under these conditions. + + + +* {{ site.data.var.ee }} no longer throws an exception when you try to change the Admin URL to a custom URL from the Admin. Previously, after changing the Admin URL, you could not log in. [GitHub-35416](https://github.com/magento/magento2/issues/35416) + + + +* Merchants can now successfully upgrade from an {{ site.data.var.ee }} 2.4.2 deployment with Klarna to {{ site.data.var.ee }} 2.4.3. [GitHub-33760](https://github.com/magento/magento2/issues/33760) + + + +* The path to {{ site.data.var.ee }} Analytics is no longer hardcoded. Previously, this hardcoded path resulted in conflicts when multiple {{ site.data.var.ee }} instances were installed on one server. [GitHub-29373](https://github.com/magento/magento2/issues/29373) + +### Accessibility + + + +* The **Shopping bag** button now provides a programmatic or textual indication of its state. Screen reader users are informed that clicking this button will expand other content, or that the associated content is expanded or collapsed. Previously, this button did not provide a programmatic or textual indication of its state. + + + +* Payment Information credit card option text elements or images of text now meet the WCAG 2.0 required minimum color contrast ratio of 4.5:1 for standard text of 18pt (24px) or 14pt (19px) if bolded. Previously, they did not meet the expected contrast ratio. + + + +* **Address book** > **Communication** > **Account information** custom focus indicators now provide a contrast ratio of at least 3:1 against the background color. + + + +* **Filter** and **Sort** button text now meet the WCAG 2.0 required minimum color contrast ratio of 4.5:1 for standard text of 18pt (24px) or 14pt (19px) if bolded. Previously, navigation buttons for carousels did not meet these minimum contrast requirements. + + + +* Screen readers announce the word “Venia” only once when navigating to Venia headers and footers. Previously, the same word was announced twice consecutively. + + + +* Buttons that trigger dropdowns now provide information to screen readers that indicate their expanded or collapsed state and accessible names. + + + +* Screen reader users are informed when a new page view is rendered. Previously, when a page title changed, the title change was not announced. + +### Adobe Stock + + + +* Users can now successfully sign out of Adobe Stock. + +### Bundle products + + + +* You can now use the `PUT /V1/products` endpoint to update product price attributes for a specific website. Previously, if some product attributes were overridden for a specific store view, you could not update a price attribute for that product in that same store view. + + + +* {{ site.data.var.ee }} now correctly calculates the cart total for a bundle product when the Product Subselect rule is applied. + +### Cache + + + +* Full page cache is no longer shown as disabled in the Admin when the {{ site.data.var.ee }} cache is flushed and `use_stale_cache` is enabled. + + + +* New Relic deployment markers now work as expected when cache is flushed. [GitHub-32649](https://github.com/magento/magento2/issues/32649) + +### Cart and checkout + + + +* The `Parent Only` attribute scope is now used properly in the Cart Rule condition. + + + +* Company name is now visible as expected in the billing and shipping address sections of the checkout workflow. + + + +* The address search pop-up on the billing step of the checkout workflow no longer causes DOM errors. + + + +* The `addProductsToCart` mutation now works correctly with multiple products. Previously, this query returned the first product with an accurate subtotal, but returned a subtotal of 0 for other products. + + + +* Permission exceptions are now handled for restricted products that are added by SKU. Shoppers are now given an appropriate message on the storefront, and the quantity field in the error table is disabled. Previously, {{ site.data.var.ee }} threw an exception like this: `There has been an error processing your request`. + + + +* The SQL query that updates affected quotes after disabling a cart price rule has been optimized to avoid locking the entire quote table. + + + +* Shoppers with global account sharing are no longer required to log in again to a secondary website in a multisite deployment when guest checkout is disabled. Customer data is now loaded when the shopper navigates to the subdomain. The shopper is no longer asked to log in again, and the previous cart contents are displayed. + + + +* Address dropdown values in the checkout workflow no longer change for the remaining items in a quote when a single quantity address item is removed in a multi-address checkout. Previously, when a product was removed from a quote during multi-address checkout, the address dropdown value changed to default for all products. + + + +* The `cart` query no longer return null responses when a product is out of stock. A new `errors` element containing the error message was introduced to the response. Previously, when you ran a query with an out-of-stock product, {{ site.data.var.ee }} displayed a `null` value under the `items` section in the response. See [cart query](https://devdocs.magento.com/guides/v2.4/graphql/queries/cart.html). + + + +* Shipping methods are now available as expected when a guest shopper creates an account after adding a product to their cart before proceeding to checkout. Previously, when a guest added a product the cart before creating an account, no shipping methods were available during checkout. After adding other products to the cart, shipping methods became available. + + + +* Shoppers can now add products to their carts when no options in the **Allow Countries** field have been selected. + + + +* Cart contents and login status are now reloaded as expected after a session times out when **Enable Persistence** is set to **Yes**. [GitHub-35182](https://github.com/magento/magento2/issues/35182) + + + +* Mini cart subtotals are now updated correctly when a shopper navigates from the shipping page to the cart page in the checkout workflow for an order with multiple shipping addresses. Previously, the subtotal was doubled. + + + +* The mini cart now displays previously added products after a session timeout when **Enable Persistence** is enabled . [GitHub-35183](https://github.com/magento/magento2/issues/35183) + + + +* Store credit is now unavailable when the Zero Subtotal Checkout payment method is disabled. Previously, the Store Credit checkbox was not functional during order placement from Admin. {{ site.data.var.ee }} did not place the order with the store credit and displayed this error: `The requested Payment Method is not available`. + + + +* Merchants can now create a credit memo in which **Refund Shipping (Incl. Tax)** is set to -0.01 and can now set this amount to 0. Previously, the credit memo could not be created under these conditions. + + + +* Coupons that are set for one-time use can now be redeemed only once as expected. [GitHub-35077](https://github.com/magento/magento2/issues/35077) + +### Cart price rule + + + +* The `Parent Only` attribute scope is now used properly in the Cart Rule condition. + +### Catalog + + + +* Product URL keys now remain unchanged when updating product name via `PUT /V1/products/` for a store view. Previously, a new URL key was generated based on the new product name and assigned to the product, which overrode the URL key in that store view. + + + +* Rule-based upsell products are no longer shown twice on the product page. + + + +* Adding a product to a category from the Page Builder product widget set to carousel mode no longer triggers a page reload. + + + +* Products set to **Not Visible Individually** no longer appear in catalog Advanced Search results. + + + +* Dynamic bundle attributes are now updated correctly on the Mass Attribute Update page. Previously, the **Dynamic SKU** attribute remained set to **Yes** even though they were disabled on the Mass Update page. + + + +* Catalog rules are now correctly applied using incremental indexers rather than a full re-index. + + + +* You can now successfully switch between list and grid views of multi-page product lists. Previously, when you navigated to the last page of a multi-page product list view before switching to the grid view, {{ site.data.var.ee }} displayed this error: `Unfortunately there are no products in this category on our website currently`. + + + +* Admin Action Log reports now display updated product IDs and updated status information as expected. + + + +* Triggers are now restored as expected to the `catalogrule_product_price` table after a full reindex. Previously, triggers were removed from the `catalogrule_product_price` table after a `catalogrule_rule` or `catalogrule_product` full re-index. + + + +* Category rules that are used to assign products to categories no longer randomly change. + + + +* {{ site.data.var.ee }} no longer throws an error when a category rule assigns a product to a category that is subsequently sorted in a multi-site deployment. + + + +* Categories can no longer be updated globally by an administrator with scope-restricted access. Previously, when multiple websites used the same category but different products, and an administrator with permission restricted to one store changed products in the category, the product selection also changed for other stores. + + + +* The product details page now displays the correct price when a non-default currency for a specified locale is used. Previously, numbers were not localized as expected on the storefront. + + + +* Products can now be enabled using a scheduled update. + + + +* The same error message is now displayed by the API and on the storefront when trying to retrieve the tier prices of a product with duplicate records. Previously, `PUT /V1/products/tier-prices` returned an incorrect error message. + + + +* {{ site.data.var.ee }} now provides validation error messages when you try to add a product URL key with a trailing hyphen. Informative tooltip text is also available. + + + +* The category list product count is now correct when using inventory single-source mode with the **Display Out-Of-Stock Products** setting enabled. A new plugin now uses `AreProductsSalableInterface` and `StockConfigurationInterface` to determine the total number of products. Previously, the category product list returned the wrong product quantity. + + + +* The new `ConfigurableWishlistItem.configured_variant` field has replaced the `ConfigurableWishlistItem.child_sku` field. The latter field triggered an internal error when a customer wishlist contained an un-configured configurable product. + + + +* URL rewrites are now generated only for the selected stores during the mass attribute update to change product visibility. Previously, the mass attribute update created a URL rewrite for the wrong store. + + + +* When the `Synchronize widget products with backend storage` setting is enabled, {{ site.data.var.ee }} adds recently view product data into the `catalog_product_frontend_action` database table. It includes the customer or visitor ID when adding records. The `recently_viewed_product` section in the response is now empty if customer ID and visitor ID are null. As a result, when the `customer/section/load` Ajax request is sent, {{ site.data.var.ee }} can correctly filter recently viewed products based on customer or visitor ID. Previously, the response included all the data available in the `catalog_product_frontend_action` database table because there was no check for an empty customer or visitor ID. + + + +* Category rules with a `Quantity` attribute for configurable products now work correctly when staging is implemented. Previously, when products had different values for `row_id` and `entity_id` in the `catalog_product_entity` table due to staging updates, the Visual Merchandiser **Match product by rule** functionality did not correctly filter the products. + + + +* Administrators can now change configurable product options in a shopper’s cart from the Admin slide panel. Previously, the slide panel did not work correctly. + + + +* Page cache is now cleared as expected for the configurable product parent when changes to a child product are saved. Previously, because the cache was not cleared, changes were not selected on the storefront configuration product page. [GitHub-34508](https://github.com/magento/magento2/issues/34508) + + + +* Product lists are now rendered correctly in the Admin. Previously, the product list did not render, and {{ site.data.var.ee }} displayed this error: `Item (Magento\Catalog\Model\Product\Interceptor) with the same ID "" already exists`. [GitHub-33145](https://github.com/magento/magento2/issues/33145) + + + +* Product prices are now the same on the product detail page and in storefront search in multi-store deployments after Catalogue Price Scope changes from **website** to **global**. Previously, the Catalog Search Results page displayed the **global** price, and the product details page displayed the **website** price. [GitHub-34074](https://github.com/magento/magento2/issues/34074) + + + +* Layered navigation now displays products with the highest prices as expected when **Price Navigation Step Calculation** is set to **Manual**. + + + +* You can now change the per-page product limit displayed within a category when **Remember Category Pagination** is enabled. Previously, the cookie `form_key` and UI `form_key` differed, and {{ site.data.var.ee }} displayed this error: `Invalid Form Key. Please refresh the page`. + + + +* The EAV indexer now processes product IDs as type `int` to prevent possible performance issues. + + + +* A new product cache is now successfully generated after you add a new image with a name that contains '.' to a product, then save the product and clean the image cache. [GitHub-32699](https://github.com/magento/magento2/issues/32699) + + + +* {{ site.data.var.ee }} now displays an error message as expected when you try to create an attribute from the product page without completing the Admin field. [GitHub-33099](https://github.com/magento/magento2/issues/33099) + +* Product ratings are now correct on all catalog product lists when the home page contains multiple catalog lists. [GitHub-33867](https://github.com/magento/magento2/issues/33867) + +### CMS content + + + +* Merchants can no longer edit an active scheduled update from the entity edit page. + + + +* An administrator with restricted permissions can now view a CMS page in the CMS hierarchy after a scheduled update. + +### Configurable products + + + +* {{ site.data.var.ee }} now displays the correct product price for a configurable product with a selected option after changing its quantity on product details page. Previously, the price was reset to the initial value after the quantity changed. + + + +* The `products` query now retrieves prices for configurable products that accurately reflect the **Display Out Of Stock** configuration setting. Previously, the query did not return accurate prices. + + + +* Configurable options are now linked to configurable products that are created in the Admin using `POST /V1/configurable-products/configurable1/child`. + + + +* Multi-select attributes are now saved correctly during product edit. Previously, {{ site.data.var.ee }} saved the default option for non-selected attributes as well as selected attributes when saving a product. + + + +* {{ site.data.var.ee }} now displays configurable attributes as expected during the creation of global `select` attributes via a patch script. Previously, eligible global attributes were hidden. + + + +* The `addConfigurableProductsToCart` mutation can now be used to add configurable products with custom options. Previously, {{ site.data.var.ee }} threw this error: `Magento 2.3.4 graphql Notice: Undefined index: option_value in /var/www/html/mg234/vendor/magento/module-configurable-product-graph-ql/Model/Resolver/ConfigurableCartItemOptions.php on line 62`. [GitHub-28860](https://github.com/magento/magento2/issues/28860) + + + +* Configurable products are now moved to the last position in the product listing after stock is updated when the **Move out of stock to the bottom** setting is enabled. A new custom database query has been implemented to negate Elasticsearch index sort order, which disregards Admin-enabled sort order. Previously, configurable products and their child products were not moved to the bottom of the list when this setting was enabled. + + + +* {{ site.data.var.ee }} now correctly displays a configurable product’s stock status, available configurations, and displayed price when the availability of one of the configurable product’s child product is changed by a scheduled update. Previously, when a configurable product had two children and the availability of one child product was disabled with a scheduled update, the parent product’s stock status was incorrectly displayed as **Out of Stock** when the update was active, After the update completed, the displayed price and the availability of its configurations was miscalculated. + +* You can now re-order configurable products with optional custom options. Previously, re-order attempts failed, and meant displayed this error: `Some of the selected options are not currently available`. [GitHub-35409](https://github.com/magento/magento2/issues/35409) + + + +* The `addConfigurableProductsToCart` mutation now works as expected with multiple products. Previously, incorrect product information was returned, or an invalid error message was returned. [GitHub-30948](https://github.com/magento/magento2/issues/30948) + +### Customer + + + +* {{ site.data.var.ee }} now displays predefined EAV system attributes correctly according to the website setting on the storefront. Previously, website-level customer attributes that were enabled for one website and disabled for another were displayed as enabled for both websites. + +### Customer segment + + + +* Customer segment-specific Related Product rules now work as expected. The issue has been fixed by calling a method to add a visitor-segment relation for a specific website. Previously, the segments for this rule fetched only on the basis of registered customers and websites. + +### Downloadable + + + +* You can now remove sample links and files from a downloadable product. [GitHub-31887](https://github.com/magento/magento2/issues/31887) + +### Email + + + +* System-issued emails are now successfully sent to recipients with ".-" in their email address. + + + +* Customers now get email reminders about their abandoned carts on the correct schedule. The new `TIMESTAMPDIFF(DAY, ,)` SQL function has replaced the `TO_DAYS()` function and calculates the difference in the timestamps on the basis of date and time. Previously, email reminders were not sent per schedule because of the incorrect calculation of two date-time values of cart abandonment (any timezone) and server time (UTC). + + + +* {{ site.data.var.ee }} now displays an error message on the Shipping page when a shopper enters an invalid email format after the shopper clicks **Place Order**. Previously, the error message was displayed on the Payment page. [GitHub-33590](https://github.com/magento/magento2/issues/33590 + +### Frameworks + + + +* The `bin/magento setup:config:set` command no longer overrides already set cache ID prefixes in `app/etc/env.php`. + + + +* The `bin/magento setup:static-content:deploy -s compact` command now includes styles from child themes as expected. Previously, theme CSS files were not present on the storefront after deployment. + + + +* A new sniff has been added to check if closing slashes are used in `void` elements. + + + +* {{ site.data.var.ee }} no longer throws an SQL error after assigning a new source to a product and changing its quantity. [GitHub-35262](https://github.com/magento/magento2/issues/35262) + + + +* Attribute sort order now works as specified in the `di.xml` file after update. + + + +* The `updateCartCurrency` function now sets string instead of an object inside the cart object. Previously, {{ site.data.var.ee }} did not load a quote using `getQuote` because the `updateCartCurrency` function set an object instead of a string inside the cart object. [GitHub-34199](https://github.com/magento/magento2/issues/34199) + + + +* Deprecation notices no longer occur in unit tests due to`\DateTimeFormatter::formatObject()`. This method now works as expected with numeric values for `$format`. + + + +* {{ site.data.var.ee }} no longer displays a `preg_replace()` error on the Admin. The third argument (`$subject`) is now of type `array|string` instead of `bool`. + + + +* The `isFreeShipping` method now returns an integer rather than a Boolean.[GitHub-35164](https://github.com/magento/magento2/issues/35164) + + + +* {{ site.data.var.ee }} no longer throws the following error when you create a plugin for any method of class `vendor/magento/module-backend/Model/Menu.php`: `Error: Call to undefined method ReflectionUnionType::getName()`. [GitHub-35292](https://github.com/magento/magento2/issues/35292) + + + +* {{ site.data.var.ee }} now returns a 404 error instead of a 500 error when you navigate to `/checkout/sidebar/updateItemQty/?item_qty=error` on the storefront. Previously, this error was thrown: `Warning: A non-numeric value encountered in /vendor/magento/module-checkout/Controller/Sidebar/UpdateItemQty.php on line 69`. [GitHub-34380](https://github.com/magento/magento2/issues/34380) + + + +* {{ site.data.var.ee }} no longer triggers a `trim(): Passing null to parameter #1 ($string) of type string is deprecated` error when the AMPQ connection is configured without SSL configuration. + + + +* Corrected the `longblog` database definition to `long blob`. [GitHub-35108](https://github.com/magento/magento2/issues/35108) + + + +* Knockout text containing single quotes are now translatable. [GitHub-34319](https://github.com/magento/magento2/issues/34319) + + + +* A `TypeError` in `magento2/app/code/Magento/Security/Model/AdminSessionsManager.php` has been corrected from int to string. [GitHub-34415](https://github.com/magento/magento2/issues/34415) + + + +* Merchants can now successfully upgrade from an {{ site.data.var.ee }} 2.4.2 deployment with Klarna to {{ site.data.var.ee }} 2.4.3. [GitHub-33760](https://github.com/magento/magento2/issues/33760) + + + +* `.htpasswd` has been added to banned locations in the `nginx` configuration file. [GitHub-35150](https://github.com/magento/magento2/issues/35150) + + + +* Load time of category product list pages have been improved by adding `Magento_Ui/js/core/app` as a `deps` to `app/code/Magento/Ui/view/frontend/requirejs-config.js`. [GitHub-34847](https://github.com/magento/magento2/issues/34847) + + + +* The `ProductRepository.php:get` method now returns cache keys once. Previously, they were returned twice. [GitHub-34958](https://github.com/magento/magento2/issues/34958) + + + +* Added an error message to a new exception that was created in the exception handler for cron jobs. [GitHub-34941](https://github.com/magento/magento2/issues/34941) + + + +* The ReadMe files for the GraphQl-GroupedProductGraphQl modules have been updated. [GitHub-34951](https://github.com/magento/magento2/issues/34951) + + + +* [GitHub-34430](https://github.com/magento/magento2/issues/34430) + + + +* The storefront print order/invoice/credit memo pages no longer display the default Luma logo instead of the logo that has been specified for display on the website. [GitHub-34942](https://github.com/magento/magento2/issues/34942) + +### General fixes + + + +* Setting the maximum session size to 0 (Admin **Store** > **Settings** > **Configuration - Advanced**) no longer logs out the administrator. [GitHub-35312](https://github.com/magento/magento2/issues/35312) + + + +* {{ site.data.var.ee }} sessions no longer end after a GraphQL request is made. Previously, the `ClearCustomerSessionAfterRequest` plugin logged out the shopper. [GitHub-34550](https://github.com/magento/magento2/issues/34550) + + + +* Customer address attributes configuration settings are now loaded correctly based the website the customer is assigned to when you add a new customer address from the Admin that is assigned to a non-default website. + + + +* Category creation is now blocked for a restricted admin on both the Category page and Product Edit page. Previously, category creation was blocked on the category page, but was still possible through the Product Edit page. + + + +* {{ site.data.var.ee }} no longer throws an exception when you add a bundle product through Page Builder. + + + +* Categories can now be selected from the category tree as a condition for a customer segment. + + + +* You can now create a customer account on an iOS device with the inclined apostrophe (’) in the first, middle, or last name. Previously, only the straight apostrophe was allowed, and using iOS 11+ default inclined apostrophe resulted in a `Name is not valid!` error. + + + +* The `products` query now returns product information that accurately reflects the "Show Related Products" configuration. The `related_products`, `upsell_products`, and `crosssell_products` fields in the GraphQL ProductInterface are now resolved according to Show Related Products, Show Upsell Products, and Show Cross-Sell Products configuration respectively. + + + +* The **Set Product as New From Date** attribute now displays the correct date when the **Set Product as New** attribute is set through a mass product bulk update. Previously, **Set Product as New From Date** was displayed as **Jan 1, 1970**. + + + +* Users with restricted roles are no longer automatically granted access to new modules. + + + +* Target rules based on categories display only products from the category that is declared in the rule. Previously, Related Product rules displayed products from categories that were assigned to product and not defined in the rule. + + + +* Related product rule conditions now work as expected with products that contain `multiselect` attributes. + + + +* Merchants can now add a tier price attribute (`tier_price`) to product comparisons. Previously, the product comparisons page crashed when the **Comparable on storefront** setting for this attribute was enabled. [GitHub-35244](https://github.com/magento/magento2/issues/35244) + + + +* {{ site.data.var.ee }} now displays an error message when you set an invalid cookie domain (**Store** > **Configurations** > **Web** > **Default Cookie Settings Cookie Domain**). Previously, the website crashed. [GitHub-35048](https://github.com/magento/magento2/issues/35048) + + + +* {{ site.data.var.ee }} no longer throws an error when an administrator with roles scoped to a single website adds product to Content Elements using PageBuilder. Previously, {{ site.data.var.ee }} threw an SQL error. + + + +* Validation has been added to the second line of the street address on the edit and add address pages. The minimum and maximum text lengths that are specified on the second are now enforced. + + + +* {{ site.data.var.ee }} no longer throws the following error during the creation of a catalog rule in the Admin after upgrade: `A technical problem with the server created an error. Try again to continue what you were doing. If the problem persists, try again later`. + + + +* {{ site.data.var.ee }} no longer throws an error when you activate the **Check here to link an RSS feed to your Wish List** checkbox before clicking on **Share Wish list**. [GitHub-34998](https://github.com/magento/magento2/issues/34998) + + + +* The title of the **Show Password** checkbox (Customer Login, Customer Registration, Customer Edit (Change Password section), and Customer Set New Password forms) is now translatable. [GitHub-34857](https://github.com/magento/magento2/issues/34857) + + + +* Updated the labels and comment descriptions in `app/code/Magento/NewRelicReporting/etc/adminhtml/system.xml`. [GitHub-31947](https://github.com/magento/magento2/issues/31947) + + + +* Removed unneeded `csp_whitelist.xml` files. [GitHub-30607](https://github.com/magento/magento2/issues/30607) + +### Gift cards + + + +* `products` queries now correctly returns product data that contains gift card products with a `gift-card` URL key. + +### GraphQL + + + +* A missing `price_range` attribute has been added to the GraphQL `BundleItemOption` type. [GitHub-35010](https://github.com/magento/magento2/issues/35010) + + + +* The `products` query no longer returns attributes as an aggregation when the **Use in Search Results** Layered Navigation setting is disabled. [GitHub-33318](https://github.com/magento/magento2/issues/33318) + + + +* A `price_including_tax` field has been added to `CartItemPrices`. [GitHub-29057](https://github.com/magento/magento2/issues/29057) + + + +* The `new_from_data` and `new_to_datefields` in `ProductInterface` are no longer deprecated. [GitHub-34783](https://github.com/magento/magento2/issues/34783) + + + +* The `getCartDetails` query now returns only one payment methods for free orders. Previously, all active payment methods were returned in the query response. [GitHub-34036](https://github.com/magento/magento2/issues/34036) + + + +* The `categories` query no longer throws an exception when fetching a list of categories one of which contains an image that can’t be found on the filesystem. Previously, {{ site.data.var.ee }} threw this exception: Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) + + + +* The `products` query now returns `category_uid` as an aggregation as expected. [GitHub-32557](https://github.com/magento/magento2/issues/32557) + + + +* The `updateCartItems` query now removes products as expected when the product stock has reached the maximum stock amount. [GitHub-30220](https://github.com/magento/magento2/issues/30220) + + + +* The `urlResolver` query now resolves the path delimiter (/) correctly when multiple homepages have the same identifier. Previously, the query did not resolve the delimiter and returned null. [GitHub-33615](https://github.com/magento/magento2/issues/33615) + + + +* `customer` queries now fetch bundle product multi-select options as expected when querying orders. [GitHub-34717](https://github.com/magento/magento2/issues/34717) + + + +* {{ site.data.var.ee }} sessions no longer end after a GraphQL request is made. Previously, the `ClearCustomerSessionAfterRequest` plugin logged out the shopper. [GitHub-34550](https://github.com/magento/magento2/issues/34550) + + + +* The `products` query no longer returns price_range values for configurable products that are affected by disabled variants. [GitHub-33629](https://github.com/magento/magento2/issues/33629) + + + +* Configurable product price range in `products` query responses are now correctly calculated when the **Display Out of Stock Products** configuration setting is enabled. Previously, disabled options were taken into account in the minimum and maximum price calculation. + + + +* The `products` query now returns correctly filtered multiple categories when sorting by position. + + + +* `setShippingAddressesOnCart` requests now successfully validate region IDs. Previously, {{ site.data.var.ee }} threw an error when you used region ID instead of region code. + + + +* `products` queries now return only the categories associated with the store passed in the request. + + + +* The `categoryList` query now returns results that reflect the queried store's root category when the store specified in the header. Previously, categories from the default root category were included in results even though another store was specified in the header. + + + +* The `products` query no longer returns attributes as an aggregation when the **Use in Search Results Layered Navigation** setting is disabled. [GitHub-33318](https://github.com/magento/magento2/issues/33318) + + + +* A missing `price_range` attribute has been added to the GraphQL `BundleItemOption` type. [GitHub-35010](https://github.com/magento/magento2/issues/35010) + + + +* The `products` query no longer returns attributes as an aggregation when the **Use in Search Results** Layered Navigation setting is disabled. [GitHub-33318](https://github.com/magento/magento2/issues/33318) + + + +* A `price_including_tax` field has been added to `CartItemPrices`. [GitHub-29057](https://github.com/magento/magento2/issues/29057) + + + +* The `new_from_data` and `new_to_datefields` in `ProductInterface` are no longer deprecated. [GitHub-34783](https://github.com/magento/magento2/issues/34783) + + + +* The `cart` query now returns only one payment methods for free orders. Previously, all active payment methods were returned in the query response. [GitHub-34036](https://github.com/magento/magento2/issues/34036) + + + +* The `categories` query no longer throws an exception when fetching a list of categories one of which contains an image that can’t be found on the filesystem. Previously, {{ site.data.var.ee }} threw this exception: Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) + + + +* The `GetProductsInCategory` query now returns `category_uid` as an aggregation as expected. [GitHub-32557](https://github.com/magento/magento2/issues/32557) + + + +* The `updateCartItems` query now removes products as expected when the product stock has reached the maximum stock amount. [GitHub-30220](https://github.com/magento/magento2/issues/30220) + + + +* `customer` queries now fetch bundle product multi-select options as expected when querying orders. [GitHub-34717](https://github.com/magento/magento2/issues/34717) + + + +* `products` queries no longer returns price_range values for configurable products that are affected by disabled variants. [GitHub-33629](https://github.com/magento/magento2/issues/33629) + + + +* Added a plugin before the `collectQuoteTotals` call to ensure store credits aren't applied multiple times. + + + +* Creating a new special price schedule with the `POST /V1/products/special-price` endpoint now works as expected. Previously, the endpoint returned the message `Future Update already exists in this time range. Set a different range and try again`. + + + +* The `generateCustomerTokenAsAdmin` mutation now retrieves customer tokens as expected. Previously, tokens were not returned, and this error was returned: `Customer email provided does not exist`. + + + +* GraphQL schema is now valid when a custom `type` product attribute is defined. Previously, the schema was invalid because the `type` attribute on products types was overwritten by the custom `type` attribute. [GitHub-34929](https://github.com/magento/magento2/issues/34929) + + + +* Customers added or updated with the `createCustomer`, `createCustomerV2`, `updateCustomer`, or `updateCustomerV2` mutation are now added with active newsletter subscriptions. Previously, customers were unsubscribed from newsletters even when the request contained proper input parameters. [GitHub-33599](https://github.com/magento/magento2/issues/33599) + + + +* The `products` query for a specific store view now returns only categories that are in the specific website's root category in multi-site deployment. Previously, the query returned categories from the root categories of other websites. [GitHub-34570](https://github.com/magento/magento2/issues/34570) + + -### Backend +* The `products` query now returns only the sub category of provided category ID. Previously, it returned all categories. [GitHub-35220](https://github.com/magento/magento2/issues/35220) -### Bundle products + -### Cache +* The `customerOrders` query now responds as expected when the `gift_message` object is specified in the response but no gift message exists. Previously, the query returned this message: `Can't load gift message for order is returned`. [GitHub-28957](https://github.com/magento/magento2/issues/28957) -### Cart and checkout + -### Catalog +* Fixed a bug with the `catalog_category_product` indexer that caused the `products` query to return categories from another store. [GitHub-31253](https://github.com/magento/magento2/issues/31253) -### Catalog rule + -### Configurable products +* The `generateCustomerToken` mutation now creates an entry in the `customer_log` as expected after generating a customer token. [GitHub-33378](https://github.com/magento/magento2/issues/33378) -### Customer + -### Email +* The `/V1/products/base-prices` endpoint now works as expected with **Catalog Price Mode - Website**. [GitHub-30132](https://github.com/magento/magento2/issues/30132) -### Frameworks +### Google Analytics -### General fixes + -### GraphQL +* The Google Tag module has been added to the codebase, which supports the transition to Google Analytics 4 in July 2023. You can currently use and collect new data in your Google Universal Analytics properties, but Google Universal will reach end-of-life in July 2023. [GitHub-35204](https://github.com/magento/magento2/issues/35204), [GitHub-35376](https://github.com/magento/magento2/issues/35376) ### Image + + +* Images on product details pages no longer flicker, and images remain centered as expected. Previously, after a product detail page completed loading an image, the image visibly shifted downwards. + ### Import/export -### Index + + +* Related, upsell, and cross-sell product position in the export CSV is now correct after the deletion of a cross-sell product from the Admin before regenerating the CSV file. Previously, cross-sell product positions were not re-calculated after a cross-sell product was removed, and product position order was incorrect. + + + +* {{ site.data.var.ee }} now checks for a custom view before filtering columns when exporting reports. Previously, exported reports did not take into account custom views, and exported columns were incorrect. + + + +* {{ site.data.var.ee }} now successfully imports images with long file names. Previously, {{ site.data.var.ee }} did not import the image and threw this error: `Imported resource (image) could not be downloaded from external resource due to timeout or access permissions in row(s):`. + + + +* Category ID attributes are now available in scheduled export filters. + + + +* Bundle products that contain a question mark (?) in the option title can now be imported successfully because of improvements to the query builder inside `populateExistingOptions` method. The option title is also displayed correctly. Previously, after the initial import, successive imports resulted in corrupted behavior and doubled options. Shoppers could not add the product to the cart, either. + + + +* Added validation for category names during import. Previously, {{ site.data.var.ee }} did not validate category names, which lead to errors when category names exceeded 255 characters. + + + +* Existing records in the `catalog_url_rewrite_product_category` table are now deleted before inserting new ones. Previously, the following error occurred during multi-store product import: `SQLSTATE[23000]: Integrity constraint violation`. [GitHub-34210](https://github.com/magento/magento2/issues/34210) ### Infrastructure + + +* The SQL query that updates affected quotes after a cart price rule is disabled has been optimized to avoid locking the entire quote table. + + + +* A deprecated Context Menu plugin has been removed from plugins list. + + + +* The TinyMCE editor toolbar-related logic in the Page Builder module has been updated as a result of introducing `delayedRender` logic for the toolbar in TinyMCE. + + + +* Race conditions no longer interrupt the creation of the `contentUpdated` event listener. [GitHub-32068](https://github.com/magento/magento2/issues/32068) + + + +* The `getTypeID` function now returns product type ID not product ID. [GitHub-35458](https://github.com/magento/magento2/issues/35458) + + + +* jQuery UI slider and `SelectMenu` mapping has been corrected in `vendor/magento/module-theme/view/base/requirejs-config.js`. + +* Observers placed on `sales_order_state_change_before` now support the retrieval of data from the order object. The `sales_order_state_change_before` `event` argument has been updated. [GitHub-26789](https://github.com/magento/magento2/issues/26789) + + + +* `indexer:reset` has been refactored to call `$indexer->invalidate()`. [GitHub-34988](https://github.com/magento/magento2/issues/34988) + #### Library removals and deprecations #### Library upgrades -### Invoice - ### Logging -### {{ site.data.var.ee }} coding standard + + +* Customer, customer address, and order actions are now logged correctly in the Admin action report. Previously, {{ site.data.var.ee }} did not log actions if the `postDispatch` handler had not been specified in configuration settings. -### Media Gallery +### {{ site.data.var.ee }} coding standard ### MFTF @@ -122,54 +859,477 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. Repetitive actions have been replaced with action groups in these tests: +`AdminConfigurableProductChildrenOutOfStockTest` [GitHub-32378](https://github.com/magento/magento2/issues/32378) +`AdminCreateStoreViewTest` [GitHub-34631](https://github.com/magento/magento2/issues/34631) + #### New tests +`AdminUnlockAdminUserEntityTest` [GitHub-34836](https://github.com/magento/magento2/issues/34836) + +`StorefrontNewsletterSubscriptionWithEnabledNeedToConfirmConfigTest` [GitHub-33344](https://github.com/magento/magento2/issues/33344) + #### Refactored tests +`AdminCancelTheCreatedOrderWithCashOnDeliveryPaymentMethodTest` [GitHub-33692](https://github.com/magento/magento2/issues/33692) + +### Newsletter + + + +* Logged-in customers are no longer marked as guests in Admin > **Marketing** > **Newsletter Subscribers**. + + + +* The newsletter subscription confirmation email now has the correct, store-specific email address in the **From** field if the customer is assigned to a non-default store and subscribed or unsubscribed from the Admin. Previously, the customer received an email with default email in **From** header. [GitHub-34963](https://github.com/magento/magento2/issues/34963) + + + +* The unsubscribe URL in the newsletter email template now works as expected. [GitHub-33310](https://github.com/magento/magento2/issues/33310) + ### Order + + +* You can now successfully create a new customer from a new order with custom customer attribute that are hidden from the storefront. Previously, {{ site.data.var.ee }} did not save the correct values for the custom customer attribute. + + + +* Reward points can now be refunded when store credit functionality is disabled. + + + +* Guest customer details are now saved successfully after an order is edited. Previously, some customer details were lost, including `customer_firstname` and `customer_lastname, x_forwarded_for`. + + + +* Merchants can no longer create a credit memo with a decimal total quantity when **Decimal qty** is disabled on a product or global setting level. Previously, merchants could create a credit memo for decimal total quantity where it was not applicable. + + + +* Filter by date now works properly for Invoices, shipments, credit memos, CMS pages, and CMS block grids when the timezone set in preferences differs from the timezone set on a local computer. Previously, the date was incorrectly parsed and the filtered results included data outside of the set date range. + + + +* {{ site.data.var.ee }} no longer changes custom email addresses that are assigned to orders when you change the main email address assigned to the customer on the Admin account edit page. Previously, when you edited the main email address for a customer, the new email address was assigned to every order created for that customer. [GitHub-34397](https://github.com/magento/magento2/issues/34397) + + + +* {{ site.data.var.ee }} now displays records from the requested store on the credit memos grid page in deployments running PHP 7.4. Previously, {{ site.data.var.ee }} threw the following error after you created a credit memo and tried to view it: `The store that was requested wasn't found. Verify the store and try again`. + + + +* {{ site.data.var.ee }} now displays credit memos on the credit memo grid page for orders created from store views whose name is prepended with numbers. Previously, {{ site.data.var.ee }} displayed the error: `The store that was requested wasn't found. Verify the store and try again. Exception in /var/www/html/vendor/magento/module-store/Model/StoreRepository.php:75`. [GitHub-35122](https://github.com/magento/magento2/issues/35122) + + + +* {{ site.data.var.ee }} now displays the free shipping cost (0) on the Admin and storefront invoice page totals. Previously, when shipping was zero for an order, {{ site.data.var.ee }} did not display the shipping amount in total on the invoice page shipping total. + + + +* {{ site.data.var.ee }} now displays correct order status during checkout when customer store credit is used. + + + +* The `increment_id` column in the `sales_order` table has been increased. Previously, third-party modules that assumed that `sales_order.increment_id` had a length of 50 characters saved only the first 32 characters of an `increment_id`. [GitHub-34521](https://github.com/magento/magento2/issues/34521) + ### Payment methods + + +* Administrators can now place an order on the Admin using the PayPal PayflowPro payment method. Previously, {{ site.data.var.ee }} displayed this error: `No such entity with cartId = 0`. + + + +* Payment Review page in the checkout workflow now displays the correct payment method name when payment is made with Venmo, PayPal Later, or PayPal. + + + +* The `cart` query no longer returns all active payment methods for free orders. [GitHub-34036](https://github.com/magento/magento2/issues/34036) + #### PayPal + + +* {{ site.data.var.ee }} now shows the correct customer name in a guest order paid for with PayPal. Previously, the customer name was displayed as Guest. + + + +* The resolver for the createPaypalExpressToken mutation has been updated to correctly use the value specified in the use_paypal_credit input field. Previously, it attempted to use an invalid `paypal_credit` field. [GitHub-35180](https://github.com/magento/magento2/issues/35180) + ### Performance + + +* The performance of dynamic block loading has been improved. Previously, visitor segments were not cached per website, which caused redundant queries to the database for the same data. + + + +* Redis cache management has been improved by the addition of TTL (expiration date) for configurable products’ associated product data caches. Previously, these caches were not evicted due to missing TTL values if Redis key eviction policy was configured to a volatile eviction policy. + + + +* The new `Grid Filter Condition Type` customer/customer address attribute controls how an attribute filter is matched against the attribute values in the database, Options include `Partial Match`, `Prefix Match`, and `Full Match`. + + + +* The Catalog Search fulltext indexer has been relocated outside the stores loop, which streamlines re-indexing. [GitHub-33984](https://github.com/magento/magento2/issues/33984) + + + +* Fixed issue with `array_merge` in loops. [GitHub-33929](https://github.com/magento/magento2/issues/33929) + ### Pricing -### ProductAlert + + +* Price attributes that have no value in the default scope (but that are defined at the store-view level) are now indexed properly. Previously, the SQL expressions that retrieves price attributes values from EAV table did not take into account the scenario in which the value was not defined in the default scope. + + + +* The price listed on the product detail page is now the same as the price listed in the checkout workflow for tier prices that differ by quantity selected (for example, a product priced differently based on buying 2 items versus 5 items). Previously, the checkout price reflected the price for the lowest product quantity. + +### Promotions + + + +* The **Times Used** value for a discount is no longer incremented twice when a guest customer places an order with a discount and subsequently registers an account. + +### ReCAPTCHA + +* The **Submit** button on the Login and Create an Account pages is now inactive until ReCaptcha is fully loaded. + +### Return Merchandise Authorizations (RMA) + + + +* The `GET /V1/returnsAttributeMetadata` endpoint now works correctly when the `rma_item` entity default attribute set ID differs from the default installation ID. Previously, this endpoint returned an empty result if these IDs differed. + + + +* The **Use Default** checkbox, which is used to enable RMA on the product edit page, now works as expected for Default Store. Previously, the checkbox was cleared immediately after the product was saved. + +### Rewards -### Product video + -### Reviews +* Reward points can now be refunded when store credit functionality is disabled. -### Sales + -### Sales Rule +* Checkout performance has been improved when reward points are applied. When `entity` is null, then the database query will not be executed because querying the `magento_reward_history` table is not mandatory under the circumstances. + + + +* Credit memos for guest orders no longer check for `customer_id`, which skips querying the `magento_reward_history' database table table for reward points. This change has improved performance. + +### Roles + +* The **Store** > **Configuration** > **Services** page now displays {{ site.data.var.ee }} Web API information as expected when Resource Access is set to **Custom** on the Role Resources tab. [GitHub-35506](https://github.com/magento/magento2/issues/35506) ### Search + + +* Filtering products by color swatch on the layered navigation displays the correct image for the products after the fix. + + + +* Elasticsearch queries now work as expected when `int` is configured as a searchable backend `type` attribute. Previously, {{ site.data.var.ee }} threw an `Elasticsearch\Common\Exceptions\BadRequest400Exception` exception. + + + +* You can now use search synonyms together with the **Minimum Terms to Match** parameter In Elasticsearch queries. Previously, if this parameter was specified in settings and search terms were added for specific keywords, the search returned no results. + + + +* {{ site.data.var.ee }} now displays an accurate search results suggestion count on the storefront in deployments where Search Suggestions and the **Show Results Count for Each Suggestion** setting are enabled. Previously, the count displayed next to the keywords was zero. + + + +* Products sorted by custom attributes on the Catalog page are now displayed in the expected order. Previously, products were sorted by their attribute option value ID, which reflects the order in which they they were added to the attribute. [GitHub-33810](https://github.com/magento/magento2/issues/33810) + + + +* Filtering products by color swatch in the layered navigation now displays the correct product images. Previously, the layered navigation `PageCache` key did not include filter parameters for configurable products. + + + +* Fixed PHP errors on the `catalogsearch/advanced/result` and  `catalogsearch/advanced/index` pages. Previously, {{ site.data.var.ee }} displayed this error when an array was passed in any advanced search string : `Warning: trim() expects parameter 1 to be string, array given | magento/module-catalog-search`. [GitHub-33586](https://github.com/magento/magento2/issues/33586) + ### Shipping -### Store + + +* {{ site.data.var.ee }} no longer throws an error when loading UPS shipping rates if no allowed shipping methods are selected. Previously, when a shopper entered a shipping address in the checkout workflow under these conditions, no other shipping methods were displayed, and {{ site.data.var.ee }} displayed an error on the storefront. [GitHub-34411](https://github.com/magento/magento2/issues/34411) + + + +* Virtual product prices are now excluded in calculation table rate shipping amount. Previously, shipping costs for these products were not calculated correctly.[GitHub-35185](https://github.com/magento/magento2/issues/35185) + + + +* Table rate shipping rates with zero price are now displayed correctly in the checkout workflow Order Summary block for orders that have had a discount coupon applied. Previously, the shipping method was not displayed. + +### Staging + + + +* {{ site.data.var.ee }} no longer cleans the full-page cache after applying a staging update for a sales rule in which the cached pages remain unchanged. + + + +* The content staging dashboard no longer displays inactive permanent updates. + + + +* Changing the end date for a staging update from the staging dashboard now successfully applies these changes to the staging update and its entities. (A queue has been introduced to process staging updates changes.) + + + +* Merchants can now remove an end date for a scheduled update or delete and recreate an update. Previously, when an end date was removed, an entity remained scheduled for that time. {{ site.data.var.ee }} now removes the outdated update for removed rollback. + + + +* Active schedule updates for a CMS page are now visible as expected in the Scheduled Changes section on the CMS page. + + + +* The `custom_design_to` attribute value is now updated as expected when a scheduled update is changed. Previously, two separate category design updates with no end time were treated as one. When one of the scheduled updates was deleted while the first one was running, the `custom_design_from` time value became greater than the `custom_design_to` time values in the next scheduled update. + + + +* Forms are now populated with data as expected after a scheduled update is edited. + + + +* The `vendor/magento/module-catalog-staging/Setup/Patch/Data/MigrateCatalogProducts.php` data patch no longer fails when the database includes product with custom options and the `special_from_date` attribute is set. + + + +* Changes are now saved during a second scheduled update when the changes are added by the running update. Previously, changes were not saved, and merchants needed to re-enter and save changes. + + + +* The Bulk actions log now displays information about failed `to be moved` scheduled updates. Previously, information about these failures was available in the `cron.log` file only. + + + +* Merchants are now restricted to using comma-separated prices when editing a product price in a scheduled update regardless of locale. Previously, prices that contained commas in a scheduled update were divided by 1000 depending on the locale. + + + +* Problems with DHL domestic shipping in deployments running PHP 8.1 have been resolved by requiring dutiable tags for international shipments only. ### Tax + + +* Fixed Product Tax (FPT) is now correctly displayed for products in the shopping cart. Previously, if multiple products in the shopping cart have **Fixed Product Tax (FPT)** and **Apply Tax To FPT** were enabled, all FPTs were assigned to the last product in the shopping cart and reset for other products. + + + +* The Fixed Product Tax (FPT) total for the order summary section of the checkout workflow is now calculated correctly. + + + +* {{ site.data.var.ee }} now updates the Excluding Tax tier price for a simple product on the product page as expected after the quantity of the simple product has changed. + + + +* Validation has been added to the store configuration page to verify if the selected country from the dropdown list is on the EU country list. The **Validate VAT Number** button is now visible only for EU countries. Previously, the button was visible for all countries, including the U.K. + + + +* Tier price are now calculated correctly when **Display Product Prices In Catalog** is set to either **Excluding Tax** or **Including and Excluding Tax**. Previously, the product details page displayed tier prices with taxes despite the setting. + + + +* Taxes are now applied correctly for orders to any valid address in storefronts using the Portuguese locale. [GitHub-34271](https://github.com/magento/magento2/issues/34271) + + + +* The `cart` query no longer includes tax when returning `subtotal_with_discount_excluding_tax`. [GitHub-33905](https://github.com/magento/magento2/issues/33905) + + + +* Web API requests for order data (`GET /V1/orders/`) no longer returns negative values for row totals. + ### Test -#### Unit tests + -### Theme +* Corrected errors with `Magento.GraphQl.CatalogGraphQl.ProductSearchTest.testSearchSuggestions` when run with AWS Elasticsearch configuration. + + + +* The `testCreateProductOnStoreLevel` integration test no longer causes a nested transaction on the database. + +* The following exception no longer occurs when running WebAPI tests for the Send Friend feature when product image has not set on PHP 8.1: `exception main.ERROR: /var/www/html/lib/internal/Magento/Framework/DataObject.php:131 strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated`. [GitHub-34864](https://github.com/magento/magento2/issues/34864) ### Translations and locales + + +* You can now use the Translate inline tool to edit the same element more that once. Previously, only the first change made using this tool was included. + + + +* The store view selector no longer blocks the translation pane when you edit Admin text or labels. You can now edit these features from the translation pane, and the interface displays these changes when you click **Submit**. + + + +* The Admin date-time format for Brazilian Portuguese and French locales is now valid. + + + +* Added a grave accent [ ` ] character to the name validator so that customer account can be created for first or last names that include this accent. + + + +* The text on the **Add to cart** button on the Product Details page now remains translated into the language specified in the associated locale. Translation files are now converted to corresponding JavaScript files based on the areas, themes, and locales when `translate_strategy=embedded`. Previously, the text reverted to English after the product was added to the cart. + + + +* Search Synonyms now respect their assigned store scope. Previously, a synonym assigned to a specific store was searchable on any other store. + + + +* Problems with the Filipino (Philippines) locale has been resolved. [GitHub-33996](https://github.com/magento/magento2/issues/33996) + ### UI + + +* Lengthy product names in the **Catalog** > **Products** grid are now word-wrapped instead of displayed in a single line. + + + +* You can now edit default stock from Admin **Stores** > **Inventory** > **Stocks**. Previously, a JavaScript error was displayed in the console when you tried to add or remove sources from default stock, although you could assign websites to default stock. + + + +* The minimal and maximum date-of-birth range is now saved as a correct timestamp and then converted from a valid timestamp to a valid date format. + + + +* The unavailability of `magento.com` no longer causes performance issues during Admin login. A timeout on the request to fetch release notification has been added. + + + +* The results of the Admin order, customer, and product grid filters now persist as expected when displayed in the Chrome browser. + + + +* You can now create a customer from the Admin when `Magento_LoginAsCustomerAdminUi` is enabled and **Store View To Login To** is set to manual selection. Previously, {{ site.data.var.ee }} threw this error: `(Magento\Framework\Exception\LocalizedException): Unable to get Customer ID`. [GitHub-33096](https://github.com/magento/magento2/issues/33096) + + + +* The Next arrow is now disabled as expected when a shopper reaches the last thumbnail image in the product image gallery. + + + +* The **Search by keyword** input field now has an `aria-label` element instead of a placeholder on the **Catalog** > **Product** page. + + + +* Category creation is now blocked for an administrator with restricted permissions on both the category and product edit pages. Previously, category creation was blocked on the category page, but was still possible through the product edit page. + + + +* The Privacy Policy link in Admin footer now links to the new Adobe Privacy Policy. + + + +* Administrators can now access Admin menu options when JavaScript bundling is enabled in production mode. [GitHub-35325](https://github.com/magento/magento2/issues/35325) + + + +* Administrators can now set the current user’s expiration date higher than 2038 and save the user successfully. Previously, the user whose expiration date was changed could not log back in after logging out. + + + +* {{ site.data.var.ee }} now displays an informative error message when an administrator tries to save an address with excessive street lines in Admin **Store** > **Attributes** > **Customer Address**. The administrator can now delete the extra address information and successfully save the address. Previously, {{ site.data.var.ee }} committed the extra lines but did not save the data. + + + +* The product listing view configuration in the database and local storage has been updated. Custom grid views are now saved during page reload and view changes. + + + +* You can now switch between store views when website restrictions are enabled. Previously, problems with the store view switcher prevented switching store views. + + + +* The favicon icon upload form now supports `.ico` file types. Previously, when you tried to upload a favicon file with this extension type in the Admin, {{ site.data.var.ee }} displayed this error: `Warning: imagecreatefromstring(): one parameter to a memory allocation multiplication is negative or zero, failing operation gracefully in /var/www/html/vendor/magento/module-media-storage/Model/File/Validator/Image.php on line 64`. [GitHub-34858](https://github.com/magento/magento2/issues/34858) + + + +* Corrected display issues with the drop-down Select menu in the Admin grid. [GitHub-35386](https://github.com/magento/magento2/issues/35386) + + + +* [GitHub-34430](https://github.com/magento/magento2/issues/34430) + ### URL rewrites + + +* URLs for a product in a specific store view only are now removed from the `url_rewrite` table and Admin after the attribute code visibility status for the specific store view is changed to **Not Visible Individually**. Previously, all URLs were removed for the product in the `url_rewrite` table. [GitHub-34937](https://github.com/magento/magento2/issues/34937) + +### Video + + + +* You can now use YouTube URL parameters using Page Builder to add a new video. Previously, these parameters were automatically removed from the URL. + + + +* You can now set a Vimeo video to run in the background in a `banner` element when CSP is set to `restrict mode`. Previously, {{ site.data.var.ee }} threw this JavaScript error when you tried to save the element: `Refused to connect to 'https://vimeo.com/api/v2/video/76979871.json' because it violates the following Content Security Policy directive`. + ### Web API framework + + +* Mutex has been implemented for orders to prevent race conditions during update by concurrent requests. Previously, race conditions during concurrent REST API calls resulted in an overwrite of shipping status information in the Admin Items Ordered table. + + + +* Dynamic bundle attributes are now updated correctly on the Mass Attribute Update page. Previously, the **Dynamic SKU** attribute remained set to **Yes** even though they were disabled on the Mass Update page. + + + +* Product image role inheritance is now preserved unless explicitly defined in the payload when updating a product in a specific store view via the REST API. + + + +* The Swagger schema (`/rest/schema`) now uses unique operation IDs. + + + +* Cart price rules created through the `POST /V1/salesRules/` endpoint now retain existing coupon code values after changing status from disabled to enabled. [GitHub-35298](https://github.com/magento/magento2/issues/35298) + + + +* Cart price rules created through the `POST /V1/salesRules/` endpoint now contain valid `from_date` and `to_date` values. [GitHub-35265](https://github.com/magento/magento2/issues/35265) + + + +* `CartItemInterface` now includes `customizable_options`. [GitHub-31180](https://github.com/magento/magento2/issues/31180) + + + +* REST API bulk PUT and DELETE requests now work as expected when the `Magento_ReCaptchaWebapiRest` module is enabled. [GitHub-35348](https://github.com/magento/magento2/issues/35348) + + + +* The Bulk Rest API now works with the `bySku` option for configurable products. Previously, it returned a 500 error. + ### Wish list + + +* Updating an item quantity from the wish list page now updates the quantity on the product detail page as expected. {{ site.data.var.ee }} now picks up the updated value from the product URL and populates the `qty` field of product detail page from the wishlist itself. + ## Known Issues ## Community contributions From 35dca6525afb45c8089385f582f67caae7ba6627 Mon Sep 17 00:00:00 2001 From: jfrontain Date: Fri, 8 Jul 2022 16:59:24 -0500 Subject: [PATCH 267/776] removed duplicate issuedescriptions --- src/guides/v2.3/inventory/release-notes.md | 6 + .../v2.4/release-notes/b2b-release-notes.md | 4 + .../v2.4/release-notes/commerce-2-4-5.md | 120 +----- .../v2.4/release-notes/open-source-2-4-5.md | 383 ++++-------------- 4 files changed, 90 insertions(+), 423 deletions(-) diff --git a/src/guides/v2.3/inventory/release-notes.md b/src/guides/v2.3/inventory/release-notes.md index d53f0d2b620..82d010fbd6d 100644 --- a/src/guides/v2.3/inventory/release-notes.md +++ b/src/guides/v2.3/inventory/release-notes.md @@ -54,6 +54,12 @@ The release notes include: - {:.fix} The `ProductInterface.only_x_left_in_stock` field now returns 0 if inventory is 0. Previously, it returned null. [GitHub-29932](https://github.com/magento/magento2/issues/29932) +- {:.fix} You can now edit default stock from Admin **Stores** > **Inventory** > **Stocks**. Previously, a JavaScript error was displayed in the console when you tried to add or remove sources from default stock, although you could assign websites to default stock. + +- {:.fix} The category list product count is now correct when using inventory single-source mode with the **Display Out-Of-Stock Products** setting enabled. A new plugin now uses `AreProductsSalableInterface` and `StockConfigurationInterface` to determine the total number of products. Previously, the category product list returned the wrong product quantity. + +- {:.fix} Configurable products are now moved to the last position in the product listing after stock is updated when the **Move out of stock to the bottom** setting is enabled. A new custom database query has been implemented to negate Elasticsearch index sort order, which disregards Admin-enabled sort order. Previously, configurable products and their child products were not moved to the bottom of the list when this setting was enabled. + ### v1.2.4 {{site.data.var.im}} 1.2.4 (module version: `magento/inventory-metapackage = 1.2.4`) is supported with version 2.4.4 and compatible with version 2.4.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. diff --git a/src/guides/v2.4/release-notes/b2b-release-notes.md b/src/guides/v2.4/release-notes/b2b-release-notes.md index 0662b280d27..5708b994f73 100644 --- a/src/guides/v2.4/release-notes/b2b-release-notes.md +++ b/src/guides/v2.4/release-notes/b2b-release-notes.md @@ -33,6 +33,10 @@ These release notes can include: - {:.fix} Pressing **Enter** on the Quick Order page in mobile mode after entering a valid product name or SKU now takes the shopper to the next field as expected. +- {:.fix} Company name is now visible as expected in the billing and shipping address sections of the checkout workflow. + +- {:.fix} Store credit is now unavailable when the Zero Subtotal Checkout payment method is disabled. Previously, the Store Credit checkbox was not functional during order placement from Admin. {{ site.data.var.ce }} did not place the order with the store credit and displayed this error: `The requested Payment Method is not available`. + ## {{ site.data.var.ee }} B2B - Adobe Commerce 2.4.4 - {:.fix} The time required to upgrade from {{ site.data.var.ee }} 2.3.x to {{ site.data.var.ee }} 2.4.x in deployments with more than 100,000 company roles has been substantially reduced. diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md index af9e70bd7af..42ac22c7255 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-5.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -279,14 +279,6 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. ### Cart and checkout - - -* The `Parent Only` attribute scope is now used properly in the Cart Rule condition. - - - -* Company name is now visible as expected in the billing and shipping address sections of the checkout workflow. - * The address search pop-up on the billing step of the checkout workflow no longer causes DOM errors. @@ -335,18 +327,10 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * The mini cart now displays previously added products after a session timeout when **Enable Persistence** is enabled . [GitHub-35183](https://github.com/magento/magento2/issues/35183) - - -* Store credit is now unavailable when the Zero Subtotal Checkout payment method is disabled. Previously, the Store Credit checkbox was not functional during order placement from Admin. {{ site.data.var.ee }} did not place the order with the store credit and displayed this error: `The requested Payment Method is not available`. - * Merchants can now create a credit memo in which **Refund Shipping (Incl. Tax)** is set to -0.01 and can now set this amount to 0. Previously, the credit memo could not be created under these conditions. - - -* Coupons that are set for one-time use can now be redeemed only once as expected. [GitHub-35077](https://github.com/magento/magento2/issues/35077) - ### Cart price rule @@ -389,7 +373,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* Triggers are now restored as expected to the `catalogrule_product_price` table after a full reindex. Previously, triggers were removed from the `catalogrule_product_price` table after a `catalogrule_rule` or `catalogrule_product` full re-index. +* Triggers are now restored as expected to the `catalogrule_product_price` table after a full re-index. Previously, triggers were removed from the `catalogrule_product_price` table after a `catalogrule_rule` or `catalogrule_product` full re-index. @@ -419,10 +403,6 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * {{ site.data.var.ee }} now provides validation error messages when you try to add a product URL key with a trailing hyphen. Informative tooltip text is also available. - - -* The category list product count is now correct when using inventory single-source mode with the **Display Out-Of-Stock Products** setting enabled. A new plugin now uses `AreProductsSalableInterface` and `StockConfigurationInterface` to determine the total number of products. Previously, the category product list returned the wrong product quantity. - * The new `ConfigurableWishlistItem.configured_variant` field has replaced the `ConfigurableWishlistItem.child_sku` field. The latter field triggered an internal error when a customer wishlist contained an un-configured configurable product. @@ -509,14 +489,10 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * {{ site.data.var.ee }} now displays configurable attributes as expected during the creation of global `select` attributes via a patch script. Previously, eligible global attributes were hidden. - + * The `addConfigurableProductsToCart` mutation can now be used to add configurable products with custom options. Previously, {{ site.data.var.ee }} threw this error: `Magento 2.3.4 graphql Notice: Undefined index: option_value in /var/www/html/mg234/vendor/magento/module-configurable-product-graph-ql/Model/Resolver/ConfigurableCartItemOptions.php on line 62`. [GitHub-28860](https://github.com/magento/magento2/issues/28860) - - -* Configurable products are now moved to the last position in the product listing after stock is updated when the **Move out of stock to the bottom** setting is enabled. A new custom database query has been implemented to negate Elasticsearch index sort order, which disregards Admin-enabled sort order. Previously, configurable products and their child products were not moved to the bottom of the list when this setting was enabled. - * {{ site.data.var.ee }} now correctly displays a configurable product’s stock status, available configurations, and displayed price when the availability of one of the configurable product’s child product is changed by a scheduled update. Previously, when a configurable product had two children and the availability of one child product was disabled with a scheduled update, the parent product’s stock status was incorrectly displayed as **Out of Stock** when the update was active, After the update completed, the displayed price and the availability of its configurations was miscalculated. @@ -615,15 +591,11 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* Knockout text containing single quotes are now translatable. [GitHub-34319](https://github.com/magento/magento2/issues/34319) +* Knockout text containing single quotes is now translatable. [GitHub-34319](https://github.com/magento/magento2/issues/34319) -* A `TypeError` in `magento2/app/code/Magento/Security/Model/AdminSessionsManager.php` has been corrected from int to string. [GitHub-34415](https://github.com/magento/magento2/issues/34415) - - - -* Merchants can now successfully upgrade from an {{ site.data.var.ee }} 2.4.2 deployment with Klarna to {{ site.data.var.ee }} 2.4.3. [GitHub-33760](https://github.com/magento/magento2/issues/33760) +* A `TypeError` in `magento2/app/code/Magento/Security/Model/AdminSessionsManager.php` has been corrected from `int` to `string`. [GitHub-34415](https://github.com/magento/magento2/issues/34415) @@ -643,11 +615,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* The ReadMe files for the GraphQl-GroupedProductGraphQl modules have been updated. [GitHub-34951](https://github.com/magento/magento2/issues/34951) - - - -* [GitHub-34430](https://github.com/magento/magento2/issues/34430) +* The ReadMe files for the `GraphQl-GroupedProductGraphQl` modules have been updated. [GitHub-34951](https://github.com/magento/magento2/issues/34951) @@ -659,10 +627,6 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * Setting the maximum session size to 0 (Admin **Store** > **Settings** > **Configuration - Advanced**) no longer logs out the administrator. [GitHub-35312](https://github.com/magento/magento2/issues/35312) - - -* {{ site.data.var.ee }} sessions no longer end after a GraphQL request is made. Previously, the `ClearCustomerSessionAfterRequest` plugin logged out the shopper. [GitHub-34550](https://github.com/magento/magento2/issues/34550) - * Customer address attributes configuration settings are now loaded correctly based the website the customer is assigned to when you add a new customer address from the Admin that is assigned to a non-default website. @@ -763,13 +727,9 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * The `new_from_data` and `new_to_datefields` in `ProductInterface` are no longer deprecated. [GitHub-34783](https://github.com/magento/magento2/issues/34783) - - -* The `getCartDetails` query now returns only one payment methods for free orders. Previously, all active payment methods were returned in the query response. [GitHub-34036](https://github.com/magento/magento2/issues/34036) - -* The `categories` query no longer throws an exception when fetching a list of categories one of which contains an image that can’t be found on the filesystem. Previously, {{ site.data.var.ee }} threw this exception: Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) +* The `categories` query no longer throws an exception when fetching a list of categories one of which contains an image that cannot be found on the filesystem. Previously, {{ site.data.var.ee }} threw this exception: Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) @@ -793,7 +753,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* The `products` query no longer returns price_range values for configurable products that are affected by disabled variants. [GitHub-33629](https://github.com/magento/magento2/issues/33629) +* The `products` query no longer returns `price_range` values for configurable products that are affected by disabled variants. [GitHub-33629](https://github.com/magento/magento2/issues/33629) @@ -813,59 +773,23 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* The `categoryList` query now returns results that reflect the queried store's root category when the store specified in the header. Previously, categories from the default root category were included in results even though another store was specified in the header. +* The `categoryList` query now returns results that reflect the queried store's root category when the store is specified in the header. Previously, categories from the default root category were included in results even though another store was specified in the header. * The `products` query no longer returns attributes as an aggregation when the **Use in Search Results Layered Navigation** setting is disabled. [GitHub-33318](https://github.com/magento/magento2/issues/33318) - - -* A missing `price_range` attribute has been added to the GraphQL `BundleItemOption` type. [GitHub-35010](https://github.com/magento/magento2/issues/35010) - - - -* The `products` query no longer returns attributes as an aggregation when the **Use in Search Results** Layered Navigation setting is disabled. [GitHub-33318](https://github.com/magento/magento2/issues/33318) - - - -* A `price_including_tax` field has been added to `CartItemPrices`. [GitHub-29057](https://github.com/magento/magento2/issues/29057) - - - -* The `new_from_data` and `new_to_datefields` in `ProductInterface` are no longer deprecated. [GitHub-34783](https://github.com/magento/magento2/issues/34783) - * The `cart` query now returns only one payment methods for free orders. Previously, all active payment methods were returned in the query response. [GitHub-34036](https://github.com/magento/magento2/issues/34036) - - -* The `categories` query no longer throws an exception when fetching a list of categories one of which contains an image that can’t be found on the filesystem. Previously, {{ site.data.var.ee }} threw this exception: Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) - - - -* The `GetProductsInCategory` query now returns `category_uid` as an aggregation as expected. [GitHub-32557](https://github.com/magento/magento2/issues/32557) - - - -* The `updateCartItems` query now removes products as expected when the product stock has reached the maximum stock amount. [GitHub-30220](https://github.com/magento/magento2/issues/30220) - - - -* `customer` queries now fetch bundle product multi-select options as expected when querying orders. [GitHub-34717](https://github.com/magento/magento2/issues/34717) - - - -* `products` queries no longer returns price_range values for configurable products that are affected by disabled variants. [GitHub-33629](https://github.com/magento/magento2/issues/33629) - -* Added a plugin before the `collectQuoteTotals` call to ensure store credits aren't applied multiple times. +* Added a plugin before the `collectQuoteTotals` call to ensure store credits are not applied multiple times. -* Creating a new special price schedule with the `POST /V1/products/special-price` endpoint now works as expected. Previously, the endpoint returned the message `Future Update already exists in this time range. Set a different range and try again`. +* Creating a new special price schedule with the `POST /V1/products/special-price` endpoint now works as expected. Previously, the endpoint returned this error: `Future Update already exists in this time range. Set a different range and try again`. @@ -885,7 +809,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* The `products` query now returns only the sub category of provided category ID. Previously, it returned all categories. [GitHub-35220](https://github.com/magento/magento2/issues/35220) +* The `products` query now returns only the subcategory of provided category ID. Previously, it returned all categories. [GitHub-35220](https://github.com/magento/magento2/issues/35220) @@ -947,10 +871,6 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. ### Infrastructure - - -* The SQL query that updates affected quotes after a cart price rule is disabled has been optimized to avoid locking the entire quote table. - * A deprecated Context Menu plugin has been removed from plugins list. @@ -1028,11 +948,7 @@ Repetitive actions have been replaced with action groups in these tests: -* You can now successfully create a new customer from a new order with custom customer attribute that are hidden from the storefront. Previously, {{ site.data.var.ee }} did not save the correct values for the custom customer attribute. - - - -* Reward points can now be refunded when store credit functionality is disabled. +* You can now successfully create a new customer from a new order with custom customer attributes that are hidden from the storefront. Previously, {{ site.data.var.ee }} did not save the correct values for the custom customer attribute. @@ -1340,10 +1256,6 @@ Repetitive actions have been replaced with action groups in these tests: * Lengthy product names in the **Catalog** > **Products** grid are now word-wrapped instead of displayed in a single line. - - -* You can now edit default stock from Admin **Stores** > **Inventory** > **Stocks**. Previously, a JavaScript error was displayed in the console when you tried to add or remove sources from default stock, although you could assign websites to default stock. - * The minimal and maximum date-of-birth range is now saved as a correct timestamp and then converted from a valid timestamp to a valid date format. @@ -1368,10 +1280,6 @@ Repetitive actions have been replaced with action groups in these tests: * The **Search by keyword** input field now has an `aria-label` element instead of a placeholder on the **Catalog** > **Product** page. - - -* Category creation is now blocked for an administrator with restricted permissions on both the category and product edit pages. Previously, category creation was blocked on the category page, but was still possible through the product edit page. - * The Privacy Policy link in Admin footer now links to the new Adobe Privacy Policy. @@ -1430,10 +1338,6 @@ Repetitive actions have been replaced with action groups in these tests: * Mutex has been implemented for orders to prevent race conditions during update by concurrent requests. Previously, race conditions during concurrent REST API calls resulted in an overwrite of shipping status information in the Admin Items Ordered table. - - -* Dynamic bundle attributes are now updated correctly on the Mass Attribute Update page. Previously, the **Dynamic SKU** attribute remained set to **Yes** even though they were disabled on the Mass Update page. - * Product image role inheritance is now preserved unless explicitly defined in the payload when updating a product in a specific store view via the REST API. diff --git a/src/guides/v2.4/release-notes/open-source-2-4-5.md b/src/guides/v2.4/release-notes/open-source-2-4-5.md index a21f5d8d5aa..7f499ed2192 100644 --- a/src/guides/v2.4/release-notes/open-source-2-4-5.md +++ b/src/guides/v2.4/release-notes/open-source-2-4-5.md @@ -69,19 +69,19 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* You can now rename a data patch and add the old class name as an alias in the `patch_list` database table. {{ site.data.var.ee }} now checks whether data patch aliases already existed in the database before applying the patch. Previously, {{ site.data.var.ee }} threw an error under these conditions. +* You can now rename a data patch and add the old class name as an alias in the `patch_list` database table. {{ site.data.var.Ce }} now checks whether data patch aliases already existed in the database before applying the patch. Previously, {{ site.data.var.ce }} threw an error under these conditions. -* {{ site.data.var.ee }} no longer throws an exception when you try to change the Admin URL to a custom URL from the Admin. Previously, after changing the Admin URL, you could not log in. [GitHub-35416](https://github.com/magento/magento2/issues/35416) +* {{ site.data.var.ce }} no longer throws an exception when you try to change the Admin URL to a custom URL from the Admin. Previously, after changing the Admin URL, you could not log in. [GitHub-35416](https://github.com/magento/magento2/issues/35416) -* Merchants can now successfully upgrade from an {{ site.data.var.ee }} 2.4.2 deployment with Klarna to {{ site.data.var.ee }} 2.4.3. [GitHub-33760](https://github.com/magento/magento2/issues/33760) +* Merchants can now successfully upgrade from an {{ site.data.var.ce }} 2.4.2 deployment with Klarna to {{ site.data.var.ce }} 2.4.3. [GitHub-33760](https://github.com/magento/magento2/issues/33760) -* The path to {{ site.data.var.ee }} Analytics is no longer hardcoded. Previously, this hardcoded path resulted in conflicts when multiple {{ site.data.var.ee }} instances were installed on one server. [GitHub-29373](https://github.com/magento/magento2/issues/29373) +* The path to {{ site.data.var.ce }} Analytics is no longer hardcoded. Previously, this hardcoded path resulted in conflicts when multiple {{ site.data.var.ce }} instances were installed on one server. [GitHub-29373](https://github.com/magento/magento2/issues/29373) ### Accessibility @@ -127,13 +127,13 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* {{ site.data.var.ee }} now correctly calculates the cart total for a bundle product when the Product Subselect rule is applied. +* {{ site.data.var.ce }} now correctly calculates the cart total for a bundle product when the Product Subselect rule is applied. ### Cache -* Full page cache is no longer shown as disabled in the Admin when the {{ site.data.var.ee }} cache is flushed and `use_stale_cache` is enabled. +* Full page cache is no longer shown as disabled in the Admin when the {{ site.data.var.ce }} cache is flushed and `use_stale_cache` is enabled. @@ -141,14 +141,6 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. ### Cart and checkout - - -* The `Parent Only` attribute scope is now used properly in the Cart Rule condition. - - - -* Company name is now visible as expected in the billing and shipping address sections of the checkout workflow. - * The address search pop-up on the billing step of the checkout workflow no longer causes DOM errors. @@ -159,7 +151,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* Permission exceptions are now handled for restricted products that are added by SKU. Shoppers are now given an appropriate message on the storefront, and the quantity field in the error table is disabled. Previously, {{ site.data.var.ee }} threw an exception like this: `There has been an error processing your request`. +* Permission exceptions are now handled for restricted products that are added by SKU. Shoppers are now given an appropriate message on the storefront, and the quantity field in the error table is disabled. Previously, {{ site.data.var.ce }} threw an exception like this: `There has been an error processing your request`. @@ -167,7 +159,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* Shoppers with global account sharing are no longer required to log in again to a secondary website in a multisite deployment when guest checkout is disabled. Customer data is now loaded when the shopper navigates to the subdomain. The shopper is no longer asked to log in again, and the previous cart contents are displayed. +* Shoppers with global account sharing are no longer required to log in again to a secondary website in a multi-site deployment when guest checkout is disabled. Customer data is now loaded when the shopper navigates to the subdomain. The shopper is no longer asked to log in again, and the previous cart contents are displayed. @@ -175,7 +167,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* The `cart` query no longer return null responses when a product is out of stock. A new `errors` element containing the error message was introduced to the response. Previously, when you ran a query with an out-of-stock product, {{ site.data.var.ee }} displayed a `null` value under the `items` section in the response. See [cart query](https://devdocs.magento.com/guides/v2.4/graphql/queries/cart.html). +* The `cart` query no longer return null responses when a product is out of stock. A new `errors` element containing the error message was introduced to the response. Previously, when you ran a query with an out-of-stock product, {{ site.data.var.ce }} displayed a `null` value under the `items` section in the response. See [cart query](https://devdocs.magento.com/guides/v2.4/graphql/queries/cart.html). @@ -197,18 +189,10 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. * The mini cart now displays previously added products after a session timeout when **Enable Persistence** is enabled . [GitHub-35183](https://github.com/magento/magento2/issues/35183) - - -* Store credit is now unavailable when the Zero Subtotal Checkout payment method is disabled. Previously, the Store Credit checkbox was not functional during order placement from Admin. {{ site.data.var.ee }} did not place the order with the store credit and displayed this error: `The requested Payment Method is not available`. - * Merchants can now create a credit memo in which **Refund Shipping (Incl. Tax)** is set to -0.01 and can now set this amount to 0. Previously, the credit memo could not be created under these conditions. - - -* Coupons that are set for one-time use can now be redeemed only once as expected. [GitHub-35077](https://github.com/magento/magento2/issues/35077) - ### Cart price rule @@ -221,10 +205,6 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. * Product URL keys now remain unchanged when updating product name via `PUT /V1/products/` for a store view. Previously, a new URL key was generated based on the new product name and assigned to the product, which overrode the URL key in that store view. - - -* Rule-based upsell products are no longer shown twice on the product page. - * Adding a product to a category from the Page Builder product widget set to carousel mode no longer triggers a page reload. @@ -243,7 +223,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* You can now successfully switch between list and grid views of multi-page product lists. Previously, when you navigated to the last page of a multi-page product list view before switching to the grid view, {{ site.data.var.ee }} displayed this error: `Unfortunately there are no products in this category on our website currently`. +* You can now successfully switch between list and grid views of multi-page product lists. Previously, when you navigated to the last page of a multi-page product list view before switching to the grid view, {{ site.data.var.ce }} displayed this error: `Unfortunately there are no products in this category on our website currently`. @@ -251,16 +231,12 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* Triggers are now restored as expected to the `catalogrule_product_price` table after a full reindex. Previously, triggers were removed from the `catalogrule_product_price` table after a `catalogrule_rule` or `catalogrule_product` full re-index. +* Triggers are now restored as expected to the `catalogrule_product_price` table after a full re-index. Previously, triggers were removed from the `catalogrule_product_price` table after a `catalogrule_rule` or `catalogrule_product` full re-index. * Category rules that are used to assign products to categories no longer randomly change. - - -* {{ site.data.var.ee }} no longer throws an error when a category rule assigns a product to a category that is subsequently sorted in a multi-site deployment. - * Categories can no longer be updated globally by an administrator with scope-restricted access. Previously, when multiple websites used the same category but different products, and an administrator with permission restricted to one store changed products in the category, the product selection also changed for other stores. @@ -269,25 +245,17 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. * The product details page now displays the correct price when a non-default currency for a specified locale is used. Previously, numbers were not localized as expected on the storefront. - - -* Products can now be enabled using a scheduled update. - * The same error message is now displayed by the API and on the storefront when trying to retrieve the tier prices of a product with duplicate records. Previously, `PUT /V1/products/tier-prices` returned an incorrect error message. -* {{ site.data.var.ee }} now provides validation error messages when you try to add a product URL key with a trailing hyphen. Informative tooltip text is also available. - - - -* The category list product count is now correct when using inventory single-source mode with the **Display Out-Of-Stock Products** setting enabled. A new plugin now uses `AreProductsSalableInterface` and `StockConfigurationInterface` to determine the total number of products. Previously, the category product list returned the wrong product quantity. +* {{ site.data.var.ce }} now provides validation error messages when you try to add a product URL key with a trailing hyphen. Informative tooltip text is also available. -* The new `ConfigurableWishlistItem.configured_variant` field has replaced the `ConfigurableWishlistItem.child_sku` field. The latter field triggered an internal error when a customer wishlist contained an un-configured configurable product. +* The new `ConfigurableWishlistItem.configured_variant` field has replaced the `ConfigurableWishlistItem.child_sku` field. The latter field triggered an internal error when a customer wish list contained an un-configured configurable product. @@ -295,11 +263,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* When the `Synchronize widget products with backend storage` setting is enabled, {{ site.data.var.ee }} adds recently view product data into the `catalog_product_frontend_action` database table. It includes the customer or visitor ID when adding records. The `recently_viewed_product` section in the response is now empty if customer ID and visitor ID are null. As a result, when the `customer/section/load` Ajax request is sent, {{ site.data.var.ee }} can correctly filter recently viewed products based on customer or visitor ID. Previously, the response included all the data available in the `catalog_product_frontend_action` database table because there was no check for an empty customer or visitor ID. - - - -* Category rules with a `Quantity` attribute for configurable products now work correctly when staging is implemented. Previously, when products had different values for `row_id` and `entity_id` in the `catalog_product_entity` table due to staging updates, the Visual Merchandiser **Match product by rule** functionality did not correctly filter the products. +* When the `Synchronize widget products with backend storage` setting is enabled, {{ site.data.var.ce }} adds recently view product data into the `catalog_product_frontend_action` database table. It includes the customer or visitor ID when adding records. The `recently_viewed_product` section in the response is now empty if customer ID and visitor ID are null. As a result, when the `customer/section/load` Ajax request is sent, {{ site.data.var.ce }} can correctly filter recently viewed products based on customer or visitor ID. Previously, the response included all the data available in the `catalog_product_frontend_action` database table because there was no check for an empty customer or visitor ID. @@ -311,7 +275,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* Product lists are now rendered correctly in the Admin. Previously, the product list did not render, and {{ site.data.var.ee }} displayed this error: `Item (Magento\Catalog\Model\Product\Interceptor) with the same ID "" already exists`. [GitHub-33145](https://github.com/magento/magento2/issues/33145) +* Product lists are now rendered correctly in the Admin. Previously, the product list did not render, and {{ site.data.var.ce }} displayed this error: `Item (Magento\Catalog\Model\Product\Interceptor) with the same ID "" already exists`. [GitHub-33145](https://github.com/magento/magento2/issues/33145) @@ -323,7 +287,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* You can now change the per-page product limit displayed within a category when **Remember Category Pagination** is enabled. Previously, the cookie `form_key` and UI `form_key` differed, and {{ site.data.var.ee }} displayed this error: `Invalid Form Key. Please refresh the page`. +* You can now change the per-page product limit displayed within a category when **Remember Category Pagination** is enabled. Previously, the cookie `form_key` and UI `form_key` differed, and {{ site.data.var.ce }} displayed this error: `Invalid Form Key. Please refresh the page`. @@ -335,25 +299,15 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* {{ site.data.var.ee }} now displays an error message as expected when you try to create an attribute from the product page without completing the Admin field. [GitHub-33099](https://github.com/magento/magento2/issues/33099) +* {{ site.data.var.ce }} now displays an error message as expected when you try to create an attribute from the product page without completing the Admin field. [GitHub-33099](https://github.com/magento/magento2/issues/33099) * Product ratings are now correct on all catalog product lists when the home page contains multiple catalog lists. [GitHub-33867](https://github.com/magento/magento2/issues/33867) -### CMS content - - - -* Merchants can no longer edit an active scheduled update from the entity edit page. - - - -* An administrator with restricted permissions can now view a CMS page in the CMS hierarchy after a scheduled update. - ### Configurable products -* {{ site.data.var.ee }} now displays the correct product price for a configurable product with a selected option after changing its quantity on product details page. Previously, the price was reset to the initial value after the quantity changed. +* {{ site.data.var.ce }} now displays the correct product price for a configurable product with a selected option after changing its quantity on product details page. Previously, the price was reset to the initial value after the quantity changed. @@ -365,25 +319,17 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* Multi-select attributes are now saved correctly during product edit. Previously, {{ site.data.var.ee }} saved the default option for non-selected attributes as well as selected attributes when saving a product. +* Multi-select attributes are now saved correctly during product edit. Previously, {{ site.data.var.ce }} saved the default option for non-selected attributes as well as selected attributes when saving a product. -* {{ site.data.var.ee }} now displays configurable attributes as expected during the creation of global `select` attributes via a patch script. Previously, eligible global attributes were hidden. - - - -* The `addConfigurableProductsToCart` mutation can now be used to add configurable products with custom options. Previously, {{ site.data.var.ee }} threw this error: `Magento 2.3.4 graphql Notice: Undefined index: option_value in /var/www/html/mg234/vendor/magento/module-configurable-product-graph-ql/Model/Resolver/ConfigurableCartItemOptions.php on line 62`. [GitHub-28860](https://github.com/magento/magento2/issues/28860) - - +* {{ site.data.var.ce }} now displays configurable attributes as expected during the creation of global `select` attributes via a patch script. Previously, eligible global attributes were hidden. -* Configurable products are now moved to the last position in the product listing after stock is updated when the **Move out of stock to the bottom** setting is enabled. A new custom database query has been implemented to negate Elasticsearch index sort order, which disregards Admin-enabled sort order. Previously, configurable products and their child products were not moved to the bottom of the list when this setting was enabled. + - +* The `addConfigurableProductsToCart` mutation can now be used to add configurable products with custom options. Previously, {{ site.data.var.ce }} threw this error: `Magento 2.3.4 graphql Notice: Undefined index: option_value in /var/www/html/mg234/vendor/magento/module-configurable-product-graph-ql/Model/Resolver/ConfigurableCartItemOptions.php on line 62`. [GitHub-28860](https://github.com/magento/magento2/issues/28860) -* {{ site.data.var.ee }} now correctly displays a configurable product’s stock status, available configurations, and displayed price when the availability of one of the configurable product’s child product is changed by a scheduled update. Previously, when a configurable product had two children and the availability of one child product was disabled with a scheduled update, the parent product’s stock status was incorrectly displayed as **Out of Stock** when the update was active, After the update completed, the displayed price and the availability of its configurations was miscalculated. - -* You can now re-order configurable products with optional custom options. Previously, re-order attempts failed, and meant displayed this error: `Some of the selected options are not currently available`. [GitHub-35409](https://github.com/magento/magento2/issues/35409) +* You can now re-order configurable products with optional custom options. Previously, re-order attempts failed, and meant displayed this error: `Some of the selected options are not currently available`. [GitHub-35409](https://github.com/magento/magento2/issues/35409) @@ -393,13 +339,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* {{ site.data.var.ee }} now displays predefined EAV system attributes correctly according to the website setting on the storefront. Previously, website-level customer attributes that were enabled for one website and disabled for another were displayed as enabled for both websites. - -### Customer segment - - - -* Customer segment-specific Related Product rules now work as expected. The issue has been fixed by calling a method to add a visitor-segment relation for a specific website. Previously, the segments for this rule fetched only on the basis of registered customers and websites. +* {{ site.data.var.ce }} now displays predefined EAV system attributes correctly according to the website setting on the storefront. Previously, website-level customer attributes that were enabled for one website and disabled for another were displayed as enabled for both websites. ### Downloadable @@ -419,7 +359,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* {{ site.data.var.ee }} now displays an error message on the Shipping page when a shopper enters an invalid email format after the shopper clicks **Place Order**. Previously, the error message was displayed on the Payment page. [GitHub-33590](https://github.com/magento/magento2/issues/33590 +* {{ site.data.var.ce }} now displays an error message on the Shipping page when a shopper enters an invalid email format after the shopper clicks **Place Order**. Previously, the error message was displayed on the Payment page. [GitHub-33590](https://github.com/magento/magento2/issues/33590 ### Frameworks @@ -437,7 +377,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* {{ site.data.var.ee }} no longer throws an SQL error after assigning a new source to a product and changing its quantity. [GitHub-35262](https://github.com/magento/magento2/issues/35262) +* {{ site.data.var.ce }} no longer throws an SQL error after assigning a new source to a product and changing its quantity. [GitHub-35262](https://github.com/magento/magento2/issues/35262) @@ -445,7 +385,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* The `updateCartCurrency` function now sets string instead of an object inside the cart object. Previously, {{ site.data.var.ee }} did not load a quote using `getQuote` because the `updateCartCurrency` function set an object instead of a string inside the cart object. [GitHub-34199](https://github.com/magento/magento2/issues/34199) +* The `updateCartCurrency` function now sets string instead of an object inside the cart object. Previously, {{ site.data.var.ce }} did not load a quote using `getQuote` because the `updateCartCurrency` function set an object instead of a string inside the cart object. [GitHub-34199](https://github.com/magento/magento2/issues/34199) @@ -453,7 +393,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* {{ site.data.var.ee }} no longer displays a `preg_replace()` error on the Admin. The third argument (`$subject`) is now of type `array|string` instead of `bool`. +* {{ site.data.var.ce }} no longer displays a `preg_replace()` error on the Admin. The third argument (`$subject`) is now of type `array|string` instead of `bool`. @@ -461,15 +401,15 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* {{ site.data.var.ee }} no longer throws the following error when you create a plugin for any method of class `vendor/magento/module-backend/Model/Menu.php`: `Error: Call to undefined method ReflectionUnionType::getName()`. [GitHub-35292](https://github.com/magento/magento2/issues/35292) +* {{ site.data.var.ce }} no longer throws the following error when you create a plugin for any method of class `vendor/magento/module-backend/Model/Menu.php`: `Error: Call to undefined method ReflectionUnionType::getName()`. [GitHub-35292](https://github.com/magento/magento2/issues/35292) -* {{ site.data.var.ee }} now returns a 404 error instead of a 500 error when you navigate to `/checkout/sidebar/updateItemQty/?item_qty=error` on the storefront. Previously, this error was thrown: `Warning: A non-numeric value encountered in /vendor/magento/module-checkout/Controller/Sidebar/UpdateItemQty.php on line 69`. [GitHub-34380](https://github.com/magento/magento2/issues/34380) +* {{ site.data.var.ce }} now returns a 404 error instead of a 500 error when you navigate to `/checkout/sidebar/updateItemQty/?item_qty=error` on the storefront. Previously, this error was thrown: `Warning: A non-numeric value encountered in /vendor/magento/module-checkout/Controller/Sidebar/UpdateItemQty.php on line 69`. [GitHub-34380](https://github.com/magento/magento2/issues/34380) -* {{ site.data.var.ee }} no longer triggers a `trim(): Passing null to parameter #1 ($string) of type string is deprecated` error when the AMPQ connection is configured without SSL configuration. +* {{ site.data.var.ce }} no longer triggers a `trim(): Passing null to parameter #1 ($string) of type string is deprecated` error when the AMPQ connection is configured without SSL configuration. @@ -477,15 +417,11 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* Knockout text containing single quotes are now translatable. [GitHub-34319](https://github.com/magento/magento2/issues/34319) +* Knockout text containing single quotes is now translatable. [GitHub-34319](https://github.com/magento/magento2/issues/34319) -* A `TypeError` in `magento2/app/code/Magento/Security/Model/AdminSessionsManager.php` has been corrected from int to string. [GitHub-34415](https://github.com/magento/magento2/issues/34415) - - - -* Merchants can now successfully upgrade from an {{ site.data.var.ee }} 2.4.2 deployment with Klarna to {{ site.data.var.ee }} 2.4.3. [GitHub-33760](https://github.com/magento/magento2/issues/33760) +* A `TypeError` in `magento2/app/code/Magento/Security/Model/AdminSessionsManager.php` has been corrected from `int` to `string`. [GitHub-34415](https://github.com/magento/magento2/issues/34415) @@ -505,11 +441,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* The ReadMe files for the GraphQl-GroupedProductGraphQl modules have been updated. [GitHub-34951](https://github.com/magento/magento2/issues/34951) - - - -* [GitHub-34430](https://github.com/magento/magento2/issues/34430) +* The ReadMe files for the `GraphQl-GroupedProductGraphQl` modules have been updated. [GitHub-34951](https://github.com/magento/magento2/issues/34951) @@ -521,25 +453,13 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. * Setting the maximum session size to 0 (Admin **Store** > **Settings** > **Configuration - Advanced**) no longer logs out the administrator. [GitHub-35312](https://github.com/magento/magento2/issues/35312) - - -* {{ site.data.var.ee }} sessions no longer end after a GraphQL request is made. Previously, the `ClearCustomerSessionAfterRequest` plugin logged out the shopper. [GitHub-34550](https://github.com/magento/magento2/issues/34550) - * Customer address attributes configuration settings are now loaded correctly based the website the customer is assigned to when you add a new customer address from the Admin that is assigned to a non-default website. - - -* Category creation is now blocked for a restricted admin on both the Category page and Product Edit page. Previously, category creation was blocked on the category page, but was still possible through the Product Edit page. - -* {{ site.data.var.ee }} no longer throws an exception when you add a bundle product through Page Builder. - - - -* Categories can now be selected from the category tree as a condition for a customer segment. +* {{ site.data.var.ce }} no longer throws an exception when you add a bundle product through Page Builder. @@ -557,10 +477,6 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. * Users with restricted roles are no longer automatically granted access to new modules. - - -* Target rules based on categories display only products from the category that is declared in the rule. Previously, Related Product rules displayed products from categories that were assigned to product and not defined in the rule. - * Related product rule conditions now work as expected with products that contain `multiselect` attributes. @@ -571,11 +487,11 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* {{ site.data.var.ee }} now displays an error message when you set an invalid cookie domain (**Store** > **Configurations** > **Web** > **Default Cookie Settings Cookie Domain**). Previously, the website crashed. [GitHub-35048](https://github.com/magento/magento2/issues/35048) +* {{ site.data.var.ce }} now displays an error message when you set an invalid cookie domain (**Store** > **Configurations** > **Web** > **Default Cookie Settings Cookie Domain**). Previously, the website crashed. [GitHub-35048](https://github.com/magento/magento2/issues/35048) -* {{ site.data.var.ee }} no longer throws an error when an administrator with roles scoped to a single website adds product to Content Elements using PageBuilder. Previously, {{ site.data.var.ee }} threw an SQL error. +* {{ site.data.var.ce }} no longer throws an error when an administrator with roles scoped to a single website adds product to Content Elements using PageBuilder. Previously, {{ site.data.var.ce }} threw an SQL error. @@ -583,11 +499,11 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* {{ site.data.var.ee }} no longer throws the following error during the creation of a catalog rule in the Admin after upgrade: `A technical problem with the server created an error. Try again to continue what you were doing. If the problem persists, try again later`. +* {{ site.data.var.ce }} no longer throws the following error during the creation of a catalog rule in the Admin after upgrade: `A technical problem with the server created an error. Try again to continue what you were doing. If the problem persists, try again later`. -* {{ site.data.var.ee }} no longer throws an error when you activate the **Check here to link an RSS feed to your Wish List** checkbox before clicking on **Share Wish list**. [GitHub-34998](https://github.com/magento/magento2/issues/34998) +* {{ site.data.var.ce }} no longer throws an error when you activate the **Check here to link an RSS feed to your Wish List** checkbox before clicking on **Share Wish list**. [GitHub-34998](https://github.com/magento/magento2/issues/34998) @@ -601,12 +517,6 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. * Removed unneeded `csp_whitelist.xml` files. [GitHub-30607](https://github.com/magento/magento2/issues/30607) -### Gift cards - - - -* `products` queries now correctly returns product data that contains gift card products with a `gift-card` URL key. - ### GraphQL @@ -625,13 +535,9 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. * The `new_from_data` and `new_to_datefields` in `ProductInterface` are no longer deprecated. [GitHub-34783](https://github.com/magento/magento2/issues/34783) - - -* The `getCartDetails` query now returns only one payment methods for free orders. Previously, all active payment methods were returned in the query response. [GitHub-34036](https://github.com/magento/magento2/issues/34036) - -* The `categories` query no longer throws an exception when fetching a list of categories one of which contains an image that can’t be found on the filesystem. Previously, {{ site.data.var.ee }} threw this exception: Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) +* The `categories` query no longer throws an exception when fetching a list of categories one of which contains an image that cannot be found on the filesystem. Previously, {{ site.data.var.ce }} threw this exception: Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) @@ -651,11 +557,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* {{ site.data.var.ee }} sessions no longer end after a GraphQL request is made. Previously, the `ClearCustomerSessionAfterRequest` plugin logged out the shopper. [GitHub-34550](https://github.com/magento/magento2/issues/34550) - - - -* The `products` query no longer returns price_range values for configurable products that are affected by disabled variants. [GitHub-33629](https://github.com/magento/magento2/issues/33629) +* {{ site.data.var.ce }} sessions no longer end after a GraphQL request is made. Previously, the `ClearCustomerSessionAfterRequest` plugin logged out the shopper. [GitHub-34550](https://github.com/magento/magento2/issues/34550) @@ -667,7 +569,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* `setShippingAddressesOnCart` requests now successfully validate region IDs. Previously, {{ site.data.var.ee }} threw an error when you used region ID instead of region code. +* `setShippingAddressesOnCart` requests now successfully validate region IDs. Previously, {{ site.data.var.ce }} threw an error when you used region ID instead of region code. @@ -675,59 +577,27 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* The `categoryList` query now returns results that reflect the queried store's root category when the store specified in the header. Previously, categories from the default root category were included in results even though another store was specified in the header. +* The `categoryList` query now returns results that reflect the queried store's root category when the store is specified in the header. Previously, categories from the default root category were included in results even though another store was specified in the header. * The `products` query no longer returns attributes as an aggregation when the **Use in Search Results Layered Navigation** setting is disabled. [GitHub-33318](https://github.com/magento/magento2/issues/33318) - - -* A missing `price_range` attribute has been added to the GraphQL `BundleItemOption` type. [GitHub-35010](https://github.com/magento/magento2/issues/35010) - - - -* The `products` query no longer returns attributes as an aggregation when the **Use in Search Results** Layered Navigation setting is disabled. [GitHub-33318](https://github.com/magento/magento2/issues/33318) - - - -* A `price_including_tax` field has been added to `CartItemPrices`. [GitHub-29057](https://github.com/magento/magento2/issues/29057) - - - -* The `new_from_data` and `new_to_datefields` in `ProductInterface` are no longer deprecated. [GitHub-34783](https://github.com/magento/magento2/issues/34783) - * The `cart` query now returns only one payment methods for free orders. Previously, all active payment methods were returned in the query response. [GitHub-34036](https://github.com/magento/magento2/issues/34036) - - -* The `categories` query no longer throws an exception when fetching a list of categories one of which contains an image that can’t be found on the filesystem. Previously, {{ site.data.var.ee }} threw this exception: Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) - - - -* The `GetProductsInCategory` query now returns `category_uid` as an aggregation as expected. [GitHub-32557](https://github.com/magento/magento2/issues/32557) - - - -* The `updateCartItems` query now removes products as expected when the product stock has reached the maximum stock amount. [GitHub-30220](https://github.com/magento/magento2/issues/30220) - - - -* `customer` queries now fetch bundle product multi-select options as expected when querying orders. [GitHub-34717](https://github.com/magento/magento2/issues/34717) - -* `products` queries no longer returns price_range values for configurable products that are affected by disabled variants. [GitHub-33629](https://github.com/magento/magento2/issues/33629) +* `products` queries no longer returns `price_range` values for configurable products that are affected by disabled variants. [GitHub-33629](https://github.com/magento/magento2/issues/33629) -* Added a plugin before the `collectQuoteTotals` call to ensure store credits aren't applied multiple times. +* Added a plugin before the `collectQuoteTotals` call to ensure store credits are not applied multiple times. -* Creating a new special price schedule with the `POST /V1/products/special-price` endpoint now works as expected. Previously, the endpoint returned the message `Future Update already exists in this time range. Set a different range and try again`. +* Creating a new special price schedule with the `POST /V1/products/special-price` endpoint now works as expected. Previously, the endpoint returned this error: `Future Update already exists in this time range. Set a different range and try again`. @@ -747,7 +617,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* The `products` query now returns only the sub category of provided category ID. Previously, it returned all categories. [GitHub-35220](https://github.com/magento/magento2/issues/35220) +* The `products` query now returns only the subcategory of provided category ID. Previously, it returned all categories. [GitHub-35220](https://github.com/magento/magento2/issues/35220) @@ -785,11 +655,11 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* {{ site.data.var.ee }} now checks for a custom view before filtering columns when exporting reports. Previously, exported reports did not take into account custom views, and exported columns were incorrect. +* {{ site.data.var.ce }} now checks for a custom view before filtering columns when exporting reports. Previously, exported reports did not take into account custom views, and exported columns were incorrect. -* {{ site.data.var.ee }} now successfully imports images with long file names. Previously, {{ site.data.var.ee }} did not import the image and threw this error: `Imported resource (image) could not be downloaded from external resource due to timeout or access permissions in row(s):`. +* {{ site.data.var.ce }} now successfully imports images with long file names. Previously, {{ site.data.var.ce }} did not import the image and threw this error: `Imported resource (image) could not be downloaded from external resource due to timeout or access permissions in row(s):`. @@ -801,7 +671,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* Added validation for category names during import. Previously, {{ site.data.var.ee }} did not validate category names, which lead to errors when category names exceeded 255 characters. +* Added validation for category names during import. Previously, {{ site.data.var.ce }} did not validate category names, which lead to errors when category names exceeded 255 characters. @@ -809,10 +679,6 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. ### Infrastructure - - -* The SQL query that updates affected quotes after a cart price rule is disabled has been optimized to avoid locking the entire quote table. - * A deprecated Context Menu plugin has been removed from plugins list. @@ -847,14 +713,9 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* Customer, customer address, and order actions are now logged correctly in the Admin action report. Previously, {{ site.data.var.ee }} did not log actions if the `postDispatch` handler had not been specified in configuration settings. - -### {{ site.data.var.ee }} coding standard +* Customer, customer address, and order actions are now logged correctly in the Admin action report. Previously, {{ site.data.var.ce }} did not log actions if the `postDispatch` handler had not been specified in configuration settings. ### MFTF - -#### New action groups - #### Action groups Repetitive actions have been replaced with action groups in these tests: @@ -888,14 +749,6 @@ Repetitive actions have been replaced with action groups in these tests: ### Order - - -* You can now successfully create a new customer from a new order with custom customer attribute that are hidden from the storefront. Previously, {{ site.data.var.ee }} did not save the correct values for the custom customer attribute. - - - -* Reward points can now be refunded when store credit functionality is disabled. - * Guest customer details are now saved successfully after an order is edited. Previously, some customer details were lost, including `customer_firstname` and `customer_lastname, x_forwarded_for`. @@ -910,23 +763,19 @@ Repetitive actions have been replaced with action groups in these tests: -* {{ site.data.var.ee }} no longer changes custom email addresses that are assigned to orders when you change the main email address assigned to the customer on the Admin account edit page. Previously, when you edited the main email address for a customer, the new email address was assigned to every order created for that customer. [GitHub-34397](https://github.com/magento/magento2/issues/34397) +* {{ site.data.var.ce }} no longer changes custom email addresses that are assigned to orders when you change the main email address assigned to the customer on the Admin account edit page. Previously, when you edited the main email address for a customer, the new email address was assigned to every order created for that customer. [GitHub-34397](https://github.com/magento/magento2/issues/34397) -* {{ site.data.var.ee }} now displays records from the requested store on the credit memos grid page in deployments running PHP 7.4. Previously, {{ site.data.var.ee }} threw the following error after you created a credit memo and tried to view it: `The store that was requested wasn't found. Verify the store and try again`. +* {{ site.data.var.ce }} now displays records from the requested store on the credit memos grid page in deployments running PHP 7.4. Previously, {{ site.data.var.ce }} threw the following error after you created a credit memo and tried to view it: `The store that was requested wasn't found. Verify the store and try again`. -* {{ site.data.var.ee }} now displays credit memos on the credit memo grid page for orders created from store views whose name is prepended with numbers. Previously, {{ site.data.var.ee }} displayed the error: `The store that was requested wasn't found. Verify the store and try again. Exception in /var/www/html/vendor/magento/module-store/Model/StoreRepository.php:75`. [GitHub-35122](https://github.com/magento/magento2/issues/35122) +* {{ site.data.var.ce }} now displays credit memos on the credit memo grid page for orders created from store views whose name is prepended with numbers. Previously, {{ site.data.var.ce }} displayed the error: `The store that was requested wasn't found. Verify the store and try again. Exception in /var/www/html/vendor/magento/module-store/Model/StoreRepository.php:75`. [GitHub-35122](https://github.com/magento/magento2/issues/35122) -* {{ site.data.var.ee }} now displays the free shipping cost (0) on the Admin and storefront invoice page totals. Previously, when shipping was zero for an order, {{ site.data.var.ee }} did not display the shipping amount in total on the invoice page shipping total. - - - -* {{ site.data.var.ee }} now displays correct order status during checkout when customer store credit is used. +* {{ site.data.var.ce }} now displays the free shipping cost (0) on the Admin and storefront invoice page totals. Previously, when shipping was zero for an order, {{ site.data.var.ce }} did not display the shipping amount in total on the invoice page shipping total. @@ -936,7 +785,7 @@ Repetitive actions have been replaced with action groups in these tests: -* Administrators can now place an order on the Admin using the PayPal PayflowPro payment method. Previously, {{ site.data.var.ee }} displayed this error: `No such entity with cartId = 0`. +* Administrators can now place an order on the Admin using the PayPal PayflowPro payment method. Previously, {{ site.data.var.ce }} displayed this error: `No such entity with cartId = 0`. @@ -950,7 +799,7 @@ Repetitive actions have been replaced with action groups in these tests: -* {{ site.data.var.ee }} now shows the correct customer name in a guest order paid for with PayPal. Previously, the customer name was displayed as Guest. +* {{ site.data.var.ce }} now shows the correct customer name in a guest order paid for with PayPal. Previously, the customer name was displayed as Guest. @@ -958,10 +807,6 @@ Repetitive actions have been replaced with action groups in these tests: ### Performance - - -* The performance of dynamic block loading has been improved. Previously, visitor segments were not cached per website, which caused redundant queries to the database for the same data. - * Redis cache management has been improved by the addition of TTL (expiration date) for configurable products’ associated product data caches. Previously, these caches were not evicted due to missing TTL values if Redis key eviction policy was configured to a volatile eviction policy. @@ -988,43 +833,13 @@ Repetitive actions have been replaced with action groups in these tests: * The price listed on the product detail page is now the same as the price listed in the checkout workflow for tier prices that differ by quantity selected (for example, a product priced differently based on buying 2 items versus 5 items). Previously, the checkout price reflected the price for the lowest product quantity. -### Promotions - - - -* The **Times Used** value for a discount is no longer incremented twice when a guest customer places an order with a discount and subsequently registers an account. - ### ReCAPTCHA * The **Submit** button on the Login and Create an Account pages is now inactive until ReCaptcha is fully loaded. -### Return Merchandise Authorizations (RMA) - - - -* The `GET /V1/returnsAttributeMetadata` endpoint now works correctly when the `rma_item` entity default attribute set ID differs from the default installation ID. Previously, this endpoint returned an empty result if these IDs differed. - - - -* The **Use Default** checkbox, which is used to enable RMA on the product edit page, now works as expected for Default Store. Previously, the checkbox was cleared immediately after the product was saved. - -### Rewards - - - -* Reward points can now be refunded when store credit functionality is disabled. - - - -* Checkout performance has been improved when reward points are applied. When `entity` is null, then the database query will not be executed because querying the `magento_reward_history` table is not mandatory under the circumstances. - - - -* Credit memos for guest orders no longer check for `customer_id`, which skips querying the `magento_reward_history' database table table for reward points. This change has improved performance. - ### Roles -* The **Store** > **Configuration** > **Services** page now displays {{ site.data.var.ee }} Web API information as expected when Resource Access is set to **Custom** on the Role Resources tab. [GitHub-35506](https://github.com/magento/magento2/issues/35506) +* The **Store** > **Configuration** > **Services** page now displays {{ site.data.var.ce }} Web API information as expected when Resource Access is set to **Custom** on the Role Resources tab. [GitHub-35506](https://github.com/magento/magento2/issues/35506) ### Search @@ -1034,7 +849,7 @@ Repetitive actions have been replaced with action groups in these tests: -* Elasticsearch queries now work as expected when `int` is configured as a searchable backend `type` attribute. Previously, {{ site.data.var.ee }} threw an `Elasticsearch\Common\Exceptions\BadRequest400Exception` exception. +* Elasticsearch queries now work as expected when `int` is configured as a searchable backend `type` attribute. Previously, {{ site.data.var.ce }} threw an `Elasticsearch\Common\Exceptions\BadRequest400Exception` exception. @@ -1042,7 +857,7 @@ Repetitive actions have been replaced with action groups in these tests: -* {{ site.data.var.ee }} now displays an accurate search results suggestion count on the storefront in deployments where Search Suggestions and the **Show Results Count for Each Suggestion** setting are enabled. Previously, the count displayed next to the keywords was zero. +* {{ site.data.var.ce }} now displays an accurate search results suggestion count on the storefront in deployments where Search Suggestions and the **Show Results Count for Each Suggestion** setting are enabled. Previously, the count displayed next to the keywords was zero. @@ -1054,13 +869,13 @@ Repetitive actions have been replaced with action groups in these tests: -* Fixed PHP errors on the `catalogsearch/advanced/result` and  `catalogsearch/advanced/index` pages. Previously, {{ site.data.var.ee }} displayed this error when an array was passed in any advanced search string : `Warning: trim() expects parameter 1 to be string, array given | magento/module-catalog-search`. [GitHub-33586](https://github.com/magento/magento2/issues/33586) +* Fixed PHP errors on the `catalogsearch/advanced/result` and  `catalogsearch/advanced/index` pages. Previously, {{ site.data.var.ce }} displayed this error when an array was passed in any advanced search string : `Warning: trim() expects parameter 1 to be string, array given | magento/module-catalog-search`. [GitHub-33586](https://github.com/magento/magento2/issues/33586) ### Shipping -* {{ site.data.var.ee }} no longer throws an error when loading UPS shipping rates if no allowed shipping methods are selected. Previously, when a shopper entered a shipping address in the checkout workflow under these conditions, no other shipping methods were displayed, and {{ site.data.var.ee }} displayed an error on the storefront. [GitHub-34411](https://github.com/magento/magento2/issues/34411) +* {{ site.data.var.ce }} no longer throws an error when loading UPS shipping rates if no allowed shipping methods are selected. Previously, when a shopper entered a shipping address in the checkout workflow under these conditions, no other shipping methods were displayed, and {{ site.data.var.ce }} displayed an error on the storefront. [GitHub-34411](https://github.com/magento/magento2/issues/34411) @@ -1070,56 +885,6 @@ Repetitive actions have been replaced with action groups in these tests: * Table rate shipping rates with zero price are now displayed correctly in the checkout workflow Order Summary block for orders that have had a discount coupon applied. Previously, the shipping method was not displayed. -### Staging - - - -* {{ site.data.var.ee }} no longer cleans the full-page cache after applying a staging update for a sales rule in which the cached pages remain unchanged. - - - -* The content staging dashboard no longer displays inactive permanent updates. - - - -* Changing the end date for a staging update from the staging dashboard now successfully applies these changes to the staging update and its entities. (A queue has been introduced to process staging updates changes.) - - - -* Merchants can now remove an end date for a scheduled update or delete and recreate an update. Previously, when an end date was removed, an entity remained scheduled for that time. {{ site.data.var.ee }} now removes the outdated update for removed rollback. - - - -* Active schedule updates for a CMS page are now visible as expected in the Scheduled Changes section on the CMS page. - - - -* The `custom_design_to` attribute value is now updated as expected when a scheduled update is changed. Previously, two separate category design updates with no end time were treated as one. When one of the scheduled updates was deleted while the first one was running, the `custom_design_from` time value became greater than the `custom_design_to` time values in the next scheduled update. - - - -* Forms are now populated with data as expected after a scheduled update is edited. - - - -* The `vendor/magento/module-catalog-staging/Setup/Patch/Data/MigrateCatalogProducts.php` data patch no longer fails when the database includes product with custom options and the `special_from_date` attribute is set. - - - -* Changes are now saved during a second scheduled update when the changes are added by the running update. Previously, changes were not saved, and merchants needed to re-enter and save changes. - - - -* The Bulk actions log now displays information about failed `to be moved` scheduled updates. Previously, information about these failures was available in the `cron.log` file only. - - - -* Merchants are now restricted to using comma-separated prices when editing a product price in a scheduled update regardless of locale. Previously, prices that contained commas in a scheduled update were divided by 1000 depending on the locale. - - - -* Problems with DHL domestic shipping in deployments running PHP 8.1 have been resolved by requiring dutiable tags for international shipments only. - ### Tax @@ -1132,7 +897,7 @@ Repetitive actions have been replaced with action groups in these tests: -* {{ site.data.var.ee }} now updates the Excluding Tax tier price for a simple product on the product page as expected after the quantity of the simple product has changed. +* {{ site.data.var.ce }} now updates the Excluding Tax tier price for a simple product on the product page as expected after the quantity of the simple product has changed. @@ -1202,10 +967,6 @@ Repetitive actions have been replaced with action groups in these tests: * Lengthy product names in the **Catalog** > **Products** grid are now word-wrapped instead of displayed in a single line. - - -* You can now edit default stock from Admin **Stores** > **Inventory** > **Stocks**. Previously, a JavaScript error was displayed in the console when you tried to add or remove sources from default stock, although you could assign websites to default stock. - * The minimal and maximum date-of-birth range is now saved as a correct timestamp and then converted from a valid timestamp to a valid date format. @@ -1220,7 +981,7 @@ Repetitive actions have been replaced with action groups in these tests: -* You can now create a customer from the Admin when `Magento_LoginAsCustomerAdminUi` is enabled and **Store View To Login To** is set to manual selection. Previously, {{ site.data.var.ee }} threw this error: `(Magento\Framework\Exception\LocalizedException): Unable to get Customer ID`. [GitHub-33096](https://github.com/magento/magento2/issues/33096) +* You can now create a customer from the Admin when `Magento_LoginAsCustomerAdminUi` is enabled and **Store View To Login To** is set to manual selection. Previously, {{ site.data.var.ce }} threw this error: `(Magento\Framework\Exception\LocalizedException): Unable to get Customer ID`. [GitHub-33096](https://github.com/magento/magento2/issues/33096) @@ -1230,10 +991,6 @@ Repetitive actions have been replaced with action groups in these tests: * The **Search by keyword** input field now has an `aria-label` element instead of a placeholder on the **Catalog** > **Product** page. - - -* Category creation is now blocked for an administrator with restricted permissions on both the category and product edit pages. Previously, category creation was blocked on the category page, but was still possible through the product edit page. - * The Privacy Policy link in Admin footer now links to the new Adobe Privacy Policy. @@ -1248,7 +1005,7 @@ Repetitive actions have been replaced with action groups in these tests: -* {{ site.data.var.ee }} now displays an informative error message when an administrator tries to save an address with excessive street lines in Admin **Store** > **Attributes** > **Customer Address**. The administrator can now delete the extra address information and successfully save the address. Previously, {{ site.data.var.ee }} committed the extra lines but did not save the data. +* {{ site.data.var.ce }} now displays an informative error message when an administrator tries to save an address with excessive street lines in Admin **Store** > **Attributes** > **Customer Address**. The administrator can now delete the extra address information and successfully save the address. Previously, {{ site.data.var.ce }} committed the extra lines but did not save the data. @@ -1260,7 +1017,7 @@ Repetitive actions have been replaced with action groups in these tests: -* The favicon icon upload form now supports `.ico` file types. Previously, when you tried to upload a favicon file with this extension type in the Admin, {{ site.data.var.ee }} displayed this error: `Warning: imagecreatefromstring(): one parameter to a memory allocation multiplication is negative or zero, failing operation gracefully in /var/www/html/vendor/magento/module-media-storage/Model/File/Validator/Image.php on line 64`. [GitHub-34858](https://github.com/magento/magento2/issues/34858) +* The favicon icon upload form now supports `.ico` file types. Previously, when you tried to upload a favicon file with this extension type in the Admin, {{ site.data.var.ce }} displayed this error: `Warning: imagecreatefromstring(): one parameter to a memory allocation multiplication is negative or zero, failing operation gracefully in /var/www/html/vendor/magento/module-media-storage/Model/File/Validator/Image.php on line 64`. [GitHub-34858](https://github.com/magento/magento2/issues/34858) @@ -1284,7 +1041,7 @@ Repetitive actions have been replaced with action groups in these tests: -* You can now set a Vimeo video to run in the background in a `banner` element when CSP is set to `restrict mode`. Previously, {{ site.data.var.ee }} threw this JavaScript error when you tried to save the element: `Refused to connect to 'https://vimeo.com/api/v2/video/76979871.json' because it violates the following Content Security Policy directive`. +* You can now set a Vimeo video to run in the background in a `banner` element when CSP is set to `restrict mode`. Previously, {{ site.data.var.ce }} threw this JavaScript error when you tried to save the element: `Refused to connect to 'https://vimeo.com/api/v2/video/76979871.json' because it violates the following Content Security Policy directive`. ### Web API framework @@ -1292,10 +1049,6 @@ Repetitive actions have been replaced with action groups in these tests: * Mutex has been implemented for orders to prevent race conditions during update by concurrent requests. Previously, race conditions during concurrent REST API calls resulted in an overwrite of shipping status information in the Admin Items Ordered table. - - -* Dynamic bundle attributes are now updated correctly on the Mass Attribute Update page. Previously, the **Dynamic SKU** attribute remained set to **Yes** even though they were disabled on the Mass Update page. - * Product image role inheritance is now preserved unless explicitly defined in the payload when updating a product in a specific store view via the REST API. @@ -1328,7 +1081,7 @@ Repetitive actions have been replaced with action groups in these tests: -* Updating an item quantity from the wish list page now updates the quantity on the product detail page as expected. {{ site.data.var.ee }} now picks up the updated value from the product URL and populates the `qty` field of product detail page from the wishlist itself. +* Updating an item quantity from the wish list page now updates the quantity on the product detail page as expected. {{ site.data.var.ce }} now picks up the updated value from the product URL and populates the `qty` field of product detail page from the wishlist itself. ## Known Issues From ac319917ae84c7b7cc35d3be74490d6c46b0f51b Mon Sep 17 00:00:00 2001 From: jfrontain Date: Sun, 10 Jul 2022 21:39:18 -0500 Subject: [PATCH 268/776] added highlights --- .../v2.4/release-notes/commerce-2-4-5.md | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md index 42ac22c7255..5f53fb18905 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-5.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -135,7 +135,11 @@ Primary index performance has been improved by reducing the number of primary in ### GraphQL -This release includes these GraphQL enhancements: +GraphQL performance hs been improved by these enhancements: + +* **Optimized creation of unified GraphQL schemas**. Rebuilding a GraphQL schema after flushing a Commerce instance’s cache can consume many resources, particularly during heavy site traffic. The time required to rebuild a schema has been reduced significantly. + +* **Improved authorization processing** through the use of JSON Web Tokens (JWT) and session-less GraphQL API. See the [GraphQL Developer Guide]({{page.baseurl}}/graphql/) for details on these enhancements. @@ -158,6 +162,9 @@ Channel Manager can now trigger refunds from Adobe Commerce. Merchants can now m Requests are now automatically synced back to the Walmart Marketplace. +### Google Analytics + +See [Migrate from analytics.js to gtag.js (Universal Analytics) ](https://developers.google.com/analytics/devguides/migration/ua/analyticsjs-to-gtagjs​https://support.google.com/google-ads/answer/7548399?hl=en). ### PWA Studio PWA Studio v.12.x.x is compatible with {{ site.data.var.ee }} 2.4.5. @@ -173,8 +180,6 @@ For information about enhancements and bug fixes, see [PWA Studio releases](http Merchants in Spain and Italy can now offer PayPal Pay Later to shoppers. -### Braintree - ### Live Search This release introduces support for B2B customer groups and custom pricing. @@ -199,6 +204,18 @@ Page Builder column layout includes these enhancements: The Admin has been updated to align with Adobe’s branch strategy. Changes affect headers, footers, data grid color updates, and navigation elements. +### Upgrade Compatibility Tool + +New enhancements include: + +* Method signature validation now identifies incompatible changes within a method or a constructor signature. + +* Database schema validation now identifies schema changes and incompatibilities. + +* DI configuration validation now verifies references to removed or deprecated non-API core classes in `di.xml` and preferences for core classes and interfaces. + +* UCT now identifies code deprecations and provides specific recommendations for resolving each issue. + ## Fixed issues We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. From 1c698f1e6e0e4db69c3957a1ba21bda2c0eefd38 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Mon, 11 Jul 2022 14:16:37 -0500 Subject: [PATCH 269/776] Remove reference to dataFixtureDataProvider from docblock annotations --- src/guides/v2.4/test/integration/annotations.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/guides/v2.4/test/integration/annotations.md b/src/guides/v2.4/test/integration/annotations.md index 507885b66a4..d94ceeb5624 100644 --- a/src/guides/v2.4/test/integration/annotations.md +++ b/src/guides/v2.4/test/integration/annotations.md @@ -21,7 +21,6 @@ Configuration Fixture|`@magentoConfigFixture`|`@magentoConfigFixture [|| [as:alias | with:{}]`|Points to a class or a method which creates testing entities (fixtures) for test execution. These are applied during the transaction. Data Fixture Before Transaction|`@magentoDataFixtureBeforeTransaction`|`@magentoDataFixtureBeforeTransaction |`|Points to a class or a method which creates testing entities (fixtures) for test execution before the transaction has begun. You will need to implement a rollback file for changes made here. (e.g. Fixture file my_fixture.php would also require a my_fixture_rollback.php that reverts the original fixture's changed.) -Data Fixture Data Provider|`@magentoDataFixtureDataProvider`|`@magentoDataFixtureDataProvider |{}`|Points to a Data Provider callable method or contains an inline JSON string for Parameterized Data Fixtures. Application Area|`@magentoAppArea`|`@magentoAppArea adminhtml|frontend|global`|Configures test environment in the context of specified application area. Enable/Disable Cache|`@magentoCache`|`@magentoCache |all enabled|disabled`|Enables or disables certain cache segment or all of them to prevent isolation problems. Indexer Dimension Mode|`@magentoIndexerDimensionMode`|`@magentoIndexerDimensionMode `|Sets the indexer dimension mode for the test run. More information can be found in the [DevBlog](https://community.magento.com/t5/Magento-DevBlog/Indexers-parallelization-and-optimization/ba-p/104922). @@ -34,7 +33,6 @@ The Magento-specific annotations for integration tests are applied in the follow 1. `@magentoAppIsolation` 1. `@magentoDbIsolation` 1. `@magentoDataFixtureBeforeTransaction` -1. `@magentoDataFixtureDataProvider` 1. `@magentoDataFixture` 1. `@magentoIndexerDimensionMode` 1. `@magentoComponentsDir` From d3ff7924bc5eb17a70abdd48a6e22e81126d4803 Mon Sep 17 00:00:00 2001 From: jfrontain Date: Mon, 11 Jul 2022 14:40:07 -0500 Subject: [PATCH 270/776] added keharper's comments --- src/guides/v2.4/release-notes/commerce-2-4-5.md | 16 +++++++++++----- .../v2.4/release-notes/open-source-2-4-5.md | 6 +++--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md index 5f53fb18905..65986b03ded 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-5.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -64,7 +64,7 @@ Security improvements for this release improve compliance with the latest securi * `PHPStan` (^1.5.7 with constraint) [GitHub-35315](https://github.com/magento/magento2/issues/35315) -* DHL Integration schema has been updated from v6.0 to v6.2. DHL has deprecated v6.0 +* DHL Integration schema has been updated from v6.0 to v6.2. DHL has deprecated v6.0. This upgrade will not result in a change in product behavior. Outdated JavaScript libraries have been updated to their latest versions, and outdated dependencies have been removed. These changes are backward compatible. @@ -178,7 +178,13 @@ New features for this release include: For information about enhancements and bug fixes, see [PWA Studio releases](https://github.com/magento/pwa-studio/releases). See [Version compatibility](https://developer.adobe.com/commerce/pwa-studio/integrations/adobe-commerce/version-compatibility/) for a list of PWA Studio versions and their compatible {{ site.data.var.ee }} core versions. ### PayPal Payment enhancements -Merchants in Spain and Italy can now offer PayPal Pay Later to shoppers. +* Merchants in Spain and Italy can now offer PayPal Pay Later to shoppers. + +* Previews of the PayPal, Credit and Pay Later buttons are now available in the Admin for the checkout, minicart, cart, and product pages. Previews reveal how these buttons will look when they are enabled and rendered on the storefront. + +#### Braintree + +The KOUNT integration has been removed due to discontinuation by Braintree. ### Live Search @@ -746,7 +752,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* The `categories` query no longer throws an exception when fetching a list of categories one of which contains an image that cannot be found on the filesystem. Previously, {{ site.data.var.ee }} threw this exception: Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) +* The `categories` query no longer throws an exception when fetching a list of categories one of which contains an image that cannot be found on the filesystem. Previously, {{ site.data.var.ee }} threw this exception: `Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) @@ -754,7 +760,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. -* The `updateCartItems` query now removes products as expected when the product stock has reached the maximum stock amount. [GitHub-30220](https://github.com/magento/magento2/issues/30220) +* The `updateCartItems` mutation now removes products as expected when the product stock has reached the maximum stock amount. [GitHub-30220](https://github.com/magento/magento2/issues/30220) @@ -1253,7 +1259,7 @@ Repetitive actions have been replaced with action groups in these tests: -* Added a grave accent [ ` ] character to the name validator so that customer account can be created for first or last names that include this accent. +* Added a grave accent [ \` ] character to the name validator so that customer account can be created for first or last names that include this accent. diff --git a/src/guides/v2.4/release-notes/open-source-2-4-5.md b/src/guides/v2.4/release-notes/open-source-2-4-5.md index 7f499ed2192..04516e57f1b 100644 --- a/src/guides/v2.4/release-notes/open-source-2-4-5.md +++ b/src/guides/v2.4/release-notes/open-source-2-4-5.md @@ -537,7 +537,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* The `categories` query no longer throws an exception when fetching a list of categories one of which contains an image that cannot be found on the filesystem. Previously, {{ site.data.var.ce }} threw this exception: Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) +* The `categories` query no longer throws an exception when fetching a list of categories one of which contains an image that cannot be found on the filesystem. Previously, {{ site.data.var.ce }} threw this exception: `Category image not found`. [GitHub-34266](https://github.com/magento/magento2/issues/34266) @@ -545,7 +545,7 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. -* The `updateCartItems` query now removes products as expected when the product stock has reached the maximum stock amount. [GitHub-30220](https://github.com/magento/magento2/issues/30220) +* The `updateCartItems` mutation now removes products as expected when the product stock has reached the maximum stock amount. [GitHub-30220](https://github.com/magento/magento2/issues/30220) @@ -947,7 +947,7 @@ Repetitive actions have been replaced with action groups in these tests: -* Added a grave accent [ ` ] character to the name validator so that customer account can be created for first or last names that include this accent. +* Added a grave accent [ \` ] character to the name validator so that customer account can be created for first or last names that include this accent. From 9d8469b4d5f3e250641ab7db29a645e92391c532 Mon Sep 17 00:00:00 2001 From: jfrontain Date: Mon, 11 Jul 2022 15:11:38 -0500 Subject: [PATCH 271/776] removed invalid link --- src/guides/v2.4/release-notes/commerce-2-4-5.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md index 65986b03ded..50273929101 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-5.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -121,7 +121,7 @@ The `laminas/laminas-session`, `laminas/laminas-text`, and `laminas/laminas-view * The library `jquery/jquery-cookie` has been replaced with `js-cookie/js-cookie`. -* The `jarallax.js` and `jaralax-video.js` libraries have been updated to use the latest version of the Vimeo REST API. See [The Basics]( https://developer.vimeo.com/api/guides/start). +* The `jarallax.js` and `jaralax-video.js` libraries have been updated to use the latest version of the Vimeo REST API. ### Performance and scalability enhancements From fd67d91f855501ef8ca832774a46189b7aca17f2 Mon Sep 17 00:00:00 2001 From: jfrontain Date: Mon, 11 Jul 2022 16:18:28 -0500 Subject: [PATCH 272/776] removed error message --- src/guides/v2.4/release-notes/commerce-2-4-5.md | 2 +- src/guides/v2.4/release-notes/open-source-2-4-5.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md index 50273929101..de36b1a652f 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-5.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -1353,7 +1353,7 @@ Repetitive actions have been replaced with action groups in these tests: -* You can now set a Vimeo video to run in the background in a `banner` element when CSP is set to `restrict mode`. Previously, {{ site.data.var.ee }} threw this JavaScript error when you tried to save the element: `Refused to connect to 'https://vimeo.com/api/v2/video/76979871.json' because it violates the following Content Security Policy directive`. +* You can now set a Vimeo video to run in the background in a `banner` element when CSP is set to `restrict mode`. Previously, {{ site.data.var.ee }} threw a JavaScript error. ### Web API framework diff --git a/src/guides/v2.4/release-notes/open-source-2-4-5.md b/src/guides/v2.4/release-notes/open-source-2-4-5.md index 04516e57f1b..403c26b4894 100644 --- a/src/guides/v2.4/release-notes/open-source-2-4-5.md +++ b/src/guides/v2.4/release-notes/open-source-2-4-5.md @@ -1041,7 +1041,7 @@ Repetitive actions have been replaced with action groups in these tests: -* You can now set a Vimeo video to run in the background in a `banner` element when CSP is set to `restrict mode`. Previously, {{ site.data.var.ce }} threw this JavaScript error when you tried to save the element: `Refused to connect to 'https://vimeo.com/api/v2/video/76979871.json' because it violates the following Content Security Policy directive`. +* You can now set a Vimeo video to run in the background in a `banner` element when CSP is set to `restrict mode`. Previously, {{ site.data.var.ce }} threw a JavaScript error. ### Web API framework From c8719ccb8790da35dda01363e4bbcf563125abe2 Mon Sep 17 00:00:00 2001 From: vkolesny Date: Mon, 11 Jul 2022 16:33:31 -0500 Subject: [PATCH 273/776] ACP2E-994: [Documentation] Add notice that Admin, Bearer and other types of tokens are not supported to skip providing of HTTP X-Captcha header. --- src/guides/v2.4/graphql/protected-mutations.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/guides/v2.4/graphql/protected-mutations.md b/src/guides/v2.4/graphql/protected-mutations.md index e8977d8ce73..4519a7b8096 100644 --- a/src/guides/v2.4/graphql/protected-mutations.md +++ b/src/guides/v2.4/graphql/protected-mutations.md @@ -5,10 +5,10 @@ title: Protected mutations If CAPTCHA or reCAPTCHA is enabled on pages requiring shopper input, then in most cases, the corresponding mutations that send requests to the Magento server must include an HTTP header that contains a value entered by the shopper (for CAPTCHA) or generated by the Google API (for reCAPTCHA). However, if you specify an integration authorization token in the header of the mutation, then you do not supply a header specific to CAPTCHA or reCAPTCHA. -HTTP `X-Captcha` header: +HTTP `X-Captcha` and `X-ReCaptcha` headers: -* Cannot be received by automated script or non-UI API call. It is captured and returned by UI Web form only. -* Is optional in protected mutation API calls with providing **_integration authorization_** tokens only. It cannot be skipped with Admin and Bearer tokens. +* Cannot be received by automated script or non-UI API call. They are captured and returned by UI Web form only. +* Are optional in protected mutation API calls with providing **_integration authorization_** tokens only. They cannot be skipped with Admin and Bearer tokens. ## CAPTCHA From ef73f41360ede572a0877ea7449242f44028b408 Mon Sep 17 00:00:00 2001 From: vkolesny Date: Tue, 12 Jul 2022 10:09:55 -0500 Subject: [PATCH 274/776] ACP2E-994: [Documentation] Add notice that Admin, Bearer and other types of tokens are not supported to skip providing of HTTP X-Captcha header. --- .../v2.3/graphql/protected-mutations.md | 30 ++++++++++++++++- src/guides/v2.3/rest/protected-endpoints.md | 32 +++++++++++++++++-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/guides/v2.3/graphql/protected-mutations.md b/src/guides/v2.3/graphql/protected-mutations.md index f9d4552ccbc..4519a7b8096 100644 --- a/src/guides/v2.3/graphql/protected-mutations.md +++ b/src/guides/v2.3/graphql/protected-mutations.md @@ -3,10 +3,19 @@ group: graphql title: Protected mutations --- -If CAPTCHA is enabled on pages requiring shopper input, then in most cases, the corresponding mutations that send requests to the Magento server must include the shopper's CAPTCHA response. Supply the shopper's response in the HTTP `X-Captcha` header. The exception to this policy is that you do not send the CAPTCHA response if you specify an integration authorization token in the header of the mutation. +If CAPTCHA or reCAPTCHA is enabled on pages requiring shopper input, then in most cases, the corresponding mutations that send requests to the Magento server must include an HTTP header that contains a value entered by the shopper (for CAPTCHA) or generated by the Google API (for reCAPTCHA). However, if you specify an integration authorization token in the header of the mutation, then you do not supply a header specific to CAPTCHA or reCAPTCHA. + +HTTP `X-Captcha` and `X-ReCaptcha` headers: + +* Cannot be received by automated script or non-UI API call. They are captured and returned by UI Web form only. +* Are optional in protected mutation API calls with providing **_integration authorization_** tokens only. They cannot be skipped with Admin and Bearer tokens. + +## CAPTCHA The following table lists the forms that can be configured to require CAPTCHA. Go to **Stores** > **Configuration** > **Customers** > **Customer Configuration** > **CAPTCHA** > **Forms** to enable or disable CAPTCHA on these forms. +The mutation that corresponds to a CAPTCHA-enabled form must include the HTTP `X-Captcha` header, along with the text the shopper entered in response to the CAPTCHA challenge. + Form name | Mutation --- | --- Add Gift Card Code | `applyGiftCardToCart` @@ -22,6 +31,25 @@ Payflow Pro | `setPaymentMethodOnCart`, `setPaymentMethodAndPlaceOrder` Send to Friend Form | `sendEmailToFriend` Share Wishlist Form | Not applicable +## reCAPTCHA + +The following table lists the forms that can be configured to require reCAPTCHA. Go to **Stores** > **Configuration** > **Security** > **Google reCAPTCHA Storefront** > **Storefront** to enable or disable reCAPTCHA on these forms. If reCAPTCHA is enabled, unless an integration token is provided, always specify the HTTP `X-ReCaptcha` header and the value generated by the Google API. + +Field name | Mutation +--- | --- +Enable for Customer Login | `generateCustomerToken` +Enable for Forgot Password | `changeCustomerPassword` +Enable for Create New Customer Account | `createCustomer`, `createCustomerV2` +Enable for Edit Customer Account | `updateCustomer`, `updateCustomerV2` +Enable for Contact Us | Not applicable +Enable for Product Review | `createProductReview` +Enable for Newsletter Subscription | `subscribeEmailToNewsletter` +Enable for Send To Friend | `sendEmailToFriend` +Enable for PayPal PayflowPro payment form | `createPayflowProToken` +Enable for Braintree payment form | Not applicable +Enable for Checkout/Placing Order | `setPaymentMethodOnCart`, `setPaymentMethodAndPlaceOrder` +Enable for Coupon Codes | `applyCouponToCart` + {:.ref-header} Related topics diff --git a/src/guides/v2.3/rest/protected-endpoints.md b/src/guides/v2.3/rest/protected-endpoints.md index 5f7154d1f47..25b0220a2f7 100644 --- a/src/guides/v2.3/rest/protected-endpoints.md +++ b/src/guides/v2.3/rest/protected-endpoints.md @@ -5,10 +5,19 @@ functional_areas: - Integration --- -If CAPTCHA is enabled on pages requiring shopper input, then in most cases, the corresponding REST endpoints that send requests to the Magento server must include the shopper's CAPTCHA response. Supply the shopper's response in the HTTP `X-Captcha` header. The exception to this policy is that you do not send the CAPTCHA response if you specify an integration authorization token in the header of the REST endpoint. +If CAPTCHA or reCAPTCHA is enabled on pages requiring shopper input, then in most cases, the corresponding endpoints that send requests to the Magento server must include an HTTP header that contains a value entered by the shopper (for CAPTCHA) or generated by the Google API (for reCAPTCHA). However, if you specify an integration authorization token in the header of the endpoint, then you do not supply a header specific to CAPTCHA or reCAPTCHA. + +HTTP `X-Captcha` and `X-ReCaptcha` headers: + +* Cannot be received by automated script or non-UI API call. They are captured and returned by UI Web form only. +* Are optional in protected mutation API calls with providing **_integration authorization_** tokens only. They cannot be skipped with Admin and Bearer tokens. + +## CAPTCHA The following table lists the forms that can be configured to require CAPTCHA. Go to **Stores** > **Configuration** > **Customers** > **Customer Configuration** > **CAPTCHA** > **Forms** to enable or disable CAPTCHA on these forms. +The endpoint that corresponds to a CAPTCHA-enabled form must include the HTTP `X-Captcha` header, along with the text the shopper entered in response to the CAPTCHA challenge. + Form name | REST endpoint --- | --- Add Gift Card Code | `POST /V1/carts/mine/giftCards`
    `POST /V1/carts/guest-carts/:cartId/giftCards` @@ -24,7 +33,26 @@ Payflow Pro | Not applicable Send to Friend Form | Not applicable Share Wishlist Form | Not applicable +## reCAPTCHA + +The following table lists the forms that can be configured to require reCAPTCHA. Go to **Stores** > **Configuration** > **Security** > **Google reCAPTCHA Storefront** > **Storefront** to enable or disable reCAPTCHA on these forms. If reCAPTCHA is enabled, unless an integration token is provided, always specify the HTTP `X-ReCaptcha` header and the value generated by the Google API. + +Field name | Mutation +--- | --- +Enable for Customer Login | `PUT /V1/integration/customer/token` +Enable for Forgot Password | `PUT /V1/customers/me/password` +Enable for Create New Customer Account | `POST /V1/customers` +Enable for Edit Customer Account | `PUT /V1/customers/me` +Enable for Contact Us | Not applicable +Enable for Product Review | Not applicable +Enable for Newsletter Subscription | Not applicable +Enable for Send To Friend | Not applicable +Enable for PayPal PayflowPro payment form | Not applicable +Enable for Braintree payment form | Not applicable +Enable for Checkout/Placing Order | `POST /V1/carts/mine/payment-information`
    `POST /V1/carts/mine/set-payment-information`
    `POST /V1/guest-carts/:cartId/payment-information`
    `POST /V1/guest-carts/:cartId/set-payment-information` +Enable for Coupon Codes | `PUT /V1/carts/:cartId/coupons/:couponCode`
    `PUT /V1/guest-carts/:cartId/coupons/:couponCode` + {:.ref-header} Related topics -[Construct a request]({{page.baseurl}}/get-started/gs-web-api-request.html +[Construct a request]({{page.baseurl}}/get-started/gs-web-api-request.html) \ No newline at end of file From 61a3ffab5bacf1dec15b42a82ca2dc7b2ccba839 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 12 Jul 2022 11:49:50 -0500 Subject: [PATCH 275/776] Added migration metadata --- src/guides/v2.4/inventory/index.md | 67 +++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) mode change 120000 => 100644 src/guides/v2.4/inventory/index.md diff --git a/src/guides/v2.4/inventory/index.md b/src/guides/v2.4/inventory/index.md deleted file mode 120000 index 1f43c3af6c6..00000000000 --- a/src/guides/v2.4/inventory/index.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/inventory/index.md \ No newline at end of file diff --git a/src/guides/v2.4/inventory/index.md b/src/guides/v2.4/inventory/index.md new file mode 100644 index 00000000000..3ca7992d66f --- /dev/null +++ b/src/guides/v2.4/inventory/index.md @@ -0,0 +1,66 @@ +--- +group: inventory +title: Inventory Management overview +landing-page: Inventory +migrated_to: https://developer-stage.adobe.com/commerce/webapi/rest/modules/inventory/ +layout: migrated +--- + +{{site.data.var.ce}} and {{site.data.var.ee}} v2.3 include new and expanded features and APIs for {{site.data.var.im}}. {{site.data.var.im}} replaces all core APIs in the Open Source `CatalogInventory` module and the `ScalableInventory` module in Commerce. It also provides additional APIs to extend and add functionality. + +{{site.data.var.im}} features include + +* Different configurations for merchants whose inventory originates from a single source and from multiple sources +* Stocks for tracking available aggregated quantities through assigned sources +* Concurrent checkout protection +* Shipment matching algorithms + +Merchants install {{site.data.var.im}} as part of v2.3.x and upgrades with the name `magento/inventory-composer-metapackage`. For details, see [Install {{site.data.var.im}}]({{site.baseurl}}/extensions/inventory-management/). + +**Magento Community Contribution** – Magento thanks the many contributors to the [Magento Inventory (was MSI) project](https://github.com/magento/inventory), developing these features as part of the Magento Community Engineering program. + +## Terminology + +The following terms are important as you work with {{site.data.var.im}} APIs: + +* **Sources** represent physical locations that store and ship available products. These locations can include warehouses, brick-and-mortar stores, distribution centers, and drop shippers. (Any location can be designated as a source for virtual products.) + +* **Stocks** map a sales channel (currently limited to websites) to source locations and on-hand inventory. A stock can map to multiple sales channels, but a sales channel can be assigned to only one stock. + +* **Aggregate Salable Quantity** is the total virtual inventory that can be sold through a sales channel. The amount is calculated across all sources assigned to a stock. + +* **Reservations** track deductions from the salable quantity as customers add products to carts and complete checkout. When an order ships, the reservation clears and deducts the shipped amounts from specific source inventory quantities. + +## A simple scenario + +The following diagram illustrates the relationship between source stocks, aggregate stocks, and sales channels: + +![Source and aggregate stock](images/inventory-diagram-stock.png) + +In this diagram, a bicycle merchant has inventory for a mountain bike in two warehouses and a drop shipper. He has two stocks with configured website sales channels and sources. When a customer shops through the UK website, Magento aggregates bike inventory from the UK warehouse and the drop shipper sources, for a salable quantity of 95. The bike can be shipped from either the warehouse or the drop shipper, but not the NY warehouse. Amazon Marketplace has the same stock, drawing from the same aggregate stock as the UK website. + +## Important {{site.data.var.im}} objects + +* `Source` – Defines a physical stock. + +* `SourceItem` – A relation object that represents the amount of a specific product at a physical source. We use this entity for updating inventory on each source. Quantities might change as a result of synchronizing with an external Product Information Management (PIM) or Enterprise Resource Planning (ERP) system, or internally as a stock deduction during the checkout process. A `SourceItem` cannot be used for retrieving data that must be rendered on front-end, because only aggregated data should be used for all validations and UI representation. + +* `StockItem` – Also known as Aggregated Virtual Stock. This is read-only data that the re-indexation process generates. Based on a pre-defined mapping, we define what sources are assigned to the current scope (sales channel) and aggregate quantities from all assigned sources. We also use `StockItem` to check if a product is in or out of stock. Making this segregation by Read-Only interface (`StockItem`) and Write-Only interface (`SourceItem`), the Inventory architecture achieves Command Query Responsibility Segregation (CQRS). As a result, all `GET` HTTP requests should use `StockItem` entity, and all `POST/PUT` should use `SourceItem`. + +## Shipping algorithms + +When merchants are ready to make a partial or full shipment, they select the source or sources from which to send the products. Customers typically want low-cost shipping and a guarantee of safe arrival of products, while the merchant needs to ensure minimal overhead for the inventory storage and shipping costs. {{site.data.var.im}} includes an algorithm that takes these considerations into account and recommends the best shipping option or options. Magento provides an algorithm for Priority, using the source priority per stock, where each source is given a priority in the scope of a specific sales channel, and for Distance, using the locations of sources and shipping destinations. {{site.data.var.im}} also supports developer-provided extensions for other algorithms based on criteria such as cheapest shipping and closest GPS location. + +## Message queue consumers + +The following table lists all [message queue consumers]({{ page.baseurl }}/config-guide/mq/manage-message-queues.html) related to {{ site.data.var.im }}, describes what they do, and identifies the Admin system configuration settings associated with them: + +| Consumer | Description | +|-------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `inventory.source.items.cleanup` | Asynchronously deletes source items by product SKU when a product is removed.
    Required when the [**Synchronize with Catalog**]({{ site.user_guide_url }}/configuration/catalog/inventory.html) stock option is enabled in the Admin system configuration settings. | +| `inventory.mass.update` | Asynchronously processes legacy stock items, updates legacy stock items, updates default source items, and reindexes inventory for specific product SKUs.
    Required when the [**Run asynchronously**]({{ site.user_guide_url }}/configuration/catalog/inventory.html#admin-bulk-operations) bulk operation is enabled in the Admin system configuration settings. | +| `inventory.reservations.cleanup` | Asynchronously deletes reservations by product SKU after a product is removed.
    Required when the [**Synchronize with Catalog**]({{ site.user_guide_url }}/configuration/catalog/inventory.html) stock option is enabled in the Admin system configuration settings. | +| `inventory.reservations.update` | Asynchronously updates reservations by product SKU after a product is removed.
    Required when the [**Synchronize with Catalog**]({{ site.user_guide_url }}/configuration/catalog/inventory.html) stock option is enabled in the Admin system configuration settings. | +| `inventory.reservations.updateSalabilityStatus` | Asynchronously updates the salable quantity of each product assigned to a stock.
    This consumer should be up and running at all times if you are using {{ site.data.var.im }}. | +| `inventory.indexer.sourceItem` | Asynchronously reindexes source items.
    Required when the [**Stock/Source reindex strategy**]({{ site.user_guide_url }}/configuration/catalog/inventory.html#inventory-indexer-settings) is set to "aynschronous" in the Admin system configuration settings. | +| `inventory.indexer.stock` | Asynchronously reindexes stock.
    Required when the [**Stock/Source reindex strategy**]({{ site.user_guide_url }}/configuration/catalog/inventory.html#inventory-indexer-settings) is set to "aynschronous" in the Admin system configuration settings. | From 111cf11f786648a321dbe5145b921f57b4890235 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 12 Jul 2022 12:08:35 -0500 Subject: [PATCH 276/776] Switched to production domain --- src/guides/v2.4/inventory/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/inventory/index.md b/src/guides/v2.4/inventory/index.md index 3ca7992d66f..1b89dc2fd5b 100644 --- a/src/guides/v2.4/inventory/index.md +++ b/src/guides/v2.4/inventory/index.md @@ -2,7 +2,7 @@ group: inventory title: Inventory Management overview landing-page: Inventory -migrated_to: https://developer-stage.adobe.com/commerce/webapi/rest/modules/inventory/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/ layout: migrated --- From 5f0db3dc2649e97f81766b6a2c63dd01241156d8 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 12 Jul 2022 14:13:36 -0500 Subject: [PATCH 277/776] Updated link to manage-sources.md --- src/guides/v2.4/rest/modules/inventory/manage-sources.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/rest/modules/inventory/manage-sources.md b/src/guides/v2.4/rest/modules/inventory/manage-sources.md index f20cc317c18..2746f28ea44 100644 --- a/src/guides/v2.4/rest/modules/inventory/manage-sources.md +++ b/src/guides/v2.4/rest/modules/inventory/manage-sources.md @@ -1,7 +1,7 @@ --- group: rest-api title: Manage sources -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/inventory/manage-sources/ layout: migrated --- From cef197bc67d5283035a58364e46386fff825618a Mon Sep 17 00:00:00 2001 From: jfrontain Date: Tue, 12 Jul 2022 16:17:36 -0500 Subject: [PATCH 278/776] added highlights for RTM --- .../v2.4/release-notes/commerce-2-4-5.md | 84 +++++------ .../v2.4/release-notes/open-source-2-4-5.md | 137 ++++++++++++++++-- 2 files changed, 165 insertions(+), 56 deletions(-) diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md index de36b1a652f..6a6b67e1d78 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-5.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -3,9 +3,7 @@ group: release-notes title: Adobe Commerce 2.4.5 Release Notes --- -{{ site.data.var.ee }} 2.4.5 introduces support for - -This release includes almost 240 quality fixes and enhancements. +This release includes over 400 quality fixes and enhancements. {:.bs-callout-info} Releases may contain backward-incompatible changes (BIC). {{ site.data.var.ee }} 2.4.5 contains backward-incompatible changes. To review these backward-incompatible changes, see [BIC reference]({{page.baseurl}}/release-notes/backward-incompatible-changes/reference.html). (Major backward-incompatible issues are described in [BIC highlights]({{page.baseurl}}/release-notes/backward-incompatible-changes/index.html). Not all releases introduce major BICs.) @@ -50,9 +48,9 @@ Security improvements for this release improve compliance with the latest securi ### Platform enhancements -* **Adobe Commerce on-premises deployments**: Adobe Commerce 2.4.5 has been tested and confirmed to be compatible with Elasticsearch 7.17 (~7.17.0 with constraint). Merchants hosting Adobe Commerce on-premises can use either Elasticsearch or OpenSearch 1.2. +* **{{ site.data.var.ee }} on-premises deployments**: {{ site.data.var.ee }} 2.4.5 has been tested and confirmed to be compatible with Elasticsearch 7.17 (~7.17.0 with constraint). Merchants hosting {{ site.data.var.ee }} on-premises can use either Elasticsearch or OpenSearch 1.2. -* **Adobe Commerce cloud-hosted deployments**: ElasticSearch 7.11 or later is not supported on Adobe Commerce 2.4.5 cloud-hosted deployments. OpenSearch is the default search engine for Adobe Commerce 2.4.5 cloud deployments. +* **{{ site.data.var.ee }} cloud-hosted deployments**: ElasticSearch 7.11 or later is not supported on {{ site.data.var.ee }} 2.4.5 cloud-hosted deployments. OpenSearch is the default search engine for {{ site.data.var.ee }} 2.4.5 cloud deployments. {{ site.data.var.ee }} 2.4.5 now supports @@ -64,7 +62,7 @@ Security improvements for this release improve compliance with the latest securi * `PHPStan` (^1.5.7 with constraint) [GitHub-35315](https://github.com/magento/magento2/issues/35315) -* DHL Integration schema has been updated from v6.0 to v6.2. DHL has deprecated v6.0. This upgrade will not result in a change in product behavior. +The DHL Integration schema has been updated from v6.0 to v6.2. DHL has deprecated v6.0. This upgrade will not result in a change in product behavior. Outdated JavaScript libraries have been updated to their latest versions, and outdated dependencies have been removed. These changes are backward compatible. @@ -99,7 +97,7 @@ The `laminas/laminas-session`, `laminas/laminas-text`, and `laminas/laminas-view #### Other upgrades and replacements -* DHL Integration schema has been updated from v6.0 to v6.2. (DHL will deprecate the v6.0 schema mid-2022.) +* The DHL Integration schema has been updated from v6.0 to v6.2. (DHL will deprecate the v6.0 schema mid-2022.) * The default Gateway URL for USPS shipping has been updated to use `https` instead of `http`. @@ -125,39 +123,37 @@ The `laminas/laminas-session`, `laminas/laminas-text`, and `laminas/laminas-view ### Performance and scalability enhancements -{{ site.data.var.ee }} performance enhancements - -Performance enhancements in this release: - #### Price indexer optimization Primary index performance has been improved by reducing the number of primary indexes from 3 to 1 for the `catalog_product_index_price_tmp` table. This enhancement reduced the number of records created in the price index by reducing eSKU multiplication that resulted from shared catalogs. Indexing time has been significantly reduced. -### GraphQL +### Accessibility updates -GraphQL performance hs been improved by these enhancements: +This release includes enhancements to the Admin UI that improve the experience of users with vision limitations and increase conformance to standard accessibility guidelines. These enhancements include: -* **Optimized creation of unified GraphQL schemas**. Rebuilding a GraphQL schema after flushing a Commerce instance’s cache can consume many resources, particularly during heavy site traffic. The time required to rebuild a schema has been reduced significantly. +* The screen reader now summarizes search results +* Screen readers are now informed when a new page loads +* Contrast and keyboard accessibility have been improved -* **Improved authorization processing** through the use of JSON Web Tokens (JWT) and session-less GraphQL API. +### Adobe Sign Extension -See the [GraphQL Developer Guide]({{page.baseurl}}/graphql/) for details on these enhancements. +The {{ site.data.var.ee }} checkout workflow now supports the inclusion of an esignature agreement page powered by Adobe Sign. -### Adobe Sign Extension +### Branding and style changes -The Adobe Commerce check out workflow now supports the inclusion of an esignature agreement page powered by Adobe Sign. +The Admin has been updated to align with Adobe’s branch strategy. Changes affect headers, footers, data grid color updates, and navigation elements. ### B2B -This release includes multiple bug fixes. See [B2B Release Notes]({{page.baseurl}}/release-notes/b2b-release-notes.html) - **Reduced eSKU multiplication with Shared Catalogs (Customer Groups)**. The new **Enabled Shared Catalog direct product price assigning** configuration option improves product price indexer performance when enabled. +This release includes multiple bug fixes. See [B2B Release Notes]({{page.baseurl}}/release-notes/b2b-release-notes.html). + ### Channel Manager -Channel Manager can now trigger refunds from Adobe Commerce. Merchants can now manage the entire order workflow from within Adobe Commerce, including these tasks: +Channel Manager can now trigger refunds from {{ site.data.var.ee }}. Merchants can now manage the entire order workflow from within {{ site.data.var.ee }}, including these tasks: -* Process refunds from Adobe Commerce +* Process refunds from {{ site.data.var.ee }} * Refund shoppers using the origin form of payment Requests are now automatically synced back to the Walmart Marketplace. @@ -165,9 +161,24 @@ Requests are now automatically synced back to the Walmart Marketplace. ### Google Analytics See [Migrate from analytics.js to gtag.js (Universal Analytics) ](https://developers.google.com/analytics/devguides/migration/ua/analyticsjs-to-gtagjs​https://support.google.com/google-ads/answer/7548399?hl=en). + +### GraphQL + +GraphQL performance enhancements include: + +* **Optimized creation of unified GraphQL schemas**. Rebuilding a GraphQL schema after flushing a Commerce instance’s cache can consume many resources, particularly during heavy site traffic. The time required to rebuild a schema has been reduced significantly. + +* **Improved authorization processing** through the use of JSON Web Tokens (JWT) and session-less GraphQL API. + +See the [GraphQL Developer Guide]({{page.baseurl}}/graphql/) for details on these enhancements. + +### Inventory + +Inventory template security has been enhanced. + ### PWA Studio -PWA Studio v.12.x.x is compatible with {{ site.data.var.ee }} 2.4.5. +PWA Studio v.12.5.x is compatible with {{ site.data.var.ee }} 2.4.5. New features for this release include: @@ -176,6 +187,7 @@ New features for this release include: * Merchants can now select a service to deploy from the Admin (Beacon or Google Tag Manager). For information about enhancements and bug fixes, see [PWA Studio releases](https://github.com/magento/pwa-studio/releases). See [Version compatibility](https://developer.adobe.com/commerce/pwa-studio/integrations/adobe-commerce/version-compatibility/) for a list of PWA Studio versions and their compatible {{ site.data.var.ee }} core versions. + ### PayPal Payment enhancements * Merchants in Spain and Italy can now offer PayPal Pay Later to shoppers. @@ -184,35 +196,25 @@ For information about enhancements and bug fixes, see [PWA Studio releases](http #### Braintree -The KOUNT integration has been removed due to discontinuation by Braintree. +Braintree has discontinued the KOUNT integration and it has been removed from the codebase. ### Live Search This release introduces support for B2B customer groups and custom pricing. -### Accessibility updates - -This release includes enhancements to the Admin UI that improve the experience of users with vision limitations and increase conformance to standard accessibility guidelines. These enhancements include: - -* The screen reader now summarizes search results -* Screen readers are now informed when a new page loads -* Contrast and keyboard accessibility have been improved - ### Page Builder +Page Builder v.1.7.2 is compatible with {{ site.data.var.ee }} 2.4.5. + Page Builder column layout includes these enhancements: * Columns are now exposed, permitting users to control column settings on the storefront. * Column resizing now supports wrapping triggered by user actions. -### Branding and style changes - -The Admin has been updated to align with Adobe’s branch strategy. Changes affect headers, footers, data grid color updates, and navigation elements. - ### Upgrade Compatibility Tool -New enhancements include: +Enhancements include: * Method signature validation now identifies incompatible changes within a method or a constructor signature. @@ -920,22 +922,14 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * `indexer:reset` has been refactored to call `$indexer->invalidate()`. [GitHub-34988](https://github.com/magento/magento2/issues/34988) -#### Library removals and deprecations - -#### Library upgrades - ### Logging * Customer, customer address, and order actions are now logged correctly in the Admin action report. Previously, {{ site.data.var.ee }} did not log actions if the `postDispatch` handler had not been specified in configuration settings. -### {{ site.data.var.ee }} coding standard - ### MFTF -#### New action groups - #### Action groups Repetitive actions have been replaced with action groups in these tests: diff --git a/src/guides/v2.4/release-notes/open-source-2-4-5.md b/src/guides/v2.4/release-notes/open-source-2-4-5.md index 403c26b4894..44a09fa18fa 100644 --- a/src/guides/v2.4/release-notes/open-source-2-4-5.md +++ b/src/guides/v2.4/release-notes/open-source-2-4-5.md @@ -3,9 +3,7 @@ group: release-notes title: Magento Open Source 2.4.5 Release Notes --- -{{ site.data.var.ce }} 2.4.5 introduces - -This release includes almost quality fixes and enhancements. +This release includes over 290 quality fixes and enhancements. {:.bs-callout-info} Releases may contain backward-incompatible changes (BIC). {{ site.data.var.ce }} 2.4.5 contains backward-incompatible changes. To review these backward-incompatible changes, see [BIC reference]({{page.baseurl}}/release-notes/backward-incompatible-changes/reference.html). (Major backward-incompatible issues are described in [BIC highlights]({{page.baseurl}}/release-notes/backward-incompatible-changes/index.html). Not all releases introduce major BICs.) @@ -16,7 +14,7 @@ Although code for these features is bundled with quarterly releases of the {{ si ### Hotfixes included in this release -{{ site.data.var.ce }} 2.4.4 includes resolution of all issues that were addressed by the following hotfixes, which were provided for {{ site.data.var.ee }} and {{ site.data.var.ce }} 2.4.4, 2.4.3-p2, and 2.3.7-p3: +{{ site.data.var.ce }} 2.4.5 includes resolution of all issues that were addressed by the following hotfixes, which were provided for {{ site.data.var.ee }} and {{ site.data.var.ce }} 2.4.4, 2.4.3-p2, and 2.3.7-p3: ## {{ site.data.var.ce }} 2.4.5 highlights @@ -40,26 +38,147 @@ See Adobe Security Bulletin for the latest discussion of these fixed issues. Security improvements for this release improve compliance with the latest security best practices, including: +* reCAPTCHA support has been added to the Wish List Sharing, Create New Customer Account, and Gift Card forms. + +* ACL resources have been added to Inventory. + +* Inventory template security has been enhanced. + +* The `MaliciousCode` filter has been upgraded to use the `HtmlPurifier` library. + ### Platform enhancements {{ site.data.var.ce }} 2.4.5 now supports +* Composer 2.2 + +* TinyMCE (5.10.2). Earlier versions of TinyMCE (v5.9.2 or earlier) allowed arbitrary JavaScript execution when a specially crafted URL or an image with a specially crafted URL was updated. + +* jQueryUI (1.13.1) + +* `PHPStan` (^1.5.7 with constraint) [GitHub-35315](https://github.com/magento/magento2/issues/35315) + +The DHL Integration schema has been updated from v6.0 to v6.2. DHL has deprecated v6.0. This upgrade will not result in a change in product behavior. + +Outdated JavaScript libraries have been updated to their latest versions, and outdated dependencies have been removed. These changes are backward compatible. + +#### Composer dependency updates + + + +The following Composer dependencies have been updated to the latest versions with constraint: + +* `colinmollenhour/credis` (1.13.0)? +* `guzzlehttp/guzzle` (^7.4.2) +* `laminas/laminas-captcha` (updated with a constraint ^2.12) +* `laminas/laminas-db` (^2.15.0) +* `laminas/laminas-di` (^3.7.0) +* `laminas/laminas-escaper` (~2.10.0) +* `laminas/laminas-eventmanager` (^3.5.0) +* `laminas/laminas-feed` (^2.17.0) +* `laminas/laminas-mail` (^2.16.0) +* `laminas/laminas-mvc` (^3.3.3) +* `laminas/laminas-server` (^2.11.1) +* `laminas/laminas-servicemanager` (^3.11.0) +* `laminas/laminas-validator` (^2.17.0) +* `league/fly` (2.4.3) +* `monolog/monolog` (^2.5) +* `phpmd/phpmd` (^2.12.0) +* `phpstan/phpstan` (^1.5.7) +* `phpunit/phpunit` (~9.5.20) +* `php-cs-fixer` (^3.4.0) +* `webonyx/graphql-php` (14.11.6) + +The `laminas/laminas-session`, `laminas/laminas-text`, and `laminas/laminas-view` dependencies have been removed. + +#### Other upgrades and replacements + +* The DHL Integration schema has been updated from v6.0 to v6.2. (DHL will deprecate the v6.0 schema mid-2022.) + +* The default Gateway URL for USPS shipping has been updated to use `https` instead of `http`. + +* The `Froogaloop` library has been replaced with the Vimeo `Player.js` library (2.16.4). + +* The `grunt-eslint` (NPM) library has been upgraded to the latest version. + +* The `jQuery Storage` libraries have been replaced with `julien-maurel/js-storage`. + +* The `php-cs-fixer` and `phpcs` static code analysis tools are now compatible with PHP 8.x. + +* `glob.js` dependency (upgraded with constraint to ~7.2.0) + +* `serve-static.js` dependency (upgraded with constraint ~1.14.2) + +* `underscore.js` dependency (NPM) (1.14.2) + +* `moment-timezone-with-data.js` (0.5.34) + +* The library `jquery/jquery-cookie` has been replaced with `js-cookie/js-cookie`. + +* The `jarallax.js` and `jaralax-video.js` libraries have been updated to use the latest version of the Vimeo REST API. + ### GraphQL -This release includes these GraphQL enhancements: +GraphQL performance enhancements include: + +* **Optimized creation of unified GraphQL schemas**. Rebuilding a GraphQL schema after flushing a Commerce instance’s cache can consume many resources, particularly during heavy site traffic. The time required to rebuild a schema has been reduced significantly. -* **Performance improvements**: +* **Improved authorization processing** through the use of JSON Web Tokens (JWT) and session-less GraphQL API. See the [GraphQL Developer Guide]({{page.baseurl}}/graphql/) for details on these enhancements. +### Channel Manager + +Channel Manager can now trigger refunds from {{ site.data.var.ce }}. Merchants can now manage the entire order workflow from within {{ site.data.var.ce }}, including these tasks: + +* Process refunds from {{ site.data.var.ce }} +* Refund shoppers using the origin form of payment + +Requests are now automatically synced back to the Walmart Marketplace. + +### Inventory + +Inventory template security has been enhanced. + +### PWA Studio + +PWA Studio v.12.5.x is compatible with {{ site.data.var.ce }} 2.4.5. + +New features for this release include: + +* Shopper behavior data is collected on PWA Studio storefront for web analytics services. Merchants can now subscribe and extend these events as needed. + +* Merchants can now select a service to deploy from the Admin (Beacon or Google Tag Manager). + +For information about enhancements and bug fixes, see [PWA Studio releases](https://github.com/magento/pwa-studio/releases). See [Version compatibility](https://developer.adobe.com/commerce/pwa-studio/integrations/adobe-commerce/version-compatibility/) for a list of PWA Studio versions and their compatible {{ site.data.var.ee }} core versions. + ### PayPal Payment enhancements +* Merchants in Spain and Italy can now offer PayPal Pay Later to shoppers. + +* Previews of the PayPal, Credit and Pay Later buttons are now available in the Admin for the checkout, minicart, cart, and product pages. Previews reveal how these buttons will look when they are enabled and rendered on the storefront. + +#### Braintree + +Braintree has discontinued the KOUNT integration and it has been removed from the codebase. ### Accessibility updates -This release brings enhanced conformance to standard accessibility guidelines. +This release includes enhancements to the Admin UI that improve the experience of users with vision limitations and increase conformance to standard accessibility guidelines. These enhancements include: + +* The screen reader now summarizes search results +* Screen readers are now informed when a new page loads +* Contrast and keyboard accessibility have been improved ### Page Builder +Page Builder v.1.7.2 is compatible with {{ site.data.var.ee }} 2.4.5. + +Page Builder column layout includes these enhancements: + +* Columns are now exposed, permitting users to control column settings on the storefront. + +* Column resizing now supports wrapping triggered by user actions. + ## Fixed issues @@ -705,10 +824,6 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. * `indexer:reset` has been refactored to call `$indexer->invalidate()`. [GitHub-34988](https://github.com/magento/magento2/issues/34988) -#### Library removals and deprecations - -#### Library upgrades - ### Logging From 77d927ba1ef0c1c605c0b67c0ea4181a02f4bfc8 Mon Sep 17 00:00:00 2001 From: jhadobe Date: Tue, 12 Jul 2022 16:27:17 -0500 Subject: [PATCH 279/776] Symlinks, migrated to --- src/guides/v2.3/b2b/company-credit.md | 2 + src/guides/v2.3/b2b/company.md | 2 + src/guides/v2.3/b2b/extensions.md | 2 + src/guides/v2.3/b2b/negotiable-checkout.md | 2 + src/guides/v2.3/b2b/negotiable-manage.md | 2 + src/guides/v2.3/b2b/negotiable-quote.md | 2 + src/guides/v2.3/b2b/negotiable-update.md | 2 + src/guides/v2.3/b2b/shared-cat-company.md | 2 + .../v2.3/b2b/shared-cat-product-assign.md | 2 + src/guides/v2.4/b2b/bk-b2b.md | 2 + src/guides/v2.4/b2b/company-credit.md | 26 +- src/guides/v2.4/b2b/company-object.md | 2 + src/guides/v2.4/b2b/company-structures.md | 2 + src/guides/v2.4/b2b/company-users.md | 2 + src/guides/v2.4/b2b/company.md | 25 +- src/guides/v2.4/b2b/credit-manage.md | 2 + src/guides/v2.4/b2b/extensions.md | 16 +- src/guides/v2.4/b2b/integrations.md | 2 + src/guides/v2.4/b2b/negotiable-checkout.md | 972 +++++++++++++++++- src/guides/v2.4/b2b/negotiable-manage.md | 341 +++++- .../v2.4/b2b/negotiable-order-workflow.md | 2 + src/guides/v2.4/b2b/negotiable-quote.md | 75 +- src/guides/v2.4/b2b/negotiable-update.md | 162 ++- src/guides/v2.4/b2b/roles.md | 2 + src/guides/v2.4/b2b/shared-cat-company.md | 110 +- src/guides/v2.4/b2b/shared-cat-manage.md | 2 + .../v2.4/b2b/shared-cat-product-assign.md | 250 ++++- src/guides/v2.4/b2b/shared-catalog.md | 2 + 28 files changed, 2006 insertions(+), 9 deletions(-) mode change 120000 => 100644 src/guides/v2.4/b2b/company-credit.md mode change 120000 => 100644 src/guides/v2.4/b2b/company.md mode change 120000 => 100644 src/guides/v2.4/b2b/extensions.md mode change 120000 => 100644 src/guides/v2.4/b2b/negotiable-checkout.md mode change 120000 => 100644 src/guides/v2.4/b2b/negotiable-manage.md mode change 120000 => 100644 src/guides/v2.4/b2b/negotiable-quote.md mode change 120000 => 100644 src/guides/v2.4/b2b/negotiable-update.md mode change 120000 => 100644 src/guides/v2.4/b2b/shared-cat-company.md mode change 120000 => 100644 src/guides/v2.4/b2b/shared-cat-product-assign.md diff --git a/src/guides/v2.3/b2b/company-credit.md b/src/guides/v2.3/b2b/company-credit.md index 7d070b47479..04fff476129 100644 --- a/src/guides/v2.3/b2b/company-credit.md +++ b/src/guides/v2.3/b2b/company-credit.md @@ -10,6 +10,8 @@ level3_subgroup: credit functional_areas: - B2B - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/company-credit +layout: migrated --- Company credit allows company members to purchase items on credit. This is a feature specific to {{site.data.var.b2b}} that is used only for transactions between companies. The seller allocates an amount (or the credit limit) to a company and then company members can purchase items using this amount with the Payment on Account method. The credit amount used by a company is sent to the seller offline. Then the seller creates a Reimburse transaction in the system to adjust the company balance. diff --git a/src/guides/v2.3/b2b/company.md b/src/guides/v2.3/b2b/company.md index dc8b9e9fdbd..79fd1a634dd 100644 --- a/src/guides/v2.3/b2b/company.md +++ b/src/guides/v2.3/b2b/company.md @@ -10,6 +10,8 @@ level3_subgroup: company functional_areas: - B2B - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/company +layout: migrated --- The `Company` module allows multiple buyers that belong to the same company to view product prices and make purchases based on the shared catalog assigned to this company. A company can contain a hierarchy of users and teams, with roles and permissions assigned at any level. diff --git a/src/guides/v2.3/b2b/extensions.md b/src/guides/v2.3/b2b/extensions.md index d89945a8bb5..fcbf6a3f315 100644 --- a/src/guides/v2.3/b2b/extensions.md +++ b/src/guides/v2.3/b2b/extensions.md @@ -8,6 +8,8 @@ menu_node: parent ee_only: True functional_areas: - B2B +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/extensions +layout: migrated --- See [Module Reference Guide]({{ page.baseurl }}/mrg/intro.html) for information about each {{site.data.var.b2b}} module. diff --git a/src/guides/v2.3/b2b/negotiable-checkout.md b/src/guides/v2.3/b2b/negotiable-checkout.md index b6de9977468..ae1de8de7cb 100644 --- a/src/guides/v2.3/b2b/negotiable-checkout.md +++ b/src/guides/v2.3/b2b/negotiable-checkout.md @@ -5,6 +5,8 @@ ee_only: true functional_areas: - B2B - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-checkout +layout: migrated --- When the seller and buyer user agree on the quoted products and their prices, the negotiated quote is ready to be converted to an order. diff --git a/src/guides/v2.3/b2b/negotiable-manage.md b/src/guides/v2.3/b2b/negotiable-manage.md index 8df8682327d..b3efa2e71a5 100644 --- a/src/guides/v2.3/b2b/negotiable-manage.md +++ b/src/guides/v2.3/b2b/negotiable-manage.md @@ -10,6 +10,8 @@ level3_subgroup: nq functional_areas: - B2B - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-manage +layout: migrated --- This topic describes the calls required to initiate a negotiable quote and to prepare it to be converted to an order. diff --git a/src/guides/v2.3/b2b/negotiable-quote.md b/src/guides/v2.3/b2b/negotiable-quote.md index 0a5702c4e2b..86b44d955d9 100644 --- a/src/guides/v2.3/b2b/negotiable-quote.md +++ b/src/guides/v2.3/b2b/negotiable-quote.md @@ -10,6 +10,8 @@ level3_subgroup: nq functional_areas: - B2B - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-quote +layout: migrated --- Negotiable quotes are a mechanism that allows a company user (buyer) and a seller (admin user) to negotiate product and/or shipping prices before the company user places an order. Its functionality is available for companies only. diff --git a/src/guides/v2.3/b2b/negotiable-update.md b/src/guides/v2.3/b2b/negotiable-update.md index cb8ea2531bb..2cc92540cca 100644 --- a/src/guides/v2.3/b2b/negotiable-update.md +++ b/src/guides/v2.3/b2b/negotiable-update.md @@ -5,6 +5,8 @@ ee_only: true functional_areas: - B2B - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-update +layout: migrated --- Sellers and buyers can edit a negotiable quote at various times during the quote's lifecycle. Both use the `PUT /V1/negotiableQuote/:quoteId` call to update the quote. This call is defined in the diff --git a/src/guides/v2.3/b2b/shared-cat-company.md b/src/guides/v2.3/b2b/shared-cat-company.md index a0610ede008..fcc16ee0bb2 100644 --- a/src/guides/v2.3/b2b/shared-cat-company.md +++ b/src/guides/v2.3/b2b/shared-cat-company.md @@ -6,6 +6,8 @@ functional_areas: - B2B - Catalog - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/shared-cat-company +layout: migrated --- A shared catalog must be assigned to one or more companies before it can be accessed by the company users. diff --git a/src/guides/v2.3/b2b/shared-cat-product-assign.md b/src/guides/v2.3/b2b/shared-cat-product-assign.md index f8b227fb756..a7a3e745ab3 100644 --- a/src/guides/v2.3/b2b/shared-cat-product-assign.md +++ b/src/guides/v2.3/b2b/shared-cat-product-assign.md @@ -6,6 +6,8 @@ functional_areas: - B2B - Catalog - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/shared-cat-product-assign +layout: migrated --- The shared catalog configuration process includes assigning categories and products to the shared catalog. To assign these items to a shared catalog, the following conditions must be met: diff --git a/src/guides/v2.4/b2b/bk-b2b.md b/src/guides/v2.4/b2b/bk-b2b.md index 47a9ec673f9..5755fe09367 100644 --- a/src/guides/v2.4/b2b/bk-b2b.md +++ b/src/guides/v2.4/b2b/bk-b2b.md @@ -10,6 +10,8 @@ ee_only: True functional_areas: - B2B - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/ +layout: migrated --- Unlike the standard business-to-consumer model, {{site.data.var.b2b}} (Business to Business) is designed to meet the needs of sellers (Magento merchants) whose customers are primarily companies—possibly with complex organizational structures and multiple users with various roles and levels of permission. diff --git a/src/guides/v2.4/b2b/company-credit.md b/src/guides/v2.4/b2b/company-credit.md deleted file mode 120000 index 403a212241e..00000000000 --- a/src/guides/v2.4/b2b/company-credit.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/b2b/company-credit.md \ No newline at end of file diff --git a/src/guides/v2.4/b2b/company-credit.md b/src/guides/v2.4/b2b/company-credit.md new file mode 100644 index 00000000000..04fff476129 --- /dev/null +++ b/src/guides/v2.4/b2b/company-credit.md @@ -0,0 +1,25 @@ +--- +group: b2b-developer-guide +subgroup: 10_REST +title: Integrate with the CompanyCredit module +menu_title: Integrate with the CompanyCredit module +menu_order: 17 +ee_only: True +level3_menu_node: level3child +level3_subgroup: credit +functional_areas: + - B2B + - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/company-credit +layout: migrated +--- + +Company credit allows company members to purchase items on credit. This is a feature specific to {{site.data.var.b2b}} that is used only for transactions between companies. The seller allocates an amount (or the credit limit) to a company and then company members can purchase items using this amount with the Payment on Account method. The credit amount used by a company is sent to the seller offline. Then the seller creates a Reimburse transaction in the system to adjust the company balance. + +The following diagram illustrates the process flow of orders using the Payment on Account method. + +![Payment on credit]({{ site.baseurl }}/common/images/b2b/payment-on-credit.png) + +## Related information + +[Manage company credit]({{ page.baseurl }}/b2b/credit-manage.html) diff --git a/src/guides/v2.4/b2b/company-object.md b/src/guides/v2.4/b2b/company-object.md index 56cb583e0d7..62611d24761 100644 --- a/src/guides/v2.4/b2b/company-object.md +++ b/src/guides/v2.4/b2b/company-object.md @@ -10,6 +10,8 @@ level3_subgroup: company functional_areas: - B2B - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/company-object +layout: migrated --- ## Manage company objects diff --git a/src/guides/v2.4/b2b/company-structures.md b/src/guides/v2.4/b2b/company-structures.md index 2686be3c739..a4612f7c37e 100644 --- a/src/guides/v2.4/b2b/company-structures.md +++ b/src/guides/v2.4/b2b/company-structures.md @@ -5,6 +5,8 @@ ee_only: true functional_areas: - B2B - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/company-structures +layout: migrated --- {{site.data.var.b2b}} allows company users to be assigned to company teams and hierarchies. diff --git a/src/guides/v2.4/b2b/company-users.md b/src/guides/v2.4/b2b/company-users.md index 4bfd801ba06..fb3d75db647 100644 --- a/src/guides/v2.4/b2b/company-users.md +++ b/src/guides/v2.4/b2b/company-users.md @@ -5,6 +5,8 @@ ee_only: true functional_areas: - B2B - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/company-users +layout: migrated --- A company user is a customer (buyer) that is assigned extended attributes that identify the company the user belongs to. Use the `POST /V1/customers` call, which is included with {{site.data.var.ce}} and {{site.data.var.ee}}, to create the user. After the user is created, you can use the `PUT /V1/customers/:customer_id` call to set their company data with the `company_attributes` extended attributes. diff --git a/src/guides/v2.4/b2b/company.md b/src/guides/v2.4/b2b/company.md deleted file mode 120000 index c9d58e355bb..00000000000 --- a/src/guides/v2.4/b2b/company.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/b2b/company.md \ No newline at end of file diff --git a/src/guides/v2.4/b2b/company.md b/src/guides/v2.4/b2b/company.md new file mode 100644 index 00000000000..79fd1a634dd --- /dev/null +++ b/src/guides/v2.4/b2b/company.md @@ -0,0 +1,24 @@ +--- +group: b2b-developer-guide +subgroup: 10_REST +title: Integrate with the Company module +menu_title: Integrate with the Company module +menu_order: 11 +ee_only: True +level3_menu_node: level3child +level3_subgroup: company +functional_areas: + - B2B + - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/company +layout: migrated +--- + +The `Company` module allows multiple buyers that belong to the same company to view product prices and make purchases based on the shared catalog assigned to this company. A company can contain a hierarchy of users and teams, with roles and permissions assigned at any level. + +## Related information + +* [Manage company objects]({{ page.baseurl }}/b2b/company-object.html) +* [Manage company users]({{ page.baseurl }}/b2b/company-users.html) +* [Manage company roles]({{ page.baseurl }}/b2b/roles.html) +* [Manage company structures]({{ page.baseurl }}/b2b/company-structures.html) diff --git a/src/guides/v2.4/b2b/credit-manage.md b/src/guides/v2.4/b2b/credit-manage.md index 68451b178f7..f73e431bfb6 100644 --- a/src/guides/v2.4/b2b/credit-manage.md +++ b/src/guides/v2.4/b2b/credit-manage.md @@ -5,6 +5,8 @@ ee_only: true functional_areas: - B2B - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/credit-manage +layout: migrated --- The company credit entity operates with the following attributes: diff --git a/src/guides/v2.4/b2b/extensions.md b/src/guides/v2.4/b2b/extensions.md deleted file mode 120000 index 9d19b84f952..00000000000 --- a/src/guides/v2.4/b2b/extensions.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/b2b/extensions.md \ No newline at end of file diff --git a/src/guides/v2.4/b2b/extensions.md b/src/guides/v2.4/b2b/extensions.md new file mode 100644 index 00000000000..fcbf6a3f315 --- /dev/null +++ b/src/guides/v2.4/b2b/extensions.md @@ -0,0 +1,15 @@ +--- +group: b2b-developer-guide +subgroup: 20_PHP +title: Develop B2B extensions +menu_title: Develop B2B extensions +menu_order: 1 +menu_node: parent +ee_only: True +functional_areas: + - B2B +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/extensions +layout: migrated +--- + +See [Module Reference Guide]({{ page.baseurl }}/mrg/intro.html) for information about each {{site.data.var.b2b}} module. diff --git a/src/guides/v2.4/b2b/integrations.md b/src/guides/v2.4/b2b/integrations.md index 3cc19e0efb7..37e84cc4d71 100644 --- a/src/guides/v2.4/b2b/integrations.md +++ b/src/guides/v2.4/b2b/integrations.md @@ -9,6 +9,8 @@ ee_only: True functional_areas: - B2B - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/integrations +layout: migrated --- This topic lists the REST endpoints and services that are provided with {{site.data.var.b2b}}. diff --git a/src/guides/v2.4/b2b/negotiable-checkout.md b/src/guides/v2.4/b2b/negotiable-checkout.md deleted file mode 120000 index dbcc8a6f17b..00000000000 --- a/src/guides/v2.4/b2b/negotiable-checkout.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/b2b/negotiable-checkout.md \ No newline at end of file diff --git a/src/guides/v2.4/b2b/negotiable-checkout.md b/src/guides/v2.4/b2b/negotiable-checkout.md new file mode 100644 index 00000000000..ae1de8de7cb --- /dev/null +++ b/src/guides/v2.4/b2b/negotiable-checkout.md @@ -0,0 +1,971 @@ +--- +group: b2b-developer-guide +title: Negotiable quote checkout +ee_only: true +functional_areas: + - B2B + - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-checkout +layout: migrated +--- + +When the seller and buyer user agree on the quoted products and their prices, the negotiated quote is ready to be converted to an order. + +During the standard checkout process, Magento refreshes and recalculates all product and shipping prices as well as taxes. This process is different for the quote that has a negotiated price (discounted offer from the seller). The system keeps the quoted price, but checks the tax amounts. If the tax amounts are outdated, Magento recalculates them and updates the quote totals. These tax adjustments can change the order grand total. The order and invoice are created with the recalculated taxes and new grand total. All other prices in the quote remain unchanged. + +The same rule is applied when the quote has the proposed shipping price and the shipping taxes change on the checkout. The buyer pays the updated price, but this does not affect the other quote amounts. + +The following diagram illustrates the workflow for {{site.data.var.b2b}} negotiable quote checkouts: + +![Checkout process]({{ site.baseurl }}/common/images/b2b/quote-checkout-process.png) + +## Manage shipping addresses + +A negotiated quote can be initiated without a shipping address. However, before the order can be placed, the shipping address must be provided. + +**REST Endpoints:** + +```json +POST /V1/negotiable-carts/:cartId/estimate-shipping-methods +POST /V1/negotiable-carts/:cartId/estimate-shipping-methods-by-address-id +POST /V1/negotiable-carts/:cartId/shipping-information +``` + +### Estimate shipping costs specifying an address + +This call takes a full shipping address as input and estimates shipping fees. It returns a list of available shipping methods. + +**Service Name:** + +`negotiableQuoteShipmentEstimationV1` + +**Sample Usage:** + +`POST /rest//V1/negotiable-carts/86/estimate-shipping-methods` + +**Payload:** + +```json +{ + "address": { + "street": [ + "100 Big Tree Avenue" + ], + "city": "San Francisco", + "country_id": "US", + "region": "California", + "region_id": "12", + "postcode": "99999", + "telephone": "4155551212", + "firstname": "John", + "lastname": "Doe" + } +} +``` + +**Response:** + +```json +[ + { + "carrier_code": "flatrate", + "method_code": "flatrate", + "carrier_title": "Flat Rate", + "method_title": "Fixed", + "amount": 5, + "base_amount": 5, + "available": true, + "error_message": "", + "price_excl_tax": 5, + "price_incl_tax": 5 + } +] +``` + +### Estimate shipping costs specifying an address ID + +This call takes an address ID as input and estimates shipping fees. It returns a list of available shipping methods. + +**Service Name:** + +`negotiableQuoteShippingMethodManagementV1` + +**Sample Usage:** + +`POST /rest//V1/negotiable-carts/86/estimate-shipping-methods-by-address-id` + +**Payload:** + +```json +{ + "addressId": 2 +} +``` + +**Response:** + +```json +[ + { + "carrier_code": "flatrate", + "method_code": "flatrate", + "carrier_title": "Flat Rate", + "method_title": "Fixed", + "amount": 5, + "base_amount": 5, + "available": true, + "error_message": "", + "price_excl_tax": 5, + "price_incl_tax": 5 + } +] +``` + +### Set the shipping and billing information + +In this call, you specify the shipping and billing addresses, as well as the selected `shipping_carrier_code` and `shipping_method_code`. Magento returns a list of payment options and calculates the order totals. + +**Service Name:** + +`negotiableQuoteShippingMethodManagementV1` + +**Sample Usage:** + +`POST /rest//V1/negotiable-carts/86/shipping-information` + +**Payload:** + +```json +{ + "addressInformation": { + "shipping_address": { + "region": "California", + "region_id": 12, + "country_id": "US", + "street": [ + "100 Big Tree Avenue" + ], + "postcode": "99999", + "city": "San Francisco", + "telephone": "512-555-1111", + "firstname": "Jane", + "lastname": "Doe" + }, + "billing_address": { + "region": "New York", + "region_id": 43, + "region_code": "NY", + "country_id": "US", + "street": [ + "123 Oak Ave" + ], + "postcode": "10577", + "city": "Purchase", + "firstname": "Jane", + "lastname": "Doe", + "email": "jdoe@example.com", + "telephone": "512-555-1111" + }, + "shipping_carrier_code": "flatrate", + "shipping_method_code": "flatrate" + } +} +``` + +**Response:** + +{% collapsible Show code sample %} + +```json +{ + "payment_methods": [ + { + "code": "checkmo", + "title": "Check / Money order" + } + ], + "totals": { + "grand_total": 5.95, + "base_grand_total": 5.95, + "subtotal": 0.95, + "base_subtotal": 0.95, + "discount_amount": 0, + "base_discount_amount": 0, + "subtotal_with_discount": 0.95, + "base_subtotal_with_discount": 0.95, + "shipping_amount": 5, + "base_shipping_amount": 5, + "shipping_discount_amount": 0, + "base_shipping_discount_amount": 0, + "tax_amount": 0, + "base_tax_amount": 0, + "weee_tax_applied_amount": null, + "shipping_tax_amount": 0, + "base_shipping_tax_amount": 0, + "subtotal_incl_tax": 0.95, + "shipping_incl_tax": 5, + "base_shipping_incl_tax": 5, + "base_currency_code": "USD", + "quote_currency_code": "USD", + "items_qty": 1, + "items": [ + { + "item_id": 13, + "price": 0.95, + "base_price": 0.95, + "qty": 1, + "row_total": 0.95, + "base_row_total": 0.95, + "row_total_with_discount": 0, + "tax_amount": 0, + "base_tax_amount": 0, + "tax_percent": 0, + "discount_amount": 0, + "base_discount_amount": 0, + "discount_percent": 0, + "price_incl_tax": 0.95, + "base_price_incl_tax": 0.95, + "row_total_incl_tax": 0.95, + "base_row_total_incl_tax": 0.95, + "options": "[]", + "weee_tax_applied_amount": null, + "weee_tax_applied": null, + "extension_attributes": { + "negotiable_quote_item_totals": { + "cost": 0, + "catalog_price": 0.95, + "base_catalog_price": 0.95, + "catalog_price_incl_tax": 0.95, + "base_catalog_price_incl_tax": 0.95, + "cart_price": 0.95, + "base_cart_price": 0.95, + "cart_tax": 0, + "base_cart_tax": 0, + "cart_price_incl_tax": 0.95, + "base_cart_price_incl_tax": 0.95 + } + }, + "name": "Simple Product 2" + } + ], + "total_segments": [ + { + "code": "subtotal", + "title": "Subtotal", + "value": 0.95 + }, + { + "code": "giftwrapping", + "title": "Gift Wrapping", + "value": null, + "extension_attributes": { + "gw_item_ids": [], + "gw_price": "0.00", + "gw_base_price": "0.00", + "gw_items_price": "0.00", + "gw_items_base_price": "0.00", + "gw_card_price": "0.00", + "gw_card_base_price": "0.00", + "gw_base_tax_amount": "0.00", + "gw_tax_amount": "0.00", + "gw_items_base_tax_amount": "0.00", + "gw_items_tax_amount": "0.00", + "gw_card_base_tax_amount": "0.00", + "gw_card_tax_amount": "0.00", + "gw_price_incl_tax": "0.00", + "gw_base_price_incl_tax": "0.00", + "gw_card_price_incl_tax": "0.00", + "gw_card_base_price_incl_tax": "0.00", + "gw_items_price_incl_tax": "0.00", + "gw_items_base_price_incl_tax": "0.00" + } + }, + { + "code": "shipping", + "title": "Shipping & Handling (Flat Rate - Fixed)", + "value": 5 + }, + { + "code": "tax", + "title": "Tax", + "value": 0, + "extension_attributes": { + "tax_grandtotal_details": [] + } + }, + { + "code": "grand_total", + "title": "Grand Total", + "value": 5.95, + "area": "footer" + }, + { + "code": "customerbalance", + "title": "Store Credit", + "value": 0 + }, + { + "code": "reward", + "title": "0 Reward points", + "value": 0 + } + ], + "extension_attributes": { + "negotiable_quote_totals": { + "items_count": 1, + "quote_status": "submitted_by_admin", + "created_at": "2017-05-30 20:41:00", + "updated_at": "2017-05-30 20:41:00", + "customer_group": 10, + "base_to_quote_rate": 1, + "cost_total": 0, + "base_cost_total": 0, + "original_total": 0.95, + "base_original_total": 0.95, + "original_tax": 0, + "base_original_tax": 0, + "original_price_incl_tax": 0.95, + "base_original_price_incl_tax": 0.95, + "negotiated_price_type": null, + "negotiated_price_value": null + }, + "reward_points_balance": 0, + "reward_currency_amount": 0, + "base_reward_currency_amount": 0 + } + } +} +``` + +{% endcollapsible %} + +## Manage billing addresses + +If the billing address isn't provided through another call, use the `POST /V1/negotiable-carts/:cartId/billing-address` to specify it. + +**Service Name:** + +`negotiableQuoteBillingAddressManagementV1` + +**REST Endpoints:** + +```json +POST /V1/negotiable-carts/:cartId/billing-address +GET /V1/negotiable-carts/:cartId/billing-address +``` + +### Set the billing address + +This call assigns a billing address to the specified negotiable quote. + +**Sample Usage:** + +`POST /rest//V1/negotiable-carts/86/billing-address` + +**Payload:** + +```json +{ "address": { + "region": "New York", + "region_id": 43, + "region_code": "NY", + "country_id": "US", + "street": [ + "123 Oak Ave" + ], + "postcode": "10577", + "city": "Purchase", + "firstname": "Jane", + "lastname": "Doe", + "customer_id": 4, + "email": "jdoe@example.com", + "telephone": "(512) 555-1111", + "same_as_billing": 1 + } +} +``` + +**Response:** + +[] + +### Return the billing address + +This call returns the billing address for the specified negotiable quote. + +**Sample Usage:** + +`GET /rest//V1/negotiable-carts/86/billing-address` + +**Payload:** + +Not applicable + +**Response:** + +```json +{ + "id": 192, + "region": "New York", + "region_id": 43, + "region_code": "NY", + "country_id": "US", + "street": [ + "123 Oak Ave" + ], + "telephone": "(512) 555-1111", + "postcode": "10577", + "city": "Purchase", + "firstname": "Jane", + "lastname": "Doe", + "customer_id": 1, + "email": "jdoe@example.com", + "same_as_billing": 0, + "save_in_address_book": 0 +} +``` + +## Manage cart coupons + +B2B allows coupons to be used toward payment. + +**Service Name:** + +`negotiableQuoteCouponManagementV1` + +**REST Endpoints:** + +```json +PUT /V1/negotiable-carts/:cartId/coupons/:couponCode +DELETE /V1/negotiable-carts/:cartId/coupons +``` + +### Apply a coupon to a negotiable quote + +If the initial quote applies a coupon to the totals, Magento ignores the coupon when it converts the quote to a negotiable quote. However, you can apply a coupon at checkout. + +**Sample Usage:** + +`PUT /rest//V1/negotiable-carts/6/coupons/SAVE5` + +**Payload:** + +Not applicable + +**Response:** + +`true`, indicting the request was successful + +## Manage gift cards + +B2B allows gift cards to be used as payment. + +**Service Name:** + +`negotiableQuoteGiftCardAccountManagementV1` + +**REST Endpoints:** + +```json +POST /V1/negotiable-carts/:cartId/giftCards +DELETE /V1/negotiable-carts/:cartId/giftCards/:giftCardCode +``` + +### Apply a gift card to a negotiable quote + +If the initial quote applies a gift card to the totals, Magento ignores the gift card when it converts the quote to a negotiable quote. However, you can apply a gift card at checkout. + +**Sample Usage:** + +`POST /rest//V1/negotiable-carts/6/giftCards` + +**Payload:** + +```json +{ + "giftCardAccountData": { + "gift_cards": [ + "00HELHQED6RV" + ] + } +} +``` + +**Response:** + +`true` + +### Delete a gift card from at checkout + +This call removes a gift card that has been applied to a negotiable quote. + +**Sample Usage:** + +`DELETE /rest//V1/negotiable-carts/6/giftCards/00HELHQED6RV` + +**Payload:** + +Not applicable + +**Response:** + +`true`, indicating the request was successful + +## Manage payment information + +When you submit payment information, Magento creates an order and sends an order confirmation to the buyer. + +**Service Name:** + +`negotiableQuotePaymentInformationManagementV1` + +**REST Endpoints:** + +```json +POST /V1/negotiable-carts/:cartId/payment-information +GET /V1/negotiable-carts/:cartId/payment-information +POST /V1/negotiable-carts/:cartId/set-payment-information +``` + +### Set payment information without placing the order + +This call sets payment information and the billing address for the negotiable quote. However, Magento does not create an order afterward. + +**Sample Usage:** + +`POST /rest//V1/negotiable-carts/86/set-payment-information` + +**Payload:** + +```json +{ "paymentMethod": { + "po_number": "A123456", + "method": "checkmo" + }, + "billing_address": { + "region": "New York", + "region_id": 43, + "region_code": "NY", + "country_id": "US", + "street": [ + "123 Oak Ave" + ], + "postcode": "10577", + "city": "Purchase", + "firstname": "Jane", + "lastname": "Doe", + "email": "jdoe@example.com", + "telephone": "512-555-1111" + } +} +``` + +**Response:** + +`true`, indicating the payment information was set + +### Set payment information and place the order + +This call sets payment information and the billing address for the negotiable quote, then creates an order. + +**Sample Usage:** + +`POST /rest//V1/negotiable-carts/86/payment-information` + +**Payload:** + +```json +{ "paymentMethod": { + "po_number": "A123456", + "method": "checkmo" + }, + "billing_address": { + "region": "New York", + "region_id": 43, + "region_code": "NY", + "country_id": "US", + "street": [ + "123 Oak Ave" + ], + "postcode": "10577", + "city": "Purchase", + "firstname": "Jane", + "lastname": "Doe", + "email": "jdoe@example.com", + "telephone": "512-555-1111" + } +} +``` + +**Response:** + +An order ID, such as `83` + +### Return payment information + +This call payment information and all information from the `totals` object. + +**Sample Usage:** + +`GET /rest//V1/negotiable-carts/86/payment-information` + +**Payload:** + +Not applicable + +**Response:** + +{% collapsible Show code sample %} + +```json +{ + "payment_methods": [ + { + "code": "checkmo", + "title": "Check / Money order" + } + ], + "totals": { + "grand_total": 5.95, + "base_grand_total": 5.95, + "subtotal": 0.95, + "base_subtotal": 0.95, + "discount_amount": 0, + "base_discount_amount": 0, + "subtotal_with_discount": 0.95, + "base_subtotal_with_discount": 0.95, + "shipping_amount": 5, + "base_shipping_amount": 5, + "shipping_discount_amount": 0, + "base_shipping_discount_amount": 0, + "tax_amount": 0, + "base_tax_amount": 0, + "weee_tax_applied_amount": null, + "shipping_tax_amount": 0, + "base_shipping_tax_amount": 0, + "subtotal_incl_tax": 0.95, + "shipping_incl_tax": 5, + "base_shipping_incl_tax": 5, + "base_currency_code": "USD", + "quote_currency_code": "USD", + "items_qty": 1, + "items": [ + { + "item_id": 13, + "price": 0.95, + "base_price": 0.95, + "qty": 1, + "row_total": 0.95, + "base_row_total": 0.95, + "row_total_with_discount": 0, + "tax_amount": 0, + "base_tax_amount": 0, + "tax_percent": 0, + "discount_amount": 0, + "base_discount_amount": 0, + "discount_percent": 0, + "price_incl_tax": 0.95, + "base_price_incl_tax": 0.95, + "row_total_incl_tax": 0.95, + "base_row_total_incl_tax": 0.95, + "options": "[]", + "weee_tax_applied_amount": null, + "weee_tax_applied": null, + "extension_attributes": { + "negotiable_quote_item_totals": { + "cost": 0, + "catalog_price": 0.95, + "base_catalog_price": 0.95, + "catalog_price_incl_tax": 0.95, + "base_catalog_price_incl_tax": 0.95, + "cart_price": 0.95, + "base_cart_price": 0.95, + "cart_tax": 0, + "base_cart_tax": 0, + "cart_price_incl_tax": 0.95, + "base_cart_price_incl_tax": 0.95 + } + }, + "name": "Simple Product 2" + } + ], + "total_segments": [ + { + "code": "subtotal", + "title": "Subtotal", + "value": 0.95 + }, + { + "code": "giftwrapping", + "title": "Gift Wrapping", + "value": null, + "extension_attributes": { + "gw_item_ids": [], + "gw_price": "0.00", + "gw_base_price": "0.00", + "gw_items_price": "0.00", + "gw_items_base_price": "0.00", + "gw_card_price": "0.00", + "gw_card_base_price": "0.00", + "gw_base_tax_amount": "0.00", + "gw_tax_amount": "0.00", + "gw_items_base_tax_amount": "0.00", + "gw_items_tax_amount": "0.00", + "gw_card_base_tax_amount": "0.00", + "gw_card_tax_amount": "0.00", + "gw_price_incl_tax": "0.00", + "gw_base_price_incl_tax": "0.00", + "gw_card_price_incl_tax": "0.00", + "gw_card_base_price_incl_tax": "0.00", + "gw_items_price_incl_tax": "0.00", + "gw_items_base_price_incl_tax": "0.00" + } + }, + { + "code": "shipping", + "title": "Shipping & Handling (Flat Rate - Fixed)", + "value": 5 + }, + { + "code": "tax", + "title": "Tax", + "value": 0, + "extension_attributes": { + "tax_grandtotal_details": [] + } + }, + { + "code": "grand_total", + "title": "Grand Total", + "value": 5.95, + "area": "footer" + }, + { + "code": "customerbalance", + "title": "Store Credit", + "value": 0 + }, + { + "code": "reward", + "title": "0 Reward points", + "value": 0 + } + ], + "extension_attributes": { + "negotiable_quote_totals": { + "items_count": 1, + "quote_status": "submitted_by_admin", + "created_at": "2017-05-30 20:41:00", + "updated_at": "2017-06-09 20:26:49", + "customer_group": 10, + "base_to_quote_rate": 1, + "cost_total": 0, + "base_cost_total": 0, + "original_total": 0.95, + "base_original_total": 0.95, + "original_tax": 0, + "base_original_tax": 0, + "original_price_incl_tax": 0.95, + "base_original_price_incl_tax": 0.95, + "negotiated_price_type": null, + "negotiated_price_value": null + }, + "reward_points_balance": 0, + "reward_currency_amount": 0, + "base_reward_currency_amount": 0 + } + } +} +``` + +{% endcollapsible %} + +## Review cart totals + +This call is similar to `GET /V1/negotiable-carts/:cartId/payment-information`, except it does not return payment information. + +**Service Name:** + +`negotiableQuoteCartTotalRepositoryV1` + +**REST Endpoints:** + +```json +GET /V1/negotiable-carts/:cartId/totals +``` + +**Sample Usage:** + +`GET /rest//V1/negotiable-carts/86/totals` + +**Payload:** + +Not applicable + +**Response:** + +{% collapsible Show code sample %} + +```json +{ + "totals": { + "grand_total": 5.95, + "base_grand_total": 5.95, + "subtotal": 0.95, + "base_subtotal": 0.95, + "discount_amount": 0, + "base_discount_amount": 0, + "subtotal_with_discount": 0.95, + "base_subtotal_with_discount": 0.95, + "shipping_amount": 5, + "base_shipping_amount": 5, + "shipping_discount_amount": 0, + "base_shipping_discount_amount": 0, + "tax_amount": 0, + "base_tax_amount": 0, + "weee_tax_applied_amount": null, + "shipping_tax_amount": 0, + "base_shipping_tax_amount": 0, + "subtotal_incl_tax": 0.95, + "shipping_incl_tax": 5, + "base_shipping_incl_tax": 5, + "base_currency_code": "USD", + "quote_currency_code": "USD", + "items_qty": 1, + "items": [ + { + "item_id": 13, + "price": 0.95, + "base_price": 0.95, + "qty": 1, + "row_total": 0.95, + "base_row_total": 0.95, + "row_total_with_discount": 0, + "tax_amount": 0, + "base_tax_amount": 0, + "tax_percent": 0, + "discount_amount": 0, + "base_discount_amount": 0, + "discount_percent": 0, + "price_incl_tax": 0.95, + "base_price_incl_tax": 0.95, + "row_total_incl_tax": 0.95, + "base_row_total_incl_tax": 0.95, + "options": "[]", + "weee_tax_applied_amount": null, + "weee_tax_applied": null, + "extension_attributes": { + "negotiable_quote_item_totals": { + "cost": 0, + "catalog_price": 0.95, + "base_catalog_price": 0.95, + "catalog_price_incl_tax": 0.95, + "base_catalog_price_incl_tax": 0.95, + "cart_price": 0.95, + "base_cart_price": 0.95, + "cart_tax": 0, + "base_cart_tax": 0, + "cart_price_incl_tax": 0.95, + "base_cart_price_incl_tax": 0.95 + } + }, + "name": "Simple Product 2" + } + ], + "total_segments": [ + { + "code": "subtotal", + "title": "Subtotal", + "value": 0.95 + }, + { + "code": "giftwrapping", + "title": "Gift Wrapping", + "value": null, + "extension_attributes": { + "gw_item_ids": [], + "gw_price": "0.00", + "gw_base_price": "0.00", + "gw_items_price": "0.00", + "gw_items_base_price": "0.00", + "gw_card_price": "0.00", + "gw_card_base_price": "0.00", + "gw_base_tax_amount": "0.00", + "gw_tax_amount": "0.00", + "gw_items_base_tax_amount": "0.00", + "gw_items_tax_amount": "0.00", + "gw_card_base_tax_amount": "0.00", + "gw_card_tax_amount": "0.00", + "gw_price_incl_tax": "0.00", + "gw_base_price_incl_tax": "0.00", + "gw_card_price_incl_tax": "0.00", + "gw_card_base_price_incl_tax": "0.00", + "gw_items_price_incl_tax": "0.00", + "gw_items_base_price_incl_tax": "0.00" + } + }, + { + "code": "shipping", + "title": "Shipping & Handling (Flat Rate - Fixed)", + "value": 5 + }, + { + "code": "tax", + "title": "Tax", + "value": 0, + "extension_attributes": { + "tax_grandtotal_details": [] + } + }, + { + "code": "grand_total", + "title": "Grand Total", + "value": 5.95, + "area": "footer" + }, + { + "code": "customerbalance", + "title": "Store Credit", + "value": 0 + }, + { + "code": "reward", + "title": "0 Reward points", + "value": 0 + } + ], + "extension_attributes": { + "negotiable_quote_totals": { + "items_count": 1, + "quote_status": "submitted_by_admin", + "created_at": "2017-05-30 20:41:00", + "updated_at": "2017-06-09 20:26:49", + "customer_group": 10, + "base_to_quote_rate": 1, + "cost_total": 0, + "base_cost_total": 0, + "original_total": 0.95, + "base_original_total": 0.95, + "original_tax": 0, + "base_original_tax": 0, + "original_price_incl_tax": 0.95, + "base_original_price_incl_tax": 0.95, + "negotiated_price_type": null, + "negotiated_price_value": null + }, + "reward_points_balance": 0, + "reward_currency_amount": 0, + "base_reward_currency_amount": 0 + } + } +} +``` + +{% endcollapsible %} + +## Related information + +* [Integrate with the NegotiableQuote module]({{ page.baseurl }}/b2b/negotiable-quote.html) +* [Manage negotiable quotes]({{ page.baseurl }}/b2b/negotiable-manage.html) +* [Update a negotiable quote]({{ page.baseurl }}/b2b/negotiable-update.html) +* [Place a negotiable quote order]({{ page.baseurl }}/b2b/negotiable-order-workflow.html) diff --git a/src/guides/v2.4/b2b/negotiable-manage.md b/src/guides/v2.4/b2b/negotiable-manage.md deleted file mode 120000 index 0d4550977c8..00000000000 --- a/src/guides/v2.4/b2b/negotiable-manage.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/b2b/negotiable-manage.md \ No newline at end of file diff --git a/src/guides/v2.4/b2b/negotiable-manage.md b/src/guides/v2.4/b2b/negotiable-manage.md new file mode 100644 index 00000000000..b3efa2e71a5 --- /dev/null +++ b/src/guides/v2.4/b2b/negotiable-manage.md @@ -0,0 +1,340 @@ +--- +group: b2b-developer-guide +subgroup: 10_REST +title: Manage negotiable quotes +menu_title: Manage negotiable quotes +menu_order: 32 +ee_only: True +level3_menu_node: level3child +level3_subgroup: nq +functional_areas: + - B2B + - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-manage +layout: migrated +--- + +This topic describes the calls required to initiate a negotiable quote and to prepare it to be converted to an order. + + {:.bs-callout-info} +All negotiable quote calls require an admin authorization token. + +**REST Endpoints:** + +```json +POST /V1/negotiableQuote/request +POST /V1/negotiableQuote/submitToCustomer +POST /V1/negotiableQuote/decline +POST /V1/negotiableQuote/pricesUpdated +GET /V1/negotiableQuote/:quoteId/comments +GET /V1/negotiableQuote/attachmentContent +PUT /V1/negotiableQuote/:quoteId/shippingMethod +``` + +**NegotiableQuoteManagementInterface Parameters:** + +The following table lists the parameters defined in `CompanyInterface`. + +Name | Description | Format | Requirements +--- | --- | --- |--- +`quoteId` | Identifies the target quote for the operation. | integer | Required +`quoteName` | The name of the quote to be created. | string | Required +`comment` | The comment to add to the quote. | string | Optional +`files` | An array of files to add to the quote | array | Optional + +The buyer or the seller can optionally attach up to 10 files to provide details about the quote. Each file must be converted into base64. + +The `files` array contains the following parameters + +Name | Description | Format | Requirements +--- | --- | --- |--- +`base64_encoded_data` | A string in base 64 that defines the contents of the added file | string | Required +`type` | Defines the type of file, such as `text/plain` or `application/pdf`| string | Optional +`name` | The name of the file to be uploaded, such as `quote.txt` or `quote.pdf`. | string | Required + +### Request a negotiable quote + +Before negotiable quote can begin, the following conditions must be met: + +* A regular Magento quote has been created (`POST /V1/customers/:customerId/carts` or `POST /V1/customers/carts/mine`) +* The quote contains items (`POST /V1/carts/:quoteId/items`) + +If the negotiable quote requires a shipping address (for negotiation or tax calculations), you can add it to the standard quote before initiating the negotiable quote (`POST /V1/carts/:cartId/shipping-information`) + +{:.bs-callout-info} +Requesting a negotiable quote requires an admin authorization token. + +**Service Name:** + +`negotiableQuoteNegotiableQuoteManagementV1` + +**Sample Usage:** + +`POST /rest//V1/negotiableQuote/request` + +**Payload:** + +```json +{ + "quoteId": 3, + "quoteName": "First quote", + "comment": "Requesting a 5% discount", + "files": [ + { + "base64_encoded_data": "VGhhbmsgeW91IGZvciByZWFkaW5nIHRoZSBNYWdlbnRvIEIyQiBkb2N1bWVudGF0aW9uLg==", + "name": "quote.txt" + } + ] +} +``` + +**Response:** + +`true`, indicating the request was successful + +Magento creates a negotiable quote in the `Created` state. + +### Submit a negotiable quote to a buyer + +When you submit a negotiable quote to the buyer, the status for the buyer changes to "Updated". The buyer can subsequently edit or update the quote. + +The seller can send a request to submit the quote to the buyer. The request can be submitted only for quotes in the following system states: + +* Created +* Processing by admin +* Submitted by customer + +When the quote is submitted to the buyer: + +* Magento checks catalog prices (price per item), cart rules, and discounts then recalculates the prices and taxes. The shipping price and the negotiated price are not affected (if they are entered into the quote). +* Items that are no longer active or available for this buyer are removed from quote and prices are recalculated. +* The quote state is changed to Submitted by admin. + +**Service Name:** + +`negotiableQuoteNegotiableQuoteManagementV1` + +**Sample Usage:** + +`POST /rest//V1/negotiableQuote/submitToCustomer` + +**Payload:** + +```json +{ + "quoteId": 3, + "comment": "It'd be our pleasure. Please proceed with your order." +} +``` + +**Response:** + +`true`, indicating the request was successful + +### Update a quote + +Use the `PUT /V1/negotiableQuote/:quoteId` call to update a quote. See [Update a negotiable quote]({{ page.baseurl }}/b2b/negotiable-update.html) for use cases. + +### Recalculate prices + +The process of completing a negotiable quote can take days, or even longer. During that time, the prices for the items in the quote may have changed directly or indirectly. For example, someone could have changed prices in the shared catalogs or adjusted price rules, and the prices in the negotiable quote are stale. This call refreshes item prices, taxes, discounts, cart rules in the negotiable quote. Quotes that are locked for the seller will not be updated. + +The request can be applied to one or more quotes at the same time. + +**Sample Usage:** + +`POST /rest//V1/negotiableQuote/pricesUpdated` + +**Payload:** + +```json +{ + "quoteIds": [3] +} +``` + +**Response:** + +`true`, indicating the request was successful + +### Set the shipping method + +To set the shipping method, the quote must be in the `created`, `processing_by_admin` or `submitted_by_customer`. In addition, the quote must have a shipping address but no shipping method or shipping price. + +**Sample Usage:** + +`PUT /rest//V1/negotiableQuote/3/shippingMethod` + +**Payload:** + +```json +{ + "shippingMethod": "fixedrate" +} +``` + +**Response:** + +### Decline a quote + +The seller can send a request to decline the quote. The request can be submitted only for quotes in the following system states: + +* Created +* Processing by admin +* Submitted by customer + +When you decline a quote, all custom pricing will be removed from the quote. The buyer will be able to place an order using their standard catalog prices and discounts. + +**Service Name:** + +`negotiableQuoteNegotiableQuoteManagementV1` + +**Sample Usage:** + +`POST /rest//V1/negotiableQuote/decline` + +**Payload:** + +```json +{ + "quoteId": 80, + "reason": "Your order is too large. " +} +``` + +**Response:** + +`true`, indicating the request was successful + +## Miscellaneous operations + +These tasks are not essential for completing a negotiable quote, but might be useful + +### List all comments for a quote + +Magento returns all the comments associated with the specified quote ID. The comments are listed in chronological order, with the oldest comment listed first. A `creator_type` value of `3` indicates the buyer made the comment. If the value is `2`, the seller commented. + +**Sample Usage:** + +`GET /rest//V1/negotiableQuote/87/comments` + +**Payload:** + +Not applicable + +**Response:** + +```json +[ + { + "entity_id": 6, + "parent_id": 87, + "creator_type": 3, + "is_decline": 0, + "is_draft": 0, + "creator_id": 1, + "comment": "Requesting a 5% discount", + "created_at": "2017-06-01 21:14:51", + "attachments": [ + { + "attachment_id": 1, + "comment_id": 12, + "file_name": "hello.txt", + "file_path": "/h/e/hello.txt", + "file_type": null + } + ] + }, + { + "entity_id": 7, + "parent_id": 87, + "creator_type": 2, + "is_decline": 0, + "is_draft": 0, + "creator_id": 1, + "comment": "We cannot discount Configurable Product 1, because the price is already discounted. We can adjust the overall price so the remaining items are discounted 5%. Please let us know whether this is acceptable. ", + "created_at": "2017-06-01 21:29:15", + "attachments": [] + }, + { + "entity_id": 8, + "parent_id": 87, + "creator_type": 3, + "is_decline": 0, + "is_draft": 0, + "creator_id": 1, + "comment": "That is fine. Please apply the discounts to our order.", + "created_at": "2017-06-01 21:30:30", + "attachments": [] + }, + { + "entity_id": 9, + "parent_id": 87, + "creator_type": 2, + "is_decline": 0, + "is_draft": 0, + "creator_id": 1, + "comment": "We're taking $27.50 off your quote total. That's 5% of the cost of the other items in your cart.", + "created_at": "2017-06-01 21:40:19", + "attachments": [] + }, + { + "entity_id": 10, + "parent_id": 87, + "creator_type": 3, + "is_decline": 0, + "is_draft": 0, + "creator_id": 1, + "comment": "Added a shipping address", + "created_at": "2017-06-01 21:43:03", + "attachments": [] + }, + { + "entity_id": 11, + "parent_id": 87, + "creator_type": 2, + "is_decline": 0, + "is_draft": 0, + "creator_id": 1, + "comment": "OK", + "created_at": "2017-06-01 21:44:16", + "attachments": [] + } +] +``` + +### Retrieve a negotiable quote attachment + +Use the `attachmentContent` call to retrieve the files (in base64 format) attached to a negotiable quote. + +`negotiableQuoteAttachmentContentManagementV1` + +**Sample Usage:** + +`GET /rest//V1/negotiableQuote/attachmentContent` + +**Payload:** + +Not applicable + +**Response:** + +```json +{ + "quoteId": 2, + "quoteName": "First quote", + "files": [ + { + "base64_encoded_data": "VGhhbmsgeW91IGZvciByZWFkaW5nIHRoZSBNYWdlbnRvIEIyQiBkb2N1bWVudGF0aW9uLg==", + "name": "quote.txt" + } + ] +} +``` + +## Related information + +* [Integrate with the NegotiableQuote module]({{ page.baseurl }}/b2b/negotiable-quote.html) +* [Update a negotiable quote]({{ page.baseurl }}/b2b/negotiable-update.html) +* [Negotiable quote checkout]({{ page.baseurl }}/b2b/negotiable-checkout.html) +* [Place a negotiable quote order]({{ page.baseurl }}/b2b/negotiable-order-workflow.html) diff --git a/src/guides/v2.4/b2b/negotiable-order-workflow.md b/src/guides/v2.4/b2b/negotiable-order-workflow.md index fde89724ec7..50fd0990bce 100644 --- a/src/guides/v2.4/b2b/negotiable-order-workflow.md +++ b/src/guides/v2.4/b2b/negotiable-order-workflow.md @@ -2,6 +2,8 @@ group: b2b-developer-guide title: Place a negotiable quote order ee_only: true +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-order-workflow +layout: migrated --- This topic describes how REST calls can be used to place items in a shopping cart, initiate and complete the process of negotiating a quote, and reimbursing the buyer's credit upon receipt of payment. diff --git a/src/guides/v2.4/b2b/negotiable-quote.md b/src/guides/v2.4/b2b/negotiable-quote.md deleted file mode 120000 index 7665d7502cf..00000000000 --- a/src/guides/v2.4/b2b/negotiable-quote.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/b2b/negotiable-quote.md \ No newline at end of file diff --git a/src/guides/v2.4/b2b/negotiable-quote.md b/src/guides/v2.4/b2b/negotiable-quote.md new file mode 100644 index 00000000000..86b44d955d9 --- /dev/null +++ b/src/guides/v2.4/b2b/negotiable-quote.md @@ -0,0 +1,74 @@ +--- +group: b2b-developer-guide +subgroup: 10_REST +title: Integrate with the NegotiableQuote module +menu_title: Integrate with the NegotiableQuote module +menu_order: 31 +ee_only: True +level3_menu_node: level3child +level3_subgroup: nq +functional_areas: + - B2B + - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-quote +layout: migrated +--- + +Negotiable quotes are a mechanism that allows a company user (buyer) and a seller (admin user) to negotiate product and/or shipping prices before the company user places an order. Its functionality is available for companies only. + +The negotiable quote lifecycle includes a number of stages, as shown on the diagram below. + +![Negotiable quote workflow]({{ site.baseurl }}/common/images/b2b/quote-workflow.jpg) + +The quoting process itself can be a continuous process, with a number of repeating cycles until the agreement is reached. + +* The buyer creates and submits a negotiable quote +* The seller reviews and modifies or declines the quote +* The buyer reviews the seller's counteroffer +* Upon agreement, the buyer begins the checkout process and the system converts the negotiable quote into an order + +{:.bs-callout-info} +You cannot negotiate prices on individual items. + +## Quote statuses + +The quote life cycle is managed via quote statuses. The quoting interface allows both a seller and a buyer to manage items in the quote (add, delete, change quantity) as well as make an offer (or request a quote) for items and/or for shipping. + +The negotiated price set in the negotiable quote is exactly the price that will be applied on a quote during checkout, order generation, and invoice generation. + +Status | Description | Available actions to seller +--- | --- | --- +New | The buyer submitted the quote, but the seller has not opened it yet. The buyer can edit the quote.

    The system creates a new quote record with its own ID. | View +Open | The seller has opened the submitted quote and is reviewing/modifying it. The seller can edit the quote, but the buyer cannot. | View, submit, decline, save as draft.

    Edit the expiration date, item quantity, add/remove product items, enter a proposed price, add shipping method and shipping price, add comments. +Submitted | The seller has reviewed the quote and has sent it back to buyer. The seller cannot edit the quote. | View +Client reviewed | The buyer has opened the quote submitted by seller and is modifying it, by changing items or adding a shipping address. The seller cannot edit the quote. | View +Updated | The buyer has re-submitted the quote to seller. The seller can edit the quote, but the buyer cannot. | View, submit, decline, save as draft.

    Edit the expiration date, item quantity, add/remove product items, enter a proposed price, add shipping method and shipping price, add comments. +Ordered | The buyer has purchased the quote, and Magento converts the quote to an order. Neither the seller nor the buyer can edit the quote. | View +Closed | The buyer has cancelled the quote and thus stopped the negotiation process. Neither the seller nor the buyer can edit the quote.

    The buyer clicks the **Close** button from the Quote details page. (Not available using Web API) | View +Declined | The seller has declined the quote. All custom pricing (if any) is removed from the quote. In admin panel, the quote is locked for editing. | View +Expired | The quote is on the buyer's side, and the quote's expiration date has passed. | View + +The following table maps the internal Magento system state to the statuses displayed on the Storefront and Admin. + +System state | Buyer status | Seller status +--- | --- | --- +Created | Submitted | New +Processing by customer | Open | Client Reviewed +Processing by admin | Pending | Open +Submitted by customer | Submitted | Updated +Submitted by admin | Updated | Submitted +Ordered | Ordered | Ordered +Expired | Expired | Expired +Declined | Declined | Declined +Closed | Closed | Closed + +The following diagram shows the negotiable quote lifecycle from the perspective of statuses. + +![Negotiable quote status]({{ site.baseurl }}/common/images/b2b/quote-statuses.png) + +## Related information + +* [Manage negotiable quotes]({{ page.baseurl }}/b2b/negotiable-manage.html) +* [Update a negotiable quote]({{ page.baseurl }}/b2b/negotiable-update.html) +* [Negotiable quote checkout]({{ page.baseurl }}/b2b/negotiable-checkout.html) +* [Place a negotiable quote order]({{ page.baseurl }}/b2b/negotiable-order-workflow.html) diff --git a/src/guides/v2.4/b2b/negotiable-update.md b/src/guides/v2.4/b2b/negotiable-update.md deleted file mode 120000 index c78926a4640..00000000000 --- a/src/guides/v2.4/b2b/negotiable-update.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/b2b/negotiable-update.md \ No newline at end of file diff --git a/src/guides/v2.4/b2b/negotiable-update.md b/src/guides/v2.4/b2b/negotiable-update.md new file mode 100644 index 00000000000..2cc92540cca --- /dev/null +++ b/src/guides/v2.4/b2b/negotiable-update.md @@ -0,0 +1,161 @@ +--- +group: b2b-developer-guide +title: Update a negotiable quote +ee_only: true +functional_areas: + - B2B + - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-update +layout: migrated +--- + +Sellers and buyers can edit a negotiable quote at various times during the quote's lifecycle. Both use the `PUT /V1/negotiableQuote/:quoteId` call to update the quote. This call is defined in the +`quoteCartRepositoryV1` service and is functionally similar to the +`PUT /V1/carts/mine` call. + +The `quote` object now contains a set of `negotiable_quote` extension attributes that can be used to update a quote. + +Name | Description | Format | Requirements +--- | --- | --- | --- +`quote_id` | Negotiable quote ID | integer | Required to create or update a negotiable quote +`is_regular_quote` | Flag for the negotiable quote | boolean | Optional +`status` | One of `created`, `submitted_by_customer`, `submitted_by_admin`, `processing_by_customer`, `processing_by_admin`, `ordered`, `expired`, `declined`, `closed` | string | Optional +`negotiated_price_type` | 1 - Percentage discount; 2 - Fixed price; 3 - proposed total | integer | Required to set a negotiated price +`negotiated_price_value` | Discount amount defined by the seller | number | Required to set a negotiated price +`shipping_price` | Custom price for shipping defined by the seller | number | Optional +`quote_name` | Name assigned to the negotiable quote | string | Optional +`expiration_period` | Expiration date for the quote. The format must be `YYYY-MM-DD`. | string | Optional +`email_notification_status` | Recent notifications that have been sent | integer | Optional +`has_unconfirmed_changes` | Indicates there are some changes that the Admin has not seen yet | boolean | Optional +`is_shipping_tax_changed` | Indicates whether shipping taxes have changed | boolean | Optional +`is_customer_price_changed` | Indicates whether the price for the product has changed | boolean | Optional +`notifications` | Binary mask where the current notifications are stored | integer | Optional +`applied_rule_ids` | Applied shopping cart rules | string | Optional +`is_address_draft` | Drop the address if the checkout is not completed. | boolean | Optional +`deleted_sku` | The SKUs of any deleted products | string | Optional +`creator_id` | Quote creator ID | integer | Optional +`creator_type` | 1 - Integration; 2 - Admin; 3 - Customer; 4 - Guest | integer | Optional +`original_total_price` | Original total price | number | Optional +`base_original_total_price` | Base original total price | number | Optional +`negotiated_total_price` | Negotiated total price | number | Optional +`base_negotiated_total_price` | Base negotiated total price | number | Optional + +### Set a negotiated price + +In every successful negotiate quote, the seller must set the negotiated price. + +The `negotiated_price_type` can have one of the following values: + +`1` - Apply a percentage discount to the quote. The `negotiated_price_value` parameter indicates the percentage. + +`2` - Apply a fixed amount as a discount for the quote. The `negotiated_price_value` parameter specifies the amount of the discount. + +`3` - Set a proposed price for the entire quote. The `negotiated_price_value` parameter specifies the proposed price. + +**Service Name:** + +`quoteCartRepositoryV1` + +**Sample Usage:** + +`PUT /rest//V1/negotiableQuote/6` + +**Payload:** + +```json +{ + "quote": { + "id": 6, + "extension_attributes": { + "negotiable_quote": { + "negotiated_price_type": 1, + "negotiated_price_value": 5 + } + } + } +} +``` + +### Add a new quote item to the negotiable quote + +The buyer can add, update, or delete items from the quote under the following conditions: + +* The quote is in one of the following system states: `created`, `processing_by_admin`, or `submitted_by_customer`. +* The quote doesn't have a negotiated price. + +**Sample Usage:** + +`POST /rest//V1/carts/mine/items` + +**Headers:** + +```terminal +Content-Type application/json +Authorization Bearer +``` + +**Payload:** + +```json +{ + "cartItem": { + "sku": "24-MB01", + "qty": 1, + "quote_id": "7" + } +} +``` + +**Response:** + +```json +{ + "item_id": 18, + "sku": "24-MB01", + "qty": 1, + "name": "Joust Duffle Bag", + "price": 34, + "product_type": "simple", + "quote_id": "7", + "extension_attributes": { + "negotiable_quote_item": { + "item_id": 18, + "original_price": 34, + "original_tax_amount": 0, + "original_discount_amount": 0 + } + } +} +``` + +### Change the quote expiration date + +**Sample Usage:** + +`PUT /rest//V1/negotiableQuote/6` + +**Payload:** + +```json +{ + "quote": { + "id": 6, + "extension_attributes": { + "negotiable_quote": { + "expiration_period": "2017-09-30" + } + } + } +} +``` + +**Response:** + +`[]` + +## Related information + +* [Integrate with the NegotiableQuote module]({{ page.baseurl }}/b2b/negotiable-quote.html) +* [Manage negotiable quotes]({{ page.baseurl }}/b2b/negotiable-manage.html) +* [Negotiable quote checkout]({{ page.baseurl }}/b2b/negotiable-checkout.html) +* [Place a negotiable quote order]({{ page.baseurl }}/b2b/negotiable-order-workflow.html) diff --git a/src/guides/v2.4/b2b/roles.md b/src/guides/v2.4/b2b/roles.md index 004de050682..2d70ca695be 100644 --- a/src/guides/v2.4/b2b/roles.md +++ b/src/guides/v2.4/b2b/roles.md @@ -5,6 +5,8 @@ menu_title: Manage company roles ee_only: True functional_areas: - B2B +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/roles +layout: migrated --- Within a company, customers may have different job roles, levels of responsibility, and access to information about their company. {{site.data.var.b2b}} defines several types of system resources, and the Company Admin (or an integration that operates on the behalf of the Company Admin) grants or denies access to these resources using company roles. The Company Admin has access to all resources. diff --git a/src/guides/v2.4/b2b/shared-cat-company.md b/src/guides/v2.4/b2b/shared-cat-company.md deleted file mode 120000 index 20aabe16af8..00000000000 --- a/src/guides/v2.4/b2b/shared-cat-company.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/b2b/shared-cat-company.md \ No newline at end of file diff --git a/src/guides/v2.4/b2b/shared-cat-company.md b/src/guides/v2.4/b2b/shared-cat-company.md new file mode 100644 index 00000000000..fcc16ee0bb2 --- /dev/null +++ b/src/guides/v2.4/b2b/shared-cat-company.md @@ -0,0 +1,109 @@ +--- +group: b2b-developer-guide +title: Assign companies to a shared catalog +ee_only: true +functional_areas: + - B2B + - Catalog + - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/shared-cat-company +layout: migrated +--- + +A shared catalog must be assigned to one or more companies before it can be accessed by the company users. + +**Service name:** + +`sharedCatalogCompanyManagementV1` + +**REST endpoints:** + +```terminal +POST /V1/sharedCatalog/:sharedCatalogId/assignCompanies +POST /V1/sharedCatalog/:sharedCatalogId/unassignCompanies +GET /V1/sharedCatalog/:sharedCatalogId/companies +``` + +**Company parameters:** + + {:.bs-callout-info} +Although you can specify other parameters defined within a `categories` object, the `id` is the only one used to assign or unassign a category to a shared catalog. + +Name | Description | Format | Requirements +--- | --- | --- | --- +`id` | The company ID number | integer | Required to assign or unassign a company to a shared catalog + +## Assign companies to shared catalog + +This action works as an update. It does not replace companies that have already been assigned. + +If a specified company is already assigned to a different shared catalog, this request unassigns the company from the previous catalog and assigns to the new one. + +**Sample usage:** + +`POST /rest//V1/sharedCatalog/2/assignCompanies` + +**Payload:** + +```json +{ + "companies": [ + { + "id": 1 + }, + { + "id": 2 + } + ] +} +``` + +**Response:** + +`true`, indicating the operation was successful + +## Unassign companies from a shared catalog + +When you unassign a company from a custom catalog, the system automatically assigns this company to the public shared catalog. You cannot unassign a company from the public catalog. + +**Sample usage:** + +`POST /rest//V1/sharedCatalog/2/unassignCompanies` + +**Payload:** + +```json +{ + "companies": [ + { + "id": 2 + } + ] +} +``` + +**Response:** + +`true`, indicating the operation was successful + +## List the shared catalog companies + +The `GET` call returns an array of company IDs. + +**Sample Usage:** + +`GET /rest//V1/sharedCatalog/2/companies` + +**Payload:** + +Not applicable + +**Response:** + +`"[\"1\",\"2\"]"` + +## Related information + +* [Integrate with the SharedCatalog module]({{ page.baseurl }}/b2b/shared-catalog.html) +* [Manage shared catalogs]({{ page.baseurl }}/b2b/shared-cat-manage.html) +* [Assign categories and products]({{ page.baseurl }}/b2b/shared-cat-product-assign.html) diff --git a/src/guides/v2.4/b2b/shared-cat-manage.md b/src/guides/v2.4/b2b/shared-cat-manage.md index 81dd6f3226b..2183da7a4c7 100644 --- a/src/guides/v2.4/b2b/shared-cat-manage.md +++ b/src/guides/v2.4/b2b/shared-cat-manage.md @@ -6,6 +6,8 @@ functional_areas: - B2B - Catalog - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/shared-cat-manage +layout: migrated --- ## Manage custom shared catalogs diff --git a/src/guides/v2.4/b2b/shared-cat-product-assign.md b/src/guides/v2.4/b2b/shared-cat-product-assign.md deleted file mode 120000 index 54a04edd102..00000000000 --- a/src/guides/v2.4/b2b/shared-cat-product-assign.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/b2b/shared-cat-product-assign.md \ No newline at end of file diff --git a/src/guides/v2.4/b2b/shared-cat-product-assign.md b/src/guides/v2.4/b2b/shared-cat-product-assign.md new file mode 100644 index 00000000000..a7a3e745ab3 --- /dev/null +++ b/src/guides/v2.4/b2b/shared-cat-product-assign.md @@ -0,0 +1,249 @@ +--- +group: b2b-developer-guide +title: Assign categories and products to a shared catalog +ee_only: true +functional_areas: + - B2B + - Catalog + - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/shared-cat-product-assign +layout: migrated +--- + +The shared catalog configuration process includes assigning categories and products to the shared catalog. To assign these items to a shared catalog, the following conditions must be met: + +* The category structure must already be defined. You cannot create a new category to be included in a shared catalog. Use endpoints like `POST /V1/categories` to create a new category. + +* Each category must already be populated with products. You cannot add a new product to a category to be included in a shared catalog. Use endpoints like `POST /V1/products` to create a new product. + +## Assign categories + +The `sharedCatalogCategoryManagementV1` service is based on `catalogCategoryManagementV1`. To view a store's category structure, call `GET /V1/categories`. + + {:.bs-callout-info} +Products that are defined within a category are not included when you assign a category to a shared catalog. You must add products separately. + +**Service name:** + +`sharedCatalogCategoryManagementV1` + +**REST Endpoints:** + +```terminal +POST /V1/sharedCatalog/:id/assignCategories +POST /V1/sharedCatalog/:id/unassignCategories +GET /V1/sharedCatalog/:id/categories +``` + +**Category parameters:** + + {:.bs-callout-info} +Although you can specify other parameters defined within a `categories` object, the `id` is the only one used to assign or unassign a category to a shared catalog. + +Name | Description | Format | Requirements +--- | --- | --- | --- +`id` | The category ID number | integer | Required to assign or unassign a category + +### Assign categories to shared catalog + +The following example adds the Luma Gear category (`id=3`) as well as its subcategories (`id=4,5,6`) to a custom shared catalog. + +**Sample usage:** + +`POST /rest//V1/sharedCatalog/2/assignCategories` + +**Payload:** + +```json +{ + "categories": [ + { + "id": 3 + }, + { + "id": 4 + }, + { + "id": 5 + }, + { + "id": 6 + } + ] +} +``` + +**Response:** + +`true`, indicating the operation was successful + +### Unassign categories from a shared catalog + +When you unassign a category from a shared catalog, Magento also removes its products from the shared catalog. If a product is assigned to multiple categories, then Magento removes the product from the unassigned category only. + +The following example removes two categories from the shared catalog. + +**Sample usage:** + +`POST /rest//V1/sharedCatalog/2/unassignCategories` + +**Payload:** + +```json +{ + "categories": [ + { + "id": 7 + }, + + { + "id": 8 + } + ] +} +``` + +**Response:** + +`true`, indicating the operation was successful + +### List the shared catalog categories + +The `GET` call returns an array of catalog IDs. + +**Sample Usage:** + +`GET /rest//V1/sharedCatalog/2/categories` + +**Payload:** + +Not applicable + +**Response:** + +```json +[ + 3, + 4, + 5, + 6 +] +``` + +## Assign products + +The `sharedCatalogProductManagementV1` service is based on `catalogProductManagementV1`. To return a list of products defined within a category, call `GET /V1/categories/:categoryId/products`. + +**Service name:** + +`sharedCatalogProductManagementV1` + +**REST endpoints:** + +```terminal +POST /V1/sharedCatalog/:id/assignProducts +POST /V1/sharedCatalog/:id/unassignProducts +GET /V1/sharedCatalog/:id/products +``` + +**Category parameters:** + + {:.bs-callout-info} +Although you can specify other parameters defined within a `products` object, the `sku` is the only one used to assign or unassign a product to a shared catalog. + +Name | Description | Format | Requirements +--- | --- | --- | --- +`sku` | The product's SKU identifier | string | Required to assign or unassign a product to a shared catalog + +### Assign products to shared catalog + +The following example adds two products each in the Bags, Fitness Equipment, and Watches categories to a custom shared catalog. The specified products do not have to be in the same category. + +**Sample usage:** + +`POST /rest//V1/sharedCatalog/2/assignProducts` + +**Payload:** + +```json +{ + "products": [ + { + "sku": "24-MB01" + }, + { + "sku": "24-MB04" + }, + { + "sku": "24-UG06" + }, + { + "sku": "24-UG07" + }, + { + "sku": "24-MG04" + }, + { + "sku": "24-MG01" + } + ] +} +``` + +**Response:** + +`true`, indicating the operation was successful + +### Unassign products from the shared catalog + +Unassigning a product does not remove it from its category or categories. + +**Sample usage:** + +`POST /rest//V1/sharedCatalog/2/unassignProducts` + +**Payload:** + +```json +{ + "products": [ + { + "sku": "24-MG01" + } + ] +} +``` + +**Response:** + +`true`, indicating the operation was successful + +### List the shared catalog products + +The `GET` call returns an array of SKUs. + +**Sample Usage:** + +`GET /rest//V1/sharedCatalog/2/products` + +**Payload:** + +Not applicable + +**Response:** + +```json +[ + "24-MB01", + "24-MB04", + "24-UG06", + "24-UG07", + "24-MG04" +] +``` + +## Related information + +* [Integrate with the SharedCatalog module]({{ page.baseurl }}/b2b/shared-catalog.html) +* [Manage shared catalogs]({{ page.baseurl }}/b2b/shared-cat-manage.html) +* [Assign companies]({{ page.baseurl }}/b2b/shared-cat-company.html) diff --git a/src/guides/v2.4/b2b/shared-catalog.md b/src/guides/v2.4/b2b/shared-catalog.md index ba46914c0ea..e6cb5a8a9b0 100644 --- a/src/guides/v2.4/b2b/shared-catalog.md +++ b/src/guides/v2.4/b2b/shared-catalog.md @@ -11,6 +11,8 @@ functional_areas: - B2B - Catalog - Integration +migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/shared-catalog +layout: migrated --- A shared catalog is an entity that allows a seller to set special rules for the products that company users (buyers) can purchase. By using shared catalogs, a seller can apply different pricing levels for different companies. Also, shared catalogs allow a seller to configure the visibility of categories and products specifically for different companies. From cd87ecf539ea78cbe17a83605747a355a34c7816 Mon Sep 17 00:00:00 2001 From: jfrontain Date: Tue, 12 Jul 2022 16:32:29 -0500 Subject: [PATCH 280/776] changed branch to brand --- src/guides/v2.4/release-notes/commerce-2-4-5.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md index 6a6b67e1d78..639c547b60f 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-5.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -141,7 +141,7 @@ The {{ site.data.var.ee }} checkout workflow now supports the inclusion of an es ### Branding and style changes -The Admin has been updated to align with Adobe’s branch strategy. Changes affect headers, footers, data grid color updates, and navigation elements. +The Admin has been updated to align with Adobe’s brand strategy. Changes affect headers, footers, data grid color updates, and navigation elements. ### B2B From 16afef6986d38ddd71176989d79d0d55ddbd34bb Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 12 Jul 2022 17:22:35 -0500 Subject: [PATCH 281/776] Moved file and added redirect --- src/_data/toc/extensions.yml | 4 +- src/_data/toc/installation-guide.yml | 4 + src/extensions/install/index.md | 2 + .../install-gde/install/cli/extensions.md | 180 ++++++++++++++++++ 4 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 src/guides/v2.4/install-gde/install/cli/extensions.md diff --git a/src/_data/toc/extensions.yml b/src/_data/toc/extensions.yml index d3d2df94efd..60c6f76caa2 100644 --- a/src/_data/toc/extensions.yml +++ b/src/_data/toc/extensions.yml @@ -6,8 +6,8 @@ pages: versionless: true - label: Install extensions - url: /extensions/install/ - versionless: true + url: /install-gde/install/cli/extensions.html + exclude_versions: ["2.3"] - label: Amazon Sales Channel versionless: true diff --git a/src/_data/toc/installation-guide.yml b/src/_data/toc/installation-guide.yml index ac364e24268..3122c82790b 100644 --- a/src/_data/toc/installation-guide.yml +++ b/src/_data/toc/installation-guide.yml @@ -148,6 +148,10 @@ pages: - label: Remove sample data modules or update sample data url: /install-gde/install/cli/install-cli-sample-data-other.html + - label: Install an extension + url: /install-gde/install/cli/extensions.html + exclude_versions: ["2.3"] + - label: Uninstall language packages url: /install-gde/install/cli/install-cli-uninstall-langpk.html diff --git a/src/extensions/install/index.md b/src/extensions/install/index.md index 99f1a03ac23..8e4223288d7 100644 --- a/src/extensions/install/index.md +++ b/src/extensions/install/index.md @@ -14,6 +14,8 @@ redirect_from: - guides/v2.3/comp-mgr/extens-man/extensman-uninst-final.html - guides/v2.3/comp-mgr/extens-man/extensman-update.html - guides/v2.3/comp-mgr/extens-man/step3-parent.html +redirect_to: + - guides/v2.4/install-gde/install/cli/extensions.html --- Code that extends or customizes {{site.data.var.ee}} and {{site.data.var.ce}} behavior is called an extension. You can optionally package and distribute extensions on the [Commerce Marketplace](https://marketplace.magento.com) or another extension distribution system. diff --git a/src/guides/v2.4/install-gde/install/cli/extensions.md b/src/guides/v2.4/install-gde/install/cli/extensions.md new file mode 100644 index 00000000000..4206f1dbc51 --- /dev/null +++ b/src/guides/v2.4/install-gde/install/cli/extensions.md @@ -0,0 +1,180 @@ +--- +group: installation-guide +title: Install an extension +--- + +Code that extends or customizes {{site.data.var.ee}} and {{site.data.var.ce}} behavior is called an extension. You can optionally package and distribute extensions on the [Commerce Marketplace](https://marketplace.magento.com) or another extension distribution system. + +Extensions include: + +- Modules (extend Magento capabilities) +- Themes (change the look and feel of your [storefront](https://glossary.magento.com/storefront) and Admin) +- Language packages (localize the storefront and Admin) + +{:.bs-callout-tip} +This topic explains how to use the command line to install extensions you purchase from the Commerce Marketplace. You can use the same procedure to install _any_ extension; all you need is the extension's [Composer](https://glossary.magento.com/composer) name and version. To find it, open the extension's `composer.json` file and note the values for `"name"` and `"version"`. + +Prior to installation, you may want to: + +1. Back up your database. +1. Enable maintenance mode: + + ```bash + bin/magento maintenance:enable + ``` + +To install an extension, you must: + +1. Get an extension from the Commerce Marketplace or another extension developer. +1. If you install an extension from the Commerce Marketplace, make sure that the `repo.magento.com` repository exists in your `composer.json` file: + + ```bash + "repositories": [ + { + "type": "composer", + "url": "https://repo.magento.com/" + } + ] + ``` + +1. Get the extension's Composer name and version. +1. Update the `composer.json` file in your Magento project with the name and version of the extension. +1. Verify that the extension installed properly. +1. Enable and configure the extension. + +## Get the extension's Composer name and version + +If you already know the extension's Composer name and version, skip this step and continue with [Update your `composer.json` file](#update-composer-json). + +To get the extension's Composer name and version from the Commerce Marketplace: + +1. Log in to [Commerce Marketplace](https://marketplace.magento.com) with the username and password you used to purchase the extension. + +1. In the upper-right corner, click **Your name** > **My Profile**. + + ![Access your Marketplace account]({{ site.baseurl }}/common/images/marketplace-my-profile.png){:width="200px"} + +1. Click **My Purchases**. + + ![Marketplace purchase history]({{ site.baseurl }}/common/images/marketplace-my-purchases.png){:width="650px"} + +1. Find the extension you want to install and click **Technical Details**. + + ![Technical details shows the extension's Composer name]({{ site.baseurl }}/common/images/marketplace-extension-technical-details.png){:width="200px"} + +{:.bs-callout-tip} +Alternatively, you can find the Composer name and version of _any_ extension (whether you purchased it on Commerce Marketplace or somewhere else) in the extension's `composer.json` file. + +## Update your `composer.json` file {#update-composer-json} + +Add the extension's name and version to your `composer.json` file: + +1. Navigate to your Magento project directory and update your `composer.json` file. + + ```bash + composer require : + ``` + + For example, + + ```bash + composer require j2t/module-payplug:2.0.2 + ``` + +1. Enter your [authentication keys]({{ site.baseurl }}/guides/v2.3/install-gde/prereq/connect-auth.html). Your public key is your username; your private key is your password. + +1. Wait for Composer to finish updating your project dependencies and make sure there aren't any errors: + + ```terminal + Updating dependencies (including require-dev) + Package operations: 1 install, 0 updates, 0 removals + - Installing j2t/module-payplug (2.0.2): Downloading (100%) + Writing lock file + Generating autoload files + ``` + {:.no-copy} + +## Verify the extension + +To verify that the extension installed properly, run the following command: + +```bash +bin/magento module:status J2t_Payplug +``` + +By default, the extension is probably disabled: + +```terminal +Module is disabled +``` + +The extension name is in the format `_`; this is a different format from the Composer name. Use this format to enable the extension. If you are unsure of the extension name, run: + +```bash +bin/magento module:status +``` + +and look for the extension under "List of disabled modules". + +## Enable the extension + +Some extensions won't work properly unless you clear Magento-generated static view files first. Use the `--clear-static-content` option to clear static view files when you're enabling an extension. + +1. Enable the extension and clear static view files: + + ```bash + bin/magento module:enable J2t_Payplug --clear-static-content + ``` + + You should see the following output: + + ```terminal + The following modules have been enabled: + - J2t_Payplug + + To make sure that the enabled modules are properly registered, run 'setup:upgrade'. + Cache cleared successfully. + Generated classes cleared successfully. Please run the 'setup:di:compile' command to generate classes. + Generated static view files cleared successfully. + ``` + +1. Register the extension: + + ```bash + bin/magento setup:upgrade + ``` + +1. Recompile your Magento project: In Production mode, you may receive a message to "Please rerun Magento compile command". Magento does not prompt you to run the compile command in Developer mode. + + ```bash + bin/magento setup:di:compile + ``` + +1. Verify that the extension is enabled: + + ```bash + bin/magento module:status J2t_Payplug + ``` + + You should see output verifying that the extension is no longer disabled: + + ```terminal + Module is enabled + ``` + +1. Clean the cache: + + ```bash + bin/magento cache:clean + ``` + +1. Configure the extension in Admin as needed. + +{:.bs-callout-tip} +If you encounter errors when loading the storefront in a browser, use the following command to clear the cache: +
    +`bin/magento cache:flush` + +## Upgrade an extension + +{% include upgrade/module.md %} \ No newline at end of file From fe372bc233d1073dff757eb527dd001a620cd945 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 12 Jul 2022 17:35:54 -0500 Subject: [PATCH 282/776] Added migration metadata --- src/extensions/vendor/vendor.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/extensions/vendor/vendor.md b/src/extensions/vendor/vendor.md index 41e1468c7b5..239728c9e22 100644 --- a/src/extensions/vendor/vendor.md +++ b/src/extensions/vendor/vendor.md @@ -5,6 +5,8 @@ permalink: extensions/vendor/ redirect_from: - /extensions/vendor/yotpo/release-notes.html - /extensions/vendor/dotdigital/release-notes.html +migrated_to: https://experienceleague.adobe.com/docs/commerce-operations/upgrade-guide/modules/upgrade.html +layout: migrated --- {:.bs-callout-warning} From c9b6b46166cf67c44d378dc8afcb560a9302c9f4 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 12 Jul 2022 17:45:52 -0500 Subject: [PATCH 283/776] Added migration metadata for intro --- src/extensions/index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/extensions/index.md b/src/extensions/index.md index cbeba537548..4129aee025b 100644 --- a/src/extensions/index.md +++ b/src/extensions/index.md @@ -1,6 +1,8 @@ --- group: extensions title: Introduction +migrated_to: https://experienceleague.adobe.com/docs/commerce-admin/start/resources/commerce-marketplace.html +layout: migrated --- Extensions allow you to add custom features, functionality, services, and integrations to your Admin and storefront. Extension developers package and install custom code as extensions, modules, components, addons, etc. You can design and develop extensions or purchase and install extensions from the Commerce Marketplace or third-party providers. From cfbed95c88cdeacc50bceacaacb8e9ce04a68cb1 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Wed, 13 Jul 2022 09:19:57 -0500 Subject: [PATCH 284/776] Removed inventory mgmt notes --- src/guides/v2.3/inventory/release-notes.md | 40 ---------------------- 1 file changed, 40 deletions(-) diff --git a/src/guides/v2.3/inventory/release-notes.md b/src/guides/v2.3/inventory/release-notes.md index 130e6889cdd..e08a1437df9 100644 --- a/src/guides/v2.3/inventory/release-notes.md +++ b/src/guides/v2.3/inventory/release-notes.md @@ -22,46 +22,6 @@ The release notes include: - {:.fix}Fixes and improvements - {:.bug}Known issues -### v1.2.x - -{{site.data.var.im}} 1.2.x (module version: `magento/inventory-metapackage = 1.2.4`) is supported with version 2.4.4 and compatible with version 2.4.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. - -- {:.fix} The default inventory stock status of bundle and grouped products is now updated as expected when a merchant creates a shipment from the Admin. Previously, the status of these products remained unchanged after a shipment was created. - -- {:.fix} Configurable products are now returned back to stock when one of these conditions is met: the parent product has at least one saved child in stock, or the configurable product itself was updated and set as **in stock** and had at least one child in stock. - -- {:.fix} Inventory changes implemented through the REST API are now reflected as expected on product detail pages. The cache for catalog products is now cleaned after comparing the last and current stock statuses. Previously, omitting the callback function resulted in the incorrect evaluation of stock status changes, which did not trigger the necessary cache cleaning. As a result, the storefront did not reflect the inventory changes. - -- {:.fix} Products that are assigned to default stock and that were previously out of stock are now visible on the storefront after updating the source item using `/V1/inventory/source-items`. Previously, this REST API endpoint set the wrong `stock_status`. - -- {:.fix} Unassigning inventory sources through bulk action (**Catalog** > **Products** > **Select Products** > **Actions - Unassign Inventory Source**) now works as expected when sources include SKUs that are duplicates with the exception of a leading zero (for example, `01234` and `1234`). Previously, Magento did not unassign inventory sources and threw an error. - -- {:.fix} Product stock status is now always **in stock** on the storefront when infinite back orders are enabled and the product is assigned to a custom stock, regardless of the quantity backordered. Previously, products went out of stock even when back orders were enabled. - -- {:.fix} Configurable product parent and child product stock is now updated correctly after the source item is updated with `POST /V1/inventory/source-items`. After the child product has been updated through the API, a new Inventory plugin for default stock checks and updates configurable product quantity and status. - -- {:.fix} Out-of-stock grouped products are no longer listed on the storefront Category page. - -- {:.fix} Corrected the package name in `CatalogInventory` `composer.json`. - -- {:.fix} Back order status is now correctly represented in the Admin after placing an order with zero quantity product in a multi source/stock deployment. [GitHub-33756](https://github.com/magento/magento2/issues/33756) - -- {:.fix} Out-of-stock bundle products are no longer displayed on the storefront Category page when the bundle product is updated from the stocks section. - -- {:.fix} Compatibility issues with PHP 7.4 have been resolved. - -- {:.fix} The performance of save operations that include bundle products that contain many options (several hundred) has been improved. Previously, saving these large bundle products took several minutes and sometimes resulted in timeouts in deployments with Inventory services enabled. [GitHub-34732](https://github.com/magento/magento2/issues/34732) - -- {:.fix} The product bulk action tool (**Catalog** > **Products** > **Select Products** > **Actions** > **Assign Inventory Source**) now works as expected when assigning inventory source to multiple products when SKUs are duplicated with the exception of a leading 0 (for example, 01234 and 1234). Previously, only one product was assigned an Inventory source. [GitHub-35171](https://github.com/magento/magento2/issues/35171) - -- {:.fix} The `ProductInterface.only_x_left_in_stock` field now returns 0 if inventory is 0. Previously, it returned null. [GitHub-29932](https://github.com/magento/magento2/issues/29932) - -- {:.fix} You can now edit default stock from Admin **Stores** > **Inventory** > **Stocks**. Previously, a JavaScript error was displayed in the console when you tried to add or remove sources from default stock, although you could assign websites to default stock. - -- {:.fix} The category list product count is now correct when using inventory single-source mode with the **Display Out-Of-Stock Products** setting enabled. A new plugin now uses `AreProductsSalableInterface` and `StockConfigurationInterface` to determine the total number of products. Previously, the category product list returned the wrong product quantity. - -- {:.fix} Configurable products are now moved to the last position in the product listing after stock is updated when the **Move out of stock to the bottom** setting is enabled. A new custom database query has been implemented to negate Elasticsearch index sort order, which disregards Admin-enabled sort order. Previously, configurable products and their child products were not moved to the bottom of the list when this setting was enabled. - ### v1.2.4 {{site.data.var.im}} 1.2.4 (module version: `magento/inventory-metapackage = 1.2.4`) is supported with version 2.4.4 and compatible with version 2.4.0 of {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}}. From 22e4df0f4a2b0036d351b111d3831e5ecea62ebb Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Wed, 13 Jul 2022 09:21:04 -0500 Subject: [PATCH 285/776] Removed B2B notes --- .../v2.4/release-notes/b2b-release-notes.md | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/src/guides/v2.4/release-notes/b2b-release-notes.md b/src/guides/v2.4/release-notes/b2b-release-notes.md index 04b66bc0748..845a7abca93 100644 --- a/src/guides/v2.4/release-notes/b2b-release-notes.md +++ b/src/guides/v2.4/release-notes/b2b-release-notes.md @@ -11,34 +11,6 @@ These release notes can include: - {:.new} New features - {:.fix} Fixes and improvements -## {{ site.data.var.ee }} B2B 1.3.4 - Adobe Commerce 2.4.5 - -- {:.fix} {{ site.data.var.ee }} no longer sends email notifications each time an existing Company is updated by an API call. Emails are now sent only when a company is created. - -- {:.fix} {{ site.data.var.ee }} now correctly calculates a negotiable quote grand total when the **Enable Cross Border Trade** tax calculation setting is enabled. - -- {:.fix} Configurable products are now moved to the last position in the product listing after stock is updated when the **Move out of stock to the bottom** setting is enabled. A new custom database query has been implemented to ensure Elasticsearch index sort order now honors the Admin-enabled sort order. Previously, configurable products and their child products were not moved to the bottom of the list when this setting was enabled. - -- {:.fix} Purchase Order email now honors the email sending setting of each website in a multi-site deployment. A check for the **Disable Email Communications** setting has been added to the custom logic for email queues. Previously, {{ site.data.var.ee }} did not honor the email sending setting of the secondary website. - -- {:.fix} The title of the SKU field of the Quick Order page has been edited for clarity. - -- {:.fix} {{ site.data.var.ee }} now displays a more informative error message when a shopper enters an invalid SKU in the **Enter SKU or Product Name** field. - -- {:.fix} The **Account Created in** field for a company administrator now retains its value as expected after you save the company. - -- {:.fix} The `customer` query no longer returns empty results when it retrieves requisition lists that are filtered by `uid`. - -- {:.fix} Added a plugin before the `collectQuoteTotals` call to ensure that store credits are applied only once. - -- {:.fix} Customers are now redirected to the login page when their account is deleted by an administrator from the Admin. Previously, {{ site.data.var.ee }} threw an error. The plugin (`SessionPlugin`) code block is now inside the `try…catch` block. Previously, this code was not wrapped inside the generic exception handling block. - -- {:.fix} Pressing **Enter** on the Quick Order page in mobile mode after entering a valid product name or SKU now takes the shopper to the next field as expected. - -- {:.fix} Company name is now visible as expected in the billing and shipping address sections of the checkout workflow. - -- {:.fix} Store credit is now unavailable when the Zero Subtotal Checkout payment method is disabled. Previously, the Store Credit checkbox was not functional during order placement from Admin. {{ site.data.var.ce }} did not place the order with the store credit and displayed this error: `The requested Payment Method is not available`. - ## {{ site.data.var.ee }} B2B - Adobe Commerce 2.4.4 - {:.fix} The time required to upgrade from {{ site.data.var.ee }} 2.3.x to {{ site.data.var.ee }} 2.4.x in deployments with more than 100,000 company roles has been substantially reduced. From 70fd5969736a420380393e30d13cd0997c352490 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Wed, 13 Jul 2022 12:28:08 -0500 Subject: [PATCH 286/776] Added migration metadata --- .../v2.4/inventory/inventory-cli-reference.md | 172 +++++++++++++++++- 1 file changed, 171 insertions(+), 1 deletion(-) mode change 120000 => 100644 src/guides/v2.4/inventory/inventory-cli-reference.md diff --git a/src/guides/v2.4/inventory/inventory-cli-reference.md b/src/guides/v2.4/inventory/inventory-cli-reference.md deleted file mode 120000 index aedaef136be..00000000000 --- a/src/guides/v2.4/inventory/inventory-cli-reference.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/inventory/inventory-cli-reference.md \ No newline at end of file diff --git a/src/guides/v2.4/inventory/inventory-cli-reference.md b/src/guides/v2.4/inventory/inventory-cli-reference.md new file mode 100644 index 00000000000..fef7b7da6d4 --- /dev/null +++ b/src/guides/v2.4/inventory/inventory-cli-reference.md @@ -0,0 +1,171 @@ +--- +group: inventory +title: Inventory CLI reference +functional_areas: + - Configuration + - System + - Setup +migrated_to: https://experienceleague.adobe.com/docs/commerce-admin/inventory/cli.html +layout: migrated +--- + +{{site.data.var.im}} provides commands to manage inventory data and configuration settings. + +These commands include: + +- Checking and resolving reservation inconsistencies affecting salable quantity +- Adding geocodes for the Distance Priority algorithm + +## Resolve reservations inconsistencies + +[Reservations]({{ page.baseurl }}/inventory/reservations.html) place a salable quantity hold for product SKUs per stock. When you ship, add products, cancel, or refund an order, compensation reservations enter to place or clear these holds. + +{{site.data.var.im}} provides two commands to check and resolve reservation inconsistencies: + +- [`inventory:reservation:list-inconsistencies`](#list-inconsistencies-command) +- [`inventory:reservation:create-compensations`](#create-compensations-command) + +### What causes reservation inconsistencies? + +{{site.data.var.im}} generates reservations for key events: + +- Order placement (initial reservation) +- Order shipment (compensation reservation) +- Refund order or issue a credit memo (compensation reservation) +- Order cancellation (compensation reservation) + +Reservation inconsistencies may occur when {{site.data.var.im}} loses the initial reservation and enters too many reservation compensations (overcompensating and leading to inconsistent amounts), or correctly places the initial reservation but loses compensational reservations. Reservations can be manually reviewed and checked in the `inventory_reservation` table. + +The following configurations and events can cause reservation inconsistencies: + +- **Upgrade Magento to 2.3.x with orders not in a final state (Complete, Canceled, or Closed).** {{site.data.var.im}} will create compensational reservations for these orders, but it will not enter or have the initial reservation that deducts from the salable quantity. We recommend using these commands after upgrading to Magento v2.3.x from 2.1.x or 2.2.x. If you have pending orders, the commands correctly update your salable quantity and reservations for sales and order fulfillment. +- **You do not manage stock then later change this configuration.** You may start using 2.3.x with **Manage Stock** set to "No" in the Magento configuration. Magento does not place reservations at order placement and shipment events. If you later enable the **Manage Stock** configuration and some orders were created at that time, the Salable Qty would be corrupted with compensation reservation when you handle and fulfill that order. +- **You re-assign the Stock for a Website while orders submit to that website**. The initial reservation enters for the initial stock and all compensational reservation enter to the new stock. +- **The sum total of all reservations may not resolve to `0`.** All reservations in the scope of an Order in a final state (Complete, Canceled, Closed) should resolve to `0`, clearing all salable quantity holds. + +### List inconsistencies command + +The `list-inconsistencies` command detects and lists all reservation inconsistencies. Use the command options to check only completed or incomplete orders, or all. + +```bash +bin/magento inventory:reservation:list-inconsistencies +``` + +Command options: + +- `-c`, `--complete-orders` - Returns inconsistencies for completed orders. Incorrect reservations may still be on hold for completed orders. +- `-i`, `--incomplete-orders` - Returns inconsistencies for incomplete orders (partially shipped, unshipped). Incorrect reservations may hold too much or not enough salable quantity for the orders. +- `-b`, `--bunch-size` - Defines how many orders to load at once. +- `-r`, `--raw` - Raw output. + +Responses using `-r` return in `:::` format: + +- Order ID indicates the scope of the inconsistency. +- SKU indicates the product with the inconsistency. +- Quantity sets the amount to enter for the reservation compensation. +- Stock ID defines to scope for stock, which uses the reservations to calculate salable quantity. + +Examples: + +```terminal +bin/magento inventory:reservation:list-inconsistencies + +Inconsistencies found on following entries: +Order 172: +- Product bike-123 should be compensated by +2.000000 for stock 1 +``` + +```terminal +bin/magento inventory:reservation:list-inconsistencies -r + +172:bike-123:+2.000000:1 +``` + +If no issues are found, this message returns: No order inconsistencies were found. + +### Create compensations command + +The `create-compensations` command creates compensation reservations. Depending on the issue, new reservations are created to either place or release a hold on salable quantity. + +To create reservations, provide compensations using the format `:::` such as `172:bike-123:+2.000000:1`. + +```bash +bin/magento inventory:reservation:create-compensations +``` + +Command option: + +- `-r`, `--raw` - Returns raw output. + +If the format of the request is incorrect, the following message displays: + +```terminal +Error while parsing argument "your_incorrect_format_argument". Given argument does not match pattern "/(?P.*):(?P.*):(?P.*):(?P.*)/". +``` + +As the command creates reservations, it displays messages indicating the updates by SKU, order, and stock. + +```terminal +bin/magento inventory:reservation:create-compensations 172:bike-123:+2.000000:1 + +Following reservations were created: +- Product bike-123 was compensated by +2.000000 for stock 1 +``` + +If the SKU for a compensation entry includes spaces, enclose the SKU in quotation marks. + +```bash +bin/magento inventory:reservation:create-compensations 172:"bike 123":+2.000000:1 +``` + +### Detect inconsistencies and create compensations + +You can detect inconsistences and immediately create compensations by using a pipe to run both the `list-inconsistencies` and `create-compensations`. Use the `-r` command option to generate and submit the raw data to `create-compensations`. + +```bash +bin/magento inventory:reservation:list-inconsistencies -r | bin/magento inventory:reservation:create-compensations +``` + +Example response: + +```bash +bin/magento inventory:reservation:list-inconsistencies -r | bin/magento inventory:reservation:create-compensations +``` + +```terminal +Following reservations were created: +- Product bike-123 was compensated by +2.000000 for stock 1 +- Product bikehat-456 was compensated by +1.000000 for stock 1 +``` + +After updates complete, run the list command to verify: + +```bash +bin/magento inventory:reservation:list-inconsistencies -r +``` + +```terminal +No order inconsistencies were found. +``` + +You can also pipe the commands to detect inconsistencies and create compensations for only incomplete (`-i`) or complete (`-c`) orders. + +```bash +bin/magento inventory:reservation:list-inconsistencies -r -i | bin/magento inventory:reservation:create-compensations +``` + +```bash +bin/magento inventory:reservation:list-inconsistencies -r -c | bin/magento inventory:reservation:create-compensations +``` + +## Import geocodes + +{{site.data.var.im}} provides the [Distance Priority](https://docs.magento.com/m2/ce/user_guide/catalog/inventory-configure-distance-priority.html) algorithm, which helps determine the best option for shipping a full or partial order. The algorithm uses GPS information or geocodes to calculate the distance between the source (a warehouse or other physical location) of each item in an order and the shipping address. Based on those results, the algorithm recommends which source should be used to ship out each item in the order. + +The merchant selects the provider of the GPS or geocode data required to calculate distances: + +- **Google MAP** uses [Google Maps Platform](https://cloud.google.com/maps-platform) services to calculate the distance and time between the shipping destination address and source locations. This option requires a Google billing plan and may incur charges through Google. + +- **Offline calculation** calculates the distance using data downloaded from [geonames.org](https://www.geonames.org/) and imported into Magento with a command. This option is free of charge. + +{% include config/cli-inventory.md %} From 957df85380a702d4116d57552e3a5aba73869340 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Wed, 13 Jul 2022 12:38:32 -0500 Subject: [PATCH 287/776] Added migration metadata --- src/guides/v2.3/inventory/reservations.md | 2 ++ src/guides/v2.3/inventory/source-selection-algorithms.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/guides/v2.3/inventory/reservations.md b/src/guides/v2.3/inventory/reservations.md index e5a1ec2500d..926b331a00e 100644 --- a/src/guides/v2.3/inventory/reservations.md +++ b/src/guides/v2.3/inventory/reservations.md @@ -1,6 +1,8 @@ --- group: inventory title: Reservations +migrated_to: https://experienceleague.adobe.com/docs/commerce-admin/inventory/basics/selection-reservations.html +layout: migrated --- Adobe Commerce and Magento Open Source use _reservations_ to calculate and keep track of the salable quantity of each product assigned to a stock. When a customer places an order, the system checks whether the quantity requested for each item is available for sale. If yes, the system creates a reservation as an inventory request for each item, thereby reducing the salable quantity available for purchase. As items are shipped, cancelled or refunded, the system issues additional reservations that compensate the original. A cron job removes the original reservation and all compensatory reservations from the database when all ordered items have been shipped, cancelled, or refunded. diff --git a/src/guides/v2.3/inventory/source-selection-algorithms.md b/src/guides/v2.3/inventory/source-selection-algorithms.md index 4af64e9ec2d..6195457ab1f 100644 --- a/src/guides/v2.3/inventory/source-selection-algorithms.md +++ b/src/guides/v2.3/inventory/source-selection-algorithms.md @@ -1,6 +1,8 @@ --- group: inventory title: Source selection algorithms +migrated_to: https://experienceleague.adobe.com/docs/commerce-admin/inventory/basics/selection-reservations.html +layout: migrated --- The **Source Selection Algorithm (SSA)** recommends how to fulfill partial and full shipments. The merchant decides which business needs take precedence when deciding which shipping method to use: From 3ff7b517cb27d66094d5e0dd1e91a670a4256a85 Mon Sep 17 00:00:00 2001 From: vkolesny Date: Wed, 13 Jul 2022 15:52:09 -0500 Subject: [PATCH 288/776] ACP2E-994: [Documentation] Add notice that Admin, Bearer and other types of tokens are not supported to skip providing of HTTP X-Captcha header. --- src/guides/v2.3/graphql/protected-mutations.md | 10 +++++----- src/guides/v2.3/rest/protected-endpoints.md | 6 +++--- src/guides/v2.4/graphql/protected-mutations.md | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/guides/v2.3/graphql/protected-mutations.md b/src/guides/v2.3/graphql/protected-mutations.md index 4519a7b8096..70703e404a2 100644 --- a/src/guides/v2.3/graphql/protected-mutations.md +++ b/src/guides/v2.3/graphql/protected-mutations.md @@ -5,10 +5,10 @@ title: Protected mutations If CAPTCHA or reCAPTCHA is enabled on pages requiring shopper input, then in most cases, the corresponding mutations that send requests to the Magento server must include an HTTP header that contains a value entered by the shopper (for CAPTCHA) or generated by the Google API (for reCAPTCHA). However, if you specify an integration authorization token in the header of the mutation, then you do not supply a header specific to CAPTCHA or reCAPTCHA. -HTTP `X-Captcha` and `X-ReCaptcha` headers: +The HTTP `X-Captcha` and `X-ReCaptcha` headers: -* Cannot be received by automated script or non-UI API call. They are captured and returned by UI Web form only. -* Are optional in protected mutation API calls with providing **_integration authorization_** tokens only. They cannot be skipped with Admin and Bearer tokens. +* Cannot be received by an automated script or a non-UI API call. They are captured and returned by the UI Web form only. +* Is optional in protected mutation API calls that provide **_integration authorization_** tokens only. It cannot be skipped when you provide an Admin or Bearer token. ## CAPTCHA @@ -39,8 +39,8 @@ Field name | Mutation --- | --- Enable for Customer Login | `generateCustomerToken` Enable for Forgot Password | `changeCustomerPassword` -Enable for Create New Customer Account | `createCustomer`, `createCustomerV2` -Enable for Edit Customer Account | `updateCustomer`, `updateCustomerV2` +Enable for Create New Customer Account | `createCustomer` +Enable for Edit Customer Account | `updateCustomer` Enable for Contact Us | Not applicable Enable for Product Review | `createProductReview` Enable for Newsletter Subscription | `subscribeEmailToNewsletter` diff --git a/src/guides/v2.3/rest/protected-endpoints.md b/src/guides/v2.3/rest/protected-endpoints.md index 25b0220a2f7..a0f931a0711 100644 --- a/src/guides/v2.3/rest/protected-endpoints.md +++ b/src/guides/v2.3/rest/protected-endpoints.md @@ -7,10 +7,10 @@ functional_areas: If CAPTCHA or reCAPTCHA is enabled on pages requiring shopper input, then in most cases, the corresponding endpoints that send requests to the Magento server must include an HTTP header that contains a value entered by the shopper (for CAPTCHA) or generated by the Google API (for reCAPTCHA). However, if you specify an integration authorization token in the header of the endpoint, then you do not supply a header specific to CAPTCHA or reCAPTCHA. -HTTP `X-Captcha` and `X-ReCaptcha` headers: +The HTTP `X-Captcha` and `X-ReCaptcha` headers: -* Cannot be received by automated script or non-UI API call. They are captured and returned by UI Web form only. -* Are optional in protected mutation API calls with providing **_integration authorization_** tokens only. They cannot be skipped with Admin and Bearer tokens. +* Cannot be received by an automated script or a non-UI API call. They are captured and returned by the UI Web form only. +* Is optional in protected mutation API calls that provide **_integration authorization_** tokens only. It cannot be skipped when you provide an Admin or Bearer token. ## CAPTCHA diff --git a/src/guides/v2.4/graphql/protected-mutations.md b/src/guides/v2.4/graphql/protected-mutations.md index 4519a7b8096..30f262aed70 100644 --- a/src/guides/v2.4/graphql/protected-mutations.md +++ b/src/guides/v2.4/graphql/protected-mutations.md @@ -5,10 +5,10 @@ title: Protected mutations If CAPTCHA or reCAPTCHA is enabled on pages requiring shopper input, then in most cases, the corresponding mutations that send requests to the Magento server must include an HTTP header that contains a value entered by the shopper (for CAPTCHA) or generated by the Google API (for reCAPTCHA). However, if you specify an integration authorization token in the header of the mutation, then you do not supply a header specific to CAPTCHA or reCAPTCHA. -HTTP `X-Captcha` and `X-ReCaptcha` headers: +The HTTP `X-Captcha` and `X-ReCaptcha` headers: -* Cannot be received by automated script or non-UI API call. They are captured and returned by UI Web form only. -* Are optional in protected mutation API calls with providing **_integration authorization_** tokens only. They cannot be skipped with Admin and Bearer tokens. +* Cannot be received by an automated script or a non-UI API call. They are captured and returned by the UI Web form only. +* Is optional in protected mutation API calls that provide **_integration authorization_** tokens only. It cannot be skipped when you provide an Admin or Bearer token. ## CAPTCHA From e0cea10690f370a562e5f48c472bc14b0c523ea1 Mon Sep 17 00:00:00 2001 From: vkolesny Date: Wed, 13 Jul 2022 16:50:23 -0500 Subject: [PATCH 289/776] ACP2E-994: [Documentation] Add notice that Admin, Bearer and other types of tokens are not supported to skip providing of HTTP X-Captcha header. --- src/guides/v2.3/graphql/protected-mutations.md | 2 +- src/guides/v2.3/rest/protected-endpoints.md | 2 +- src/guides/v2.4/graphql/protected-mutations.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/guides/v2.3/graphql/protected-mutations.md b/src/guides/v2.3/graphql/protected-mutations.md index 70703e404a2..6a8d9f2e3aa 100644 --- a/src/guides/v2.3/graphql/protected-mutations.md +++ b/src/guides/v2.3/graphql/protected-mutations.md @@ -8,7 +8,7 @@ If CAPTCHA or reCAPTCHA is enabled on pages requiring shopper input, then in mos The HTTP `X-Captcha` and `X-ReCaptcha` headers: * Cannot be received by an automated script or a non-UI API call. They are captured and returned by the UI Web form only. -* Is optional in protected mutation API calls that provide **_integration authorization_** tokens only. It cannot be skipped when you provide an Admin or Bearer token. +* Are optional in protected mutation API calls that provide **_integration authorization_** tokens only. They cannot be skipped when you provide an Admin or Bearer token. ## CAPTCHA diff --git a/src/guides/v2.3/rest/protected-endpoints.md b/src/guides/v2.3/rest/protected-endpoints.md index a0f931a0711..01949db2912 100644 --- a/src/guides/v2.3/rest/protected-endpoints.md +++ b/src/guides/v2.3/rest/protected-endpoints.md @@ -10,7 +10,7 @@ If CAPTCHA or reCAPTCHA is enabled on pages requiring shopper input, then in mos The HTTP `X-Captcha` and `X-ReCaptcha` headers: * Cannot be received by an automated script or a non-UI API call. They are captured and returned by the UI Web form only. -* Is optional in protected mutation API calls that provide **_integration authorization_** tokens only. It cannot be skipped when you provide an Admin or Bearer token. +* Are optional in protected mutation API calls that provide **_integration authorization_** tokens only. They cannot be skipped when you provide an Admin or Bearer token. ## CAPTCHA diff --git a/src/guides/v2.4/graphql/protected-mutations.md b/src/guides/v2.4/graphql/protected-mutations.md index 30f262aed70..cebafe54f0d 100644 --- a/src/guides/v2.4/graphql/protected-mutations.md +++ b/src/guides/v2.4/graphql/protected-mutations.md @@ -8,7 +8,7 @@ If CAPTCHA or reCAPTCHA is enabled on pages requiring shopper input, then in mos The HTTP `X-Captcha` and `X-ReCaptcha` headers: * Cannot be received by an automated script or a non-UI API call. They are captured and returned by the UI Web form only. -* Is optional in protected mutation API calls that provide **_integration authorization_** tokens only. It cannot be skipped when you provide an Admin or Bearer token. +* Are optional in protected mutation API calls that provide **_integration authorization_** tokens only. They cannot be skipped when you provide an Admin or Bearer token. ## CAPTCHA From efe8d4452e6cf00fcf864ee116c04bce9fb6e0b3 Mon Sep 17 00:00:00 2001 From: jhadobe Date: Wed, 13 Jul 2022 17:00:14 -0500 Subject: [PATCH 290/776] Changing migrated to location --- src/guides/v2.3/b2b/company-credit.md | 2 -- src/guides/v2.3/b2b/company.md | 2 -- src/guides/v2.3/b2b/extensions.md | 2 -- src/guides/v2.3/b2b/negotiable-checkout.md | 2 -- src/guides/v2.3/b2b/negotiable-manage.md | 2 -- src/guides/v2.3/b2b/negotiable-quote.md | 2 -- src/guides/v2.3/b2b/negotiable-update.md | 2 -- src/guides/v2.3/b2b/shared-cat-company.md | 2 -- src/guides/v2.3/b2b/shared-cat-product-assign.md | 2 -- .../config-guide/cli/config-cli-subcommands-catalog-sync.md | 2 -- src/guides/v2.3/install-gde/install/cli/dev_downgrade.md | 2 -- src/guides/v2.3/inventory/release-notes.md | 2 -- src/guides/v2.4/b2b/bk-b2b.md | 2 +- src/guides/v2.4/b2b/company-credit.md | 2 +- src/guides/v2.4/b2b/company-object.md | 2 +- src/guides/v2.4/b2b/company-structures.md | 2 +- src/guides/v2.4/b2b/company-users.md | 2 +- src/guides/v2.4/b2b/company.md | 2 +- src/guides/v2.4/b2b/credit-manage.md | 2 +- src/guides/v2.4/b2b/extensions.md | 2 +- src/guides/v2.4/b2b/integrations.md | 2 +- src/guides/v2.4/b2b/negotiable-checkout.md | 2 +- src/guides/v2.4/b2b/negotiable-manage.md | 2 +- src/guides/v2.4/b2b/negotiable-order-workflow.md | 2 +- src/guides/v2.4/b2b/negotiable-quote.md | 2 +- src/guides/v2.4/b2b/negotiable-update.md | 2 +- src/guides/v2.4/b2b/roles.md | 2 +- src/guides/v2.4/b2b/shared-cat-company.md | 2 +- src/guides/v2.4/b2b/shared-cat-manage.md | 2 +- src/guides/v2.4/b2b/shared-cat-product-assign.md | 2 +- src/guides/v2.4/b2b/shared-catalog.md | 2 +- 31 files changed, 19 insertions(+), 43 deletions(-) diff --git a/src/guides/v2.3/b2b/company-credit.md b/src/guides/v2.3/b2b/company-credit.md index 04fff476129..7d070b47479 100644 --- a/src/guides/v2.3/b2b/company-credit.md +++ b/src/guides/v2.3/b2b/company-credit.md @@ -10,8 +10,6 @@ level3_subgroup: credit functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/company-credit -layout: migrated --- Company credit allows company members to purchase items on credit. This is a feature specific to {{site.data.var.b2b}} that is used only for transactions between companies. The seller allocates an amount (or the credit limit) to a company and then company members can purchase items using this amount with the Payment on Account method. The credit amount used by a company is sent to the seller offline. Then the seller creates a Reimburse transaction in the system to adjust the company balance. diff --git a/src/guides/v2.3/b2b/company.md b/src/guides/v2.3/b2b/company.md index 79fd1a634dd..dc8b9e9fdbd 100644 --- a/src/guides/v2.3/b2b/company.md +++ b/src/guides/v2.3/b2b/company.md @@ -10,8 +10,6 @@ level3_subgroup: company functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/company -layout: migrated --- The `Company` module allows multiple buyers that belong to the same company to view product prices and make purchases based on the shared catalog assigned to this company. A company can contain a hierarchy of users and teams, with roles and permissions assigned at any level. diff --git a/src/guides/v2.3/b2b/extensions.md b/src/guides/v2.3/b2b/extensions.md index fcbf6a3f315..d89945a8bb5 100644 --- a/src/guides/v2.3/b2b/extensions.md +++ b/src/guides/v2.3/b2b/extensions.md @@ -8,8 +8,6 @@ menu_node: parent ee_only: True functional_areas: - B2B -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/extensions -layout: migrated --- See [Module Reference Guide]({{ page.baseurl }}/mrg/intro.html) for information about each {{site.data.var.b2b}} module. diff --git a/src/guides/v2.3/b2b/negotiable-checkout.md b/src/guides/v2.3/b2b/negotiable-checkout.md index ae1de8de7cb..b6de9977468 100644 --- a/src/guides/v2.3/b2b/negotiable-checkout.md +++ b/src/guides/v2.3/b2b/negotiable-checkout.md @@ -5,8 +5,6 @@ ee_only: true functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-checkout -layout: migrated --- When the seller and buyer user agree on the quoted products and their prices, the negotiated quote is ready to be converted to an order. diff --git a/src/guides/v2.3/b2b/negotiable-manage.md b/src/guides/v2.3/b2b/negotiable-manage.md index b3efa2e71a5..8df8682327d 100644 --- a/src/guides/v2.3/b2b/negotiable-manage.md +++ b/src/guides/v2.3/b2b/negotiable-manage.md @@ -10,8 +10,6 @@ level3_subgroup: nq functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-manage -layout: migrated --- This topic describes the calls required to initiate a negotiable quote and to prepare it to be converted to an order. diff --git a/src/guides/v2.3/b2b/negotiable-quote.md b/src/guides/v2.3/b2b/negotiable-quote.md index 86b44d955d9..0a5702c4e2b 100644 --- a/src/guides/v2.3/b2b/negotiable-quote.md +++ b/src/guides/v2.3/b2b/negotiable-quote.md @@ -10,8 +10,6 @@ level3_subgroup: nq functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-quote -layout: migrated --- Negotiable quotes are a mechanism that allows a company user (buyer) and a seller (admin user) to negotiate product and/or shipping prices before the company user places an order. Its functionality is available for companies only. diff --git a/src/guides/v2.3/b2b/negotiable-update.md b/src/guides/v2.3/b2b/negotiable-update.md index 2cc92540cca..cb8ea2531bb 100644 --- a/src/guides/v2.3/b2b/negotiable-update.md +++ b/src/guides/v2.3/b2b/negotiable-update.md @@ -5,8 +5,6 @@ ee_only: true functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-update -layout: migrated --- Sellers and buyers can edit a negotiable quote at various times during the quote's lifecycle. Both use the `PUT /V1/negotiableQuote/:quoteId` call to update the quote. This call is defined in the diff --git a/src/guides/v2.3/b2b/shared-cat-company.md b/src/guides/v2.3/b2b/shared-cat-company.md index fcc16ee0bb2..a0610ede008 100644 --- a/src/guides/v2.3/b2b/shared-cat-company.md +++ b/src/guides/v2.3/b2b/shared-cat-company.md @@ -6,8 +6,6 @@ functional_areas: - B2B - Catalog - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/shared-cat-company -layout: migrated --- A shared catalog must be assigned to one or more companies before it can be accessed by the company users. diff --git a/src/guides/v2.3/b2b/shared-cat-product-assign.md b/src/guides/v2.3/b2b/shared-cat-product-assign.md index a7a3e745ab3..f8b227fb756 100644 --- a/src/guides/v2.3/b2b/shared-cat-product-assign.md +++ b/src/guides/v2.3/b2b/shared-cat-product-assign.md @@ -6,8 +6,6 @@ functional_areas: - B2B - Catalog - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/shared-cat-product-assign -layout: migrated --- The shared catalog configuration process includes assigning categories and products to the shared catalog. To assign these items to a shared catalog, the following conditions must be met: diff --git a/src/guides/v2.3/config-guide/cli/config-cli-subcommands-catalog-sync.md b/src/guides/v2.3/config-guide/cli/config-cli-subcommands-catalog-sync.md index 8b3df767d61..6f04777b919 100644 --- a/src/guides/v2.3/config-guide/cli/config-cli-subcommands-catalog-sync.md +++ b/src/guides/v2.3/config-guide/cli/config-cli-subcommands-catalog-sync.md @@ -1,8 +1,6 @@ --- group: configuration-guide title: Catalog Sync -migrated_to: https://experienceleague.adobe.com/docs/commerce-merchant-services/user-guides/catalog-sync.html -layout: migrated --- Adobe Commerce and Magento Open Source compiles catalog data into tables using indexers. This process is automatically [triggered by several events]({{ site.user_guide_url }}/system/index-management-events.html), such as changes to a product's price or inventory levels. To allow some Commerce services to use that catalog data, a catalog sync process runs hourly. The catalog sync process exports product data from the Commerce server to Commerce services, which are deployed as SaaS, on an ongoing basis. For example, the [Product Recommendations]({{ site.user_guide_url }}/marketing/product-recommendations.html) feature needs up-to-date catalog information so that it can accurately return recommendations with correct names, pricing, and availability. Use the command-line interface to trigger the catalog sync and reindex product data for consumption by Commerce services. diff --git a/src/guides/v2.3/install-gde/install/cli/dev_downgrade.md b/src/guides/v2.3/install-gde/install/cli/dev_downgrade.md index 9f4afccffd4..c400519be9c 100644 --- a/src/guides/v2.3/install-gde/install/cli/dev_downgrade.md +++ b/src/guides/v2.3/install-gde/install/cli/dev_downgrade.md @@ -4,8 +4,6 @@ functional_areas: - Install - System - Setup -migrated_to: https://developer.adobe.com/commerce/contributor/guides/install/change-version/ -layout: migrated --- This topic discusses how a contributing developer can change versions of the Magento software after cloning the `develop` branch. This might be necessary to perform some tasks that require a specific Magento version other than `develop`. diff --git a/src/guides/v2.3/inventory/release-notes.md b/src/guides/v2.3/inventory/release-notes.md index e08a1437df9..6b9f7e481c1 100644 --- a/src/guides/v2.3/inventory/release-notes.md +++ b/src/guides/v2.3/inventory/release-notes.md @@ -1,8 +1,6 @@ --- group: inventory title: Release Notes -migrated_to: https://experienceleague.adobe.com/docs/commerce-admin/inventory/release-notes.html -layout: migrated --- **{{site.data.var.im}} (provided by the [Magento Inventory (was MSI)](https://github.com/magento/inventory) project)** is available with {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}} 2.3.x. Merchants can use {{site.data.var.im}} to manage inventory for all product types in a single warehouse and across complex shipping networks. Manage these locations as sources, tracking on-hand inventory quantities per product. Stocks connect these sources with sales channels (websites) to provide an accurate salable quantity, calculating available on-hand products, pending orders (reservations), and configured thresholds. {{site.data.var.im}} also updates order and shipment options, giving you full control over your inventory and deductions at the source level. diff --git a/src/guides/v2.4/b2b/bk-b2b.md b/src/guides/v2.4/b2b/bk-b2b.md index 5755fe09367..3559eb4f7d9 100644 --- a/src/guides/v2.4/b2b/bk-b2b.md +++ b/src/guides/v2.4/b2b/bk-b2b.md @@ -10,7 +10,7 @@ ee_only: True functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/ +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/ layout: migrated --- diff --git a/src/guides/v2.4/b2b/company-credit.md b/src/guides/v2.4/b2b/company-credit.md index 04fff476129..ce7c258dcf8 100644 --- a/src/guides/v2.4/b2b/company-credit.md +++ b/src/guides/v2.4/b2b/company-credit.md @@ -10,7 +10,7 @@ level3_subgroup: credit functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/company-credit +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/company-credit layout: migrated --- diff --git a/src/guides/v2.4/b2b/company-object.md b/src/guides/v2.4/b2b/company-object.md index 62611d24761..d546d293410 100644 --- a/src/guides/v2.4/b2b/company-object.md +++ b/src/guides/v2.4/b2b/company-object.md @@ -10,7 +10,7 @@ level3_subgroup: company functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/company-object +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/company-object layout: migrated --- diff --git a/src/guides/v2.4/b2b/company-structures.md b/src/guides/v2.4/b2b/company-structures.md index a4612f7c37e..00c869acc03 100644 --- a/src/guides/v2.4/b2b/company-structures.md +++ b/src/guides/v2.4/b2b/company-structures.md @@ -5,7 +5,7 @@ ee_only: true functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/company-structures +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/company-structures layout: migrated --- diff --git a/src/guides/v2.4/b2b/company-users.md b/src/guides/v2.4/b2b/company-users.md index fb3d75db647..c8fa1332123 100644 --- a/src/guides/v2.4/b2b/company-users.md +++ b/src/guides/v2.4/b2b/company-users.md @@ -5,7 +5,7 @@ ee_only: true functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/company-users +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/company-users layout: migrated --- diff --git a/src/guides/v2.4/b2b/company.md b/src/guides/v2.4/b2b/company.md index 79fd1a634dd..988e8f59d46 100644 --- a/src/guides/v2.4/b2b/company.md +++ b/src/guides/v2.4/b2b/company.md @@ -10,7 +10,7 @@ level3_subgroup: company functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/company +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/company layout: migrated --- diff --git a/src/guides/v2.4/b2b/credit-manage.md b/src/guides/v2.4/b2b/credit-manage.md index f73e431bfb6..70df140e0db 100644 --- a/src/guides/v2.4/b2b/credit-manage.md +++ b/src/guides/v2.4/b2b/credit-manage.md @@ -5,7 +5,7 @@ ee_only: true functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/credit-manage +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/credit-manage layout: migrated --- diff --git a/src/guides/v2.4/b2b/extensions.md b/src/guides/v2.4/b2b/extensions.md index fcbf6a3f315..3118cbc2793 100644 --- a/src/guides/v2.4/b2b/extensions.md +++ b/src/guides/v2.4/b2b/extensions.md @@ -8,7 +8,7 @@ menu_node: parent ee_only: True functional_areas: - B2B -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/extensions +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/extensions layout: migrated --- diff --git a/src/guides/v2.4/b2b/integrations.md b/src/guides/v2.4/b2b/integrations.md index 37e84cc4d71..881b7d8b58c 100644 --- a/src/guides/v2.4/b2b/integrations.md +++ b/src/guides/v2.4/b2b/integrations.md @@ -9,7 +9,7 @@ ee_only: True functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/integrations +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/integrations layout: migrated --- diff --git a/src/guides/v2.4/b2b/negotiable-checkout.md b/src/guides/v2.4/b2b/negotiable-checkout.md index ae1de8de7cb..8f97747f17f 100644 --- a/src/guides/v2.4/b2b/negotiable-checkout.md +++ b/src/guides/v2.4/b2b/negotiable-checkout.md @@ -5,7 +5,7 @@ ee_only: true functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-checkout +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/negotiable-checkout layout: migrated --- diff --git a/src/guides/v2.4/b2b/negotiable-manage.md b/src/guides/v2.4/b2b/negotiable-manage.md index b3efa2e71a5..15d8085364f 100644 --- a/src/guides/v2.4/b2b/negotiable-manage.md +++ b/src/guides/v2.4/b2b/negotiable-manage.md @@ -10,7 +10,7 @@ level3_subgroup: nq functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-manage +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/negotiable-manage layout: migrated --- diff --git a/src/guides/v2.4/b2b/negotiable-order-workflow.md b/src/guides/v2.4/b2b/negotiable-order-workflow.md index 50fd0990bce..5d4dc9fc83b 100644 --- a/src/guides/v2.4/b2b/negotiable-order-workflow.md +++ b/src/guides/v2.4/b2b/negotiable-order-workflow.md @@ -2,7 +2,7 @@ group: b2b-developer-guide title: Place a negotiable quote order ee_only: true -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-order-workflow +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/negotiable-order-workflow layout: migrated --- diff --git a/src/guides/v2.4/b2b/negotiable-quote.md b/src/guides/v2.4/b2b/negotiable-quote.md index 86b44d955d9..820181da91f 100644 --- a/src/guides/v2.4/b2b/negotiable-quote.md +++ b/src/guides/v2.4/b2b/negotiable-quote.md @@ -10,7 +10,7 @@ level3_subgroup: nq functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-quote +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/negotiable-quote layout: migrated --- diff --git a/src/guides/v2.4/b2b/negotiable-update.md b/src/guides/v2.4/b2b/negotiable-update.md index 2cc92540cca..a9589e93c3d 100644 --- a/src/guides/v2.4/b2b/negotiable-update.md +++ b/src/guides/v2.4/b2b/negotiable-update.md @@ -5,7 +5,7 @@ ee_only: true functional_areas: - B2B - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/negotiable-update +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/negotiable-update layout: migrated --- diff --git a/src/guides/v2.4/b2b/roles.md b/src/guides/v2.4/b2b/roles.md index 2d70ca695be..b19b4415b7b 100644 --- a/src/guides/v2.4/b2b/roles.md +++ b/src/guides/v2.4/b2b/roles.md @@ -5,7 +5,7 @@ menu_title: Manage company roles ee_only: True functional_areas: - B2B -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/roles +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/roles layout: migrated --- diff --git a/src/guides/v2.4/b2b/shared-cat-company.md b/src/guides/v2.4/b2b/shared-cat-company.md index fcc16ee0bb2..7f2c35b3610 100644 --- a/src/guides/v2.4/b2b/shared-cat-company.md +++ b/src/guides/v2.4/b2b/shared-cat-company.md @@ -6,7 +6,7 @@ functional_areas: - B2B - Catalog - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/shared-cat-company +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/shared-cat-company layout: migrated --- diff --git a/src/guides/v2.4/b2b/shared-cat-manage.md b/src/guides/v2.4/b2b/shared-cat-manage.md index 2183da7a4c7..195d57cbfd2 100644 --- a/src/guides/v2.4/b2b/shared-cat-manage.md +++ b/src/guides/v2.4/b2b/shared-cat-manage.md @@ -6,7 +6,7 @@ functional_areas: - B2B - Catalog - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/shared-cat-manage +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/shared-cat-manage layout: migrated --- diff --git a/src/guides/v2.4/b2b/shared-cat-product-assign.md b/src/guides/v2.4/b2b/shared-cat-product-assign.md index a7a3e745ab3..25061a60aac 100644 --- a/src/guides/v2.4/b2b/shared-cat-product-assign.md +++ b/src/guides/v2.4/b2b/shared-cat-product-assign.md @@ -6,7 +6,7 @@ functional_areas: - B2B - Catalog - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/shared-cat-product-assign +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/shared-cat-product-assign layout: migrated --- diff --git a/src/guides/v2.4/b2b/shared-catalog.md b/src/guides/v2.4/b2b/shared-catalog.md index e6cb5a8a9b0..608fc0551cc 100644 --- a/src/guides/v2.4/b2b/shared-catalog.md +++ b/src/guides/v2.4/b2b/shared-catalog.md @@ -11,7 +11,7 @@ functional_areas: - B2B - Catalog - Integration -migrated_to: https://developer.adobe.com/commerce/webapi/rest/modules/b2b/shared-catalog +migrated_to: https://developer.adobe.com/commerce/webapi/rest/b2b/shared-catalog layout: migrated --- From a17cfd737cc8cc00be84a47b4e6bff4768cd3647 Mon Sep 17 00:00:00 2001 From: jhadobe Date: Wed, 13 Jul 2022 17:12:06 -0500 Subject: [PATCH 291/776] Fixing errant changes --- .../config-guide/cli/config-cli-subcommands-catalog-sync.md | 2 ++ src/guides/v2.3/install-gde/install/cli/dev_downgrade.md | 2 ++ src/guides/v2.3/inventory/release-notes.md | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/guides/v2.3/config-guide/cli/config-cli-subcommands-catalog-sync.md b/src/guides/v2.3/config-guide/cli/config-cli-subcommands-catalog-sync.md index 6f04777b919..8b3df767d61 100644 --- a/src/guides/v2.3/config-guide/cli/config-cli-subcommands-catalog-sync.md +++ b/src/guides/v2.3/config-guide/cli/config-cli-subcommands-catalog-sync.md @@ -1,6 +1,8 @@ --- group: configuration-guide title: Catalog Sync +migrated_to: https://experienceleague.adobe.com/docs/commerce-merchant-services/user-guides/catalog-sync.html +layout: migrated --- Adobe Commerce and Magento Open Source compiles catalog data into tables using indexers. This process is automatically [triggered by several events]({{ site.user_guide_url }}/system/index-management-events.html), such as changes to a product's price or inventory levels. To allow some Commerce services to use that catalog data, a catalog sync process runs hourly. The catalog sync process exports product data from the Commerce server to Commerce services, which are deployed as SaaS, on an ongoing basis. For example, the [Product Recommendations]({{ site.user_guide_url }}/marketing/product-recommendations.html) feature needs up-to-date catalog information so that it can accurately return recommendations with correct names, pricing, and availability. Use the command-line interface to trigger the catalog sync and reindex product data for consumption by Commerce services. diff --git a/src/guides/v2.3/install-gde/install/cli/dev_downgrade.md b/src/guides/v2.3/install-gde/install/cli/dev_downgrade.md index c400519be9c..9f4afccffd4 100644 --- a/src/guides/v2.3/install-gde/install/cli/dev_downgrade.md +++ b/src/guides/v2.3/install-gde/install/cli/dev_downgrade.md @@ -4,6 +4,8 @@ functional_areas: - Install - System - Setup +migrated_to: https://developer.adobe.com/commerce/contributor/guides/install/change-version/ +layout: migrated --- This topic discusses how a contributing developer can change versions of the Magento software after cloning the `develop` branch. This might be necessary to perform some tasks that require a specific Magento version other than `develop`. diff --git a/src/guides/v2.3/inventory/release-notes.md b/src/guides/v2.3/inventory/release-notes.md index 6b9f7e481c1..e08a1437df9 100644 --- a/src/guides/v2.3/inventory/release-notes.md +++ b/src/guides/v2.3/inventory/release-notes.md @@ -1,6 +1,8 @@ --- group: inventory title: Release Notes +migrated_to: https://experienceleague.adobe.com/docs/commerce-admin/inventory/release-notes.html +layout: migrated --- **{{site.data.var.im}} (provided by the [Magento Inventory (was MSI)](https://github.com/magento/inventory) project)** is available with {{site.data.var.ce}}, {{site.data.var.ee}}, and {{site.data.var.ece}} 2.3.x. Merchants can use {{site.data.var.im}} to manage inventory for all product types in a single warehouse and across complex shipping networks. Manage these locations as sources, tracking on-hand inventory quantities per product. Stocks connect these sources with sales channels (websites) to provide an accurate salable quantity, calculating available on-hand products, pending orders (reservations), and configured thresholds. {{site.data.var.im}} also updates order and shipment options, giving you full control over your inventory and deductions at the source level. From 7a0310cac3354347d10ada1f7d178e567568673c Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Thu, 14 Jul 2022 07:54:59 -0500 Subject: [PATCH 292/776] Update routes.md --- src/cloud/project/routes.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/cloud/project/routes.md b/src/cloud/project/routes.md index ffa02b2ba2b..be193646fc0 100644 --- a/src/cloud/project/routes.md +++ b/src/cloud/project/routes.md @@ -100,11 +100,24 @@ For example, the `refactorcss` branch for the `mswy7hzcuhcjw` project hosted in ```text https://refactorcss-oy3m2pq-mswy7hzcuhcjw.us.magentosite.cloud/ ``` - {:.no-copy} +{:.no-copy} {:.bs-callout-info} If your Cloud project supports multiple stores, follow the route configuration instructions for [multiple websites or stores]({{ site.baseurl }}/cloud/project/project-multi-sites.html). +### Trailing slash + +Route definitions contain a trailing slash to indicate a folder or directory; however, the same content can be served with or without a trailing slash. The following URLs resolve the same but can be seen as _two different_ URLs: + +```text +https://www.example.com/blog/ + +https://www.example1.com/blog +``` +{:.no-copy} + +It is a best practice to use a trailing slash for directories, but whichever method you choose, it is very important to **stay consistent** to avoid generating two locations. + ## Route protocols All environments support both HTTP and HTTPS automatically. From 1bac1caad37b3628e5e4c5be4d57c88d998f3bfd Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Thu, 14 Jul 2022 08:00:22 -0500 Subject: [PATCH 293/776] typo --- src/cloud/project/routes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cloud/project/routes.md b/src/cloud/project/routes.md index be193646fc0..0d3191dd207 100644 --- a/src/cloud/project/routes.md +++ b/src/cloud/project/routes.md @@ -112,7 +112,7 @@ Route definitions contain a trailing slash to indicate a folder or directory; ho ```text https://www.example.com/blog/ -https://www.example1.com/blog +https://www.example.com/blog ``` {:.no-copy} From b1749486857d46021f8ee9b687980bb8f68fba28 Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Thu, 14 Jul 2022 08:04:17 -0500 Subject: [PATCH 294/776] change to better term --- src/cloud/project/routes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cloud/project/routes.md b/src/cloud/project/routes.md index 0d3191dd207..733b837ad5e 100644 --- a/src/cloud/project/routes.md +++ b/src/cloud/project/routes.md @@ -107,7 +107,7 @@ If your Cloud project supports multiple stores, follow the route configuration i ### Trailing slash -Route definitions contain a trailing slash to indicate a folder or directory; however, the same content can be served with or without a trailing slash. The following URLs resolve the same but can be seen as _two different_ URLs: +Route definitions contain a trailing slash to indicate a folder or directory; however, the same content can be served with or without a trailing slash. The following URLs resolve the same but can be interpreted as _two different_ URLs: ```text https://www.example.com/blog/ From 512b327237362728707df50b59f9aeed299d59cd Mon Sep 17 00:00:00 2001 From: Heather Guthrie Date: Thu, 14 Jul 2022 08:57:50 -0500 Subject: [PATCH 295/776] correct ID reference in integration topic --- src/cloud/integrations/github-integration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cloud/integrations/github-integration.md b/src/cloud/integrations/github-integration.md index 57f963afeb4..2fe5ebae0a4 100644 --- a/src/cloud/integrations/github-integration.md +++ b/src/cloud/integrations/github-integration.md @@ -186,7 +186,7 @@ To remove the GitHub integration: 1. Delete the integration. ```bash - magento-cloud integration:delete + magento-cloud integration:delete ``` Also, you can remove the GitHub integration by logging in to your GitHub account and removing the web hook in the _Webhooks_ tab of the repository _Settings_. From 37fba1e452c892c2f6111d2e9a9203f20bd94fe5 Mon Sep 17 00:00:00 2001 From: Andrew Ortiz Date: Fri, 15 Jul 2022 10:04:10 +0530 Subject: [PATCH 296/776] Fix errant charcter in SPF record example Compare Adobe Commerce docs: https://devdocs.magento.com/cloud/project/sendgrid.html#sender-and-domain-authentication Compare to other docs on this issue ( Sendgrid specific ) https://dmarcly.com/blog/how-to-set-up-spf-and-dkim-for-sendgrid https://mxtoolbox.com/c/outboundemailsources?public=SendGrid SPF in general: https://www.dmarcanalyzer.com/spf/how-to-create-an-spf-txt-record/ --- src/cloud/project/sendgrid.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cloud/project/sendgrid.md b/src/cloud/project/sendgrid.md index 44ea9b0b53d..94fe8be9fbe 100644 --- a/src/cloud/project/sendgrid.md +++ b/src/cloud/project/sendgrid.md @@ -45,7 +45,7 @@ To enable domain authentication: **Example `TXT` record with account ID:** ```text ->v=spf1 include:u17504801.wl.sendgrid.net -all +v=spf1 include:u17504801.wl.sendgrid.net -all ``` **Example `CNAME` records:** From e638327ace544bb10f9e343de77d24c6203c9f63 Mon Sep 17 00:00:00 2001 From: Alexandra Zota Date: Fri, 15 Jul 2022 14:26:24 +0300 Subject: [PATCH 297/776] ACP2E-913: update setBillingAddressOnCart with vat_id input --- src/_includes/graphql/cart-address-input-24.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/_includes/graphql/cart-address-input-24.md b/src/_includes/graphql/cart-address-input-24.md index 04b04bcac68..fd94aa5f4ba 100644 --- a/src/_includes/graphql/cart-address-input-24.md +++ b/src/_includes/graphql/cart-address-input-24.md @@ -11,3 +11,4 @@ Attribute | Data Type | Description `save_in_address_book` | Boolean | Determines whether to save the address in the customer's address book. The default value is true. `street` | [String]! | An array containing the street for the billing or shipping address `telephone` | String | The telephone number for the billing or shipping address +`vat_id` | String | The VAT company identification number for billing or shipping address. \ No newline at end of file From 21db235f8a3a2874fe18d1e51c98adf618572b03 Mon Sep 17 00:00:00 2001 From: Alexandra Zota Date: Fri, 15 Jul 2022 15:14:44 +0300 Subject: [PATCH 298/776] ACP2E-996: update cart discounts section with: All applicable promotions for a requested cart are returned together: Line item discounts Cart rules/discounts Coupons Gift Cards Store Credit --- src/guides/v2.4/graphql/queries/cart.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/guides/v2.4/graphql/queries/cart.md b/src/guides/v2.4/graphql/queries/cart.md index e574c96b197..7f897d9e418 100644 --- a/src/guides/v2.4/graphql/queries/cart.md +++ b/src/guides/v2.4/graphql/queries/cart.md @@ -267,6 +267,9 @@ In this query, the **Buy 3 tee shirts and get the 4th free** cart price rule fro 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. +If other promotions or price adjustments are applied to the cart through either store credit or gift cards, these will reflect under "discounts" with the appropriate label. + + **Request:** ```graphql @@ -332,15 +335,21 @@ The `3T1free` rule is applied first, and Magento returns the price of a single s }, "discounts": [ { - "label": "3T1free", + "label": "Discount (3T1free, 10% Off for New Customers)", + "amount": { + "value": 37.7 + } + }, + { + "label": "Gift Card", "amount": { - "value": 29 + "value": 0.1 } }, { - "label": "10% Off for New Customers", + "label": "Store Credit", "amount": { - "value": 8.7 + "value": 0.1 } } ] From e13bbad8fcd2cb748b7197788dbb754669de5666 Mon Sep 17 00:00:00 2001 From: Alexandra Zota Date: Fri, 15 Jul 2022 16:05:55 +0300 Subject: [PATCH 299/776] ACP2E-996: update cart discounts section with: All applicable promotions for a requested cart are returned together: Line item discounts Cart rules/discounts Coupons Gift Cards Store Credit --- src/guides/v2.4/graphql/queries/cart.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/guides/v2.4/graphql/queries/cart.md b/src/guides/v2.4/graphql/queries/cart.md index 7f897d9e418..08728457953 100644 --- a/src/guides/v2.4/graphql/queries/cart.md +++ b/src/guides/v2.4/graphql/queries/cart.md @@ -269,7 +269,6 @@ The `3T1free` rule is applied first, and Magento returns the price of a single s If other promotions or price adjustments are applied to the cart through either store credit or gift cards, these will reflect under "discounts" with the appropriate label. - **Request:** ```graphql From 829a10bc401a7b45d6ab1fa1aca5d06f08e96b64 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Fri, 15 Jul 2022 09:31:33 -0500 Subject: [PATCH 300/776] Revert 2.3 and apply to 2.4 --- src/guides/v2.3/inventory/reservations.md | 2 - .../inventory/source-selection-algorithms.md | 2 - src/guides/v2.4/inventory/reservations.md | 183 +++++++++++++++- .../inventory/source-selection-algorithms.md | 204 +++++++++++++++++- 4 files changed, 385 insertions(+), 6 deletions(-) mode change 120000 => 100644 src/guides/v2.4/inventory/reservations.md mode change 120000 => 100644 src/guides/v2.4/inventory/source-selection-algorithms.md diff --git a/src/guides/v2.3/inventory/reservations.md b/src/guides/v2.3/inventory/reservations.md index 926b331a00e..e5a1ec2500d 100644 --- a/src/guides/v2.3/inventory/reservations.md +++ b/src/guides/v2.3/inventory/reservations.md @@ -1,8 +1,6 @@ --- group: inventory title: Reservations -migrated_to: https://experienceleague.adobe.com/docs/commerce-admin/inventory/basics/selection-reservations.html -layout: migrated --- Adobe Commerce and Magento Open Source use _reservations_ to calculate and keep track of the salable quantity of each product assigned to a stock. When a customer places an order, the system checks whether the quantity requested for each item is available for sale. If yes, the system creates a reservation as an inventory request for each item, thereby reducing the salable quantity available for purchase. As items are shipped, cancelled or refunded, the system issues additional reservations that compensate the original. A cron job removes the original reservation and all compensatory reservations from the database when all ordered items have been shipped, cancelled, or refunded. diff --git a/src/guides/v2.3/inventory/source-selection-algorithms.md b/src/guides/v2.3/inventory/source-selection-algorithms.md index 6195457ab1f..4af64e9ec2d 100644 --- a/src/guides/v2.3/inventory/source-selection-algorithms.md +++ b/src/guides/v2.3/inventory/source-selection-algorithms.md @@ -1,8 +1,6 @@ --- group: inventory title: Source selection algorithms -migrated_to: https://experienceleague.adobe.com/docs/commerce-admin/inventory/basics/selection-reservations.html -layout: migrated --- The **Source Selection Algorithm (SSA)** recommends how to fulfill partial and full shipments. The merchant decides which business needs take precedence when deciding which shipping method to use: diff --git a/src/guides/v2.4/inventory/reservations.md b/src/guides/v2.4/inventory/reservations.md deleted file mode 120000 index 92a3d53b050..00000000000 --- a/src/guides/v2.4/inventory/reservations.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/inventory/reservations.md \ No newline at end of file diff --git a/src/guides/v2.4/inventory/reservations.md b/src/guides/v2.4/inventory/reservations.md new file mode 100644 index 00000000000..926b331a00e --- /dev/null +++ b/src/guides/v2.4/inventory/reservations.md @@ -0,0 +1,182 @@ +--- +group: inventory +title: Reservations +migrated_to: https://experienceleague.adobe.com/docs/commerce-admin/inventory/basics/selection-reservations.html +layout: migrated +--- + +Adobe Commerce and Magento Open Source use _reservations_ to calculate and keep track of the salable quantity of each product assigned to a stock. When a customer places an order, the system checks whether the quantity requested for each item is available for sale. If yes, the system creates a reservation as an inventory request for each item, thereby reducing the salable quantity available for purchase. As items are shipped, cancelled or refunded, the system issues additional reservations that compensate the original. A cron job removes the original reservation and all compensatory reservations from the database when all ordered items have been shipped, cancelled, or refunded. + +{:.bs-callout-info} +The reservation capability requires the `inventory.reservations.updateSalabilityStatus` message queue consumer to be running at all times. To check if it is running, use the `bin/magento queue:consumers:list` command. If you do not see it in the list, start it: `bin/magento queue:consumers:start inventory.reservations.updateSalabilityStatus`. + +Reservations prevent the merchant from overselling products, even in cases where the latency between order placement and order processing is high. In addition, reservations are append-only operations that help prevent blocking operations and race conditions at the time of checkout. + +## Reservation calculations + +The system creates a reservation for each product when the following events occur: + +* A customer or merchant places an order. +* A customer or merchant fully or partially cancels an order. +* The merchant creates a shipment for a physical product. +* The merchant creates an invoice for a virtual or downloadable product. +* The merchant issues a credit memo. + +Reservations are append-only operations, similar to a log of events. The initial reservation is assigned a negative quantity value. All subsequent reservations created while processing the order are positive values. When the order is complete, the sum of all reservations for the product is 0. + +Before the system can issue a reservation in response to a new order, it determines whether there are enough salable items to fulfill the order. The following quantities factor into the calculation: + +* **StockItem quantity**. The StockItem quantity is the aggregated amount of inventory from all the physical sources for the current sales channel. If the Baltimore source has 20 units of a product, the Austin source has 25 units of the same product, while the Reno source has 10, and all these sources are linked to Stock A, then the StockItem count for thus product is 55 (20 + 25 + 10). (When items are shipped, the Inventory indexer updates the quantities available at each source.) + +* **Outstanding reservations**. The system totals all the initial reservations that have not been compensated. This number will always be negative. If customer A has a reservation for 10 items, and customer B has a reservation 5 for items, then outstanding reservations for the product total -15. + +Therefore, the merchant can fulfill an incoming order as long as the customer orders less than 40 (55 + -15) units. + +When you complete processing an order (Complete, Canceled, Closed), all reservations in the scope of that order should resolve to `0`. This clears all salable quantity holds. + +{:.bs-callout-info} +Backorders (with Out-of-Stock Thresholds) and Notify for Quantity Below Threshold settings also affect the calculation of salable quantities, but they are outside the scope of this topic. For more information about these settings, see [Configuring Inventory Management](https://docs.magento.com/m2/ce/user_guide/catalog/inventory-configure-inventory-management.html) in the _Admin User Guide_. + +## Reservation objects + +A reservation contains the following information: + +Parameter | Data type | Description +--- | --- | --- +`reservation_id` | Integer | A system-generated ID +`stock_id` | Integer | The ID of the stock the product is assigned to +`sku` | String | The SKU of the product +`quantity` | Float | The number of items in this reservation +`metadata` | String | The event type, object type, and object ID for this reservation. For example, `{"event_type":"order_placed","object_type":"order","object_id":"8"}` + +The metadata `event_type` can have the following values: + +* `order_placed` +* `order_canceled` +* `shipment_created` +* `creditmemo_created` +* `invoice_created` + +Currently, the metadata object type must be `order`, and the object ID is the order ID. + +In future releases, it might be possible to create a reservation when a customer adds an item to a shopping cart. Each item could be reserved for a fixed amount of time, such as 15 minutes, allowing the customer to reserve items while continuing to shop. When this type of reservation is enabled, the metadata could contain additional types of information. + +## Reservation lifecycle + +The following example shows the sequence of reservations generated for a simple order. + +1. The customer makes a purchase order for 25 units of product `SKU-1`. The reservation contains the following information: + + ```text + reservation_id = 1 + stock_id = 1 + sku = SKU-1 + quantity = -25 + event_type = order_placed + ``` + +1. The customer sends an invoice for 20 items, essentially canceling 5 of the units ordered. + + ```text + reservation_id = 2 + stock_id = 1 + sku = SKU-1 + quantity = 5 + event_type = order_canceled + ``` + +1. The merchant ships the purchased 20 units. + + ```text + reservation_id = 3 + stock_id = 1 + sku = `SKU-1` + quantity = 20 + event_type = shipment_created + ``` + +The three `quantity` values sum up to 0 (-25 + 5 + 20). Note that the system does not modify any existing reservations. + +## Removing processed reservations + +The `inventory_cleanup_reservations` cron job executes SQL queries to clear the reservation database table. By default, it runs daily at midnight, but you can configure the times and frequency. The cron job runs a script that queries the database to find complete reservation sequences in which the sum of quantity values is 0. When all reservations for a given product that originated on the same day (or other configured time) have been compensated, the cron job deletes the reservations all at once. + +The `inventory_reservations_cleanup` cron job is not the same as the `inventory.reservations.cleanup` message queue consumer. The consumer asynchronously deletes reservations by product SKU after a product has been removed, whereas the cron job clears the entire reservations table. The consumer is required when you enable the [**Synchronize with Catalog**]({{ site.user_guide_url }}/configuration/catalog/inventory.html) stock option in the Admin system configuration. See [Manage message queues]({{ page.baseurl }}/config-guide/mq/manage-message-queues.html). + +Often, all initial reservations produced in a single day cannot compensated that same day. This situation could occur when a customer places an order minutes before the cron job begins or makes the purchase with an offline payment method, such as a bank transfer. The compensated reservation sequences remain in the database until they have all been compensated. This practice does not interfere with reservation calculations, because the total for each reservation is 0. + +{:.bs-callout-info} +{{site.data.var.im}} provides commands to detect and manage reservation inconsistencies. See [Inventory CLI reference]({{page.baseurl}}/inventory/inventory-cli-reference.html). + +## Interfaces and services + +All interfaces and services are defined in the `InventoryReservations` and `InventoryReservationsApi` modules. + +### Data interface + +`ReservationInterface` defines the constants and getter methods required for managing reservations. + +### Reservation services + +When an event such as an order placement, cancellation, refund, or shipment occurs, the Append Reservation Service creates a reservation for each SKU, indicating how many items to add to the salable quantity total. The service guarantees the client does not use the `ReservationAppend` service to update existing reservations. (Reservations are append-only entities.) For example, use the service to check whether the `ReservationId`, which is passed in the scope of `ReservationInterface`, has been nullified. + +```php +interface AppendReservationsInterface +{ + /** + * Append reservations + * + * @param ReservationInterface[] $reservations + * @return void + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\CouldNotSaveException + */ + public function execute(array $reservations): void; +} +``` + +Do NOT use the `AppendReservationsInterface` service directly in the business logic that creates a business event. Instead, use a more high-level service: + +```php +namespace Magento\InventorySalesApi\Api; + +/** + * This service is responsible for creating reservations upon a sale event. + * + * @api + */ +interface PlaceReservationsForSalesEventInterface +{ + /** + * @param \Magento\InventorySalesApi\Api\Data\ItemToSellInterface[] $items + * @param \Magento\InventorySalesApi\Api\Data\SalesChannelInterface $salesChannel + * @param \Magento\InventorySalesApi\Api\Data\SalesEventInterface $salesEvent + * @return void + * + * @throws \Magento\Framework\Exception\LocalizedException + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\CouldNotSaveException + */ + public function execute( + array $items, + \Magento\InventorySalesApi\Api\Data\SalesChannelInterface $salesChannel, + \Magento\InventorySalesApi\Api\Data\SalesEventInterface $salesEvent + ): void; +} +``` + +### Checkout services + +In Inventory Management, a product's `Quantity` value is not static. The salable quantity is now retrieved as a result of a dedicated service call. This differs from the previous `CatalogInventory` implementation, which defined the `Product` `StockItem` interface. (`CatalogInventory` has been deprecated.) + +Use the following dynamic services introduced instead of `StockItem`: + +Interface | Description +--- | --- +`GetProductSalableQtyInterface` | Returns the salable product quantity for the specified stock ID +`IsProductSalableInterface` | Checks whether the product is salable +`IsProductSalableForRequestedQtyInterface` | Checks whether there is enough salable quantity to fulfill an order or place the product into a shopping cart + +## Web API support + +Adobe Commerce and Magento Open Source web APIs (REST and SOAP) impose restrictions for entity interfaces that are outside the scope of reservations. Most notably, Web APIs require getter and setter methods. Because reservations are append-only immutable entities, there are no reservation setter methods. Therefore, reservation Web APIs are not supported. diff --git a/src/guides/v2.4/inventory/source-selection-algorithms.md b/src/guides/v2.4/inventory/source-selection-algorithms.md deleted file mode 120000 index 065e453824a..00000000000 --- a/src/guides/v2.4/inventory/source-selection-algorithms.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/inventory/source-selection-algorithms.md \ No newline at end of file diff --git a/src/guides/v2.4/inventory/source-selection-algorithms.md b/src/guides/v2.4/inventory/source-selection-algorithms.md new file mode 100644 index 00000000000..6195457ab1f --- /dev/null +++ b/src/guides/v2.4/inventory/source-selection-algorithms.md @@ -0,0 +1,203 @@ +--- +group: inventory +title: Source selection algorithms +migrated_to: https://experienceleague.adobe.com/docs/commerce-admin/inventory/basics/selection-reservations.html +layout: migrated +--- + +The **Source Selection Algorithm (SSA)** recommends how to fulfill partial and full shipments. The merchant decides which business needs take precedence when deciding which shipping method to use: + +* Should the products be delivered from the sources designated as having the highest priority? +* Should the total shipment cost be the primary factor in choosing a shipment method? +* Should the shipments originate from the closest source? +* Should the fastest shipping method with the shortest delivery time be used, even if it's not the cheapest? + +Magento provides the following algorithms: + +* Source priority +* Distance priority + +Third party developers can create additional algorithms to help merchants decide which shipping option best meets their needs. + +Magento does not enforce or save the results of SSA recommendations. The recommendations reflect conditions at the moment when the algorithm runs, but conditions change over time. For example, the amount of in-stock products will always fluctuate, and shipping costs might change. The merchant can also modify the recommendations by adjusting quantities for deduction or even by re-assigning the shipment's sources of origin. + +## Source Priority algorithm + +Custom stocks include an assigned list of sources to sell and ship available product inventory through the storefront. This algorithm uses the order of assigned sources in your stock to make recommendations. + +When run, the algorithm: + +* Works through the configured order of sources at the stock level starting at the top +* Skips any disabled sources +* Continues down the list until the order shipment is filled +* Recommends a quantity to ship and source per product based on the order in the list, available quantity, and quantity ordered + +## Distance Priority algorithm + +The Distance Priority algorithm compares the location of the shipping destination address with each source location to determine the closest source to fulfill shipments. The distance may be determined by physical distance or time spent traveling from one location to another, using imported database location data or Google directions (driving, walking, or bicycling). + +You have two options for calculating distance: + +**Google MAP:** Uses Google Maps Platform services to calculate the distance and time between the shipping destination address and source locations. This option uses the source's Latitude and Longitude (GPS coordinates) and may use the street address depending on the computation mode. You must provide a Google API key with Geocoding API and Distance Matrix API enabled. This option requires a Google billing plan and may incur charges through Google. + +**Offline Calculation:** Calculates the distance using downloaded and imported geocodes to determine the closest source to the shipping destination address. The geocodes are derived from the city, state, country, and postal code of both the shipping address and the source. + +To support offline calculations, Magento provides a command that downloads country-specific geocode data from [geonames.org](https://geonames.org) and imports this information into the database. + +We recommend entering full street address and GPS coordinate information in your sources if using the Distance Priority algorithm. Google MAP uses your GPS coordinates and your street address. Offline Calculation uses the city, state, country, and zip codes. + +{% include config/cli-inventory.md %} + +## SSA interfaces + +The source priority algorithm recommends delivering products from sources having the highest priority. The `SourceSelectionServiceInterface` accepts an `InventoryRequestInterface` object, which in turn contains the stock ID and a list of items to be shipped. Each item contains only the SKU and quantity. Other potentially relevant data, such as shipping address, is not included, because the priority algorithm does not need it. + +Additional input data might be needed for more sophisticated algorithms, such as the Distance Priority algorithm. In this case, the algorithm needs the shipping address and all data entered for the source (GPS or full address). That's why `InventoryRequestInterface` implements `ExtensibleDataInterface` interfaces, which can be extended with custom input parameters. + +Currently, Inventory Management deducts stock from the appropriate source after the merchant creates a shipment for an order. However, that's not flexible enough--a developer might want to introduce customizations and launch the SSA when the customer proceeds to checkout. Running the SSA at this point could provide the customer more accurate shipping costs. Note in this case, the `Order` object has not created yet, and the system must instead rely on the `Quote` object. + +Taking into account that there are at least two valid business cases when to launch the SSA, and the data source can be an `Order` or `Quote` object, Inventory Management introduces a new layer of abstraction. The algorithm must use an abstract data container instead of a specific Magento entity. + +Use these interfaces to create your own SSA: + +* [InventoryRequestInterface](https://github.com/magento/inventory/blob/1.1.3/app/code/Magento/InventorySourceSelectionApi/Api/Data/InventoryRequestInterface.php) requests products for a given quantity and stock ID +* [ItemRequestInterface](https://github.com/magento/inventory/blob/1.1.3/app/code/Magento/InventorySourceSelectionApi/Api/Data/ItemRequestInterface.php) represents the requested quantity for a specific SKU +* [SourceSelectionServiceInterface](https://github.com/magento/inventory/blob/1.1.3/app/code/Magento/InventorySourceSelectionApi/Api/SourceSelectionServiceInterface.php) returns the source selection algorithm result for the specified `inventoryRequest` +* [GetSourceSelectionAlgorithmListInterface](https://github.com/magento/inventory/blob/1.1.3/app/code/Magento/InventorySourceSelectionApi/Api/GetSourceSelectionAlgorithmListInterface.php) returns the list of data interfaces that represent registered SSAs +* [SourceSelectionAlgorithmInterface](https://github.com/magento/inventory/blob/1.1.3/app/code/Magento/InventorySourceSelectionApi/Api/Data/SourceSelectionAlgorithmInterface.php) represents a single SSA +* [SourceSelectionInterface](https://github.com/magento/inventory/blob/1.1.3/app/code/Magento/InventorySourceSelectionApi/Model/SourceSelectionInterface.php) returns the SSA result for the specified `inventoryRequest` +* [GetDistanceInterface](https://github.com/magento/inventory/blob/1.1.3/app/code/Magento/InventoryDistanceBasedSourceSelectionApi/Api/GetDistanceInterface.php) - returns the distance between the source and the shipping address in kilometers without specifying the units. To change this behavior, provide your own implementation for `\Magento\InventoryDistanceBasedSourceSelection\Model\DistanceProvider\GoogleMap\GetDistance`. + +## Develop a custom algorithm + +As you develop your custom Source Selection Algorithm, keep these design considerations in mind: + +* Implement `SourceSelectionInterface` +* If your module provides an SSA on quotes, introduce your own `InventoryRequestFactory` +* Register your SSA within a `di.xml` file + +### Implement `SourceSelectionInterface` + +Your SSA must implement `SourceSelectionInterface`, which is shown below: + +```php?start_inline=1 +/** + * Returns source selection algorithm result for given Inventory Request + * Current interface should be implemented in order to add own Source Selection Method + * + * @api + */ +interface SourceSelectionInterface +{ + /** + * @param InventoryRequestInterface $inventoryRequest + * @return SourceSelectionResultInterface + */ + public function execute( + InventoryRequestInterface $inventoryRequest + ): SourceSelectionResultInterface; +} +```` + +For example, the following example defines the `MinimalDeliveryCostAlgorithm` class: + +```php?start_inline=1 +namespace Some\Vendor\Namespace\SourceSelection; + +/** + * Minimal Delivery Cost for Merchant algorithm + * + * @api + */ +class MinimalDeliveryCostAlgorithm implements SourceSelectionInterface +{ + public function execute( + InventoryRequestInterface $inventoryRequest + ): SourceSelectionResultInterface; + { + // TODO: Implement execute() method. + } +} +``` + +### Create a `InventoryRequest` factory for quotes (optional) + +Magento provides the [`InventoryRequestFromOrderFactory`](https://github.com/magento/inventory/blob/1.1.3/app/code/Magento/InventoryShipping/Model/InventoryRequestFromOrderFactory.php), which determines the sources to use to fulfill the order at the time a shipment is created. + +```php?start_inline=1 +class InventoryRequestFromOrderFactory +{ + /** + * @param OrderInterface $order + * @return InventoryRequestInterface + */ + public function create(OrderInterface $order) : InventoryRequestInterface + { + $requestItems = []; + $websiteId = $order->getStore()->getWebsiteId(); + $stockId = (int)$this->stockByWebsiteIdResolver->execute((int)$websiteId)->getStockId(); + /** @var OrderItemInterface|OrderItem $orderItem */ + foreach ($order->getItems() as $orderItem) { + $itemSku = $this->getSkuFromOrderItem->execute($orderItem); + $qtyToDeliver = $orderItem->getQtyToShip(); + //check if order item is not delivered yet + if ($orderItem->isDeleted() + || $orderItem->getParentItemId() + || $this->isZero((float)$qtyToDeliver) + || $orderItem->getIsVirtual() + ) { + continue; + } + $requestItems[] = $this->itemRequestFactory->create([ + 'sku' => $itemSku, + 'qty' => $qtyToDeliver + ]); + } + return $this->inventoryRequestFactory->create([ + 'stockId' => $stockId, + 'items' => $requestItems + ]); + } +} +``` + +To add an SSA at the time of checkout, introduce your own factory that produces an `InventoryRequestInterface` based on a `Quote` object, outlined as follows: + +```php?start_inline=1 +class InventoryRequestFactory +{ + /** + * @param \Magento\Quote\Api\Data\CartInterface $quote + * @return InventoryRequestInterface + */ + public function create(\Magento\Quote\Api\Data\CartInterface $quote) : InventoryRequestInterface + { + // TODO + } +} +``` + +### Configure `di.xml` + +Configure your module's `etc/di.xml` file to register your SSA with `SourceSelectionServiceInterface` and `GetSourceSelectionAlgorithmList`. + +```xml + + + + Some\Vendor\Namespace\SourceSelection\MinimalDeliveryCostAlgorithm + + + + + + + + minimalDeliveryCost + Minimal Delivery Cost + Algorithm that calculates the shipping option with the lowest shipping cost to the merchant. + + + + +``` From 57635110377c589518f58731e22029d1f0fbe306 Mon Sep 17 00:00:00 2001 From: jfrontain Date: Mon, 18 Jul 2022 08:39:09 -0500 Subject: [PATCH 301/776] added GQL highlights --- .../v2.4/release-notes/commerce-2-4-5.md | 32 ++++++++++++++----- .../v2.4/release-notes/open-source-2-4-5.md | 20 ++++++++++-- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/guides/v2.4/release-notes/commerce-2-4-5.md b/src/guides/v2.4/release-notes/commerce-2-4-5.md index 639c547b60f..ef70a13a111 100644 --- a/src/guides/v2.4/release-notes/commerce-2-4-5.md +++ b/src/guides/v2.4/release-notes/commerce-2-4-5.md @@ -135,10 +135,6 @@ This release includes enhancements to the Admin UI that improve the experience o * Screen readers are now informed when a new page loads * Contrast and keyboard accessibility have been improved -### Adobe Sign Extension - -The {{ site.data.var.ee }} checkout workflow now supports the inclusion of an esignature agreement page powered by Adobe Sign. - ### Branding and style changes The Admin has been updated to align with Adobe’s brand strategy. Changes affect headers, footers, data grid color updates, and navigation elements. @@ -147,6 +143,14 @@ The Admin has been updated to align with Adobe’s brand strategy. Changes affec **Reduced eSKU multiplication with Shared Catalogs (Customer Groups)**. The new **Enabled Shared Catalog direct product price assigning** configuration option improves product price indexer performance when enabled. +B2B-related GraphQL performance enhancements: + +* Session class proxies is now used in constructors for classes that depend upon session. Using session proxy delays the lock start time, and can consequently reduce lock duration. + +* Session has been removed from and is not longer stored in `Magento\DirectoryGraphQl\Controller\HttpHeaderProcessor\CurrencyProcessor`. + +* Administrators can now toggle between enabling and disabling session support for GraphQL tasks. + This release includes multiple bug fixes. See [B2B Release Notes]({{page.baseurl}}/release-notes/b2b-release-notes.html). ### Channel Manager @@ -160,13 +164,13 @@ Requests are now automatically synced back to the Walmart Marketplace. ### Google Analytics -See [Migrate from analytics.js to gtag.js (Universal Analytics) ](https://developers.google.com/analytics/devguides/migration/ua/analyticsjs-to-gtagjs​https://support.google.com/google-ads/answer/7548399?hl=en). +Google has updated the tracking and integration mechanisms of AdWords and Analytics in web applications through integration with GTag. This integration of Google functionality into website pages extends opportunities to track and manage content through Google Services. Adobe Commerce has a set of built-in modules including Google AdWords, Analytics, Optimizer, and TagManager that leverage the former API for integration with Google services.  In this release, we have re-implemented this integration using the GTag approach.​ See [Migrate from analytics.js to gtag.js (Universal Analytics) ](https://developers.google.com/analytics/devguides/migration/ua/analyticsjs-to-gtagjs​https://support.google.com/google-ads/answer/7548399?hl=en).​ See [Migrate from analytics.js to gtag.js (Universal Analytics) ](https://developers.google.com/analytics/devguides/migration/ua/analyticsjs-to-gtagjs​https://support.google.com/google-ads/answer/7548399?hl=en). ### GraphQL GraphQL performance enhancements include: -* **Optimized creation of unified GraphQL schemas**. Rebuilding a GraphQL schema after flushing a Commerce instance’s cache can consume many resources, particularly during heavy site traffic. The time required to rebuild a schema has been reduced significantly. +* **Optimized creation of unified GraphQL schemas**. Shoppers and administrators no longer experience decreased product performance when a merchant rebuilds their GraphQL schema. Previously, page load speeds were significantly increased when the GraphQL schema was rebuilt. The number and size of files that are required to rebuild the GraphQL schema has been reduced, which lessens the load on {{ site.data.var.ee }}. * **Improved authorization processing** through the use of JSON Web Tokens (JWT) and session-less GraphQL API. @@ -196,11 +200,13 @@ For information about enhancements and bug fixes, see [PWA Studio releases](http #### Braintree -Braintree has discontinued the KOUNT integration and it has been removed from the codebase. +* Braintree has discontinued the KOUNT fraud protection integration. It has been removed from the {{ site.data.var.ee }} codebase. + +* The **Always request 3DS** option has been added to the Admin. ### Live Search -This release introduces support for B2B customer groups and custom pricing. +This release introduces support for B2B customer groups and custom pricing. Livesearch now respects product assignments to customer groups and the pricing that is set for a specific customer group/shared catalog. ### Page Builder @@ -922,6 +928,10 @@ We are fixing hundreds of issues in the {{ site.data.var.ee }} 2.4.5 core code. * `indexer:reset` has been refactored to call `$indexer->invalidate()`. [GitHub-34988](https://github.com/magento/magento2/issues/34988) + + +* You can now use use the colon symbol in an `htmlClass` attribute value, which supports the use of additional components such as the Tailwind UI. [GitHub-34430](https://github.com/magento/magento2/issues/34430) + ### Logging @@ -1017,6 +1027,12 @@ Repetitive actions have been replaced with action groups in these tests: * The `cart` query no longer returns all active payment methods for free orders. [GitHub-34036](https://github.com/magento/magento2/issues/34036) +#### Braintree + + + +* Merchants can now submit a partial refund for orders paid with Apple Pay through Braintree. This was a known issue in {{ site.data.var.ee }} 2.4.4. + #### PayPal diff --git a/src/guides/v2.4/release-notes/open-source-2-4-5.md b/src/guides/v2.4/release-notes/open-source-2-4-5.md index 44a09fa18fa..81ccb59e9b3 100644 --- a/src/guides/v2.4/release-notes/open-source-2-4-5.md +++ b/src/guides/v2.4/release-notes/open-source-2-4-5.md @@ -117,11 +117,14 @@ The `laminas/laminas-session`, `laminas/laminas-text`, and `laminas/laminas-view * The `jarallax.js` and `jaralax-video.js` libraries have been updated to use the latest version of the Vimeo REST API. +### Google Analytics + +Google has updated the tracking and integration mechanisms of AdWords and Analytics in web applications through integration with GTag. This integration of Google functionality into website pages extends opportunities to track and manage content through Google Services. Adobe Commerce has a set of built-in modules including Google AdWords, Analytics, Optimizer, and TagManager that leverage the former API for integration with Google services.  In this release, we have re-implemented this integration using the GTag approach.​ See [Migrate from analytics.js to gtag.js (Universal Analytics) ](https://developers.google.com/analytics/devguides/migration/ua/analyticsjs-to-gtagjs​https://support.google.com/google-ads/answer/7548399?hl=en).​ See [Migrate from analytics.js to gtag.js (Universal Analytics) ](https://developers.google.com/analytics/devguides/migration/ua/analyticsjs-to-gtagjs​https://support.google.com/google-ads/answer/7548399?hl=en). ### GraphQL GraphQL performance enhancements include: -* **Optimized creation of unified GraphQL schemas**. Rebuilding a GraphQL schema after flushing a Commerce instance’s cache can consume many resources, particularly during heavy site traffic. The time required to rebuild a schema has been reduced significantly. +* **Optimized creation of unified GraphQL schemas**. Shoppers and administrators no longer experience decreased product performance when a merchant rebuilds their GraphQL schema. Previously, page load speeds were significantly increased when the GraphQL schema was rebuilt. The number and size of files that are required to rebuild the GraphQL schema has been reduced, which lessens the load on {{ site.data.var.ee }}. * **Improved authorization processing** through the use of JSON Web Tokens (JWT) and session-less GraphQL API. @@ -160,7 +163,10 @@ For information about enhancements and bug fixes, see [PWA Studio releases](http #### Braintree -Braintree has discontinued the KOUNT integration and it has been removed from the codebase. +* Braintree has discontinued the KOUNT fraud protection integration. It has been removed from the {{ site.data.var.ee }} codebase. + +* The **Always request 3DS** option has been added to the Admin. + ### Accessibility updates This release includes enhancements to the Admin UI that improve the experience of users with vision limitations and increase conformance to standard accessibility guidelines. These enhancements include: @@ -824,6 +830,10 @@ We are fixing hundreds of issues in the {{ site.data.var.ce }} 2.4.5 core code. * `indexer:reset` has been refactored to call `$indexer->invalidate()`. [GitHub-34988](https://github.com/magento/magento2/issues/34988) + + +* You can now use use the colon symbol in an `htmlClass` attribute value, which supports the use of additional components such as the Tailwind UI. [GitHub-34430](https://github.com/magento/magento2/issues/34430) + ### Logging @@ -910,6 +920,12 @@ Repetitive actions have been replaced with action groups in these tests: * The `cart` query no longer returns all active payment methods for free orders. [GitHub-34036](https://github.com/magento/magento2/issues/34036) +#### Braintree + + + +* Merchants can now submit a partial refund for orders paid with Apple Pay through Braintree. This was a known issue in {{ site.data.var.ee }} 2.4.4. + #### PayPal From 0963e1e64740d31f5d0f63b13992e69441bdaac9 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Mon, 18 Jul 2022 09:26:57 -0500 Subject: [PATCH 302/776] Reverted e638327 --- src/_includes/graphql/cart-address-input-24.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/_includes/graphql/cart-address-input-24.md b/src/_includes/graphql/cart-address-input-24.md index fd94aa5f4ba..3ca6c4629e5 100644 --- a/src/_includes/graphql/cart-address-input-24.md +++ b/src/_includes/graphql/cart-address-input-24.md @@ -10,5 +10,4 @@ Attribute | Data Type | Description `region_id` | Int | The unique ID that identifies the region for the billing or shipping address `save_in_address_book` | Boolean | Determines whether to save the address in the customer's address book. The default value is true. `street` | [String]! | An array containing the street for the billing or shipping address -`telephone` | String | The telephone number for the billing or shipping address -`vat_id` | String | The VAT company identification number for billing or shipping address. \ No newline at end of file +`telephone` | String | The telephone number for the billing or shipping address \ No newline at end of file From b638850721083b10fc24f685190a7b1f116a4a81 Mon Sep 17 00:00:00 2001 From: magedocs Date: Mon, 18 Jul 2022 14:41:59 +0000 Subject: [PATCH 303/776] Update News data --- src/_data/whats-new.yml | 59 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/src/_data/whats-new.yml b/src/_data/whats-new.yml index 911026fb232..4660beedce0 100644 --- a/src/_data/whats-new.yml +++ b/src/_data/whats-new.yml @@ -4,8 +4,65 @@ description: This page contains recent changes that we think you'd like to know We exclude from this list proofreading, spelling checks, and all minor updates. link: "/whats-new.html" thread: "/whatsnew-feed.xml" -updated: Mon Jul 4 14:38:45 2022 +updated: Mon Jul 18 14:41:56 2022 entries: +- description: The [Reservations](https://devdocs.magento.com/guides/v2.4/inventory/reservations.html), + [Source selection algorithms](https://devdocs.magento.com/guides/v2.4/inventory/source-selection-algorithms.html), + and [CLI reference](https://devdocs.magento.com/guides/v2.4/inventory/inventory-cli-reference.html) + Inventory Management topics moved to Experience League and will be redirected + soon. + versions: 2.4.x + type: Major Update + date: July 15, 2022 + link: https://github.com/magento-commerce/devdocs/pull/3050 + merge_commit: 8a4022b1e00f636a69c27a04688e9da4812b8d2f + contributor: jeff-matthews + membership: true + labels: + - Major Update + - 2.4.x + - migration +- description: Added clarification of the usage of the HTTP `X-Captcha` and `X-ReCaptcha` + headers in conjunction with integration, admin, and customer authentication tokens + for [REST](https://developer.adobe.com/commerce/webapi/rest/use-rest/protected-endpoints/) + and [GraphQL](https://devdocs.magento.com/guides/v2.4/graphql/protected-mutations.html). + versions: '' + type: Technical + date: July 14, 2022 + link: https://github.com/magento-commerce/devdocs/pull/3042 + merge_commit: 985853f7de2777e5ff07357ff328e8fd9a110279 + contributor: vkolesny + membership: true + labels: + - Technical +- description: The [B2B Developer Guide](https://devdocs.magento.com/guides/v2.4/b2b/bk-b2b.html) + has moved to the [Adobe Developer documentation](https://developer-stage.adobe.com/commerce/webapi/rest/b2b/) + and will be redirected soon. + versions: 2.4.x + type: Major Update + date: July 14, 2022 + link: https://github.com/magento-commerce/devdocs/pull/3051 + merge_commit: 0a7d1a19aa8a120aa223fed925843f0dadfd5ab6 + contributor: jhadobe + membership: true + labels: + - Major Update + - 2.4.x + - migration +- description: The [Inventory Management overview](https://devdocs.magento.com/guides/v2.4/inventory/index.html) + topic moved to the [Adobe Developer documentation](https://developer-stage.adobe.com/commerce/webapi/rest/modules/inventory/) + and will be redirected soon. + versions: 2.4.x + type: Major Update + date: July 12, 2022 + link: https://github.com/magento-commerce/devdocs/pull/3046 + merge_commit: 4dafc641eaa077d2752e4e2295cb664c81aa7691 + contributor: jeff-matthews + membership: true + labels: + - Major Update + - 2.4.x + - migration - description: Published [release notes](https://devdocs.magento.com/quality-patches/release-notes.html) for the 1.1.16 Quality Patches Tool (QPT) package release. versions: 2.3.x, 2.4.x From 36b567cf34cb22860e6cf86553978b5b4dc6b872 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Mon, 18 Jul 2022 11:24:56 -0500 Subject: [PATCH 304/776] Replaced symlinks w/ files --- .../bk-javascript-dev-guide.md | 49 +- .../javascript-dev-guide/conventions_js.md | 29 +- .../javascript/custom_js.md | 156 ++++- .../javascript/js-resources.md | 232 ++++++- .../javascript/js_debug.md | 71 +- .../javascript/js_init.md | 278 +++++++- .../javascript/js_logger.md | 277 +++++++- .../javascript/js_mixins.md | 249 ++++++- .../javascript/js_overview.md | 35 +- .../javascript/js_practice.md | 141 +++- .../javascript/product-frontend-storage.md | 201 +++++- .../javascript/requirejs.md | 185 ++++- .../widgets/jquery-widgets-about.md | 78 ++- .../widgets/widget-breadcrumbs.md | 152 ++++- .../widgets/widget-folder-tree.md | 158 ++++- .../widgets/widget-media-uploader.md | 137 +++- .../widgets/widget-multiselect.md | 265 +++++++- .../widgets/widget-popup-window.md | 222 +++++- .../widgets/widget-remaining-characters.md | 151 ++++- .../widgets/widget-row-builder.md | 353 +++++++++- .../widgets/widget-sortable.md | 128 +++- .../widgets/widget-trim-input.md | 58 +- .../widgets/widget_accordion.md | 279 +++++++- .../widgets/widget_alert.md | 267 +++++++- .../widgets/widget_collapsible.md | 584 +++++++++++++++- .../widgets/widget_confirm.md | 269 +++++++- .../widgets/widget_dialog.md | 256 ++++++- .../widgets/widget_dropdown.md | 212 +++++- .../widgets/widget_gallery.md | 635 +++++++++++++++++- .../widgets/widget_gallery_mg.md | 130 +++- .../widgets/widget_list.md | 133 +++- .../widgets/widget_loader.md | 176 ++++- .../widgets/widget_menu.md | 133 +++- .../widgets/widget_modal.md | 440 +++++++++++- .../widgets/widget_navigation.md | 86 ++- .../widget_password_strength_indicator.md | 153 ++++- .../widgets/widget_prompt.md | 314 ++++++++- .../widgets/widget_quickSearch.md | 182 ++++- .../widgets/widget_redirectUrl.md | 85 ++- .../widgets/widget_sticky.md | 123 +++- .../widgets/widget_tabs.md | 302 ++++++++- .../widgets/widget_toggle.md | 146 +++- 42 files changed, 8468 insertions(+), 42 deletions(-) mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/bk-javascript-dev-guide.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/conventions_js.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/javascript/custom_js.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/javascript/js-resources.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/javascript/js_debug.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/javascript/js_init.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/javascript/js_logger.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/javascript/js_mixins.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/javascript/js_overview.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/javascript/js_practice.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/javascript/product-frontend-storage.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/javascript/requirejs.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/jquery-widgets-about.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget-breadcrumbs.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget-folder-tree.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget-media-uploader.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget-multiselect.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget-popup-window.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget-remaining-characters.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget-row-builder.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget-sortable.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget-trim-input.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_accordion.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_alert.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_collapsible.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_confirm.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_dialog.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_dropdown.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_gallery.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_gallery_mg.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_list.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_loader.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_menu.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_modal.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_navigation.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_password_strength_indicator.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_prompt.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_quickSearch.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_redirectUrl.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_sticky.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_tabs.md mode change 120000 => 100644 src/guides/v2.4/javascript-dev-guide/widgets/widget_toggle.md diff --git a/src/guides/v2.4/javascript-dev-guide/bk-javascript-dev-guide.md b/src/guides/v2.4/javascript-dev-guide/bk-javascript-dev-guide.md deleted file mode 120000 index 6700a6091cc..00000000000 --- a/src/guides/v2.4/javascript-dev-guide/bk-javascript-dev-guide.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/javascript-dev-guide/bk-javascript-dev-guide.md \ No newline at end of file diff --git a/src/guides/v2.4/javascript-dev-guide/bk-javascript-dev-guide.md b/src/guides/v2.4/javascript-dev-guide/bk-javascript-dev-guide.md new file mode 100644 index 00000000000..b0c10891cfe --- /dev/null +++ b/src/guides/v2.4/javascript-dev-guide/bk-javascript-dev-guide.md @@ -0,0 +1,48 @@ +--- +group: javascript-developer-guide +title: JavaScript Developer Guide +landing-page: JavaScript Developer Guide +--- + +## Introduction {#overview-introduction} + +By default, the Magento application uses the [RequireJS file and module loader] to optimize the time of loading pages with included JavaScript files, and to manage dependencies of JavaScript resources. + +For information about how JS resources are located and configured, see the [JavaScript resources] topic in the Configuration Guide. + +## What's in this guide {#js_contents} + +Topics of this book describe the following: + +- [JavaScript initialization] - how to initialize JavaScript components and widgets in JavaScript files and `.phtml` templates +- [Use custom JavaScript] - how to extend or replace default JavaScript components/widgets. +- [Locate JavaScript] components - how to define which components (scripts) are used on a particular store page. +- [Magento jQuery widgets] - Magento jQuery widget API documentation. +- [Customizing JavaScript illustration] - practical illustration of custom widgets related tasks. + +JavaScript automatic testing is described in a separate [JavaScript unit testing] topic. + +## Terms used {#js_terms} + +| Term | Description | +| ------------------------------------- |--------------------------------------------------- | +| *JavaScript component (JS component)* | Any separate `.js` file decorated as [AMD module]. | +| *Ui component* | JS component located in the `Magento_Ui` module, in the [app/code/Magento/Ui/view] directory, or JS component that extends files from this module. | +| *jQuery UI widget* | A JS component/widget provided by the [jQuery UI library used in Magento]. | +| *jQuery widget* | Custom widget created using jQuery UI Widget Factory and decorated as AMD module. Many Magento JS components are the jQuery widgets. | + +[AMD module]: http://requirejs.org/docs/whyamd.html#amd +[`Magento_Ui`]: {{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Ui +[app/code/Magento/Ui/view]: {{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Ui/view +[jQuery UI library used in Magento]: {{ site.mage2bloburl }}/{{ page.guide_version }}/lib/web/jquery/jquery-ui-1.9.2.js +[jQuery Widget]: https://jqueryui.com/widget/ + +[RequireJS file and module loader]: http://requirejs.org/ +[JavaScript resources]: {{page.baseurl}}/javascript-dev-guide/javascript/js-resources.html + +[JavaScript initialization]: {{page.baseurl}}/javascript-dev-guide/javascript/js_init.html +[Use custom JavaScript]: {{page.baseurl}}/javascript-dev-guide/javascript/custom_js.html +[Locate JavaScript]: {{page.baseurl}}/javascript-dev-guide/javascript/js_debug.html +[Magento jQuery widgets]: {{page.baseurl}}/javascript-dev-guide/widgets/jquery-widgets-about.html +[Customizing JavaScript illustration]: {{page.baseurl}}/javascript-dev-guide/javascript/js_practice.html +[JavaScript unit testing]: {{page.baseurl}}/test/js/jasmine.html diff --git a/src/guides/v2.4/javascript-dev-guide/conventions_js.md b/src/guides/v2.4/javascript-dev-guide/conventions_js.md deleted file mode 120000 index 295f3fad30c..00000000000 --- a/src/guides/v2.4/javascript-dev-guide/conventions_js.md +++ /dev/null @@ -1 +0,0 @@ -../../v2.3/javascript-dev-guide/conventions_js.md \ No newline at end of file diff --git a/src/guides/v2.4/javascript-dev-guide/conventions_js.md b/src/guides/v2.4/javascript-dev-guide/conventions_js.md new file mode 100644 index 00000000000..f5e2b61932c --- /dev/null +++ b/src/guides/v2.4/javascript-dev-guide/conventions_js.md @@ -0,0 +1,28 @@ +--- +group: javascript-developer-guide +title: Conventional notations used in this Guide +--- + +## Conventional notations for paths to modules and themes + +Magento application components, including modules, themes, and language packages technically can be located anywhere under the Magento root directory. This refers to both Magento default and custom components. + +The following relative paths are used for modules and themes: + +**- ``:** + +[Theme](https://glossary.magento.com/theme) directory. Usually used when talking about custom themes, or any theme in general. + +For Magento out of the box [frontend](https://glossary.magento.com/frontend) themes, usually one of the following: + +- `app/design/frontend//` +- `vendor/magento/theme-frontend-` + +**- ``:** + +Module directory. When talking about a particular Magento module, also notation similar to the following is used: `` + +For Magento modules, the absolute path is usually one of the following: + +- `app/code//` +- `vendor/magento/module--` diff --git a/src/guides/v2.4/javascript-dev-guide/javascript/custom_js.md b/src/guides/v2.4/javascript-dev-guide/javascript/custom_js.md deleted file mode 120000 index a723830c445..00000000000 --- a/src/guides/v2.4/javascript-dev-guide/javascript/custom_js.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/javascript-dev-guide/javascript/custom_js.md \ No newline at end of file diff --git a/src/guides/v2.4/javascript-dev-guide/javascript/custom_js.md b/src/guides/v2.4/javascript-dev-guide/javascript/custom_js.md new file mode 100644 index 00000000000..b7fb83927fc --- /dev/null +++ b/src/guides/v2.4/javascript-dev-guide/javascript/custom_js.md @@ -0,0 +1,155 @@ +--- +group: javascript-developer-guide +title: Use custom JavaScript +--- + +This topic discusses how to use custom [JavaScript](https://glossary.magento.com/javascript) components with the components provided by Magento or custom replacement implementations. + +We strongly recommend that you do not change the source code of default Magento components and widgets. All customizations must be implemented in custom modules or themes. + +## Add a custom JS component {#custom_js_overview} + +To add a custom JS component (module), take the following steps: + +1. Place the custom component source file in one of the following locations: + - Your theme JS files: `/web/js` or `/_/web/js`. In this case the component is available in your theme and its [child themes]({{ page.baseurl }}/frontend-dev-guide/themes/theme-inherit.html). + - Your module view JS files: `/view/frontend/web/js`. In this case, the component is available in all modules and themes (if your module is enabled). + +1. Optionally, in the corresponding [module](https://glossary.magento.com/module) or theme, create a `requirejs-config.js` configuration file, if it does not yet exist there and set path for your resource. The RequireJS configuration file can be placed in one of the following locations: + + - Your theme: `` + - Module within your theme: `/` + - Your module (depending on the needed area - **base**, **frontend**, **adminhtml**): `/view/` + +## Replace a default JS component {#js_replace} + +To use a custom implementation of an existing Magento JS component: + +Place the custom component source file in one of the following locations: + +- Your theme JS files: `/web/js` +- Your module view JS files: `/view/frontend/web/js` + +Create a RequireJS configuration file `requirejs-config.js`, having specified the following: + +```javascript +var config = { + "map": { + "*": { + "": "" + } + } +}; +``` + +- ``: the name of the default component you replace +- ``: the name of the custom component + +For example, if you want to use a custom `navigation-menu.js` script instead of the default menu widgets, your `requirejs-config.js` should contain the following: + +```javascript +var config = { + "map": { + "*": { + "menu": "js/navigation-menu", + "mage/backend/menu": "js/navigation-menu" + } + } +}; +``` + +Place your `requirejs-config.js` file in one of the following directories (according to the location of your custom script, see step 1 of this procedure): + +- Your [theme](https://glossary.magento.com/theme) files: `` +- Your module view files: `/view/frontend` + +This way, your custom JS component is used instead of the [Magento component](https://glossary.magento.com/magento-component) in all entries all over the [frontend](https://glossary.magento.com/frontend) area. + +## Extend a default JS component {#extend_js} + +You can add a custom JS component/widget, which will extend a default Magento component/widget. + +### Extend Magento widget {#extend_js_widget} + +To extend a default Magento [jQuery](https://glossary.magento.com/jquery) widget, create `.js` with contents similar to the following: + +```javascript +define([ + 'jquery', + 'jquery-ui-modules/widget', // use individual jQuery UI component if your widget is for frontend or base areas + // 'jquery/ui', // use all 'jquery/ui' library if your widget is for adminhtml area + 'mage/' // usually widget can be found in /lib/web/mage dir +], function($){ + + $.widget('.', $.mage., { ... }); + + return $..; +}); +``` + +Where the following notation is used: + +- `.` - the name of your custom [widget](https://glossary.magento.com/widget). According to the jQuery widgets naming convention, this value must contain a [namespace](https://glossary.magento.com/namespace) and name. +- `mage.` - the name of the Magento widget that you extend. + +{:.bs-callout-info} +When using custom JS, try to keep dependencies to a minimum. Additional dependencies demand more web requests, which can slow rendering. + +{:.bs-callout-tip} +All jQuery UI components for frontend and base areas are located in `lib/web/jquery/ui-modules` dir. They can be used in JS widgets by `jquery-ui-modules` path mapping like `jquery-ui-modules/widget` and `jquery-ui-modules/slider`. +Using individual jQuery UI components instead of the monolithic jQuery UI library improves storefront performance. + +For information about initializing your custom widget in a `.phtml` template, see the [JavaScript initialization]({{ page.baseurl }}/javascript-dev-guide/javascript/js_init.html) topic. + +### Extend a default Ui component {#extend_js_component} + +To extend a default JS Ui component, your custom script must contain the following: + +```javascript +define([ + '' +], function(){ + + return .extend({ + + defaults: { ... }, // properties with default values + ... // methods of your component + }); +}); +``` + +Where the following notation is used: + +- ``: path to the default component that you extend +- ``: variable containing the default component that you extend + +For example, `Filters.js` script extends the default `filters.js`: + +```javascript +define([ + 'Magento_Ui/js/grid/filters/filters' +], function(Filters){ + + return Filters.extend({ + + defaults: { ... }, // properties with default values + ... // methods of your component + }); +}); +``` + +For information about initializing your custom JS component in a `.phtml` template, see the [JavaScript initialization]({{ page.baseurl }}/javascript-dev-guide/javascript/js_init.html) topic. + +If you need to enable the loading of default Magento JS components and widget initialization on a certain stage, add the following code in your JS script: + +```javascript +$(mage.apply); +``` + +{:.ref-header} +Related topics + +- [JavaScript resources in Magento]({{ page.baseurl }}/javascript-dev-guide/javascript/js-resources.html) +- [About AMD modules and RequireJS]({{ page.baseurl }}/javascript-dev-guide/javascript/js-resources.html) +- [JavaScript initialization]({{page.baseurl}}/javascript-dev-guide/javascript/js_init.html) +- [Advanced JavaScript bundling]({{page.baseurl}}/performance-best-practices/advanced-js-bundling.html) diff --git a/src/guides/v2.4/javascript-dev-guide/javascript/js-resources.md b/src/guides/v2.4/javascript-dev-guide/javascript/js-resources.md deleted file mode 120000 index 36a2cbdc893..00000000000 --- a/src/guides/v2.4/javascript-dev-guide/javascript/js-resources.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/javascript-dev-guide/javascript/js-resources.md \ No newline at end of file diff --git a/src/guides/v2.4/javascript-dev-guide/javascript/js-resources.md b/src/guides/v2.4/javascript-dev-guide/javascript/js-resources.md new file mode 100644 index 00000000000..c6556f88b15 --- /dev/null +++ b/src/guides/v2.4/javascript-dev-guide/javascript/js-resources.md @@ -0,0 +1,231 @@ +--- +group: javascript-developer-guide +subgroup: 1_Javascript +title: JavaScript resources in Commerce +--- + +## Overview {#m2devgde-js-resources-intro} + +This topic describes general concepts of how [JavaScript](https://glossary.magento.com/javascript) (JS) components are organized in Magento. + +To address the problem of slow page loads, we exclude JavaScript from the page headers and we added the ability to use the [RequireJS library](http://requirejs.org). + +RequireJS improves the perceived page load time because it allows JavaScript to load in the background; in particular, it enables asynchronous JavaScript loading. + +## Explore JavaScript resources {#m2devgde-js-resources-configuring} + +### JS resources location + +In Magento, you can find Javascript components on the following levels: + +* [Library](https://glossary.magento.com/library) level (`lib/web`). Resources located here are available in any place within Magento. +* Module level (`/view//web`). If the [module](https://glossary.magento.com/module) is enabled, resources added here are available in other modules and themes. +* Theme level, for a particular module (`/_/web`). Resources added here are available for [inheriting] themes. +* Theme level (`/web`). Resources added here are available for [inheriting]({{ page.baseurl }}/frontend-dev-guide/themes/theme-inherit.html) themes. + +{:.bs-callout-info} +The library level can only contain core Magento resources. Do not put custom JS files in the \`lib/web\` directory. + +### Specifying JS + +We recommend specifying JavaScript resources in the templates rather than in the [layout](https://glossary.magento.com/layout) updates, to ensure that the resources are available for body of a page. + +## Accessing JS resources + +JS resources are accessed using relative paths. + +**Example 1:** + +* File actual location: `app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js` +* File published to `pub/static`: `pub/static/frontend////Magento_ConfigurableProduct/js/configurable.js`. Here `` and `` are the currently applied in your instance [theme](https://glossary.magento.com/theme) and [locale](https://glossary.magento.com/locale). +* Called in script: + + ```javascript + require(["Magento_ConfigurableProduct/js/configurable"], function(Configurable){ + }); + ``` + +**Example 2:** + +* File actual location: `app/design/frontend/Magento/blank/Magento_Theme/web/js/theme.js` +* File published to `pub/static`: `pub/static/frontend/Magento/blank//Magento_Theme/js/theme.js` +* Called in script: + + ```javascript + require(["Magento_Theme/js/theme"], function(){ + }); + ``` + +**Example 3:** + +* File actual location: `lib/web/jquery.js` +* File published to `pub/static`: `pub/static/////jquery.js` +* Called in script: + + ```javascript + require(["jquery"], function($){ + }); + ``` + +Relative paths are also used in for [mapping and setting `paths` in requirejs-config.js configuration files]({{ page.baseurl }}/javascript-dev-guide/javascript/js-resources.html). + +## Dependencies between JavaScript resources {#m2devgde-js-resources-dependencies} + +To build a dependency on the third-party plugin, specify a [shim](http://requirejs.org/docs/api.html#config-shim) in the following configuration files: + +* `requirejs-config.js` + + ```javascript + var config = { + shim: { + "3-rd-party-plugin": ["jquery"] + } + }; + ``` + +* `.js` + + ```javascript + !(function($){ + // plugin code + // where $ == jQuery + })(jQuery); + ``` + +## RequireJS library + +### Including RequireJS {#m2devgde-js-resources-configrequirejs} + +To be available for the entire Magento instance, RequireJS library is included in the following layout files: + +* For the `adminhtml` [area]({{ page.baseurl }}/architecture/archi_perspectives/components/modules/mod_and_areas.html): + + [app/code/Magento/Backend/view/adminhtml/layout/default.xml]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Backend/view/adminhtml/layout/default.xml) + + ```xml + + + Admin + + + + + + + + + + + + + + + + ... + + + + + + + + + + + + ``` + +* For the `frontend` area, the equivalent configuration is located in [`app/code/Magento/Theme/view/frontend/layout/default.xml`]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Theme/view/frontend/layout/default.xml). + +### Including third-party JavaScript libraries + +To include a 3rd party library and use it within the entire website (using the [Slick JS Library](https://github.com/kenwheeler/slick/) as an example): + +1. Download the library and copy `slick.min.js` to the `/web/js` folder + +1. Copy `slick.less` and `slick-theme.less` to the `/web/css/source` folder. Also add both files to `/web/css/source/_extend.less`. + + ```scss + @import "slick.less"; + @import "slick-theme.less"; + ``` + +1. Create or update the theme's `requirejs-config.js` file. + + `/requirejs-config.js` + + ```javascript + var config = { + paths: { + slick: 'js/slick.min' + }, + shim: { + slick: { + deps: ['jquery'] + } + } + }; + ``` + +After these steps, clear the cache and perform a static content deployment. + +#### Result + +We should now be able to use the Slick library, for example, on any list that we want to convert into a slider. + +```html +
      +
    • 1st Element
    • +
    • 2nd Element
    • +
    • 3rd Element
    • +
    • 4th Element
    • +
    • 5th Element
    • +
    • 6th Element
    • +
    • 7th Element
    • +
    • 8th Element
    • +
    + + +``` + +![Slick Slider]({{ site.baseurl }}/common/images/js/slick-slider-result.png) + +### Mapping JS resources {#m2devgde-js-resources-mapping} + +To make configurations more precise and specific to different modules and themes, `requirejs-config.js` files can be placed in different [locations](#m2devgde-js-resources-configuring) depending on your needs. + +All configurations are collected and executed in the following order: + +1. Library configurations. +1. Configurations at the module level. +1. Configurations at the theme module level for the ancestor themes. +1. Configurations at the theme module level for a current theme. +1. Configurations at the theme level for the ancestor themes. +1. Configurations at the theme level for the current theme. + +The `baseUrl` parameter for RequireJS is specified in the following files: + +* For the `frontend` area: [app/code/Magento/Theme/view/frontend/templates/page/js/require_js.phtml]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Theme/view/frontend/templates/page/js/require_js.phtml) +* For the `adminhtml` area: [app/code/Magento/Backend/view/adminhtml/templates/page/js/require_js.phtml]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Backend/view/adminhtml/templates/page/js/require_js.phtml) + +{:.ref-header} +Related reading + +* [About AMD modules and RequireJS]({{ page.baseurl }}/javascript-dev-guide/javascript/js-resources.html) +* [RequireJS library](http://requirejs.org) +* [inheriting]({{ page.baseurl }}/frontend-dev-guide/themes/theme-inherit.html) +* [shim](http://requirejs.org/docs/api.html#config-shim) diff --git a/src/guides/v2.4/javascript-dev-guide/javascript/js_debug.md b/src/guides/v2.4/javascript-dev-guide/javascript/js_debug.md deleted file mode 120000 index 9a060cbd035..00000000000 --- a/src/guides/v2.4/javascript-dev-guide/javascript/js_debug.md +++ /dev/null @@ -1 +0,0 @@ -../../../v2.3/javascript-dev-guide/javascript/js_debug.md \ No newline at end of file diff --git a/src/guides/v2.4/javascript-dev-guide/javascript/js_debug.md b/src/guides/v2.4/javascript-dev-guide/javascript/js_debug.md new file mode 100644 index 00000000000..2e72dfadbfb --- /dev/null +++ b/src/guides/v2.4/javascript-dev-guide/javascript/js_debug.md @@ -0,0 +1,70 @@ +--- +group: javascript-developer-guide +subgroup: 1_Javascript +title: Locate JavaScript components +functional_areas: + - Testing +--- + +## Overview {#js_debug_overview} + +This topic discusses how to define which [JavaScript](https://glossary.magento.com/javascript) components and widgets are used on a particular Magento store page. + +## Locate JS components: walkthrough {#locate_widget} + +To locate scripts used for a certain element: + +1. Open the store page in a browser, and locate the element\'s `class` or `id` using browser debugging tools, such as Firebug (Firefox) or Inspect Element (Chrome). +1. Select to view the page source. +1. Find the corresponding element in the page source and see if there are `data-mage-init` or `` tag + + > This is used to target either a CSS selector or `*`. If the CSS selector matches multiple HTML elements, the script will run for each matched HTML element. For `*`, no HTML element is selected and the script will run once with the HTML DOM as its target. This method can be implemented from anywhere in the codebase to target any HTML element. This is preferred when direct access to the HTML element is restricted, or when there is no target HTML element. + +Consider the example of adding a custom carousel JS: + +1. Copy the `.carousel.js` file to the `app/design/frontend///web/js//` directory. +1. Add your RequireJS module at `app/design/frontend///web/js/carousel.js`. + + ```javascript + define(['jquery',''], function($) + { + return function(config, element) + { + $(element).(config); + }; + }); + ``` + +1. Add the RequireJS config to the `app/design/frontend///requirejs-config.js` file. + + ```javascript + var config = { + map: { + '*': { + 'carousel': 'js/carousel', + '': 'js//.carousel' + } + } + }; + ``` + +You now have two options for specifying declarative notation: + +- Use the `data-mage-init` attribute to insert the carousel in a certain element: + + ```html +
    +
    Item 1
    + ... +
    Item n
    +
    + ``` + +- Use with ` + ``` + +#### Declarative notation using the `data-mage-init` attribute {#data_mage_init} + +Use the `data-mage-init` attribute to insert a JS component in a specified HTML element. The following example inserts a JS component in the `

    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%0AgzIEm>tMB+GNXSv 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