Skip to content

Commit c8f351a

Browse files
Merge pull request #1188 from anzin/1139-add-setup-data-patch
1139: Creating a new data patch template
2 parents fae3dc2 + 9985598 commit c8f351a

File tree

12 files changed

+777
-5
lines changed

12 files changed

+777
-5
lines changed

resources/META-INF/plugin.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@
7878
<action id="MagentoCreateWidgetFile" class="com.magento.idea.magento2plugin.actions.context.xml.NewWidgetXmlAction"/>
7979
<action id="MagentoCreateLayoutFile" class="com.magento.idea.magento2plugin.actions.context.xml.NewLayoutXmlAction"/>
8080
<action id="MagentoCreateReadmeFile" class="com.magento.idea.magento2plugin.actions.context.md.NewReadmeMdAction"/>
81-
<action id="MagentoDataPatchFile" class="com.magento.idea.magento2plugin.actions.context.php.NewObserverAction"/>
81+
<action id="MagentoNewObserverFile" class="com.magento.idea.magento2plugin.actions.context.php.NewObserverAction"/>
82+
<action id="MagentoNewSetupDataPatchFile" class="com.magento.idea.magento2plugin.actions.context.php.NewSetupDataPatchAction"/>
8283
<!-- Context dependent actions -->
8384
<separator/>
8485
<add-to-group group-id="NewGroup" anchor="before" relative-to-action="NewXml"/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
#parse("PHP File Header.php")
3+
4+
namespace ${MODULE_NAME}\Setup\Patch\Data;
5+
6+
use Magento\Framework\Setup\ModuleDataSetupInterface;
7+
use Magento\Framework\Setup\Patch\DataPatchInterface;
8+
9+
/**
10+
* Patch is mechanism, that allows to do atomic upgrade data changes.
11+
*/
12+
class ${CLASS_NAME} implements DataPatchInterface
13+
{
14+
/**
15+
* @var ModuleDataSetupInterface
16+
*/
17+
private $moduleDataSetup;
18+
19+
/**
20+
* @param ModuleDataSetupInterface $moduleDataSetup
21+
*/
22+
public function __construct(
23+
ModuleDataSetupInterface $moduleDataSetup
24+
) {
25+
$this->moduleDataSetup = $moduleDataSetup;
26+
}
27+
28+
/**
29+
* Do Upgrade.
30+
*
31+
* @return void
32+
*/
33+
public function apply()
34+
{
35+
$this->moduleDataSetup->getConnection()->startSetup();
36+
37+
// TODO: The code that you want apply in the patch
38+
39+
$this->moduleDataSetup->getConnection()->endSetup();
40+
}
41+
42+
/**
43+
* Get aliases (previous names) for the patch.
44+
*
45+
* @return string[]
46+
*/
47+
public function getAliases()
48+
{
49+
return [];
50+
}
51+
52+
/**
53+
* Get array of patches that have to be executed prior to this.
54+
*
55+
* Example of implementation:
56+
*
57+
* [
58+
* \Vendor_Name\Module_Name\Setup\Patch\Patch1::class,
59+
* \Vendor_Name\Module_Name\Setup\Patch\Patch2::class
60+
* ]
61+
*
62+
* @return string[]
63+
*/
64+
public static function getDependencies()
65+
{
66+
return [];
67+
}
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<!--
2+
/*
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
-->
7+
<html>
8+
<body>
9+
<table width="100%" border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse">
10+
<tr>
11+
<td><font face="verdana" size="-1">
12+
A data patch is a class that contains data modification instructions.
13+
</font><br>
14+
</td>
15+
</tr>
16+
<tr>
17+
<td><font face="verdana" size="-1">
18+
Read more About the data and schema patches in the
19+
<a href="https://devdocs.magento.com/guides/v2.4/extension-dev-guide/declarative-schema/data-patches.html">
20+
DevDocs</a>.
21+
</font><br>
22+
</td>
23+
</tr>
24+
</table>
25+
<table width="100%" border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse">
26+
<tr>
27+
<td colspan="3"><font face="verdana" size="-1">Predefined variables explanation:</font></td>
28+
</tr>
29+
<tr>
30+
<td valign="top"><nobr><font face="verdana" size="-2"><b>${CLASS_NAME}</b></font></nobr></td>
31+
<td width="10">&nbsp;</td>
32+
<td width="100%" valign="top"><font face="verdana" size="-1">Specifies the name of your class
33+
</font>
34+
</td>
35+
</tr>
36+
</table>
37+
</body>
38+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright © Magento, Inc. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
6+
package com.magento.idea.magento2plugin.actions.context.php;
7+
8+
import com.intellij.openapi.actionSystem.AnActionEvent;
9+
import com.intellij.psi.PsiDirectory;
10+
import com.intellij.psi.PsiFile;
11+
import com.magento.idea.magento2plugin.actions.context.CustomGeneratorContextAction;
12+
import com.magento.idea.magento2plugin.actions.generation.dialog.NewSetupDataPatchDialog;
13+
import com.magento.idea.magento2plugin.magento.packages.ComponentType;
14+
import com.magento.idea.magento2plugin.magento.packages.Package;
15+
import com.magento.idea.magento2plugin.util.magento.GetMagentoModuleUtil;
16+
import org.jetbrains.annotations.NotNull;
17+
18+
public class NewSetupDataPatchAction extends CustomGeneratorContextAction {
19+
20+
public static final String ACTION_NAME = "Magento 2 Setup Data Patch";
21+
public static final String ACTION_DESCRIPTION = "Create a new Magento 2 Setup Data Patch";
22+
public static final String SETUP_DIRECTORY = "Setup";
23+
public static final String PATCH_DIRECTORY = "Patch";
24+
public static final String DATA_DIRECTORY = "Data";
25+
26+
public NewSetupDataPatchAction() {
27+
super(ACTION_NAME, ACTION_DESCRIPTION);
28+
}
29+
30+
@Override
31+
public void actionPerformed(final @NotNull AnActionEvent event) {
32+
final GetMagentoModuleUtil.MagentoModuleData moduleData = getModuleData();
33+
34+
if (event.getProject() == null || moduleData == null || getDirectory() == null) {
35+
return;
36+
}
37+
final String[] module = moduleData.getName().split(Package.vendorModuleNameSeparator);
38+
39+
if (module.length != 2) { //NOPMD
40+
return;
41+
}
42+
final PsiDirectory rootDirectory = moduleData.getModuleDir().findSubdirectory(
43+
SETUP_DIRECTORY
44+
);
45+
46+
if (rootDirectory == null) {
47+
return;
48+
}
49+
NewSetupDataPatchDialog.open(event.getProject(), rootDirectory, module[0], module[1]);
50+
}
51+
52+
@Override
53+
protected boolean isVisible(
54+
final @NotNull GetMagentoModuleUtil.MagentoModuleData moduleData,
55+
final PsiDirectory targetDirectory,
56+
final PsiFile targetFile
57+
) {
58+
if (!moduleData.getType().equals(ComponentType.module)) {
59+
return false;
60+
}
61+
62+
if (SETUP_DIRECTORY.equals(targetDirectory.getName())) {
63+
return moduleData.getModuleDir().equals(targetDirectory.getParentDirectory());
64+
}
65+
66+
if (PATCH_DIRECTORY.equals(targetDirectory.getName())) {
67+
final PsiDirectory setupDirCandidate = targetDirectory.getParentDirectory();
68+
69+
return setupDirCandidate != null
70+
&& SETUP_DIRECTORY.equals(setupDirCandidate.getName())
71+
&& moduleData.getModuleDir().equals(setupDirCandidate.getParentDirectory());
72+
}
73+
74+
if (DATA_DIRECTORY.equals(targetDirectory.getName())) {
75+
final PsiDirectory patchDirCandidate = targetDirectory.getParentDirectory();
76+
77+
if (patchDirCandidate == null) {
78+
return false;
79+
}
80+
final PsiDirectory setupDirCandidate = patchDirCandidate.getParentDirectory();
81+
82+
return setupDirCandidate != null
83+
&& PATCH_DIRECTORY.equals(patchDirCandidate.getName())
84+
&& SETUP_DIRECTORY.equals(setupDirCandidate.getName())
85+
&& moduleData.getModuleDir().equals(setupDirCandidate.getParentDirectory());
86+
}
87+
88+
return false;
89+
}
90+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright © Magento, Inc. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
6+
package com.magento.idea.magento2plugin.actions.generation;
7+
8+
import com.intellij.psi.PsiDirectory;
9+
import org.jetbrains.annotations.NotNull;
10+
11+
public class ModuleSetupDataPatchData {
12+
13+
private final String packageName;
14+
private final String moduleName;
15+
private final PsiDirectory baseDir;
16+
private final String className;
17+
18+
/**
19+
* Constructor.
20+
*
21+
* @param packageName String
22+
* @param moduleName String
23+
* @param baseDir PsiDirectory
24+
*/
25+
public ModuleSetupDataPatchData(
26+
final @NotNull String packageName,
27+
final @NotNull String moduleName,
28+
final @NotNull PsiDirectory baseDir,
29+
final @NotNull String className
30+
) {
31+
this.packageName = packageName;
32+
this.moduleName = moduleName;
33+
this.baseDir = baseDir;
34+
this.className = className;
35+
}
36+
37+
public @NotNull String getPackageName() {
38+
return packageName;
39+
}
40+
41+
public @NotNull String getModuleName() {
42+
return moduleName;
43+
}
44+
45+
public @NotNull PsiDirectory getBaseDir() {
46+
return baseDir;
47+
}
48+
49+
public @NotNull String getClassName() {
50+
return className;
51+
}
52+
}

src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java

+13-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.magento.idea.magento2plugin.actions.generation.ModuleObserverData;
1818
import com.magento.idea.magento2plugin.actions.generation.data.ObserverEventsXmlData;
1919
import com.magento.idea.magento2plugin.actions.generation.data.ui.ComboBoxItemData;
20+
import com.magento.idea.magento2plugin.actions.generation.dialog.reflection.GetReflectionFieldUtil;
2021
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.annotation.FieldValidation;
2122
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.annotation.RuleRegistry;
2223
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.rule.DirectoryRule;
@@ -37,6 +38,7 @@
3738
import java.awt.event.KeyEvent;
3839
import java.awt.event.WindowAdapter;
3940
import java.awt.event.WindowEvent;
41+
import java.lang.reflect.Field;
4042
import java.util.ArrayList;
4143
import java.util.Collection;
4244
import java.util.List;
@@ -239,27 +241,34 @@ protected void onOK() {
239241

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

243-
if (directoryFiles != null) {
246+
if (directoryFiles != null && classNameField != null) {
244247
for (final PsiFile file : directoryFiles) {
245248
final String className = ModuleObserverFile.resolveClassNameFromInput(
246249
getClassName()
247250
);
251+
248252
if (file.getName().equals(className + ModuleObserverFile.EXTENSION)) {
249253
showErrorMessage(
250-
fieldsValidationsList.get(1).getField(),
254+
classNameField,
251255
"Class name " + className + " already exist."
252256
);
253257

254258
return false;
255259
}
256260
}
257261
}
258-
if (!getDirectoryStructure().isEmpty()
262+
final Field directoryStructureField = GetReflectionFieldUtil.getByName(
263+
"directoryStructure",
264+
this.getClass()
265+
);
266+
267+
if (!getDirectoryStructure().isEmpty() && directoryStructureField != null
259268
&& !DirectoryRule.getInstance().check(getDirectoryStructure())
260269
) {
261270
showErrorMessage(
262-
this.getClass().getDeclaredFields()[11],
271+
directoryStructureField,
263272
"The Directory Path field does not contain a valid directory."
264273
);
265274

0 commit comments

Comments
 (0)