Skip to content

Commit ff20eae

Browse files
author
Vitaliy
authored
Merge pull request #458 from bohdan-harniuk/309-add-db-schema-whitelist-generation
309 add db schema whitelist generation
2 parents e0a6140 + a8db2e1 commit ff20eae

File tree

9 files changed

+541
-9
lines changed

9 files changed

+541
-9
lines changed

resources/META-INF/plugin.xml

+1
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@
226226
<internalFileTemplate name="Magento Data Model"/>
227227
<internalFileTemplate name="Magento Data Model Interface"/>
228228
<internalFileTemplate name="Magento Module Declarative Schema XML"/>
229+
<internalFileTemplate name="Magento Module Declarative Schema Whitelist JSON"/>
229230

230231
<defaultLiveTemplates file="/liveTemplates/MagentoPWA.xml"/>
231232

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
#if (${TABLE_NAME})
3+
"${TABLE_NAME}": {
4+
#if (${COLUMNS})
5+
"column": {
6+
#set ($columns = ${COLUMNS})
7+
#foreach ($column in $columns)
8+
"$column": true,
9+
#end
10+
},
11+
#end
12+
#if (${INDEXES})
13+
"index": {
14+
#set ($indexes = ${INDEXES})
15+
#foreach ($index in $indexes)
16+
"$index": true,
17+
#end
18+
},
19+
#end
20+
#if (${CONSTRAINTS})
21+
"constraint": {
22+
#set ($constraints = ${CONSTRAINTS})
23+
#foreach ($constraint in $constraints)
24+
"$constraint": true,
25+
#end
26+
}
27+
#end
28+
}
29+
#end
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<html lang="en">
2+
<body>
3+
<p face="verdana" size="-1">
4+
The db_schema_whitelist.json file provides a history of all tables, columns, and keys added with declarative schema. It is required to allow drop operations.<br>
5+
</p>
6+
<p>
7+
Read more about <a href="https://devdocs.magento.com/guides/v2.4/extension-dev-guide/declarative-schema/migration-commands.html#create-whitelist">Create a schema whitelist</a>.
8+
</p>
9+
<p>
10+
The magento 2 whitelist generation command gets INDEX and CONSTRAINTS referenceId from the real database, db_schema.xml data used only as recommendations.
11+
Please, pay attention, in the PHP Storm file generation referenceId used from the db_schema.xml file and should be checked from the real database.
12+
</p>
13+
14+
<table width="100%" border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse">
15+
<tr>
16+
<td colspan="3"><font face="verdana" size="-1">Template's predefined variables:</font></td>
17+
</tr>
18+
<tr>
19+
<td valign="top"><nobr><font face="verdana" size="-2"><b>${TABLE_NAME}</b></font></nobr></td>
20+
<td width="10">&nbsp;</td>
21+
<td width="100%" valign="top"><font face="verdana" size="-1">Database table name.</font></td>
22+
</tr>
23+
<tr>
24+
<td valign="top"><nobr><font face="verdana" size="-2"><b>${COLUMNS}</b></font></nobr></td>
25+
<td width="10">&nbsp;</td>
26+
<td width="100%" valign="top"><font face="verdana" size="-1">Database table columns names.</font></td>
27+
</tr>
28+
<tr>
29+
<td valign="top"><nobr><font face="verdana" size="-2"><b>${INDEXES}</b></font></nobr></td>
30+
<td width="10">&nbsp;</td>
31+
<td width="100%" valign="top"><font face="verdana" size="-1">Database table indexes names.</font></td>
32+
</tr>
33+
<tr>
34+
<td valign="top"><nobr><font face="verdana" size="-2"><b>${CONSTRAINTS}</b></font></nobr></td>
35+
<td width="10">&nbsp;</td>
36+
<td width="100%" valign="top"><font face="verdana" size="-1">Database table constraints names.</font></td>
37+
</tr>
38+
</table>
39+
</body>
40+
</html>

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

+27-9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.rule.Lowercase;
1717
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.rule.NotEmptyRule;
1818
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.rule.TableNameLength;
19+
import com.magento.idea.magento2plugin.actions.generation.generator.DbSchemaWhitelistJsonGenerator;
1920
import com.magento.idea.magento2plugin.actions.generation.generator.DbSchemaXmlGenerator;
2021
import com.magento.idea.magento2plugin.magento.files.ModuleDbSchemaXml;
2122
import com.magento.idea.magento2plugin.magento.packages.database.TableColumnTypes;
@@ -131,7 +132,15 @@ private void onOK() {
131132
if (!validateFormFields()) {
132133
return;
133134
}
134-
generateDbSchemaXmlFile();
135+
final DbSchemaXmlData dbSchemaXmlData = new DbSchemaXmlData(
136+
getTableName(),
137+
getTableResource(),
138+
getTableEngine(),
139+
getTableComment(),
140+
getColumns()
141+
);
142+
generateDbSchemaXmlFile(dbSchemaXmlData);
143+
generateWhitelistJsonFile(dbSchemaXmlData);
135144

136145
this.setVisible(false);
137146
}
@@ -154,17 +163,26 @@ public static void open(
154163

155164
/**
156165
* Run db_schema.xml file generator.
166+
*
167+
* @param dbSchemaXmlData DbSchemaXmlData
157168
*/
158-
private void generateDbSchemaXmlFile() {
169+
private void generateDbSchemaXmlFile(final @NotNull DbSchemaXmlData dbSchemaXmlData) {
159170
new DbSchemaXmlGenerator(
160-
new DbSchemaXmlData(
161-
getTableName(),
162-
getTableResource(),
163-
getTableEngine(),
164-
getTableComment(),
165-
getColumns()
166-
),
171+
dbSchemaXmlData,
172+
project,
173+
moduleName
174+
).generate(NewDbSchemaAction.ACTION_NAME, false);
175+
}
176+
177+
/**
178+
* Run db_schema_whitelist.json file generator.
179+
*
180+
* @param dbSchemaXmlData DbSchemaXmlData
181+
*/
182+
private void generateWhitelistJsonFile(final @NotNull DbSchemaXmlData dbSchemaXmlData) {
183+
new DbSchemaWhitelistJsonGenerator(
167184
project,
185+
dbSchemaXmlData,
168186
moduleName
169187
).generate(NewDbSchemaAction.ACTION_NAME, false);
170188
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
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.generator;
7+
8+
import com.intellij.json.psi.JsonElement;
9+
import com.intellij.json.psi.JsonElementGenerator;
10+
import com.intellij.json.psi.JsonFile;
11+
import com.intellij.json.psi.JsonObject;
12+
import com.intellij.json.psi.JsonProperty;
13+
import com.intellij.json.psi.JsonPsiUtil;
14+
import com.intellij.json.psi.impl.JsonObjectImpl;
15+
import com.intellij.openapi.command.WriteCommandAction;
16+
import com.intellij.openapi.editor.Document;
17+
import com.intellij.openapi.project.Project;
18+
import com.intellij.psi.PsiDocumentManager;
19+
import com.intellij.psi.PsiFile;
20+
import com.magento.idea.magento2plugin.actions.generation.data.DbSchemaXmlData;
21+
import com.magento.idea.magento2plugin.actions.generation.generator.util.FindOrCreateDbSchemaWhitelistJson;
22+
import com.magento.idea.magento2plugin.magento.files.ModuleDbSchemaWhitelistJson;
23+
import com.magento.idea.magento2plugin.magento.files.ModuleDbSchemaXml;
24+
import java.util.Arrays;
25+
import java.util.Map;
26+
import java.util.Properties;
27+
import org.jetbrains.annotations.NotNull;
28+
29+
/**
30+
* The db_schema_whitelist.json file generator.
31+
*/
32+
public class DbSchemaWhitelistJsonGenerator extends FileGenerator {
33+
34+
private final Project project;
35+
private final JsonElementGenerator jsonElementGenerator;
36+
private final DbSchemaXmlData dbSchemaXmlData;
37+
private final String moduleName;
38+
39+
/**
40+
* The db_schema_whitelist.json file generator constructor.
41+
*
42+
* @param project Project
43+
* @param dbSchemaXmlData DbSchemaXmlData
44+
* @param moduleName String
45+
*/
46+
public DbSchemaWhitelistJsonGenerator(
47+
final @NotNull Project project,
48+
final @NotNull DbSchemaXmlData dbSchemaXmlData,
49+
final @NotNull String moduleName
50+
) {
51+
super(project);
52+
this.project = project;
53+
jsonElementGenerator = new JsonElementGenerator(project);
54+
this.dbSchemaXmlData = dbSchemaXmlData;
55+
this.moduleName = moduleName;
56+
}
57+
58+
/**
59+
* Generate db_schema_whitelist.json file.
60+
*
61+
* @param actionName String
62+
*
63+
* @return PsiFile
64+
*/
65+
@Override
66+
public PsiFile generate(final String actionName) {
67+
final FindOrCreateDbSchemaWhitelistJson findOrCreateDbSchemaWhitelistJson =
68+
new FindOrCreateDbSchemaWhitelistJson(project);
69+
final JsonFile dbSchemaWhitelist = (JsonFile)
70+
findOrCreateDbSchemaWhitelistJson.execute(actionName, moduleName);
71+
72+
final JsonElement topNode = dbSchemaWhitelist.getTopLevelValue();
73+
74+
for (final JsonProperty prop : ((JsonObjectImpl) topNode).getPropertyList()) {
75+
if (prop.getName().equals(dbSchemaXmlData.getTableName())) {
76+
return dbSchemaWhitelist;
77+
}
78+
}
79+
80+
WriteCommandAction.runWriteCommandAction(project, () -> {
81+
final JsonObject tableObject = jsonElementGenerator.createObject("");
82+
final JsonObject columnsObject = jsonElementGenerator.createObject("");
83+
final JsonObject constraintObject = jsonElementGenerator.createObject("");
84+
final JsonObject indexObject = jsonElementGenerator.createObject("");
85+
86+
for (final Map<String, String> columnData : dbSchemaXmlData.getColumns()) {
87+
final String columnName = columnData.get(ModuleDbSchemaXml.XML_ATTR_COLUMN_NAME);
88+
final boolean isIdentity =
89+
Boolean.parseBoolean(
90+
columnData.get(ModuleDbSchemaXml.XML_ATTR_COLUMN_IDENTITY)
91+
);
92+
93+
if (isIdentity) {
94+
JsonPsiUtil.addProperty(
95+
constraintObject,
96+
jsonElementGenerator.createProperty(
97+
ModuleDbSchemaXml.XML_ATTR_REFERENCE_ID_PK,
98+
"true"
99+
),
100+
false
101+
);
102+
103+
final String indexReferenceId = ModuleDbSchemaXml.generateIndexReferenceId(
104+
dbSchemaXmlData.getTableName(),
105+
Arrays.asList(columnName)
106+
);
107+
108+
JsonPsiUtil.addProperty(
109+
indexObject,
110+
jsonElementGenerator.createProperty(
111+
indexReferenceId,
112+
"true"
113+
),
114+
false
115+
);
116+
}
117+
118+
JsonPsiUtil.addProperty(
119+
columnsObject,
120+
jsonElementGenerator.createProperty(columnName, "true"),
121+
false
122+
);
123+
}
124+
125+
addChildObjectToObject(
126+
tableObject,
127+
ModuleDbSchemaWhitelistJson.COLUMN_OBJECT_NAME,
128+
columnsObject
129+
);
130+
131+
if (!indexObject.getPropertyList().isEmpty()) {
132+
addChildObjectToObject(
133+
tableObject,
134+
ModuleDbSchemaWhitelistJson.INDEX_OBJECT_NAME,
135+
indexObject
136+
);
137+
}
138+
139+
if (!constraintObject.getPropertyList().isEmpty()) {
140+
addChildObjectToObject(
141+
tableObject,
142+
ModuleDbSchemaWhitelistJson.CONSTRAINT_OBJECT_NAME,
143+
constraintObject
144+
);
145+
}
146+
147+
addChildObjectToObject(
148+
(JsonObject) topNode,
149+
dbSchemaXmlData.getTableName(),
150+
tableObject
151+
);
152+
});
153+
154+
final PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project);
155+
final Document document = psiDocumentManager.getDocument(dbSchemaWhitelist);
156+
157+
if (document != null) {
158+
psiDocumentManager.commitDocument(document);
159+
}
160+
161+
return dbSchemaWhitelist;
162+
}
163+
164+
/**
165+
* Add child object with specified name to the target object.
166+
*
167+
* @param target JsonObject
168+
* @param childName String
169+
* @param child JsonObject
170+
*/
171+
private void addChildObjectToObject(
172+
final @NotNull JsonObject target,
173+
final @NotNull String childName,
174+
final @NotNull JsonObject child
175+
) {
176+
JsonPsiUtil.addProperty(
177+
target,
178+
jsonElementGenerator.createProperty(
179+
childName,
180+
child.getText()
181+
),
182+
false
183+
);
184+
}
185+
186+
@Override
187+
@SuppressWarnings("PMD.UncommentedEmptyMethodBody")
188+
protected void fillAttributes(final Properties attributes) {}
189+
}

0 commit comments

Comments
 (0)