Skip to content

1139: Creating a new data patch template #1188

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Sep 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@
<action id="MagentoCreateWidgetFile" class="com.magento.idea.magento2plugin.actions.context.xml.NewWidgetXmlAction"/>
<action id="MagentoCreateLayoutFile" class="com.magento.idea.magento2plugin.actions.context.xml.NewLayoutXmlAction"/>
<action id="MagentoCreateReadmeFile" class="com.magento.idea.magento2plugin.actions.context.md.NewReadmeMdAction"/>
<action id="MagentoDataPatchFile" class="com.magento.idea.magento2plugin.actions.context.php.NewObserverAction"/>
<action id="MagentoNewObserverFile" class="com.magento.idea.magento2plugin.actions.context.php.NewObserverAction"/>
<action id="MagentoNewSetupDataPatchFile" class="com.magento.idea.magento2plugin.actions.context.php.NewSetupDataPatchAction"/>
<!-- Context dependent actions -->
<separator/>
<add-to-group group-id="NewGroup" anchor="before" relative-to-action="NewXml"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php
#parse("PHP File Header.php")

namespace ${MODULE_NAME}\Setup\Patch\Data;

use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;

/**
* Patch is mechanism, that allows to do atomic upgrade data changes.
*/
class ${CLASS_NAME} implements DataPatchInterface
{
/**
* @var ModuleDataSetupInterface
*/
private $moduleDataSetup;

/**
* @param ModuleDataSetupInterface $moduleDataSetup
*/
public function __construct(
ModuleDataSetupInterface $moduleDataSetup
) {
$this->moduleDataSetup = $moduleDataSetup;
}

/**
* Do Upgrade.
*
* @return void
*/
public function apply()
{
$this->moduleDataSetup->getConnection()->startSetup();

// TODO: The code that you want apply in the patch

$this->moduleDataSetup->getConnection()->endSetup();
}

/**
* Get aliases (previous names) for the patch.
*
* @return string[]
*/
public function getAliases()
{
return [];
}

/**
* 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()
{
return [];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!--
/*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<html>
<body>
<table width="100%" border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse">
<tr>
<td><font face="verdana" size="-1">
A data patch is a class that contains data modification instructions.
</font><br>
</td>
</tr>
<tr>
<td><font face="verdana" size="-1">
Read more About the data and schema patches in the
<a href="https://devdocs.magento.com/guides/v2.4/extension-dev-guide/declarative-schema/data-patches.html">
DevDocs</a>.
</font><br>
</td>
</tr>
</table>
<table width="100%" border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse">
<tr>
<td colspan="3"><font face="verdana" size="-1">Predefined variables explanation:</font></td>
</tr>
<tr>
<td valign="top"><nobr><font face="verdana" size="-2"><b>${CLASS_NAME}</b></font></nobr></td>
<td width="10">&nbsp;</td>
<td width="100%" valign="top"><font face="verdana" size="-1">Specifies the name of your class
</font>
</td>
</tr>
</table>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

package com.magento.idea.magento2plugin.actions.context.php;

import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.magento.idea.magento2plugin.actions.context.CustomGeneratorContextAction;
import com.magento.idea.magento2plugin.actions.generation.dialog.NewSetupDataPatchDialog;
import com.magento.idea.magento2plugin.magento.packages.ComponentType;
import com.magento.idea.magento2plugin.magento.packages.Package;
import com.magento.idea.magento2plugin.util.magento.GetMagentoModuleUtil;
import org.jetbrains.annotations.NotNull;

public class NewSetupDataPatchAction extends CustomGeneratorContextAction {

public static final String ACTION_NAME = "Magento 2 Setup Data Patch";
public static final String ACTION_DESCRIPTION = "Create a new Magento 2 Setup Data Patch";
public static final String SETUP_DIRECTORY = "Setup";
public static final String PATCH_DIRECTORY = "Patch";
public static final String DATA_DIRECTORY = "Data";

public NewSetupDataPatchAction() {
super(ACTION_NAME, ACTION_DESCRIPTION);
}

@Override
public void actionPerformed(final @NotNull AnActionEvent event) {
final GetMagentoModuleUtil.MagentoModuleData moduleData = getModuleData();

if (event.getProject() == null || moduleData == null || getDirectory() == null) {
return;
}
final String[] module = moduleData.getName().split(Package.vendorModuleNameSeparator);

if (module.length != 2) { //NOPMD
return;
}
final PsiDirectory rootDirectory = moduleData.getModuleDir().findSubdirectory(
SETUP_DIRECTORY
);

if (rootDirectory == null) {
return;
}
NewSetupDataPatchDialog.open(event.getProject(), rootDirectory, module[0], module[1]);
}

@Override
protected boolean isVisible(
final @NotNull GetMagentoModuleUtil.MagentoModuleData moduleData,
final PsiDirectory targetDirectory,
final PsiFile targetFile
) {
if (!moduleData.getType().equals(ComponentType.module)) {
return false;
}

if (SETUP_DIRECTORY.equals(targetDirectory.getName())) {
return moduleData.getModuleDir().equals(targetDirectory.getParentDirectory());
}

if (PATCH_DIRECTORY.equals(targetDirectory.getName())) {
final PsiDirectory setupDirCandidate = targetDirectory.getParentDirectory();

return setupDirCandidate != null
&& SETUP_DIRECTORY.equals(setupDirCandidate.getName())
&& moduleData.getModuleDir().equals(setupDirCandidate.getParentDirectory());
}

if (DATA_DIRECTORY.equals(targetDirectory.getName())) {
final PsiDirectory patchDirCandidate = targetDirectory.getParentDirectory();

if (patchDirCandidate == null) {
return false;
}
final PsiDirectory setupDirCandidate = patchDirCandidate.getParentDirectory();

return setupDirCandidate != null
&& PATCH_DIRECTORY.equals(patchDirCandidate.getName())
&& SETUP_DIRECTORY.equals(setupDirCandidate.getName())
&& moduleData.getModuleDir().equals(setupDirCandidate.getParentDirectory());
}

return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

package com.magento.idea.magento2plugin.actions.generation;

import com.intellij.psi.PsiDirectory;
import org.jetbrains.annotations.NotNull;

public class ModuleSetupDataPatchData {

private final String packageName;
private final String moduleName;
private final PsiDirectory baseDir;
private final String className;

/**
* Constructor.
*
* @param packageName String
* @param moduleName String
* @param baseDir PsiDirectory
*/
public ModuleSetupDataPatchData(
final @NotNull String packageName,
final @NotNull String moduleName,
final @NotNull PsiDirectory baseDir,
final @NotNull String className
) {
this.packageName = packageName;
this.moduleName = moduleName;
this.baseDir = baseDir;
this.className = className;
}

public @NotNull String getPackageName() {
return packageName;
}

public @NotNull String getModuleName() {
return moduleName;
}

public @NotNull PsiDirectory getBaseDir() {
return baseDir;
}

public @NotNull String getClassName() {
return className;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.magento.idea.magento2plugin.actions.generation.ModuleObserverData;
import com.magento.idea.magento2plugin.actions.generation.data.ObserverEventsXmlData;
import com.magento.idea.magento2plugin.actions.generation.data.ui.ComboBoxItemData;
import com.magento.idea.magento2plugin.actions.generation.dialog.reflection.GetReflectionFieldUtil;
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.annotation.FieldValidation;
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.annotation.RuleRegistry;
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.rule.DirectoryRule;
Expand All @@ -37,6 +38,7 @@
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
Expand Down Expand Up @@ -239,27 +241,34 @@ protected void onOK() {

private boolean validateFields() {
final PsiFile[] directoryFiles = getDirectoryFiles(baseDir);
final Field classNameField = GetReflectionFieldUtil.getByName("className", this.getClass());

if (directoryFiles != null) {
if (directoryFiles != null && classNameField != null) {
for (final PsiFile file : directoryFiles) {
final String className = ModuleObserverFile.resolveClassNameFromInput(
getClassName()
);

if (file.getName().equals(className + ModuleObserverFile.EXTENSION)) {
showErrorMessage(
fieldsValidationsList.get(1).getField(),
classNameField,
"Class name " + className + " already exist."
);

return false;
}
}
}
if (!getDirectoryStructure().isEmpty()
final Field directoryStructureField = GetReflectionFieldUtil.getByName(
"directoryStructure",
this.getClass()
);

if (!getDirectoryStructure().isEmpty() && directoryStructureField != null
&& !DirectoryRule.getInstance().check(getDirectoryStructure())
) {
showErrorMessage(
this.getClass().getDeclaredFields()[11],
directoryStructureField,
"The Directory Path field does not contain a valid directory."
);

Expand Down
Loading