Utiliser la classe DataPatchInterface dans un module
Objectif
Mettre en place un module utilisant la classe DataPatchInterface
Introduction
Magento propose 2 classes permettant de définir des actions qui seront réalisées, une seule fois, lors de l'exécution de la commande bin/magento setup:upgrade
. Les 2 classes qui nous intéressent sont \Magento\Framework\Setup\Patch\DataPatchInterface
et \Magento\Framework\Setup\Patch\SchemaPatchInterface
.
Tutoriel
Le projet Git de cet article est disponible sur Froggit, lien vers le dépôt.
Fonctionnement du patch
Le Data Patch, ou patch de données, ne sera appliqué qu'une seule fois. Une fois la commande bin/magento setup:upgrade
exécutée, le patch sera ajouté à la liste des patchs appliqués par Magento. Cette liste est disponible dans la table patch_list
.
Pour être appliqué, le patch doit avoir une version supérieure à celle spécifiée dans le fichier etc/module.xml
. Pour notre exemple, le module aura la version 1.0.0 et le patch aura la version 1.0.1.
Création du patch
Le patch doit être créé dans le fichier Setup\Patch\Data
. Le fichier peut comporter le nom que l'on souhaite. Pour le tutoriel, nous allons créer des pages CMS, nous allons nommer le patch CreateCmsPage
. Voici le contenu du fichier :
<?php
namespace BejeanDeveloppement\SetupDataPatch\Setup\Patch\Data;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Framework\Setup\Patch\PatchVersionInterface;
/**
* Class CreateCmsPage
*
* @package BejeanDeveloppement\SetupDataPatch\Setup\Patch\Data
*/
class CreateCmsPage implements DataPatchInterface, PatchVersionInterface
{
/**
* CreateCmsPage constructor.
*/
public function __construct() {
}
/**
* @return void
*/
public function apply()
{
}
/**
* @return array
*/
public static function getDependencies(): array
{
return [];
}
/**
* @return array
*/
public function getAliases(): array
{
return [];
}
/**
* @return string
*/
public static function getVersion(): string
{
return '1.0.1';
}
}
Le patch implémente 2 interfaces Magento\Framework\Setup\Patch\DataPatchInterface
et Magento\Framework\Setup\Patch\PatchVersionInterface
.
La première interface étend une autre interface Magento\Framework\Setup\Patch\PatchInterface
qui permet de gérer l'application et les alias du patch. Cette interface étend une dernière interface Magento\Framework\Setup\Patch\DependentPatchInterface
qui permet de gérer les dépendances.
La seconde interface permet de gérer la version du patch. Comme indiqué ci-dessus, le patch aura la version 1.0.1.
A ce moment, le patch est prêt à être appliqué. Si la commande bin/magento setup:upgrade
est exécutée, le patch sera appliqué et ajouté à la table patch_list
.
Création d'une nouvelle page
Pour créer une nouvelle page, nous allons injecter 2 nouvelles classes : Magento\Cms\Api\Data\PageInterfaceFactory
et Magento\Cms\Api\PageRepositoryInterface
. La première classe permettra la création de la nouvelle page et la seconde réalisera l'enregistrement en base de données.
La création de la page se réalisée dans la méthode apply
, de cette manière :
/**
* @return void
* @throws LocalizedException
*/
public function apply()
{
$pageData = array(
'identifier' => 'ma-page',
'title' => 'Mon titre',
'content' => 'Mon Contenu',
'is_active' => 1,
'stores' => array(0),
'page_layout' => '1column'
);
$page = $this->pageInterfaceFactory->create()
->setData($pageData);
$this->pageRepository->save($page);
}
La première étape consiste à créer un tableau qui sera injecté, via la méthode setData
dans l'objet $page
. La seconde est dernière étape enregistre, dans la base de données, l'objet, via la classe PageRepository
.
Pensez à supprimer le patch dans la table patch_list
si vous avez exécuté la commande setup:upgrade
précédemment.
Lancez la commande bin/magento setup:upgrade
puis vérifier, dans la base de données, la présence d'une nouvelle page dans les tables cms_page
, cms_page_store
et url_rewrite
. Le patch doit également être présent dans la table patch_list
.
Suppression de la page
Pour supprimer la page, nous allons utiliser la commande bin/magento module:uninstall --non-composer BejeanDeveloppement_SetupDataPatch
. Cette dernière permet de désinstaller un module, l'argument --non-composer
permet de supprimer un module qui a été installé dans le dossier app/code
et dont qui n'a pas été installé par Composer.
La commande n'est pas magique, pour supprimer la page, il est nécessaire d'implémenter l'interface Magento\Framework\Setup\Patch\PatchRevertableInterface
qui permet d'utiliser la méthode revert
au sein du patch.
Une fois l'interface implémentée, il est nécessaire d'injecter 2 nouvelles classes au patch Magento\Framework\Api\SearchCriteriaInterface
et Magento\Framework\Api\Search\FilterGroup
qui permettront de rechercher la page à supprimer.
Au sein de la méthode revert
, il faut créer la variable $searchCriteria
qui sera un objet SearchCriteria
qui comportera un ou plusieurs objets FilterGroup
. La variable $searchCriteria
sera passé en paramètre à la méthode getList
de l'objet $this->pageRepository
. Ce dernier retournera un tableau d'objets qui sera assigné à la variable $items
.
Cette dernière sera parcourue par une boucle foreach
qui contrôlera que l'identifiant de la page à supprimer correspond à ma-page
. Puis la suppression sera réalisée par la méthode delete
de l'objet $this->pageRepository
.
Voici le contenu de la méthode revert
:
/**
* @throws LocalizedException
*/
public function revert()
{
$searchCriteria = $this->searchCriteria->setFilterGroups(
array(
$this->filterGroups->setData('identifier', 'ma-page')
)
);
$items = $this->pageRepository->getList($searchCriteria)->getItems();
foreach ($items as $page) {
if ($page->getIdentifier() === 'ma-page') {
$this->pageRepository->delete($page);
}
}
}
En lançant la commande bin/magento module:uninstall --non-composer BejeanDeveloppement_SetupDataPatch
pour supprimer la page et le module.
Pour supprimer complètement le module il est nécessaire de supprimer les fichiers sources situés dans le dossier app/code
.