From fb6dbd7f39a8a6f6acc7774b4f4e086ae903076a Mon Sep 17 00:00:00 2001 From: Amit Bera Date: Sat, 3 Aug 2019 19:32:04 +0530 Subject: [PATCH 01/14] Update 1. Utilize modes and application initialization.md --- .../1. Utilize modes and application initialization.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/2. Request Flow Processing/1. Utilize modes and application initialization.md b/2. Request Flow Processing/1. Utilize modes and application initialization.md index 935bee5..1a79ce0 100644 --- a/2. Request Flow Processing/1. Utilize modes and application initialization.md +++ b/2. Request Flow Processing/1. Utilize modes and application initialization.md @@ -1,11 +1,11 @@ # Utilize modes and application initialization ## Identify the steps for application initialization. -[app/bootstrap.php](https://github.com/magento/magento2/blob/2.2-develop/app/bootstrap.php): +[app/bootstrap.php](https://github.com/magento/magento2/blob/2.3-develop/app/bootstrap.php): - composer autoloader, functions, umask, timezone UTC, php precision -[\Magento\Framework\App\Bootstrap](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/Bootstrap.php)::*create* +[\Magento\Framework\App\Bootstrap](https://github.com/magento/magento2/blob/2.3-develop/lib/internal/Magento/Framework/App/Bootstrap.php)::*create* - configure autoloader - PSR-4 prepend generation\Magento From c78270a11b23f2f91120350a33e90da9908fa00a Mon Sep 17 00:00:00 2001 From: Amit Bera Date: Fri, 25 Oct 2019 10:42:29 +0530 Subject: [PATCH 02/14] Wrong code referenceBlock should use. Use of wrong --- .../10.1 Demonstrate ability to customize My Account.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/10. Customer Management/10.1 Demonstrate ability to customize My Account.md b/10. Customer Management/10.1 Demonstrate ability to customize My Account.md index e85d527..1edfc15 100644 --- a/10. Customer Management/10.1 Demonstrate ability to customize My Account.md +++ b/10. Customer Management/10.1 Demonstrate ability to customize My Account.md @@ -16,9 +16,9 @@ Describe how to customize the “My Account” section. * See COPYING.txt for license details. */ --> - + - + Russell Special @@ -26,7 +26,7 @@ Describe how to customize the “My Account” section. 165 - + ``` From f942a1d78bcd3398d1df08bf418aaff95a1ad24f Mon Sep 17 00:00:00 2001 From: Radu Barbu Date: Mon, 18 Nov 2019 17:17:13 +0200 Subject: [PATCH 03/14] =?UTF-8?q?Update=201.=20Describe=20Magento=E2=80=99?= =?UTF-8?q?s=20module-based=20architecture.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ... Describe Magento\342\200\231s module-based architecture.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/1. Magento Architecture and Customization Techniques/1. Describe Magento\342\200\231s module-based architecture.md" "b/1. Magento Architecture and Customization Techniques/1. Describe Magento\342\200\231s module-based architecture.md" index c263b21..6cf6d17 100755 --- "a/1. Magento Architecture and Customization Techniques/1. Describe Magento\342\200\231s module-based architecture.md" +++ "b/1. Magento Architecture and Customization Techniques/1. Describe Magento\342\200\231s module-based architecture.md" @@ -104,7 +104,7 @@ Examples [1],[2],[3],[4],[5],[6] taken from [Magento DevDocs - Register your com Minimization of software dependencies is a cornerstone of Magento architecture. Based on this principle there are several logical limitations: 1. One module is responsible only for one feature. 1. Module dependencies on other modules must be declared explicitly. -1. Excluding or disabling a module should not disabling another module. +1. Excluding or disabling a module should not disable another module. # How do different modules interact with each other? Magento 2 is [PSR-4](https://www.php-fig.org/psr/psr-4/) compliant. As a main principle of module interaction Magento 2 declares a dependency injection pattern and service contracts. From 37659a573a914e0160d019eb7fa494bc81feaa95 Mon Sep 17 00:00:00 2001 From: Subrata Bauri Date: Wed, 27 Nov 2019 15:18:19 +0530 Subject: [PATCH 04/14] Fix links to correct Magento 2 filesystem + Changed the line number for - Implementation via virtual types to read data from layout.xml --- ...ze configuration XML and variables scope.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/1. Magento Architecture and Customization Techniques/3. Utilize configuration XML and variables scope.md b/1. Magento Architecture and Customization Techniques/3. Utilize configuration XML and variables scope.md index f6b6e71..999d18e 100644 --- a/1. Magento Architecture and Customization Techniques/3. Utilize configuration XML and variables scope.md +++ b/1. Magento Architecture and Customization Techniques/3. Utilize configuration XML and variables scope.md @@ -46,7 +46,7 @@ # Interfaces for work with configs -#### [\Magento\Framework\Config\Reader\Filesystem](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Config/Reader/Filesystem.php) -> [\Magento\Framework\Config\ReaderInterface](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Config/ReaderInterface.php) +#### [\Magento\Framework\Config\Reader\Filesystem](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Config/Reader/Filesystem.php) -> [\Magento\Framework\Config\ReaderInterface](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Config/ReaderInterface.php) Gets .xsd names from schema locator, gets full .xml file list from file resolver, merges all files, validates, runs converter to get resulting array. - read(scope) + `fileResolver->get(_filename)` @@ -56,27 +56,27 @@ Gets .xsd names from schema locator, gets full .xml file list from file resolver - `_idAttributes`, `_fileName`, `_schemaFile` (from schemaLocator), `_perFileSchema` (from schemaLocator), filename (menu.xml) - schemaFile from schemaLocator -#### [\Magento\Framework\Config\ConverterInterface](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Config/ConverterInterface.php) +#### [\Magento\Framework\Config\ConverterInterface](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Config/ConverterInterface.php) Convert an array to any format - `convert(\DOMDocument $source)` -#### [\Magento\Framework\Config\SchemaLocatorInterface](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Config/SchemaLocatorInterface.php) - full path to .xsd +#### [\Magento\Framework\Config\SchemaLocatorInterface](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Config/SchemaLocatorInterface.php) - full path to .xsd - `getPerFileSchema` - per file before merge - `getSchema` - merged file -#### [\Magento\Framework\Config\ValidationStateInterface](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Config/ValidationStateInterface.php) +#### [\Magento\Framework\Config\ValidationStateInterface](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Config/ValidationStateInterface.php) This interface retrieves the validation state. - `isValidationRequired()` -[\Magento\Framework\App\Arguments\ValidationState](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/Arguments/ValidationState.php) is default implementation, that require validation only in developer mode. +[\Magento\Framework\App\Arguments\ValidationState](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/Arguments/ValidationState.php) is default implementation, that require validation only in developer mode. -#### [\Magento\Framework\Config\ScopeListInterface](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Config/ScopeListInterface.php) +#### [\Magento\Framework\Config\ScopeListInterface](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Config/ScopeListInterface.php) This interface the list of all scopes. - `getAllScopes()` -#### [\Magento\Framework\Config\Data](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Config/Data.php) -> [\Magento\Framework\Config\DataInterface](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Config/DataInterface.php) +#### [\Magento\Framework\Config\Data](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Config/Data.php) -> [\Magento\Framework\Config\DataInterface](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Config/DataInterface.php) Helps to get the configuration data in a specified scope. - `merge(array $config);` @@ -84,8 +84,8 @@ Helps to get the configuration data in a specified scope. ###### Links and examples: -- Product types configs model to read data from [product_types.xml](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/Catalog/etc/product_types.xml): [\Magento\Catalog\Model\ProductTypes](https://github.com/magento/magento2/tree/2.2-develop/app/code/Magento/Catalog/Model/ProductTypes) -- Implementation via virtual types to read data from layout.xml: [Magento/Theme/etc/di.xml](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/Theme/etc/di.xml#L48) +- Product types configs model to read data from [product_types.xml](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Catalog/etc/product_types.xml): [\Magento\Catalog\Model\ProductTypes](https://github.com/magento/magento2/tree/2.3/app/code/Magento/Catalog/Model/ProductTypes) +- Implementation via virtual types to read data from layout.xml: [Magento/Theme/etc/di.xml](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Theme/etc/di.xml#L42) - https://www.atwix.com/magento-2/working-with-custom-configuration-files/ From dd4c334e43f2be1f1c52d56a497a0a0d1c1dc3e6 Mon Sep 17 00:00:00 2001 From: Radu Barbu Date: Mon, 18 Nov 2019 17:28:09 +0200 Subject: [PATCH 05/14] =?UTF-8?q?Update=201.=20Describe=20Magento=E2=80=99?= =?UTF-8?q?s=20module-based=20architecture.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix broken link --- ...cribe Magento\342\200\231s module-based architecture.md" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/1. Magento Architecture and Customization Techniques/1. Describe Magento\342\200\231s module-based architecture.md" "b/1. Magento Architecture and Customization Techniques/1. Describe Magento\342\200\231s module-based architecture.md" index 6cf6d17..775852f 100755 --- "a/1. Magento Architecture and Customization Techniques/1. Describe Magento\342\200\231s module-based architecture.md" +++ "b/1. Magento Architecture and Customization Techniques/1. Describe Magento\342\200\231s module-based architecture.md" @@ -143,7 +143,7 @@ Specifically: >The module extends another module’s configuration. >The module extends another module’s layout. > -> -- [Magento DevDocs - Module dependency types](http://devdocs.magento.com/guides/v2.2/architecture/archi_perspectives/components/modules/mod_depend_types.html) +> -- [Magento DevDocs - Module dependency types](http://devdocs.magento.com/guides/v2.2/architecture/archi_perspectives/components/modules/mod_depend.html) Magento module install order flow: >1. The module serving as a dependency for another module @@ -154,10 +154,10 @@ Following dependencies should not be created: >1. Undeclared >1. Incorrect > -> -- [Magento DevDocs - Module dependency types](http://devdocs.magento.com/guides/v2.2/architecture/archi_perspectives/components/modules/mod_depend_types.html) +> -- [Magento DevDocs - Module dependency types](http://devdocs.magento.com/guides/v2.2/architecture/archi_perspectives/components/modules/mod_depend.html) ->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 or the service provider interface (SPI). - [Magento DevDocs - Module dependency types](http://devdocs.magento.com/guides/v2.2/architecture/archi_perspectives/components/modules/mod_depend_types.html) +>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 or the service provider interface (SPI). - [Magento DevDocs - Module dependency types](http://devdocs.magento.com/guides/v2.2/architecture/archi_perspectives/components/modules/mod_depend.html) ### Magento areas A Magento area organizes code for optimized request processing by loading components parts which are related only to the specific area. Areas are registered in the `di.xml` file. From 0266dc85dfe2642a469013c856f846a1518780de Mon Sep 17 00:00:00 2001 From: SubrataBauri Date: Thu, 28 Nov 2019 03:41:44 +0530 Subject: [PATCH 06/14] Fix links to Magento 2.3 filesystem + For Magento Architecture and Customization Techniques --- ...gento\342\200\231s directory structure.md" | 2 +- ...nstrate how to use dependency injection.md | 6 +++--- .../5. Demonstrate ability to use plugins.md | 6 +++--- ...gure event observers and scheduled jobs.md | 20 +++++++++---------- .../7. Utilize the CLI.md | 4 ++-- ...nstrate the ability to manage the cache.md | 10 +++++----- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git "a/1. Magento Architecture and Customization Techniques/2. Describe Magento\342\200\231s directory structure.md" "b/1. Magento Architecture and Customization Techniques/2. Describe Magento\342\200\231s directory structure.md" index 2e95168..e6c9eb8 100755 --- "a/1. Magento Architecture and Customization Techniques/2. Describe Magento\342\200\231s directory structure.md" +++ "b/1. Magento Architecture and Customization Techniques/2. Describe Magento\342\200\231s directory structure.md" @@ -37,7 +37,7 @@ In addition, you can choose the component root directory to start development. T > > -- [Magento DevDocs - About component file structure](https://devdocs.magento.com/guides/v2.2/extension-dev-guide/prepare/prepare_file-str.html) -Class [Magento\Framework\Module\ModuleList\Loader](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Module/ModuleList/Loader.php#L78) load `etc/module.xml` files and sort modules by sequence. +Class [Magento\Framework\Module\ModuleList\Loader](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Module/ModuleList/Loader.php#L78) load `etc/module.xml` files and sort modules by sequence. The sequence use for sorting events, plugins, preferences and layouts. diff --git a/1. Magento Architecture and Customization Techniques/4. Demonstrate how to use dependency injection.md b/1. Magento Architecture and Customization Techniques/4. Demonstrate how to use dependency injection.md index 6d2ada0..d3c7c92 100644 --- a/1. Magento Architecture and Customization Techniques/4. Demonstrate how to use dependency injection.md +++ b/1. Magento Architecture and Customization Techniques/4. Demonstrate how to use dependency injection.md @@ -9,11 +9,11 @@ Magento loads di.xml files and merges them all together from the following stage ### Object manager -Under the hood, the [ObjectManager](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/ObjectManager/ObjectManager.php) +Under the hood, the [ObjectManager](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/ObjectManager/ObjectManager.php) will use PHP reflection features to look at a class’s __construct type hints/parameters, automatically instantiate the object for us, and then pass it into the constructor as an argument. -[AbstractFactory](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php) > [\Magento\Framework\ObjectManager\FactoryInterface](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/ObjectManager/FactoryInterface.php) +[AbstractFactory](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php) > [\Magento\Framework\ObjectManager\FactoryInterface](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/ObjectManager/FactoryInterface.php) and their implementations use to resolve arguments and create new objects. By default, all objects created via automatic constructor dependency injection are singleton objects, @@ -26,7 +26,7 @@ if ($isShared) { $argument = $this->objectManager->create($argumentType); } ``` -[\Magento\Framework\ObjectManager\Factory::resolveArgument()](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php#L143-L147) +[\Magento\Framework\ObjectManager\Factory::resolveArgument()](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php#L143-L147) ### Arguments diff --git a/1. Magento Architecture and Customization Techniques/5. Demonstrate ability to use plugins.md b/1. Magento Architecture and Customization Techniques/5. Demonstrate ability to use plugins.md index 4019557..33ee2a7 100644 --- a/1. Magento Architecture and Customization Techniques/5. Demonstrate ability to use plugins.md +++ b/1. Magento Architecture and Customization Techniques/5. Demonstrate ability to use plugins.md @@ -3,7 +3,7 @@ There are three types of plugins in magento: around, before and after. __Important__: Classes, abstract classes and interfaces that are implementations of or inherit from classes that have plugins will also inherit plugins from the parent class. -For example, if you create a plugin for [\Magento\Catalog\Block\Product\AbstractProduct](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/Catalog/Block/Product/AbstractProduct.php), +For example, if you create a plugin for [\Magento\Catalog\Block\Product\AbstractProduct](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Catalog/Block/Product/AbstractProduct.php), plugin methods will be called for all child classes, such as \Magento\Catalog\Block\Product\View, \Magento\Catalog\Block\Product\ProductList\Upsell etc. ### Limitations @@ -131,9 +131,9 @@ Magento automatically generates `Interceptor` class for the plugin target and st } ``` -[\Magento\Framework\Interception\Interceptor](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Interception/Interceptor.php): +[\Magento\Framework\Interception\Interceptor](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Interception/Interceptor.php): -- $pluginList = [\Magento\Framework\Interception\PluginListInterface](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Interception/PluginListInterface.php) +- $pluginList = [\Magento\Framework\Interception\PluginListInterface](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Interception/PluginListInterface.php) - $subjectType = 'MyBeautifulClass' - `___init` - called in in constructor, pluginList = get from object manager, subjectType = class name - pluginList->getNext diff --git a/1. Magento Architecture and Customization Techniques/6. Configure event observers and scheduled jobs.md b/1. Magento Architecture and Customization Techniques/6. Configure event observers and scheduled jobs.md index 4299e18..2bbc44b 100644 --- a/1. Magento Architecture and Customization Techniques/6. Configure event observers and scheduled jobs.md +++ b/1. Magento Architecture and Customization Techniques/6. Configure event observers and scheduled jobs.md @@ -45,7 +45,7 @@ Example: ``` Observer class should be placed in the /Observer directory and implement -[Magento\Framework\Event\ObserverInterface](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Event/ObserverInterface.php) +[Magento\Framework\Event\ObserverInterface](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Event/ObserverInterface.php) interface. ```php @@ -63,8 +63,8 @@ class MyObserver implements \Magento\Framework\Event\ObserverInterface ### Dispatching events -Events dispatch by [Magento\Framework\Event\Manager](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Event/Manager.php) class -that implement [Magento\Framework\Event\ManagerInterface](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Event/ManagerInterface.php) interface: +Events dispatch by [Magento\Framework\Event\Manager](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Event/Manager.php) class +that implement [Magento\Framework\Event\ManagerInterface](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Event/ManagerInterface.php) interface: > dispatch($eventName, array $data = []); Example: @@ -144,8 +144,8 @@ generate check for standalone process ``` -[\Magento\Cron\Model\Config\Data](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/Cron/Model/Config/Data.php) extends [\Magento\Framework\Config\Data](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Config/Data.php) -- merges [\Magento\Cron\Model\Config\Reader\Db::get](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/Cron/Model/Config/Reader/Db.php#L51) from Database +[\Magento\Cron\Model\Config\Data](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Cron/Model/Config/Data.php) extends [\Magento\Framework\Config\Data](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Config/Data.php) +- merges [\Magento\Cron\Model\Config\Reader\Db::get](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Cron/Model/Config/Reader/Db.php#L51) from Database Sample DB structure: ``` @@ -153,7 +153,7 @@ default/crontab/GROUP/jobs/JOB/schedule/cron_expr = '* * * * *' default/crontab/GROUP/jobs/JOB/schedule/config_path = 'some/config/path' -- try to read schedule from this config, store view scope default/crontab/GROUP/jobs/JOB/run/model = 'class::method' ``` -DB config usage example: [ProductAlert, system.xml](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/ProductAlert/etc/adminhtml/system.xml#L38:L45), [ProductAlert, crontab.xml](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/ProductAlert/etc/crontab.xml), backend model: [Magento\Cron\Model\Config\Backend\Product\Alert](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/Cron/Model/Config/Backend/Product/Alert.php) +DB config usage example: [ProductAlert, system.xml](https://github.com/magento/magento2/blob/2.3/app/code/Magento/ProductAlert/etc/adminhtml/system.xml#L38:L45), [ProductAlert, crontab.xml](https://github.com/magento/magento2/blob/2.3/app/code/Magento/ProductAlert/etc/crontab.xml), backend model: [Magento\Cron\Model\Config\Backend\Product\Alert](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Cron/Model/Config/Backend/Product/Alert.php) `bin/magento cron:install` example: ``` @@ -180,7 +180,7 @@ TODO: find out ### Identify the function and proper use of automatically available events -Model events [\Magento\Framework\Model\AbstractModel](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Model/AbstractModel.php): +Model events [\Magento\Framework\Model\AbstractModel](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Model/AbstractModel.php): - `model_load_before`, `{$_eventPrefix}_load_before` - `model_load_after`, `{$_eventPrefix}_load_after` @@ -191,18 +191,18 @@ Model events [\Magento\Framework\Model\AbstractModel](https://github.com/magento - `model_delete_after`, `{$_eventPrefix}_delete_after` - `model_delete_commit_after`, `{$_eventPrefix}_delete_commit_after` -Flat collection events [\Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php): +Flat collection events [\Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Model/ResourceModel/Db/Collection/AbstractCollection.php): - `core_collection_abstract_load_before`, `{_eventPrefix}_load_before` - `core_collection_abstract_load_after`, `{_eventPrefix}_load_after` only if `_eventPrefix` and `_eventObject` defined: `{prefix}_load_before`, `{prefix}_load_after` -EAV collection events [\Magento\Eav\Model\Entity\Collection\AbstractCollection](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php): +EAV collection events [\Magento\Eav\Model\Entity\Collection\AbstractCollection](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php): - eav_collection_abstract_load_before -[\Magento\Framework\Model\AbstractModel](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Model/AbstractModel.php): +[\Magento\Framework\Model\AbstractModel](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Model/AbstractModel.php): - _eventObject = 'object' - _eventPrefix = 'core_abstract', e.g. 'catalog_category' diff --git a/1. Magento Architecture and Customization Techniques/7. Utilize the CLI.md b/1. Magento Architecture and Customization Techniques/7. Utilize the CLI.md index b79ff68..0738dae 100644 --- a/1. Magento Architecture and Customization Techniques/7. Utilize the CLI.md +++ b/1. Magento Architecture and Customization Techniques/7. Utilize the CLI.md @@ -97,8 +97,8 @@ class ExampleCommand extends \Symfony\Component\Console\Command\Command } ``` -- Declare your command in [\Magento\Framework\Console\CommandListInterface](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Console/CommandListInterface.php) using dependency injection ({module}/etc/di.xml). -See also CommandListInterface implementation: [\Magento\Framework\Console\CommandList](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Console/CommandList.php) +- Declare your command in [\Magento\Framework\Console\CommandListInterface](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Console/CommandListInterface.php) using dependency injection ({module}/etc/di.xml). +See also CommandListInterface implementation: [\Magento\Framework\Console\CommandList](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Console/CommandList.php) {module}/etc/di.xml: ```xml diff --git a/1. Magento Architecture and Customization Techniques/8. Demonstrate the ability to manage the cache.md b/1. Magento Architecture and Customization Techniques/8. Demonstrate the ability to manage the cache.md index 38d8cf8..7882399 100644 --- a/1. Magento Architecture and Customization Techniques/8. Demonstrate the ability to manage the cache.md +++ b/1. Magento Architecture and Customization Techniques/8. Demonstrate the ability to manage the cache.md @@ -127,14 +127,14 @@ Sessions and caching data should never be stored in one database in Redis. In th ### Describe how to clear the cache programmatically. To clear the cache programmatically you neeed to call next the methods: -- [\Magento\Framework\App\CacheInterface::remove($identifier)](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/CacheInterface.php#L48) - remove cached data by identifier -- [\Magento\Framework\App\CacheInterface::clean($tags = [])](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/CacheInterface.php#L56) - clean cached data by specific tag +- [\Magento\Framework\App\CacheInterface::remove($identifier)](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/CacheInterface.php#L48) - remove cached data by identifier +- [\Magento\Framework\App\CacheInterface::clean($tags = [])](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/CacheInterface.php#L56) - clean cached data by specific tag ##### What mechanisms are available for clearing all or part of the cache? Dispatch a `clean_cache_by_tags` event with parameter of the object you want to clear from the cache. -Example: [\Magento\Framework\Model\AbstractModel](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Model/AbstractModel.php#L817) (afterSave, afterDelete methods) +Example: [\Magento\Framework\Model\AbstractModel](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Model/AbstractModel.php#L817) (afterSave, afterDelete methods) ```php Date: Fri, 29 Nov 2019 18:15:51 +0530 Subject: [PATCH 07/14] Fix code links for Request Flow Processing --- ...ze modes and application initialization.md | 68 +++++++++---------- ...rate ability to process URLs in Magento.md | 40 +++++------ ...te ability to customize request routing.md | 12 ++-- 3 files changed, 60 insertions(+), 60 deletions(-) diff --git a/2. Request Flow Processing/1. Utilize modes and application initialization.md b/2. Request Flow Processing/1. Utilize modes and application initialization.md index 1a79ce0..4875813 100644 --- a/2. Request Flow Processing/1. Utilize modes and application initialization.md +++ b/2. Request Flow Processing/1. Utilize modes and application initialization.md @@ -1,19 +1,19 @@ # Utilize modes and application initialization ## Identify the steps for application initialization. -[app/bootstrap.php](https://github.com/magento/magento2/blob/2.3-develop/app/bootstrap.php): +[app/bootstrap.php](https://github.com/magento/magento2/blob/2.3/app/bootstrap.php): - composer autoloader, functions, umask, timezone UTC, php precision -[\Magento\Framework\App\Bootstrap](https://github.com/magento/magento2/blob/2.3-develop/lib/internal/Magento/Framework/App/Bootstrap.php)::*create* +[\Magento\Framework\App\Bootstrap](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/Bootstrap.php)::*create* - configure autoloader - PSR-4 prepend generation\Magento -[\Magento\Framework\App\Bootstrap](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/Bootstrap.php)::*createApplication* +[\Magento\Framework\App\Bootstrap](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/Bootstrap.php)::*createApplication* - just call object manager->create -[\Magento\Framework\App\Bootstrap](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/Bootstrap.php)::*run* +[\Magento\Framework\App\Bootstrap](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/Bootstrap.php)::*run* - set error handler - assert maintenance @@ -27,30 +27,30 @@ ### Application class -[bootstrap->createApplication()](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/Bootstrap.php#L230) +[bootstrap->createApplication()](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/Bootstrap.php#L230) - - [\Magento\Framework\App\Http](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/Http.php) - index.php, pub/index.php + - [\Magento\Framework\App\Http](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/Http.php) - index.php, pub/index.php load config area by front name front controller->dispatch event `controller_front_send_response_before` - - [\Magento\Framework\App\Cron](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/Cron.php) - pub/cron.php + - [\Magento\Framework\App\Cron](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/Cron.php) - pub/cron.php config area `crontab` load translations dispatch event `default` - - [\Magento\MediaStorage\App\Media](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/MediaStorage/App/Media.php) - pub/get.php + - [\Magento\MediaStorage\App\Media](https://github.com/magento/magento2/blob/2.3/app/code/Magento/MediaStorage/App/Media.php) - pub/get.php access /media/* when using DB image storage and physical file doesn't exist - - [\Magento\Framework\App\StaticResource](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/StaticResource.php) - pub/static.php + - [\Magento\Framework\App\StaticResource](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/StaticResource.php) - pub/static.php 404 in production /$area/$resource/$file/... params, load config by params sends file in response assetRepo->createAsset - \Magento\Framework\View\Asset\File assetPublisher->publish - materialize (copy/symlink) file if doesn't exist - - [\Magento\Indexer\App\Indexer](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/Indexer/App/Indexer.php) - module-indexer, unused? - - [\Magento\Backend\App\UserConfig](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/Backend/App/UserConfig.php) - module-backend, unused? + - [\Magento\Indexer\App\Indexer](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Indexer/App/Indexer.php) - module-indexer, unused? + - [\Magento\Backend\App\UserConfig](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Backend/App/UserConfig.php) - module-backend, unused? Notes: @@ -61,7 +61,7 @@ Notes: ### HTTP application -[\Magento\Framework\App\Http::launch](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/Http.php#L128) +[\Magento\Framework\App\Http::launch](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/Http.php#L128) 1. detect config area by front name ```php @@ -71,19 +71,19 @@ $this->_state->setAreaCode($areaCode); $this->_objectManager->configure($this->_configLoader->load($areaCode)); ``` -`\Magento\Framework\App\AreaList` - areas from argument di.xml ([AreaList](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/AreaList.php)) +`\Magento\Framework\App\AreaList` - areas from argument di.xml ([AreaList](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/AreaList.php)) - frontend = [frontname null, router "standard"] --- *default when nothing matched* - adminhtml - [frontNameResolver=..., router "admin"] - [\Magento\Backend\App\Area\FrontNameResolver::getFrontName(checkhost)](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/Backend/App/Area/FrontNameResolver.php#L83) + [\Magento\Backend\App\Area\FrontNameResolver::getFrontName(checkhost)](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Backend/App/Area/FrontNameResolver.php#L83) system config `admin/url/use_custom`, `admin/url/custom` - crontab = null - webapi_rest = [frontName `/rest`] - webapi_soap = [frontname `/soap`] -1. [ObjectManagerInterface->configure()](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/ObjectManager/ObjectManager.php#L82) - selected area code +1. [ObjectManagerInterface->configure()](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/ObjectManager/ObjectManager.php#L82) - selected area code 1. result = FrontControllerInterface->dispatch() -1. [ResultInterface->renderResult()](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Controller/AbstractResult.php#L122) into response object +1. [ResultInterface->renderResult()](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Controller/AbstractResult.php#L122) into response object 1. event `controller_front_send_response_before` (request, response) @@ -102,7 +102,7 @@ $this->_objectManager->configure($this->_configLoader->load($areaCode)); - "webapi_rest (frontName `/rest`) - preference module-webapi/etc/webapi_rest/di.xml - *\Magento\Webapi\Controller\Rest* - "webapi_soap" (frontname `/soap`) - preference module-webapi/etc/webapi_soap/di.xml - *\Magento\Webapi\Controller\Soap* -### [\Magento\Framework\App\FrontController](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/FrontController.php): +### [\Magento\Framework\App\FrontController](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/FrontController.php): - routerList - action = router[].match @@ -112,37 +112,37 @@ $this->_objectManager->configure($this->_configLoader->load($areaCode)); ### Router match - action can be: - generic \Magento\Framework\App\ActionInterface::execute - not used? -- [\Magento\Framework\App\Action\AbstractAction](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/Action/AbstractAction.php)::dispatch - context, request, response, result factory, result redirect factory +- [\Magento\Framework\App\Action\AbstractAction](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/Action/AbstractAction.php)::dispatch - context, request, response, result factory, result redirect factory ### Dispatch/execute action - result can be: -- [\Magento\Framework\Controller\ResultInterface](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Controller/ResultInterface.php) - renderResult, setHttpResponseCode, setHeader +- [\Magento\Framework\Controller\ResultInterface](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Controller/ResultInterface.php) - renderResult, setHttpResponseCode, setHeader Implementations: - - [Result\Raw](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Controller/Result/Raw.php) -> Result\AbstractResult - - [Result\Json](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Controller/Result/Json.php) -> Result\AbstractResult - - [Result\Forward](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Controller/Result/Forward.php) -> Result\AbstractResult - - [\Magento\Framework\View\Result\Layout](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/View/Result/Layout.php) -> Result\AbstractResult - - [\Magento\Framework\View\Result\Page](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/View/Result/Page.php) -> \Magento\Framework\View\Result\Layout - - [Result\Redirect](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Controller/Result/Redirect.php) -> Result\AbstractResult + - [Result\Raw](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Controller/Result/Raw.php) -> Result\AbstractResult + - [Result\Json](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Controller/Result/Json.php) -> Result\AbstractResult + - [Result\Forward](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Controller/Result/Forward.php) -> Result\AbstractResult + - [\Magento\Framework\View\Result\Layout](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/View/Result/Layout.php) -> Result\AbstractResult + - [\Magento\Framework\View\Result\Page](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/View/Result/Page.php) -> \Magento\Framework\View\Result\Layout + - [Result\Redirect](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Controller/Result/Redirect.php) -> Result\AbstractResult -- [\Magento\Framework\App\ResponseInterface](https://github.com/magento/magento2/blob/2.2-develop/lib/internal//Magento/Framework/App/ResponseInterface.php) - sendResponse +- [\Magento\Framework\App\ResponseInterface](https://github.com/magento/magento2/blob/2.3/lib/internal//Magento/Framework/App/ResponseInterface.php) - sendResponse Implementations: - - [Console\Response](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/Console/Response.php) - - [\Magento\MediaStorage\Model\File\Storage\FileInterface](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/MediaStorage/Model/File/Storage/Response.php) -> \Magento\Framework\App\Response\Http - - [\Magento\Framework\HTTP\PhpEnvironment\Response](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/HTTP/PhpEnvironment/Response.php) -> \Zend\Http\PhpEnvironment\Response - - [\Magento\Framework\Webapi\Response](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Webapi/Response.php) -> \Magento\Framework\HTTP\PhpEnvironment\Response - - [\Magento\Framework\Webapi\Rest\Response](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Webapi/Rest/Response.php) -> \Magento\Framework\Webapi\Response + - [Console\Response](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/Console/Response.php) + - [\Magento\MediaStorage\Model\File\Storage\FileInterface](https://github.com/magento/magento2/blob/2.3/app/code/Magento/MediaStorage/Model/File/Storage/Response.php) -> \Magento\Framework\App\Response\Http + - [\Magento\Framework\HTTP\PhpEnvironment\Response](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/HTTP/PhpEnvironment/Response.php) -> \Zend\Http\PhpEnvironment\Response + - [\Magento\Framework\Webapi\Response](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Webapi/Response.php) -> \Magento\Framework\HTTP\PhpEnvironment\Response + - [\Magento\Framework\Webapi\Rest\Response](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Webapi/Rest/Response.php) -> \Magento\Framework\Webapi\Response -### [\Magento\Webapi\Controller\Rest](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/Webapi/Controller/Rest.php) -> \Magento\Framework\App\FrontControllerInterface: +### [\Magento\Webapi\Controller\Rest](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Webapi/Controller/Rest.php) -> \Magento\Framework\App\FrontControllerInterface: -- preference for FrontController set in [etc/webapi_rest/di.xml](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/Webapi/etc/webapi_rest/di.xml#L32) +- preference for FrontController set in [etc/webapi_rest/di.xml](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Webapi/etc/webapi_rest/di.xml#L32) - process path [/$store]/... - specific store, [/all]/... - admin store (0), /... - default store - a. process schema request /schema - b. or process api request (resolve route, invoke route -> service class with params) -### [\Magento\Webapi\Controller\Soap](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/Webapi/Controller/Soap.php) -> \Magento\Framework\App\FrontControllerInterface: +### [\Magento\Webapi\Controller\Soap](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Webapi/Controller/Soap.php) -> \Magento\Framework\App\FrontControllerInterface: - process path (same as REST) - a. generate WSDL ?wsdl diff --git a/2. Request Flow Processing/2. Demonstrate ability to process URLs in Magento.md b/2. Request Flow Processing/2. Demonstrate ability to process URLs in Magento.md index a2d54b2..fc642cf 100644 --- a/2. Request Flow Processing/2. Demonstrate ability to process URLs in Magento.md +++ b/2. Request Flow Processing/2. Demonstrate ability to process URLs in Magento.md @@ -1,12 +1,12 @@ # Demonstrate ability to process URLs in Magento ## Describe how Magento processes a given URL. -urlBuilder - [\Magento\Framework\UrlInterface](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/UrlInterface.php): getUrl +urlBuilder - [\Magento\Framework\UrlInterface](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/UrlInterface.php): getUrl Instances: -- [\Magento\Framework\Url](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Url.php) -- [\Magento\Backend\Model\Url](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/Backend/Model/Url.php) +- [\Magento\Framework\Url](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Url.php) +- [\Magento\Backend\Model\Url](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Backend/Model/Url.php) 1. preprocess route params @@ -43,7 +43,7 @@ Instances: ### What is necessary to create a custom URL structure? -- register custom router, e.g. [Magento\Robots\Controller\Router](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/Robots/Controller/Router.php) +- register custom router, e.g. [Magento\Robots\Controller\Router](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Robots/Controller/Router.php) - create rewrite record for specific URL @@ -88,32 +88,32 @@ Module UrlRewrite: Product: - event `catalog_product_save_before` - generate URL key by product name (if url key wasn't provided) - * [ProductUrlKeyAutogeneratorObserver](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/CatalogUrlRewrite/Observer/ProductUrlKeyAutogeneratorObserver.php) - * [\Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator::getUrlKey](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/CatalogUrlRewrite/Model/ProductUrlPathGenerator.php#L125) + * [ProductUrlKeyAutogeneratorObserver](https://github.com/magento/magento2/blob/2.3/app/code/Magento/CatalogUrlRewrite/Observer/ProductUrlKeyAutogeneratorObserver.php) + * [\Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator::getUrlKey](https://github.com/magento/magento2/blob/2.3/app/code/Magento/CatalogUrlRewrite/Model/ProductUrlPathGenerator.php#L125) - event `catalog_product_save_after` - generate and replace URL rewrites (when changed url_key, categories, websites or visibility) - * [ProductProcessUrlRewriteSavingObserver](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/CatalogUrlRewrite/Observer/ProductProcessUrlRewriteSavingObserver.php) - * [\Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator::generate](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/CatalogUrlRewrite/Model/ProductUrlRewriteGenerator.php#L128) + * [ProductProcessUrlRewriteSavingObserver](https://github.com/magento/magento2/blob/2.3/app/code/Magento/CatalogUrlRewrite/Observer/ProductProcessUrlRewriteSavingObserver.php) + * [\Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator::generate](https://github.com/magento/magento2/blob/2.3/app/code/Magento/CatalogUrlRewrite/Model/ProductUrlRewriteGenerator.php#L128) * deleteByData, replace Category: - event `catalog_category_save_before` - generate URL key, update child categories - * [CategoryUrlPathAutogeneratorObserver](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/CatalogUrlRewrite/Observer/CategoryUrlPathAutogeneratorObserver.php) + * [CategoryUrlPathAutogeneratorObserver](https://github.com/magento/magento2/blob/2.3/app/code/Magento/CatalogUrlRewrite/Observer/CategoryUrlPathAutogeneratorObserver.php) * \Magento\CatalogUrlRewrite\Observer\CategoryUrlPathAutogeneratorObserver::updateUrlPathForChildren * \Magento\CatalogUrlRewrite\Observer\CategoryUrlPathAutogeneratorObserver::updateUrlPathForCategory * \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator::getUrlPath * child category.url_path - event `catalog_category_save_after` - when changed (key, anchor, products) - * [CategoryProcessUrlRewriteSavingObserver](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/CatalogUrlRewrite/Observer/CategoryProcessUrlRewriteSavingObserver.php#L90) - * [\Magento\CatalogUrlRewrite\Observer\UrlRewriteHandler::generateProductUrlRewrites](https://github.com/magento/magento2/blob/2.2-develop/app/code//Magento/CatalogUrlRewrite/Observer/UrlRewriteHandler.php#L124) + * [CategoryProcessUrlRewriteSavingObserver](https://github.com/magento/magento2/blob/2.3/app/code/Magento/CatalogUrlRewrite/Observer/CategoryProcessUrlRewriteSavingObserver.php#L90) + * [\Magento\CatalogUrlRewrite\Observer\UrlRewriteHandler::generateProductUrlRewrites](https://github.com/magento/magento2/blob/2.3/app/code//Magento/CatalogUrlRewrite/Observer/UrlRewriteHandler.php#L124) * ... lots of logic ## Describe how action controllers and results function. -[App\Action\Action::dispatch](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/Action/Action.php#L91): +[App\Action\Action::dispatch](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/Action/Action.php#L91): - event `controller_action_predispatch` - event `controller_action_predispatch_$routeName`, e.g. `..._checkout` @@ -134,41 +134,41 @@ Category: - Controller\Response\Redirect - another controller URL ### How are different response types generated? -[\Magento\Framework\Controller\ResultInterface](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Controller/ResultInterface.php): +[\Magento\Framework\Controller\ResultInterface](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Controller/ResultInterface.php): - renderResult - setHttpResponseCode - setHeader -[Controller\AbstractResult](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Controller/AbstractResult.php): +[Controller\AbstractResult](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Controller/AbstractResult.php): - *renderResult* - required by interface - applies headers and calls *render*. children must implement this - setHttpResponseCode - setHeader - setStatusHeader -[Controller\Result\Raw](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Controller/Result/Raw.php): +[Controller\Result\Raw](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Controller/Result/Raw.php): - setContents - *render* - set response body -[Controller\Result\Json](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Controller/Result/Json.php): +[Controller\Result\Json](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Controller/Result/Json.php): - setData - array - setJsonData - string - *render* - processes inline translations, sets application/json header and response body json string -[Controller\Result\Forward](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Controller/Result/Forward.php): +[Controller\Result\Forward](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Controller/Result/Forward.php): - setModule, setController, setParams - *forward* - does the trick, modifies request object, marks request not dispatched - *render* - does nothing, forward must be called manually -[Controller\Result\Redirect](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Controller/Result/Redirect.php): +[Controller\Result\Redirect](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Controller/Result/Redirect.php): - setUrl, setPath - custom address - setRefererUrl, setRefererOrBaseUrl - go back function -[View\Result\Layout](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/View/Result/Layout.php): - renders layout without `default` handle and page layout (1-column etc.) +[View\Result\Layout](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/View/Result/Layout.php): - renders layout without `default` handle and page layout (1-column etc.) - *renderResult* * event `layout_render_before` @@ -179,7 +179,7 @@ Category: - addDefaultHandle = $fullActionName, e.g. `checkout_cart_index` - addHandle, addUpdate -[View\Result\Page](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/View/Result/Page.php): - wraps layout into page layout +[View\Result\Page](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/View/Result/Page.php): - wraps layout into page layout - same events as above - *render* - renders layout, assigns vars and renders outer page template - assign - values into viewVars property. default diff --git a/2. Request Flow Processing/3. Demonstrate ability to customize request routing.md b/2. Request Flow Processing/3. Demonstrate ability to customize request routing.md index e03a85f..0a36f95 100644 --- a/2. Request Flow Processing/3. Demonstrate ability to customize request routing.md +++ b/2. Request Flow Processing/3. Demonstrate ability to customize request routing.md @@ -41,17 +41,17 @@ reference route by ID and add own module "before" original module. ### How do you handle custom 404 pages? -1. If [front controller](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/FrontController.php#L61-L65) catches [\Magento\Framework\Exception\NotFoundException](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Exception/NotFoundException.php), it changes action name *"noroute"* and continues loop. +1. If [front controller](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/FrontController.php#L61-L65) catches [\Magento\Framework\Exception\NotFoundException](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Exception/NotFoundException.php), it changes action name *"noroute"* and continues loop. E.g. catalog/product/view/id/1 throws NotFoundException. catalog/product/noroute is checked. 1. If standard router recognizes front name but can't find controller, it tries to find *"noroute"* action from last checked module. E.g. catalog/brand/info controller doesn't exist, so catalog/brand/noroute will be checked. - [\Magento\Framework\App\Router\Base::getNotFoundAction](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/Router/Base.php#L237) + [\Magento\Framework\App\Router\Base::getNotFoundAction](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/Router/Base.php#L237) 1. If all routers didn't match, default controller provides two opportunities: - - set default 404 route in admin config `web/default/no_route` (see: [\Magento\Framework\App\Router\NoRouteHandler::process](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/Router/NoRouteHandler.php#L34)) - - register custom handler in [noRouteHandlerList](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/Router/NoRouteHandlerList.php): - * backend (sortOrder: 10) [Magento\Backend\App\Router\NoRouteHandler](https://github.com/magento/magento2/blob/2.2-develop/app/code/Magento/Backend/App/Router/NoRouteHandler.php#L44) -> `adminhtml/noroute/index` - * default (sortOrder: 100) [Magento\Framework\App\Router\NoRouteHandler](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/App/Router/NoRouteHandler.php) + - set default 404 route in admin config `web/default/no_route` (see: [\Magento\Framework\App\Router\NoRouteHandler::process](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/Router/NoRouteHandler.php#L34)) + - register custom handler in [noRouteHandlerList](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/Router/NoRouteHandlerList.php): + * backend (sortOrder: 10) [Magento\Backend\App\Router\NoRouteHandler](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Backend/App/Router/NoRouteHandler.php#L44) -> `adminhtml/noroute/index` + * default (sortOrder: 100) [Magento\Framework\App\Router\NoRouteHandler](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/App/Router/NoRouteHandler.php) From f15511782ce6a2397d0206d3cb0132c10fbecae7 Mon Sep 17 00:00:00 2001 From: portchris Date: Thu, 2 Jan 2020 16:46:40 +1300 Subject: [PATCH 08/14] Area was missing from File fallback rule Update Section: Demonstrate the ability to use layout fallback for customizations and debugging - File fallback rule --- .../4. Determine the layout initialization process.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2. Request Flow Processing/4. Determine the layout initialization process.md b/2. Request Flow Processing/4. Determine the layout initialization process.md index 6223c03..58a9123 100644 --- a/2. Request Flow Processing/4. Determine the layout initialization process.md +++ b/2. Request Flow Processing/4. Determine the layout initialization process.md @@ -316,7 +316,7 @@ Collector\Library - Source of base layout files introduced by modules * - when set 'module_name': * //templates - * /view//templates + * /view//templates * /view/base/templates - View\Design\FileResolution\Fallback\Resolver\Simple::resolveFile(fileRule) From 97671cc4a1e5cddef8accbdc054cdb534232c181 Mon Sep 17 00:00:00 2001 From: portchris Date: Thu, 2 Jan 2020 16:57:23 +1300 Subject: [PATCH 09/14] Missing in file paths Update Section: Demonstrate the ability to use layout fallback for customizations and debugging - File fallback rule Update Section: Determine module layout XML schema - layouts.xml, declare available page layouts --- .../4. Determine the layout initialization process.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/2. Request Flow Processing/4. Determine the layout initialization process.md b/2. Request Flow Processing/4. Determine the layout initialization process.md index 6223c03..9a2ad77 100644 --- a/2. Request Flow Processing/4. Determine the layout initialization process.md +++ b/2. Request Flow Processing/4. Determine the layout initialization process.md @@ -164,7 +164,7 @@ Same as layout plus: ### layouts.xml - declare available page layouts -- /view//layouts.xml +- /view//layouts.xml - /_/layouts.xml - base: @@ -316,7 +316,7 @@ Collector\Library - Source of base layout files introduced by modules * - when set 'module_name': * //templates - * /view//templates + * /view//templates * /view/base/templates - View\Design\FileResolution\Fallback\Resolver\Simple::resolveFile(fileRule) From 0ab4344782c211f49b153ad2f5d625860467424d Mon Sep 17 00:00:00 2001 From: Cyildirim Date: Sat, 18 Jan 2020 22:01:30 +0000 Subject: [PATCH 10/14] Link url fix and examples have been added on 4.1 --- .../1. Demonstrate ability to use data-related classes.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/4. Working with Databases in Magento/1. Demonstrate ability to use data-related classes.md b/4. Working with Databases in Magento/1. Demonstrate ability to use data-related classes.md index 3593d32..05a1c4b 100644 --- a/4. Working with Databases in Magento/1. Demonstrate ability to use data-related classes.md +++ b/4. Working with Databases in Magento/1. Demonstrate ability to use data-related classes.md @@ -106,16 +106,18 @@ public function getDataModel() Based on interface, calls all SETTERS with given data to fill data object -[Api\DataObjectHelper::populateWithArray](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Api/DataObjectHelper.php#L80) +[Api\DataObjectHelper::populateWithArray](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Api/DataObjectHelper.php#L80) - calls data object SETTERS `set*`, `setIs*` with given raw data - handles `custom_attributes` - data object.setCustomAttribute +Example: [Magento\Customer\Controller\Account\Edit::execute](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Customer/Controller/Account/Edit.php#L78) + ## buildOutputDataArray Based on given interface, calls all GETTERS to make resulting data array. -[Reflection\DataObjectProcessor::buildOutputDataArray](https://github.com/magento/magento2/blob/2.2-develop/lib/internal/Magento/Framework/Reflection/DataObjectProcessor.php#L72): +[Reflection\DataObjectProcessor::buildOutputDataArray](https://github.com/magento/magento2/blob/2.3/lib/internal/Magento/Framework/Reflection/DataObjectProcessor.php#L81): - \Magento\Framework\Reflection\MethodsMap::getMethodsMap - method name and getter return types - filter only getters: is..., has..., get... - get data using interface getter, e.g. $object->getSku() - based on Interface definition @@ -125,3 +127,5 @@ Based on given interface, calls all GETTERS to make resulting data array. - process return object: build return value objects with their return type annotation - process return array: cast each element to type, e.g. int[] => (int) each value - cast element to type + +Example: [Magento\Customer\Model\Address::updateData](https://github.com/magento/magento2/blob/2.3/app/code/Magento/Customer/Model/Address.php#L145) From 820a6fda741a8480c9668117571c6cd21108c409 Mon Sep 17 00:00:00 2001 From: Roman Date: Sun, 30 Aug 2020 20:13:26 +0300 Subject: [PATCH 11/14] Create Customer segments.md --- .../Customer segments.md | 259 ++++++++++++++++++ 1 file changed, 259 insertions(+) create mode 100644 xx. Magento Commerce Features/Customer segments.md diff --git a/xx. Magento Commerce Features/Customer segments.md b/xx. Magento Commerce Features/Customer segments.md new file mode 100644 index 0000000..a02679f --- /dev/null +++ b/xx. Magento Commerce Features/Customer segments.md @@ -0,0 +1,259 @@ +# Customer Segments + +Conditions: + +- customer address attributes +- customer attributes +- cart item, total qty, totals +- products in cart, in wishlist, viewed products, ordered products, viewed date, ordered date +- order address, totals, number of orders, average total amount, order date, order status - only logged in + +Listens all model evetns, matches conditions by \Magento\CustomerSegment\Model\Segment\Condition\Order\Address::getMatchedEvents + + +## Database + +- magento_customersegment_segment - name, conditions, actions +- magento_customersegment_website - many-to-many +- magento_customersegment_customer - website, added/updated date +- magento_customersegment_event - after saving segment rule, holds events that related to selected conditions + + +## Admin conditions + +namespace Magento\CustomerSegment; + +Admin form - old widget style tabs: + +- Block\Adminhtml\Customersegment\Edit\Tab\General +- Block\Adminhtml\Customersegment\Edit\Tab\Conditions + +Rendering conditions form: + +render conditions -> renderer \Magento\Rule\Block\Conditions -> segment.getConditions -> root Model\Segment\Condition\Combine\Root + + +Condition classes - hold matching rules: + +- Model\Condition\Combine\AbstractCombine +- Model\Segment\Condition\Order\Address - order_address join sales_order join customer_entity +- Model\Segment\Condition\Sales\Combine + - Model\Segment\Condition\Sales\Ordersnumber - COUNT(*) + - Model\Segment\Condition\Sales\Salesamount - sum/avg sales_order.base_grand_total + - Model\Segment\Condition\Sales\Purchasedquantity - sum/avg sales_order.total_qty_ordered +- Model\Segment\Condition\Customer\Address + - Model\Segment\Condition\Customer\Address\DefaultAddress + + +## Refresh Segment Data + +Some conditions don't work for guest visitors, despite description! Example - cart grand total amount: + +- click "Refresh" inside segment admin +- Controller\Adminhtml\Report\Customer\Customersegment\Refresh::execute +- Model\Segment::matchCustomers +- Model\ResourceModel\Segment::aggregateMatchedCustomers +- Model\ResourceModel\Segment::processConditions +- Model\Segment\Condition\Combine\Root::getSatisfiedIds +- // individual conditions +- Model\Segment\Condition\Shoppingcart\Amount::getSatisfiedIds + +```SQL +SELECT `quote`.`customer_id` FROM `quote` +WHERE (quote.is_active=1) AND (quote.store_id IN('1')) AND (quote.base_grand_total >= '100') AND (customer_id IS NOT NULL) +``` + + +## Viewed product index + +Condition by recently viewed events **SEEMS BROKEN** when full page cache is enabled. +This condition relies on `report_viewed_product_index` table, which is handled by report module. + +Configuration: + +- `reports/options/enabled` +- `reports/options/product_view_enabled` + +\Magento\Reports\Model\ReportStatus::isReportEnabled + +\Magento\Reports\Model\Product\Index\Viewed + +`catalog_controller_product_view` -> \Magento\Reports\Observer\CatalogProductViewObserver +- save into `report_viewed_product_index` +- save into `report_event`, take customer from session + +This does not work when full page cache is enabled and Varnish returns HTML directly. + + +## Listening to events and updating matched customers + +Segments needs to listen to some events related to conditions. After segment with conditions is saved, +table `magento_customersegment_event` holds events that it listens to. + +Segment rule table holds rendered `condition_sql` column with placeholders: +- :customer_id +- :website_id +- :quote_id +- :visitor_id + +Updating customer segments on events: + +- event `customer_login` +- Observer\ProcessEventObserver::execute +- Model\Customer::processEvent +- Model\Customer::getActiveSegmentsForEvent +- Model\ResourceModel\Segment\Collection::addEventFilter - join table `magento_customersegment_event` +- Model\Customer::_processSegmentsValidation +- Model\Segment::validateCustomer + * visitor_id, quote_id passed for guest +- Model\Segment\Condition\Combine\Root::isSatisfiedBy + * all conditions[].isSatisfiedBy + * all conditions[].Model\Condition\Combine\AbstractCombine::getConditionsSql + + +Result: + +- Matched segments are added to `magento_customersegment_customer` +- http context \Magento\CustomerSegment\Helper\Data::CONTEXT_SEGMENT = 'customer_segment' is updated with new segments +- customerSession.setCustomerSegmentIds + + +Event -> interested segment rules. + + +## Impact on performance + +1. Customer segments are added to full page cache keys + + \Magento\CustomerSegment\Helper\Data::CONTEXT_SEGMENT = 'customer_segment' + + \Magento\PageCache\Model\App\Response\HttpPlugin::beforeSendResponse + \Magento\Framework\App\Response\Http::sendVary + \Magento\Framework\App\Http\Context::getVaryString + + Example: + + ```php + sha1($this->serializer->serialize([ + 'customer_group' => '1', + 'customer_logged_in' => true, + 'customer_segment' => ["1"] + ])) + ``` + + This lowers chances of hitting cached page, increasing load on the server. + +1. Listens to many object save events, calculates matching conditions + + +## DepersonalizePlugin + +Does 2 things: + +1. Makes sure customerSession.CustomerSegmentIds is not deleted by Customer module DepersonalizePlugin +1. Sets full page cache key httpContext->setValue(Data::CONTEXT_SEGMENT) + + +\Magento\Framework\Pricing\Render\Layout::loadLayout: +``` + $this->layout->getUpdate()->load(); + // 1. \Magento\Customer\Model\Layout\DepersonalizePlugin::beforeGenerateXml: + // - remember customerGroupId and formKey from session + // 2. \Magento\CustomerSegment\Model\Layout\DepersonalizePlugin::beforeGenerateXml: + // - remember customerSegmentIds from customer session + $this->layout->generateXml(); + $this->layout->generateElements(); + // 3. \Magento\PageCache\Model\Layout\DepersonalizePlugin::afterGenerateElements: + // - event `depersonalize_clear_session` + // - session_write_close(); + // - clear message session + // 4. \Magento\Customer\Model\Layout\DepersonalizePlugin::afterGenerateElements: + // - clear customer session + // - restore session._form_key + // - restore customer session.customerGroupId, empty customer object with customer group + // 5. \Magento\Catalog\Model\Layout\DepersonalizePlugin::afterGenerateElements: + // - clear catalog session + // 6. \Magento\Persistent\Model\Layout\DepersonalizePlugin::afterGenerateElements: + // - clear persistent session + // 7. \Magento\CustomerSegment\Model\Layout\DepersonalizePlugin::afterGenerateElements: + // - httpContext->setValue(Data::CONTEXT_SEGMENT) + // - restore customerSession->setCustomerSegmentIds + // 8. \Magento\Checkout\Model\Layout\DepersonalizePlugin::afterGenerateElements: + // - clear checkout session +``` + +## All Depersonalize examples + +\Magento\Catalog\Model\Layout\DepersonalizePlugin::afterGenerateElements: +- clear catalog session + + + +## Catalog frontend action + +Magento has alternative implementation of recently viewed products, handled by Catalog module. +It works with full page cache, but: + +- is **not integrated** into customer segment conditions +- frontend synchronization must be enabled, adding extra calls on every page + +When sync is enabled, it makes 2 AJAX calls with every page opening: +- synchronize recently viewed products from local storage +- synchronize recently compared products from local storage + +Configuration: + +- `catalog/recently_products/synchronize_with_backend` = 0 +- `catalog/recently_products/recently_viewed_lifetime` = 1000 +- `catalog/recently_products/scope` - store view, store, website + +Other: + +- db table `catalog_product_frontend_action` +- cron `catalog_product_frontend_actions_flush` - every minute \Magento\Catalog\Cron\FrontendActionsFlush: +- deletes compared, viewed older than (default 1000) seconds +- frontend controller 'catalog/product_frontend_action/synchronize' + +Notable classes: + +- Magento\Catalog\Model\FrontendStorageConfigurationPool +- Magento\Catalog\Model\Widget\RecentlyViewedStorageConfiguration + + +\Magento\Catalog\Block\FrontendStorageManager: + +- recently_viewed_product +- recently_compared_product +- product_data_storage +- vendor/magento/module-catalog/view/frontend/web/js/storage-manager.js + +customer data section: + +- recently_viewed_product +- recently_compared_product +- product_data_storage + +Triggering recently viewed update on frontend: + +- catalog_product_view.xml +- Magento\Catalog\Block\Ui\ProductViewCounter +- vendor/magento/module-catalog/view/frontend/templates/product/view/counter.phtml +- vendor/magento/module-catalog/view/frontend/web/js/product/view/provider.js + +\Magento\Catalog\Model\ProductRender - DTO + +\Magento\Catalog\Ui\DataProvider\Product\ProductRenderCollectorComposite::collect: + +- Url - url, addToCartButton, addToCompareButton +- AdditionalInfo - isSalable, type, name, id +- Image - images +- Price - priceInfo +- ... wishlist, review, tax, gift card, bundle price + + +widget `catalog_recently_compared` template `product/widget/compared/list.phtml`: + +- UI component `widget_recently_compared` - listing, columns +- Magento_Catalog/js/product/provider-compared.js +- Magento_Catalog/js/product/storage/storage-service.js +- Magento_Catalog/js/product/storage/data-storage.js - get product data from customer section. recently viewed, compared From 1ecc89422f442c7fbc57a6bc3c8107aaaa8f9331 Mon Sep 17 00:00:00 2001 From: Roman Date: Tue, 1 Sep 2020 22:01:14 +0300 Subject: [PATCH 12/14] Update Customer segments.md --- .../Customer segments.md | 56 ++++++++++++++++--- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/xx. Magento Commerce Features/Customer segments.md b/xx. Magento Commerce Features/Customer segments.md index a02679f..ac327fe 100644 --- a/xx. Magento Commerce Features/Customer segments.md +++ b/xx. Magento Commerce Features/Customer segments.md @@ -87,10 +87,26 @@ This does not work when full page cache is enabled and Varnish returns HTML dire ## Listening to events and updating matched customers -Segments needs to listen to some events related to conditions. After segment with conditions is saved, -table `magento_customersegment_event` holds events that it listens to. +Segments needs to listen to some events related to conditions. -Segment rule table holds rendered `condition_sql` column with placeholders: +After segment with conditions is saved, table `magento_customersegment_event` holds events that it listens to: + +- Model\Segment::beforeSave +- Model\Segment::collectMatchedEvents +- recursively for each added conditions children: + - Model\Condition\Combine\AbstractCombine::getMatchedEvents + + +Segment rule table holds rendered `condition_sql`: + +- Model\Segment::beforeSave +- Model\Rule\Condition\Combine\Root::getConditionsSql +- recursively for each added conditions children: + - Model\Condition\Combine\AbstractCombine::getConditionsSql + - `_prepareConditionsSql` + + +`condition_sql` column placeholders: - :customer_id - :website_id - :quote_id @@ -182,11 +198,35 @@ Does 2 things: // - clear checkout session ``` -## All Depersonalize examples - -\Magento\Catalog\Model\Layout\DepersonalizePlugin::afterGenerateElements: -- clear catalog session - +## Create segment programmatically + +Doesn't have API interfaces, repository. + +```PHP +/** @var \Magento\CustomerSegment\Model\Segment $segment */ +$segment = $this->segmentFactory->create(); +$segment->setName($name); +$segment->setDescription(null); +$segment->setIsActive(1); +$segment->setWebsiteIds(array_keys($this->storeManager->getWebsites())); +$segment->setApplyTo(\Magento\CustomerSegment\Model\Segment::APPLY_TO_VISITORS_AND_REGISTERED); +// @see \Magento\Rule\Model\AbstractModel::loadPost +$segment->getConditions()->setConditions([])->loadArray([ + 'type' => \Magento\CustomerSegment\Model\Segment\Condition\Combine\Root::class, + 'aggregator' => 'all', + 'operator' => '', + 'value' => '1', + 'conditions' => [ + [ + 'type' => \Magento\CustomerSegment\Model\Segment\Condition\Shoppingcart\Amount::class, + 'attribute' => 'grand_total', + 'operator' => '>=', + 'value' => '100', + ] + ], +]); +$segment->save(); +``` ## Catalog frontend action From 8794f4e986dae6c67b3730daa3d0d641e1d5714e Mon Sep 17 00:00:00 2001 From: portchris Date: Mon, 27 Apr 2020 20:53:40 +1200 Subject: [PATCH 13/14] Better define an Require JS alias and preference - Take notes from Magento devdocs to better explain Require JS alias, previous was more of a preference. - Take notes from Magento devdocs to better explain Require JS preference, previous was more of an alias. --- .../4. Utilize JavaScript in Magento.md | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/3. Customizing the Magento UI/4. Utilize JavaScript in Magento.md b/3. Customizing the Magento UI/4. Utilize JavaScript in Magento.md index d71a833..0e90ef1 100644 --- a/3. Customizing the Magento UI/4. Utilize JavaScript in Magento.md +++ b/3. Customizing the Magento UI/4. Utilize JavaScript in Magento.md @@ -224,24 +224,27 @@ it’s easier and more effective to use a UI component. We are interested in: - map as alias - same as defining virtual type preference in DI ```js -var config = { - map: { - '*': { - 'Magento_Swatches/js/swatch-renderer' : 'Custom_Module/js/swatch-renderer' - } +map: { + '*': { + alias: 'Vendor_Module/js/complex/path/amd-module' } -}; +} ``` +Now we can use our 'Vendor_Module/js/complex/path/module' using `alias` in any RequireJS module or config file without needing to type the entire path. For example, in Magento, `catalogAddToCart` is mapped to 'Magento_Catalog/js/catalog-add-to-cart' and can be used anywhere as a RequireJS module name. + - map as preference - same as preference in DI, replace one class with another ```js var config = { - map: { - '*': { - uiElement: 'Magento_Ui/js/lib/core/element/element', - } + "map": { + "*": { + "": "" } + } }; ``` +* : the name of the default component you replace +* : the name of the custom component + - mixins - same as around plugins in DI. This is Magento customization over requireJS ```js var config = { From cd36d7e5f5df2365cef4122622a8337447fc34a8 Mon Sep 17 00:00:00 2001 From: Roman Date: Sat, 5 Sep 2020 00:15:05 +0300 Subject: [PATCH 14/14] Create Staging.md --- xx. Magento Commerce Features/Staging.md | 245 +++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 xx. Magento Commerce Features/Staging.md diff --git a/xx. Magento Commerce Features/Staging.md b/xx. Magento Commerce Features/Staging.md new file mode 100644 index 0000000..53a5e74 --- /dev/null +++ b/xx. Magento Commerce Features/Staging.md @@ -0,0 +1,245 @@ +# Magento 2 Staging + +## High level staging implementation overview + +- Future editions of products/categories etc. are saved as a copy with a timestamped from-to columns. +- Current staging version is saved as a flag, used in all collections to add WHERE condition +- You can browse (preview) frontend site seeing future versions passing version and signature GET parameters + + +## Demonstrate an understanding of the events processing flow + +Influence of Staging on the event processing. + +What is a modification of the event processing mechanism introduced by the staging module? + + +\Magento\Staging\Model\Event\Manager: + +- ban some events in preview mode - none by default +- ban some observers in preview mode + + - `catalog_category_prepare_save` + - `catalog_category_save_after` + - `catalog_category_save_before` + - `catalog_category_move_after` + + +## DB collection flag `disable_staging_preview` + +- connection->select() +- \Magento\Framework\DB\Adapter\Pdo\Mysql::select +- Magento\Framework\DB\SelectFactory::create +- Magento\Framework\DB\Select\SelectRenderer +- // work with select... +- \Magento\Framework\DB\Select::assemble +- \Magento\Framework\DB\Select\SelectRenderer::render + - \Magento\Framework\DB\Select\FromRenderer + - \Magento\Staging\Model\Select\FromRenderer + + +``` +from = [ + flag = [ + joinType = 'from' + tableName = 'flag' + ] +] +``` + +``` +$select->where($alias . '.created_in <= ?', $versionId); +$select->where($alias . '.updated_in > ?', $versionId); +``` + +Only known staged tables are affected - \Magento\Staging\Model\StagingList::getEntitiesTables - `*_entity` + + +## Staging modification to the Magento database operations (row_id, entity managers) + +Flow modifications introduced by staging (triggers, row_id, data versions). + +- deletes foreign keys to removed entity_id column +- creates foreign key to row_id +- replaces indexes + +**Triggers** created differently! Attributes no longer have entity_id for `_cl` tables, so one more +extra call to load entity_id by row_id is added to each update by schedule trigger. + +\Magento\Framework\Mview\View\Subscription::buildStatement +vs +\Magento\CatalogStaging\Model\Mview\View\Attribute\Subscription::buildStatement + + +trg_catalog_product_entity_int_after_insert: +```SQL +-- before +INSERT IGNORE INTO `catalog_product_flat_cl` (`entity_id`) VALUES (NEW.`entity_id`); +-- after +SET @entity_id = (SELECT `entity_id` FROM `catalog_product_entity` WHERE `row_id` = NEW.`row_id`); +INSERT IGNORE INTO `catalog_product_flat_cl` (`entity_id`) values(@entity_id); +``` + +trg_catalog_product_entity_int_after_update: +```SQL +-- before +IF (NEW.`value_id` <=> OLD.`value_id` OR NEW.`attribute_id` <=> OLD.`attribute_id` OR NEW.`store_id` <=> OLD.`store_id` OR NEW.`entity_id` <=> OLD.`entity_id` OR NEW.`value` <=> OLD.`value`) THEN INSERT IGNORE INTO `catalog_product_flat_cl` (`entity_id`) VALUES (NEW.`entity_id`); END IF; +-- after +SET @entity_id = (SELECT `entity_id` FROM `catalog_product_entity` WHERE `row_id` = NEW.`row_id`); +IF (NOT(NEW.`value_id` <=> OLD.`value_id`) OR NOT(NEW.`attribute_id` <=> OLD.`attribute_id`) OR NOT(NEW.`store_id` <=> OLD.`store_id`) OR NOT(NEW.`value` <=> OLD.`value`) OR NOT(NEW.`row_id` <=> OLD.`row_id`)) THEN INSERT IGNORE INTO `catalog_product_flat_cl` (`entity_id`) values(@entity_id); END IF; +``` + +trg_catalog_product_entity_int_after_delete: +```SQL +-- before +INSERT IGNORE INTO `catalog_product_flat_cl` (`entity_id`) VALUES (OLD.`entity_id`); +-- after +SET @entity_id = (SELECT `entity_id` FROM `catalog_product_entity` WHERE `row_id` = OLD.`row_id`); +INSERT IGNORE INTO `catalog_product_flat_cl` (`entity_id`) values(@entity_id); +``` + + +## sequence tables + +Staging migration scripts do this: `row_id` becomes auto_increment, and `entity_id` (`page_id` etc.) column +is no longer auto incremented, but still required! + +Requests like `INSERT INTO cms_page (identified) VALUES("test_page")` would result in error because page_id +is normally auto_increment and not passed in request. + +Magento fixes this by manually generating auto increments for entity_id in separate sequence tables. + +Exmple: + +- \Magento\Framework\Model\ResourceModel\Db\CreateEntityRow::prepareData +- `$output[$metadata->getIdentifierField()] = $metadata->generateIdentifier();` +- \Magento\Framework\EntityManager\Sequence\Sequence::getNextValue +- insert and return next ID into `sequence_*` table + +`sequence_cms_page`, `sequence_catalog_category`, `sequence_catalogrule`, ... + +In community edition (no staging), `$metadata->generateIdentifier()` because sequenceTable is not passed. + + +- \Magento\Framework\EntityManager\MetadataPool::getMetadata +- \Magento\Framework\EntityManager\MetadataPool::createMetadata +- new \Magento\Framework\EntityManager\EntityMetadata + - `sequence` argument: \Magento\Framework\EntityManager\Sequence\SequenceFactory::create: + - no staging - sequence = null + - staging defines `sequenceTable` - `new \Magento\Framework\EntityManager\Sequence\Sequence(connection, sequenceTable)` + + + +## Common staging plugins + +- FrontControllerInterface::beforeDispatch - validate `___version`, `___timestamp`, `___signature` +- Magento\PageCache\Model\Config::afterIsEnabled - disabled in preview mode +- Magento\Store\Model\BaseUrlChecker - disabled in preview mode +- Magento\Framework\Stdlib\DateTime\Timezone::isScopeDateInInterval - interval never validated in preview mode +- Magento\Store\Model\StoreResolver::getCurrentStoreId - use `___store` in preview mode +- Magento\Customer\Model\Session::regenerateId, destroy - never regenerate/destroy in preview mode +- getUrl - adds `___version`, `___store`, possibly `__timestamp`, `__signature` in preview mode +- disables block_html caching + + +## Staging-related modifications of the indexing process + +- plugin before Magento\Catalog\Controller\Category\View +- \Magento\CatalogStaging\Model\Plugin\Controller\View::beforeExecute +- \Magento\CatalogStaging\Model\Indexer\Category\Product\Preview::execute +- \Magento\Catalog\Model\Indexer\Category\Product\AbstractAction::reindex + +Reindex using temporary tables with suffix `_catalog_staging_tmp`, +e.g. `catalog_category_product_index_store1_catalog_staging_tmp` + + +## Save staging update + +\Magento\SalesRuleStaging\Controller\Adminhtml\Update\Save::execute +\Magento\Staging\Model\Entity\Update\Save::execute + +``` +staging[mode]: save +staging[update_id]: +staging[name]: 3 September +staging[description]: Everything is new +staging[start_time]: 2020-09-03T07:00:00.000Z +staging[end_time]: +``` + +\Magento\Staging\Model\Entity\Update\Action\Pool::getAction( + entityType = 'Magento\SalesRule\Api\Data\RuleInterface', + namespace = 'save', + actionType = mode = 'save' +) + +- \Magento\Staging\Model\Entity\Update\Action\Save\SaveAction: + - \Magento\Staging\Model\Entity\Update\Action\Save\SaveAction::createUpdate + - \Magento\Staging\Model\EntityStaging::schedule + - \Magento\CatalogRuleStaging\Model\CatalogRuleStaging::schedule + - validates intersecting updates + - sets `created_in`, saves entity model (catalog rule) +- Magento\CatalogRuleStaging\Model\Rule\Hydrator +- \Magento\CatalogRuleStaging\Model\Rule\Retriever::getEntity - $this->ruleRepository->get($entityId) + + +## Preview + +All links are automatially updated: +- \Magento\Framework\Url::getUrl +- \Magento\Framework\Url\RouteParamsPreprocessorComposite::execute +- \Magento\Staging\Model\Preview\RouteParamsPreprocessor::execute +- `[_query][___version]=`, `[_query][___store]=` +- `__timestamp=`, `__signature=` + +Example: + +vendor/magento/module-catalog/view/frontend/layout/default.xml: +```XML + + + + + + +``` + +- \Magento\Store\Model\Argument\Interpreter\ServiceUrl::evaluate +- https://m24ee.local/rest/default/V1/?___store=default&___version=1599422820&__signature=b5cd66d9ea383ea57356f28cf2dd0f8edeecbc516b4d7982f8aef2ce4bcd4d32&__timestamp=1599165421products-render-info + + +URL examples: + +- REST - `?___version=` +- category - `?update_id=` + + +Preview from admin panel: + +- https://m24ee.local/admin/staging/update/preview/key/.../?preview_store=default&preview_url=https:/m24ee.local/&preview_version=1599116400 + - header and iframe +- https://m24ee.local/?___version=1599116400&___store=default&__timestamp=1599077245&__signature=a8f3a05adb92374873a3f9c4e1d36c1bddcc9748b32b046af4264b496243f95d + + +\Magento\Staging\Plugin\Framework\App\FrontController::beforeDispatch - validate signature: + +``` +__signature = hash(sha256, "__version,__timestamp", secret key from env.php) +``` + + +## Set current version + +\Magento\CatalogStaging\Model\Category\DataProvider::getCurrentCategory + +``` +$updateId = (int) $this->request->getParam('update_id'); +$this->versionManager->setCurrentVersionId($update->getId()); +``` + + +## checkout-staging + +- disable place order in preview +- any quote, saved in preview mode, is saved in db table `quote_preview` and deleted by cron