Skip to content

Commit 441031d

Browse files
Merge branch '4.3.0-develop' of github.com:magento/magento2-phpstorm-plugin into 828-rename-inspection-titles
2 parents 103b417 + 875b63d commit 441031d

File tree

46 files changed

+3818
-35
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+3818
-35
lines changed

resources/META-INF/plugin.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
<action id="MagentoCreateViewFile" class="com.magento.idea.magento2plugin.actions.context.xml.NewViewXmlAction"/>
7676
<action id="MagentoCreateWebapiFile" class="com.magento.idea.magento2plugin.actions.context.xml.NewWebapiXmlAction"/>
7777
<action id="MagentoCreateWidgetFile" class="com.magento.idea.magento2plugin.actions.context.xml.NewWidgetXmlAction"/>
78+
<action id="MagentoCreateLayoutFile" class="com.magento.idea.magento2plugin.actions.context.xml.NewLayoutXmlAction"/>
7879
<!-- Context dependent actions -->
7980
<separator/>
8081
<add-to-group group-id="NewGroup" anchor="before" relative-to-action="NewXml"/>
@@ -126,6 +127,9 @@
126127
<action id="MagentoCreateAWebApiInterfaceForService.Menu" class="com.magento.idea.magento2plugin.actions.generation.NewWebApiInterfaceAction">
127128
<add-to-group group-id="EditorPopupMenu"/>
128129
</action>
130+
<action id="MagentoInjectConstructorArgumentAction.Menu" class="com.magento.idea.magento2plugin.actions.generation.InjectConstructorArgumentAction">
131+
<add-to-group group-id="EditorPopupMenu"/>
132+
</action>
129133

130134
<action id="CopyMagentoPath"
131135
class="com.magento.idea.magento2plugin.actions.CopyMagentoPath"
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
<?xml version="1.0"?>
22
#parse("XML File Header.xml")
3-
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
3+
#if (${IS_ADMIN} == "true")
4+
#set ($isAdmin = true)
5+
#else
6+
#set ($isAdmin = false)
7+
#end
8+
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" #if ($isAdmin)layout="admin-1column"#end
9+
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
410
</page>

resources/magento2/common.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,5 @@ common.template.type=Email Type
7272
common.diagnostic.reportButtonText=Report Me
7373
common.diagnostic.reportSubmittedTitle=The report is successfully submitted!
7474
common.diagnostic.reportSubmittedMessage=Thank you for submitting your report! We will check it as soon as possible.
75+
common.layout.filename=Layout File Name
7576
common.targetMethod=Target Method

resources/magento2/validation.properties

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ validator.alphaAndDashCharacters=The {0} field must contain alphabets and dashes
99
validator.alreadyDeclared={0} is already declared in the {1} module
1010
validator.startWithNumberOrCapitalLetter=The {0} field must start with a number or a capital letter
1111
validator.onlyNumbers=The {0} field must contain numbers only
12+
validator.onlyIntegerOrFloatNumbers=The {0} field must contain only integer or float numbers
1213
validator.mustNotBeNegative={0} must not be negative
1314
validator.identifier=The {0} field must contain letters, numbers, dashes, and underscores only
1415
validator.identifier.colon=The {0} field must contain letters, numbers, colons, dashes, and underscores only
@@ -41,3 +42,8 @@ validator.lowerSnakeCase=The {0} field must be of the lower snake case format
4142
validator.menuIdentifierInvalid=The menu identifier is invalid
4243
validator.someFieldsHaveErrors=Please, check the dialog. Some fields have errors
4344
validator.dbSchema.invalidColumnType=Invalid ''{0}'' column type specified
45+
validator.arrayValuesDialog.invalidValueForRowWithName=Invalid value ''{0}'' specified for the row with name ''{1}''
46+
validator.arrayValuesDialog.namesMustBeUnique=Duplicated items names
47+
validator.arrayValuesDialog.nameMustNotBeEmpty=The array name cannot be empty
48+
validator.layoutNameRuleInvalid=The layout name is invalid
49+
validator.layoutNameUnderscoreQtyInvalid=Wrong layout name, please check

src/com/magento/idea/magento2plugin/actions/CopyMagentoPath.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
import com.intellij.psi.PsiFile;
1616
import com.intellij.psi.PsiManager;
1717
import com.magento.idea.magento2plugin.util.magento.GetModuleNameByDirectoryUtil;
18+
import java.util.ArrayList;
1819
import java.util.Arrays;
1920
import java.util.List;
21+
import javax.imageio.ImageIO;
2022
import org.jetbrains.annotations.NotNull;
2123
import org.jetbrains.annotations.Nullable;
2224

@@ -27,6 +29,8 @@ public class CopyMagentoPath extends CopyPathProvider {
2729
public static final String CSS_EXTENSION = "css";
2830
private final List<String> acceptedTypes
2931
= Arrays.asList(PHTML_EXTENSION, JS_EXTENSION, CSS_EXTENSION);
32+
private static final List<String> SUPPORTED_IMAGE_EXTENSIONS
33+
= new ArrayList<>(Arrays.asList(ImageIO.getReaderFormatNames()));
3034
public static final String SEPARATOR = "::";
3135
private int index;
3236

@@ -44,6 +48,15 @@ public class CopyMagentoPath extends CopyPathProvider {
4448
"web/"
4549
};
4650

51+
/**
52+
* Copy Magento Path actions for phtml, css, js, images extensions.
53+
*/
54+
public CopyMagentoPath() {
55+
super();
56+
57+
SUPPORTED_IMAGE_EXTENSIONS.add("svg");
58+
}
59+
4760
@Override
4861
public void update(@NotNull final AnActionEvent event) {
4962
final VirtualFile virtualFile = event.getData(PlatformDataKeys.VIRTUAL_FILE);
@@ -54,7 +67,8 @@ public void update(@NotNull final AnActionEvent event) {
5467

5568
private boolean isNotValidFile(final VirtualFile virtualFile) {
5669
return virtualFile != null && virtualFile.isDirectory()
57-
|| virtualFile != null && !acceptedTypes.contains(virtualFile.getExtension());
70+
|| virtualFile != null && !acceptedTypes.contains(virtualFile.getExtension())
71+
&& !SUPPORTED_IMAGE_EXTENSIONS.contains(virtualFile.getExtension());
5872
}
5973

6074
@Override
@@ -85,24 +99,23 @@ private boolean isNotValidFile(final VirtualFile virtualFile) {
8599
if (PHTML_EXTENSION.equals(virtualFile.getExtension())) {
86100
paths = templatePaths;
87101
} else if (JS_EXTENSION.equals(virtualFile.getExtension())
88-
|| CSS_EXTENSION.equals(virtualFile.getExtension())) {
102+
|| CSS_EXTENSION.equals(virtualFile.getExtension())
103+
|| SUPPORTED_IMAGE_EXTENSIONS.contains(virtualFile.getExtension())) {
89104
paths = webPaths;
90105
} else {
91106
return fullPath.toString();
92107
}
93-
int endIndex;
94108

95109
try {
96-
endIndex = getIndexOf(paths, fullPath, paths[++index]);
97-
} catch (ArrayIndexOutOfBoundsException exception) {
98-
// endIndex could not be found.
99-
return "";
100-
}
101-
final int offset = paths[index].length();
110+
final int endIndex = getIndexOf(paths, fullPath, paths[++index]);
111+
final int offset = paths[index].length();
102112

103-
fullPath.replace(0, endIndex + offset, "");
113+
fullPath.replace(0, endIndex + offset, "");
104114

105-
return moduleName + SEPARATOR + fullPath;
115+
return moduleName + SEPARATOR + fullPath;
116+
} catch (ArrayIndexOutOfBoundsException exception) {
117+
return fullPath.toString();
118+
}
106119
}
107120

108121
/**
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
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.xml;
7+
8+
import com.intellij.openapi.actionSystem.AnAction;
9+
import com.intellij.openapi.actionSystem.AnActionEvent;
10+
import com.intellij.openapi.actionSystem.DataContext;
11+
import com.intellij.openapi.actionSystem.LangDataKeys;
12+
import com.intellij.openapi.project.Project;
13+
import com.intellij.psi.PsiDirectory;
14+
import com.intellij.psi.PsiElement;
15+
import com.intellij.psi.PsiFile;
16+
import com.magento.idea.magento2plugin.MagentoIcons;
17+
import com.magento.idea.magento2plugin.actions.generation.dialog.NewLayoutTemplateDialog;
18+
import com.magento.idea.magento2plugin.magento.files.LayoutXml;
19+
import com.magento.idea.magento2plugin.magento.packages.Areas;
20+
import com.magento.idea.magento2plugin.magento.packages.ComponentType;
21+
import com.magento.idea.magento2plugin.magento.packages.Package;
22+
import com.magento.idea.magento2plugin.project.Settings;
23+
import com.magento.idea.magento2plugin.util.magento.GetMagentoModuleUtil;
24+
import java.util.Arrays;
25+
import java.util.List;
26+
import org.jetbrains.annotations.NotNull;
27+
import org.jetbrains.annotations.Nullable;
28+
29+
public class NewLayoutXmlAction extends AnAction {
30+
31+
public static final String ACTION_NAME = "Magento 2 Layout File";
32+
public static final String ACTION_DESCRIPTION = "Create a new Magento 2 layout.xml file";
33+
private PsiDirectory targetDirectory;
34+
35+
/**
36+
* New layout.xml file generation action constructor.
37+
*/
38+
public NewLayoutXmlAction() {
39+
super(ACTION_NAME, ACTION_DESCRIPTION, MagentoIcons.MODULE);
40+
}
41+
42+
@Override
43+
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
44+
public void update(final @NotNull AnActionEvent event) {
45+
setIsAvailableForEvent(event, false);
46+
final Project project = event.getProject();
47+
48+
if (project == null || !Settings.isEnabled(project)) {
49+
return;
50+
}
51+
final DataContext context = event.getDataContext();
52+
final PsiElement targetElement = LangDataKeys.PSI_ELEMENT.getData(context);
53+
final PsiDirectory targetDirectoryCandidate = resolveTargetDirectory(targetElement);
54+
55+
if (targetDirectoryCandidate == null) {
56+
return;
57+
}
58+
final GetMagentoModuleUtil.MagentoModuleData moduleData = GetMagentoModuleUtil
59+
.getByContext(targetDirectoryCandidate, project);
60+
61+
if (moduleData == null) {
62+
return;
63+
}
64+
final PsiDirectory viewDir = moduleData.getViewDir();
65+
66+
if (viewDir == null) {
67+
return;
68+
}
69+
final List<String> allowedDirectories = Arrays.asList(
70+
Package.moduleViewDir,
71+
Areas.adminhtml.toString(),
72+
Areas.frontend.toString()
73+
);
74+
if (!allowedDirectories.contains(targetDirectoryCandidate.getName())
75+
|| !moduleData.getType().equals(ComponentType.module)) {
76+
return;
77+
}
78+
final PsiDirectory parentDir = targetDirectoryCandidate.getParentDirectory();
79+
80+
if (parentDir == null
81+
|| !targetDirectoryCandidate.equals(viewDir) && !parentDir.equals(viewDir)) {
82+
return;
83+
}
84+
targetDirectory = targetDirectoryCandidate;
85+
setIsAvailableForEvent(event, true);
86+
}
87+
88+
@Override
89+
public void actionPerformed(final @NotNull AnActionEvent event) {
90+
if (event.getProject() == null || targetDirectory == null) {
91+
return;
92+
}
93+
94+
NewLayoutTemplateDialog.open(event.getProject(), targetDirectory);
95+
}
96+
97+
/**
98+
* Set is action available for event.
99+
*
100+
* @param event AnActionEvent
101+
* @param isAvailable boolean
102+
*/
103+
private void setIsAvailableForEvent(
104+
final @NotNull AnActionEvent event,
105+
final boolean isAvailable
106+
) {
107+
event.getPresentation().setVisible(isAvailable);
108+
event.getPresentation().setEnabled(isAvailable);
109+
}
110+
111+
/**
112+
* Resolve target directory.
113+
*
114+
* @param targetElement PsiElement
115+
*
116+
* @return PsiDirectory
117+
*/
118+
private @Nullable PsiDirectory resolveTargetDirectory(final PsiElement targetElement) {
119+
PsiDirectory target = null;
120+
121+
if (targetElement instanceof PsiDirectory) {
122+
target = (PsiDirectory) targetElement;
123+
} else if (targetElement instanceof PsiFile) {
124+
target = ((PsiFile) targetElement).getContainingDirectory();
125+
}
126+
127+
if (target == null) {
128+
return null;
129+
}
130+
131+
if (LayoutXml.PARENT_DIR.equals(target.getName())) {
132+
target = target.getParentDirectory();
133+
}
134+
135+
return target;
136+
}
137+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
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.openapi.actionSystem.AnAction;
9+
import com.intellij.openapi.actionSystem.AnActionEvent;
10+
import com.intellij.openapi.project.Project;
11+
import com.jetbrains.php.lang.psi.elements.Method;
12+
import com.jetbrains.php.lang.psi.elements.Parameter;
13+
import com.jetbrains.php.lang.psi.elements.PhpClass;
14+
import com.magento.idea.magento2plugin.MagentoIcons;
15+
import com.magento.idea.magento2plugin.actions.generation.dialog.NewArgumentInjectionDialog;
16+
import com.magento.idea.magento2plugin.magento.packages.MagentoPhpClass;
17+
import com.magento.idea.magento2plugin.project.Settings;
18+
import com.magento.idea.magento2plugin.util.RegExUtil;
19+
import com.magento.idea.magento2plugin.util.php.PhpPsiElementsUtil;
20+
import org.jetbrains.annotations.NotNull;
21+
22+
public class InjectConstructorArgumentAction extends AnAction {
23+
24+
public static final String ACTION_NAME = "Inject argument";
25+
public static final String ACTION_DESCRIPTION = "Inject argument through the DI";
26+
public static final String GATHER_ARRAY_VALUES_ACTION_DESCRIPTION = "Specify array values";
27+
private PhpClass currentPhpClass;
28+
private Parameter currentParameter;
29+
30+
/**
31+
* Inject constructor argument action constructor.
32+
*/
33+
public InjectConstructorArgumentAction() {
34+
super(ACTION_NAME, ACTION_DESCRIPTION, MagentoIcons.MODULE);
35+
}
36+
37+
@Override
38+
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
39+
public void update(final @NotNull AnActionEvent event) {
40+
setIsAvailableForEvent(event, false);
41+
final Project project = event.getProject();
42+
43+
if (project == null || !Settings.isEnabled(project)) {
44+
return;
45+
}
46+
final PhpClass phpClass = PhpPsiElementsUtil.getPhpClass(event);
47+
48+
if (phpClass == null) {
49+
return;
50+
}
51+
// Excluding argument injection generators for Test/ and *Test.php files
52+
// in order to not overload the context menu.
53+
final String filename = phpClass.getContainingFile().getName();
54+
55+
if (filename.matches(RegExUtil.Magento.TEST_FILE_NAME)
56+
|| phpClass.getPresentableFQN().matches(RegExUtil.Magento.TEST_CLASS_FQN)) {
57+
return;
58+
}
59+
final Parameter parameter = PhpPsiElementsUtil.getMethodArgument(event);
60+
61+
if (parameter == null) {
62+
return;
63+
}
64+
final Method method = parameter.getParent().getParent() instanceof Method
65+
? (Method) parameter.getParent().getParent() : null;
66+
67+
if (method == null) {
68+
return;
69+
}
70+
71+
if (!method.getAccess().isPublic()
72+
|| !MagentoPhpClass.CONSTRUCT_METHOD_NAME.equals(method.getName())) {
73+
return;
74+
}
75+
currentPhpClass = phpClass;
76+
currentParameter = parameter;
77+
setIsAvailableForEvent(event, true);
78+
}
79+
80+
@Override
81+
public void actionPerformed(final @NotNull AnActionEvent event) {
82+
if (event.getProject() == null
83+
|| currentPhpClass == null
84+
|| currentParameter == null) {
85+
return;
86+
}
87+
88+
NewArgumentInjectionDialog.open(
89+
event.getProject(),
90+
currentPhpClass,
91+
currentParameter
92+
);
93+
}
94+
95+
/**
96+
* Set is action available for event.
97+
*
98+
* @param event AnActionEvent
99+
* @param isAvailable boolean
100+
*/
101+
private void setIsAvailableForEvent(
102+
final @NotNull AnActionEvent event,
103+
final boolean isAvailable
104+
) {
105+
event.getPresentation().setVisible(isAvailable);
106+
event.getPresentation().setEnabled(isAvailable);
107+
}
108+
}

0 commit comments

Comments
 (0)