From 4915ec4bb941b27779aab027e16df1bc530d06cb Mon Sep 17 00:00:00 2001 From: "andrii.zinkevych" Date: Mon, 19 Sep 2022 15:14:15 +0300 Subject: [PATCH 1/5] 1139: Creating a new observer template --- resources/META-INF/plugin.xml | 1 + .../Magento Module Observer File.php.ft | 22 ++ .../Magento Module Observer File.php.html | 49 +++ .../context/php/NewObserverAction.java | 61 ++++ .../generation/ModuleObserverData.java | 69 ++++ .../generation/dialog/NewObserverDialog.form | 182 +++++++++++ .../generation/dialog/NewObserverDialog.java | 294 ++++++++++++++++++ .../generator/ModuleObserverGenerator.java | 66 ++++ .../magento/files/ModuleObserverFile.java | 59 ++++ .../TestClassObserver.php | 21 ++ .../ModuleObserverGeneratorTest.java | 40 +++ 11 files changed, 864 insertions(+) create mode 100644 resources/fileTemplates/internal/Magento Module Observer File.php.ft create mode 100644 resources/fileTemplates/internal/Magento Module Observer File.php.html create mode 100644 src/com/magento/idea/magento2plugin/actions/context/php/NewObserverAction.java create mode 100644 src/com/magento/idea/magento2plugin/actions/generation/ModuleObserverData.java create mode 100644 src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.form create mode 100644 src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java create mode 100644 src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleObserverGenerator.java create mode 100644 src/com/magento/idea/magento2plugin/magento/files/ModuleObserverFile.java create mode 100644 testData/actions/generation/generator/ModuleObserverGenerator/generateModuleObserverFile/TestClassObserver.php create mode 100644 tests/com/magento/idea/magento2plugin/actions/generation/generator/ModuleObserverGeneratorTest.java diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index e7c65a8c5..cb6caa8e9 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -79,6 +79,7 @@ + diff --git a/resources/fileTemplates/internal/Magento Module Observer File.php.ft b/resources/fileTemplates/internal/Magento Module Observer File.php.ft new file mode 100644 index 000000000..2725425e8 --- /dev/null +++ b/resources/fileTemplates/internal/Magento Module Observer File.php.ft @@ -0,0 +1,22 @@ +getEvent(); + // TODO: Implement observer method. + } +} diff --git a/resources/fileTemplates/internal/Magento Module Observer File.php.html b/resources/fileTemplates/internal/Magento Module Observer File.php.html new file mode 100644 index 000000000..6f627a70a --- /dev/null +++ b/resources/fileTemplates/internal/Magento Module Observer File.php.html @@ -0,0 +1,49 @@ + + + + + + + + + + +
+ Observers are a certain type of Magento class that can influence + general behavior, performance, or change business logic. Observers are executed whenever the + event they are configured to watch is dispatched by the event manager. + + Read more about observers. + +
+ Check out the + + Observers best practices to have a clean and professional implementation. +
+ + + + + + + + + + + + + + + + + + + +
Predefined variables explanation:
${NAMESPACE} Namespace for the class.
${CLASS_NAME} Class name.
${EVENT_NAME} The name of the observer for the event definition.
+ + diff --git a/src/com/magento/idea/magento2plugin/actions/context/php/NewObserverAction.java b/src/com/magento/idea/magento2plugin/actions/context/php/NewObserverAction.java new file mode 100644 index 000000000..6ec2cd58d --- /dev/null +++ b/src/com/magento/idea/magento2plugin/actions/context/php/NewObserverAction.java @@ -0,0 +1,61 @@ +/* + * 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.NewObserverDialog; +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 NewObserverAction extends CustomGeneratorContextAction { + + public static final String ACTION_NAME = "Magento 2 Observer"; + public static final String ACTION_DESCRIPTION = "Create a new Magento 2 Observer"; + public static final String ROOT_DIRECTORY = "Observer"; + + public NewObserverAction() { + 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[] templateData = moduleData.getName().split(Package.vendorModuleNameSeparator); + + if (templateData.length != 2) { //NOPMD + return; + } + + NewObserverDialog.open( + event.getProject(), + getDirectory(), + templateData[0], + templateData[1] + ); + } + + @Override + protected boolean isVisible( + final @NotNull GetMagentoModuleUtil.MagentoModuleData moduleData, + final PsiDirectory targetDirectory, + final PsiFile targetFile + ) { + if (!moduleData.getType().equals(ComponentType.module)) { + return false; + } + + return ROOT_DIRECTORY.equals(targetDirectory.getName()); + } +} diff --git a/src/com/magento/idea/magento2plugin/actions/generation/ModuleObserverData.java b/src/com/magento/idea/magento2plugin/actions/generation/ModuleObserverData.java new file mode 100644 index 000000000..490a21b57 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/actions/generation/ModuleObserverData.java @@ -0,0 +1,69 @@ +/* + * 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 ModuleObserverData { + + private final String packageName; + private final String moduleName; + private final String classFqn; + private final String evenName; + private final PsiDirectory baseDir; + private final String className; + + /** + * Constructor. + * + * @param packageName String + * @param moduleName String + * @param classFqn String + * @param evenName String + * @param baseDir PsiDirectory + * @param className PsiDirectory + */ + public ModuleObserverData( + final @NotNull String packageName, + final @NotNull String moduleName, + final @NotNull String classFqn, + final @NotNull String evenName, + final @NotNull PsiDirectory baseDir, + final @NotNull String className + ) { + this.packageName = packageName; + this.moduleName = moduleName; + this.classFqn = classFqn; + this.evenName = evenName; + this.baseDir = baseDir; + this.className = className; + } + + public @NotNull String getPackageName() { + return packageName; + } + + public @NotNull String getModuleName() { + return moduleName; + } + + public @NotNull String getClassFqn() { + return classFqn; + } + + public @NotNull PsiDirectory getBaseDir() { + return baseDir; + } + + public @NotNull String getClassName() { + return className; + } + + public @NotNull String getEventName() { + return evenName; + } +} diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.form b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.form new file mode 100644 index 000000000..0fde5f7ec --- /dev/null +++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.form @@ -0,0 +1,182 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java new file mode 100644 index 000000000..d0a66b683 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java @@ -0,0 +1,294 @@ +/* + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +package com.magento.idea.magento2plugin.actions.generation.dialog; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.ComboBox; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiFile; +import com.intellij.util.indexing.FileBasedIndex; +import com.magento.idea.magento2plugin.actions.context.php.NewObserverAction; +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.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; +import com.magento.idea.magento2plugin.actions.generation.dialog.validator.rule.IdentifierWithColonRule; +import com.magento.idea.magento2plugin.actions.generation.dialog.validator.rule.NotEmptyRule; +import com.magento.idea.magento2plugin.actions.generation.dialog.validator.rule.PhpClassRule; +import com.magento.idea.magento2plugin.actions.generation.generator.ModuleObserverGenerator; +import com.magento.idea.magento2plugin.actions.generation.generator.ObserverEventsXmlGenerator; +import com.magento.idea.magento2plugin.actions.generation.generator.util.DirectoryGenerator; +import com.magento.idea.magento2plugin.magento.files.ModuleObserverFile; +import com.magento.idea.magento2plugin.magento.packages.Areas; +import com.magento.idea.magento2plugin.magento.packages.Package; +import com.magento.idea.magento2plugin.stubs.indexes.EventNameIndex; +import com.magento.idea.magento2plugin.ui.FilteredComboBox; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.KeyStroke; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.ArrayList; +import java.util.Collection; + +@SuppressWarnings({ + "PMD.TooManyFields", + "PMD.ExcessiveImports", + "PMD.UnusedPrivateMethod", + "PMD.AvoidInstantiatingObjectsInLoops", + "PMD.ReturnEmptyCollectionRatherThanNull" +}) +public class NewObserverDialog extends AbstractDialog { + private static final String OBSERVER_NAME = "Observer Name"; + private static final String CLASS_NAME = "Class Name"; + private final Project project; + private final PsiDirectory baseDir; + private final String moduleName; + private final String modulePackage; + private JPanel contentPanel; + private JButton buttonOK; + private JButton buttonCancel; + + @FieldValidation(rule = RuleRegistry.NOT_EMPTY, + message = {NotEmptyRule.MESSAGE, OBSERVER_NAME}) + @FieldValidation(rule = RuleRegistry.IDENTIFIER_WITH_COLON, + message = {IdentifierWithColonRule.MESSAGE, OBSERVER_NAME}) + private JTextField observerName; + @FieldValidation(rule = RuleRegistry.NOT_EMPTY, + message = {NotEmptyRule.MESSAGE, CLASS_NAME}) + @FieldValidation(rule = RuleRegistry.PHP_CLASS, + message = {PhpClassRule.MESSAGE, CLASS_NAME}) + private JTextField className; + private JTextField directoryStructure; + private FilteredComboBox eventName; + private JComboBox observerArea; + private JLabel observerNameLabel;// NOPMD + private JLabel observerNameErrorMessage;// NOPMD + private JLabel classNameLabel;// NOPMD + private JLabel classNameErrorMessage;// NOPMD + private JLabel directoryStructureLabel;// NOPMD + private JLabel directoryStructureErrorMessage;// NOPMD + private JLabel evenNamesLabel;// NOPMD + private JLabel targetAreaLabel;// NOPMD + + /** + * Constructor. + * + * @param project Project + * @param directory PsiDirectory + * @param modulePackage String + * @param moduleName String + */ + public NewObserverDialog( + final Project project, + final PsiDirectory directory, + final String modulePackage, + final String moduleName + ) { + super(); + + this.project = project; + this.baseDir = directory; + this.modulePackage = modulePackage; + this.moduleName = moduleName; + + setContentPane(contentPanel); + setModal(true); + setTitle(NewObserverAction.ACTION_DESCRIPTION); + getRootPane().setDefaultButton(buttonOK); + + buttonOK.addActionListener((final ActionEvent event) -> onOK()); + buttonCancel.addActionListener((final ActionEvent event) -> onCancel()); + + // call onCancel() when cross is clicked + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(final WindowEvent event) { + onCancel(); + } + }); + + // call onCancel() on ESCAPE + contentPanel.registerKeyboardAction( + (final ActionEvent event) -> onCancel(), + KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT + ); + + addComponentListener( + new FocusOnAFieldListener(() -> className.requestFocusInWindow()) + ); + } + + /** + * Open dialog. + * + * @param project Project + * @param directory PsiDirectory + */ + public static void open( + final Project project, + final PsiDirectory directory, + final String modulePackage, + final String moduleName + ) { + final NewObserverDialog dialog = new NewObserverDialog( + project, + directory, + modulePackage, + moduleName + ); + dialog.pack(); + dialog.centerDialog(dialog); + dialog.setVisible(true); + } + + public String getObserverName() { + return observerName.getText().trim(); + } + + public String getClassName() { + return className.getText().trim(); + } + + public String getEvenName() { + return eventName.getSelectedItem().toString(); + } + + public String getObserverArea() { + return this.observerArea.getSelectedItem().toString(); + } + + public String getDirectoryStructure() { + return directoryStructure.getText().trim(); + } + + protected void onOK() { + if (validateFields()) { + PsiDirectory observerDirectory = baseDir; + + if (!getDirectoryStructure().isEmpty()) { + observerDirectory = DirectoryGenerator.getInstance().findOrCreateSubdirectories( + baseDir, getDirectoryStructure() + ); + } + new ModuleObserverGenerator( + new ModuleObserverData( + modulePackage, + moduleName, + getObserverClassFqn(), + getEvenName(), + observerDirectory, + ModuleObserverFile.resolveClassNameFromInput(getClassName()) + ), project).generate(NewObserverAction.ACTION_NAME, true); + + new ObserverEventsXmlGenerator(new ObserverEventsXmlData( + getObserverArea(), + getModuleName().replace( + Package.fqnSeparator, + Package.vendorModuleNameSeparator + ), + getEvenName(), + getObserverName(), + getObserverClassFqn().concat(Package.fqnSeparator).concat( + ModuleObserverFile.resolveClassNameFromInput(getClassName()) + ) + ), project).generate(NewObserverAction.ACTION_NAME); + exit(); + } + } + + private void createUIComponents() { + observerArea = new ComboBox<>(); + + for (final Areas areaEntry : Areas.values()) { + observerArea.addItem(new ComboBoxItemData(areaEntry.toString(), areaEntry.toString())); + } + + final Collection events = FileBasedIndex.getInstance().getAllKeys( + EventNameIndex.KEY, project + ); + + this.eventName = new FilteredComboBox(new ArrayList<>(events)); + } + + private boolean validateFields() { + final PsiFile[] directoryFiles = getDirectoryFiles(baseDir); + final String directory = getDirectoryStructure(); + + if (directoryFiles != null) { + for (final PsiFile file : directoryFiles) { + final String className = ModuleObserverFile.resolveClassNameFromInput( + getClassName() + ); + if (file.getName().equals(className + ModuleObserverFile.EXTENSION)) { + showErrorMessage( + fieldsValidationsList.get(1).getField(), + "Class name " + className + " already exist." + ); + + return false; + } + } + } + if (!directory.isEmpty() && !DirectoryRule.getInstance().check(directory)) { + showErrorMessage( + this.getClass().getDeclaredFields()[11], + "The Directory Path field does not contain a valid directory." + ); + + return false; + } + + return validateFormFields(); + } + + private PsiFile[] getDirectoryFiles(final PsiDirectory targetDirectory) { + PsiDirectory directory = targetDirectory; + + if (!getDirectoryStructure().isEmpty()) { + final String[] directories = getDirectoryStructure().split(Package.V_FILE_SEPARATOR); + + for(final String dir : directories) { + final PsiDirectory subdirectory = directory.findSubdirectory(dir); + + if (subdirectory == null) { + return null; + } + + directory = subdirectory; + } + } + + return directory.getFiles(); + } + + private String getModuleName() { + return modulePackage.concat(Package.fqnSeparator).concat(moduleName); + } + + private String getObserverClassFqn() { + final String folderStructureFqn = getDirectoryStructure().replace( + Package.V_FILE_SEPARATOR, Package.fqnSeparator + ); + String folderFqn = NewObserverAction.ROOT_DIRECTORY; + + if (!folderStructureFqn.isEmpty()) { + folderFqn += Package.fqnSeparator.concat(folderStructureFqn); + } + + return getModuleName().concat(Package.fqnSeparator).concat(folderFqn); + } +} diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleObserverGenerator.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleObserverGenerator.java new file mode 100644 index 000000000..c3c36edba --- /dev/null +++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleObserverGenerator.java @@ -0,0 +1,66 @@ +/* + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +package com.magento.idea.magento2plugin.actions.generation.generator; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFile; +import com.magento.idea.magento2plugin.actions.generation.ModuleObserverData; +import com.magento.idea.magento2plugin.actions.generation.generator.util.FileFromTemplateGenerator; +import com.magento.idea.magento2plugin.magento.files.ModuleObserverFile; +import java.util.Properties; +import org.jetbrains.annotations.NotNull; + +public class ModuleObserverGenerator extends FileGenerator { + + private final ModuleObserverData moduleObserverData; + private final FileFromTemplateGenerator fileFromTemplateGenerator; + + /** + * Construct generator. + * + * @param moduleObserverData ModuleObserverData + * @param project Project + */ + public ModuleObserverGenerator( + final @NotNull ModuleObserverData moduleObserverData, + final Project project + ) { + super(project); + this.moduleObserverData = moduleObserverData; + this.fileFromTemplateGenerator = new FileFromTemplateGenerator(project); + } + + /** + * Generate file. + * + * @param actionName String + * + * @return PsiFile + */ + @Override + public PsiFile generate(final String actionName) { + return fileFromTemplateGenerator.generate( + new ModuleObserverFile(moduleObserverData.getClassName()), + getAttributes(), + moduleObserverData.getBaseDir(), + actionName + ); + } + + /** + * Fill template properties. + * + * @param attributes Properties + */ + @Override + protected void fillAttributes(final Properties attributes) { + attributes.setProperty("CLASS_NAME", ModuleObserverFile.resolveClassNameFromInput( + moduleObserverData.getClassName() + )); + attributes.setProperty("NAMESPACE", moduleObserverData.getClassFqn()); + attributes.setProperty("EVENT_NAME", moduleObserverData.getEventName()); + } +} diff --git a/src/com/magento/idea/magento2plugin/magento/files/ModuleObserverFile.java b/src/com/magento/idea/magento2plugin/magento/files/ModuleObserverFile.java new file mode 100644 index 000000000..926b030e8 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/magento/files/ModuleObserverFile.java @@ -0,0 +1,59 @@ +/* + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +package com.magento.idea.magento2plugin.magento.files; + +import com.intellij.lang.Language; +import com.jetbrains.php.lang.PhpLanguage; +import org.jetbrains.annotations.NotNull; + +public class ModuleObserverFile implements ModuleFileInterface { + + public static final String FILE_SUFFIX = "Observer"; + public static final String EXTENSION = ".php"; + public static final String TEMPLATE = "Magento Module Observer File"; + private final String className; + + public ModuleObserverFile( + final @NotNull String className + ) { + this.className = resolveClassNameFromInput(className); + } + + /** + * Resolve class name from user input. + * + * @param input String + * + * @return String + */ + public static String resolveClassNameFromInput(final String input) { + if (input.length() <= FILE_SUFFIX.length()) { + return input + FILE_SUFFIX; + } + String suffix = input.substring(input.length() - FILE_SUFFIX.length()); + + if (FILE_SUFFIX.equals(suffix)) { + return input; + } else { + return input + FILE_SUFFIX; + } + } + + @Override + public String getFileName() { + return className + EXTENSION; + } + + @Override + public String getTemplate() { + return TEMPLATE; + } + + @Override + public Language getLanguage() { + return PhpLanguage.INSTANCE; + } +} diff --git a/testData/actions/generation/generator/ModuleObserverGenerator/generateModuleObserverFile/TestClassObserver.php b/testData/actions/generation/generator/ModuleObserverGenerator/generateModuleObserverFile/TestClassObserver.php new file mode 100644 index 000000000..ce5260c2c --- /dev/null +++ b/testData/actions/generation/generator/ModuleObserverGenerator/generateModuleObserverFile/TestClassObserver.php @@ -0,0 +1,21 @@ +getEvent(); + // TODO: Implement observer method. + } +} diff --git a/tests/com/magento/idea/magento2plugin/actions/generation/generator/ModuleObserverGeneratorTest.java b/tests/com/magento/idea/magento2plugin/actions/generation/generator/ModuleObserverGeneratorTest.java new file mode 100644 index 000000000..910f65c77 --- /dev/null +++ b/tests/com/magento/idea/magento2plugin/actions/generation/generator/ModuleObserverGeneratorTest.java @@ -0,0 +1,40 @@ +/* + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +package com.magento.idea.magento2plugin.actions.generation.generator; + +import com.intellij.psi.PsiFile; +import com.magento.idea.magento2plugin.actions.generation.ModuleObserverData; +import com.magento.idea.magento2plugin.magento.files.ModuleObserverFile; + +public final class ModuleObserverGeneratorTest extends BaseGeneratorTestCase { + private static final String CLASS_NAME = "TestClassObserver"; + + /** + * Test module README.md file generation. + */ + public void testGenerateModuleObserverFile() { + final PsiFile expectedFile = myFixture.configureByFile( + getFixturePath(CLASS_NAME + ModuleObserverFile.EXTENSION) + ); + final ModuleObserverGenerator generator = new ModuleObserverGenerator( + new ModuleObserverData( + "Foo", + "Bar", + "Foo\\Bar\\Observer", + "test_event_name", + getProjectDirectory(), + CLASS_NAME + ), + myFixture.getProject() + ); + final PsiFile generatedFile = generator.generate("test"); + + assertGeneratedFileIsCorrect( + expectedFile, + generatedFile + ); + } +} From 13edf083af3053b889626c38d93961172b71d31f Mon Sep 17 00:00:00 2001 From: "andrii.zinkevych" Date: Mon, 19 Sep 2022 18:28:03 +0300 Subject: [PATCH 2/5] 1139: Fixed static tests --- .../generation/dialog/NewObserverDialog.java | 21 ++++++++++--------- .../magento/files/ModuleObserverFile.java | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java index d0a66b683..0f437db8e 100644 --- a/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java +++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java @@ -28,6 +28,12 @@ import com.magento.idea.magento2plugin.magento.packages.Package; import com.magento.idea.magento2plugin.stubs.indexes.EventNameIndex; import com.magento.idea.magento2plugin.ui.FilteredComboBox; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.ArrayList; +import java.util.Collection; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; @@ -35,12 +41,6 @@ import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.KeyStroke; -import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.util.ArrayList; -import java.util.Collection; @SuppressWarnings({ "PMD.TooManyFields", @@ -226,7 +226,6 @@ private void createUIComponents() { private boolean validateFields() { final PsiFile[] directoryFiles = getDirectoryFiles(baseDir); - final String directory = getDirectoryStructure(); if (directoryFiles != null) { for (final PsiFile file : directoryFiles) { @@ -243,7 +242,9 @@ private boolean validateFields() { } } } - if (!directory.isEmpty() && !DirectoryRule.getInstance().check(directory)) { + if (!getDirectoryStructure().isEmpty() + && !DirectoryRule.getInstance().check(getDirectoryStructure()) + ) { showErrorMessage( this.getClass().getDeclaredFields()[11], "The Directory Path field does not contain a valid directory." @@ -261,7 +262,7 @@ private PsiFile[] getDirectoryFiles(final PsiDirectory targetDirectory) { if (!getDirectoryStructure().isEmpty()) { final String[] directories = getDirectoryStructure().split(Package.V_FILE_SEPARATOR); - for(final String dir : directories) { + for (final String dir : directories) { final PsiDirectory subdirectory = directory.findSubdirectory(dir); if (subdirectory == null) { @@ -286,7 +287,7 @@ private String getObserverClassFqn() { String folderFqn = NewObserverAction.ROOT_DIRECTORY; if (!folderStructureFqn.isEmpty()) { - folderFqn += Package.fqnSeparator.concat(folderStructureFqn); + folderFqn = folderFqn.concat(Package.fqnSeparator).concat(folderStructureFqn); } return getModuleName().concat(Package.fqnSeparator).concat(folderFqn); diff --git a/src/com/magento/idea/magento2plugin/magento/files/ModuleObserverFile.java b/src/com/magento/idea/magento2plugin/magento/files/ModuleObserverFile.java index 926b030e8..c6489a352 100644 --- a/src/com/magento/idea/magento2plugin/magento/files/ModuleObserverFile.java +++ b/src/com/magento/idea/magento2plugin/magento/files/ModuleObserverFile.java @@ -33,7 +33,7 @@ public static String resolveClassNameFromInput(final String input) { if (input.length() <= FILE_SUFFIX.length()) { return input + FILE_SUFFIX; } - String suffix = input.substring(input.length() - FILE_SUFFIX.length()); + final String suffix = input.substring(input.length() - FILE_SUFFIX.length()); if (FILE_SUFFIX.equals(suffix)) { return input; From e91c64ab878a4d786d26610f8821d3c236f3bb8b Mon Sep 17 00:00:00 2001 From: bohdan-harniuk Date: Mon, 19 Sep 2022 20:57:59 +0300 Subject: [PATCH 3/5] 1139: Code refactoring --- .../internal/Magento Module Observer File.php.ft | 4 ++++ .../actions/context/php/NewObserverAction.java | 3 ++- .../generation/dialog/NewObserverDialog.form | 16 +++++++++------- .../TestClassObserver.php | 4 ++++ .../generator/ModuleObserverGeneratorTest.java | 1 + 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/resources/fileTemplates/internal/Magento Module Observer File.php.ft b/resources/fileTemplates/internal/Magento Module Observer File.php.ft index 2725425e8..052c02f93 100644 --- a/resources/fileTemplates/internal/Magento Module Observer File.php.ft +++ b/resources/fileTemplates/internal/Magento Module Observer File.php.ft @@ -6,12 +6,16 @@ namespace ${NAMESPACE}; use Magento\Framework\Event\ObserverInterface; use Magento\Framework\Event\Observer; +/** +* Observes the `${EVENT_NAME}` event. +*/ class ${CLASS_NAME} implements ObserverInterface { /** * Observer for ${EVENT_NAME}. * * @param Observer $observer + * * @return void */ public function execute(Observer $observer) diff --git a/src/com/magento/idea/magento2plugin/actions/context/php/NewObserverAction.java b/src/com/magento/idea/magento2plugin/actions/context/php/NewObserverAction.java index 6ec2cd58d..87af99e92 100644 --- a/src/com/magento/idea/magento2plugin/actions/context/php/NewObserverAction.java +++ b/src/com/magento/idea/magento2plugin/actions/context/php/NewObserverAction.java @@ -52,7 +52,8 @@ protected boolean isVisible( final PsiDirectory targetDirectory, final PsiFile targetFile ) { - if (!moduleData.getType().equals(ComponentType.module)) { + if (!moduleData.getType().equals(ComponentType.module) + || !moduleData.getModuleDir().equals(targetDirectory.getParentDirectory())) { return false; } diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.form b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.form index 0fde5f7ec..720f151f3 100644 --- a/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.form +++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.form @@ -7,7 +7,7 @@ - + @@ -15,7 +15,7 @@ - + @@ -102,7 +102,9 @@ - + + + @@ -116,7 +118,9 @@ - + + + @@ -146,9 +150,7 @@ - - - + diff --git a/testData/actions/generation/generator/ModuleObserverGenerator/generateModuleObserverFile/TestClassObserver.php b/testData/actions/generation/generator/ModuleObserverGenerator/generateModuleObserverFile/TestClassObserver.php index ce5260c2c..106eb8ae2 100644 --- a/testData/actions/generation/generator/ModuleObserverGenerator/generateModuleObserverFile/TestClassObserver.php +++ b/testData/actions/generation/generator/ModuleObserverGenerator/generateModuleObserverFile/TestClassObserver.php @@ -5,12 +5,16 @@ use Magento\Framework\Event\ObserverInterface; use Magento\Framework\Event\Observer; +/** + * Observes the `test_event_name` event. + */ class TestClassObserver implements ObserverInterface { /** * Observer for test_event_name. * * @param Observer $observer + * * @return void */ public function execute(Observer $observer) diff --git a/tests/com/magento/idea/magento2plugin/actions/generation/generator/ModuleObserverGeneratorTest.java b/tests/com/magento/idea/magento2plugin/actions/generation/generator/ModuleObserverGeneratorTest.java index 910f65c77..e7d3d70e4 100644 --- a/tests/com/magento/idea/magento2plugin/actions/generation/generator/ModuleObserverGeneratorTest.java +++ b/tests/com/magento/idea/magento2plugin/actions/generation/generator/ModuleObserverGeneratorTest.java @@ -10,6 +10,7 @@ import com.magento.idea.magento2plugin.magento.files.ModuleObserverFile; public final class ModuleObserverGeneratorTest extends BaseGeneratorTestCase { + private static final String CLASS_NAME = "TestClassObserver"; /** From 4de086412d6e189271cf2a5be8b8a4526b77bcaf Mon Sep 17 00:00:00 2001 From: bohdan-harniuk Date: Mon, 19 Sep 2022 21:36:38 +0300 Subject: [PATCH 4/5] 1139: Code refactoring --- .../generation/dialog/NewObserverDialog.java | 104 ++++++++++++------ 1 file changed, 71 insertions(+), 33 deletions(-) diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java index 0f437db8e..91d4185d5 100644 --- a/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java +++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java @@ -9,6 +9,7 @@ import com.intellij.openapi.ui.ComboBox; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; +import com.intellij.ui.DocumentAdapter; import com.intellij.util.indexing.FileBasedIndex; import com.magento.idea.magento2plugin.actions.context.php.NewObserverAction; import com.magento.idea.magento2plugin.actions.generation.ModuleObserverData; @@ -28,12 +29,14 @@ import com.magento.idea.magento2plugin.magento.packages.Package; import com.magento.idea.magento2plugin.stubs.indexes.EventNameIndex; import com.magento.idea.magento2plugin.ui.FilteredComboBox; +import com.magento.idea.magento2plugin.util.CamelCaseToSnakeCase; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.Collection; +import java.util.Locale; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; @@ -41,15 +44,17 @@ import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.KeyStroke; +import javax.swing.event.DocumentEvent; +import org.jetbrains.annotations.NotNull; @SuppressWarnings({ "PMD.TooManyFields", "PMD.ExcessiveImports", - "PMD.UnusedPrivateMethod", "PMD.AvoidInstantiatingObjectsInLoops", "PMD.ReturnEmptyCollectionRatherThanNull" }) public class NewObserverDialog extends AbstractDialog { + private static final String OBSERVER_NAME = "Observer Name"; private static final String CLASS_NAME = "Class Name"; private final Project project; @@ -127,6 +132,14 @@ public void windowClosing(final WindowEvent event) { JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ); + className.getDocument().addDocumentListener(new DocumentAdapter() { + @SuppressWarnings("PMD.AccessorMethodGeneration") + @Override + public void textChanged(final @NotNull DocumentEvent event) { + autoCompleteObserverName(); + } + }); + addComponentListener( new FocusOnAFieldListener(() -> className.requestFocusInWindow()) ); @@ -155,6 +168,10 @@ public static void open( dialog.setVisible(true); } + private String getModuleName() { + return modulePackage.concat(Package.fqnSeparator).concat(moduleName); + } + public String getObserverName() { return observerName.getText().trim(); } @@ -181,7 +198,8 @@ protected void onOK() { if (!getDirectoryStructure().isEmpty()) { observerDirectory = DirectoryGenerator.getInstance().findOrCreateSubdirectories( - baseDir, getDirectoryStructure() + baseDir, + getDirectoryStructure() ); } new ModuleObserverGenerator( @@ -192,38 +210,29 @@ baseDir, getDirectoryStructure() getEvenName(), observerDirectory, ModuleObserverFile.resolveClassNameFromInput(getClassName()) - ), project).generate(NewObserverAction.ACTION_NAME, true); - - new ObserverEventsXmlGenerator(new ObserverEventsXmlData( - getObserverArea(), - getModuleName().replace( - Package.fqnSeparator, - Package.vendorModuleNameSeparator ), - getEvenName(), - getObserverName(), - getObserverClassFqn().concat(Package.fqnSeparator).concat( - ModuleObserverFile.resolveClassNameFromInput(getClassName()) - ) - ), project).generate(NewObserverAction.ACTION_NAME); + project + ).generate(NewObserverAction.ACTION_NAME, true); + + new ObserverEventsXmlGenerator( + new ObserverEventsXmlData( + getObserverArea(), + getModuleName().replace( + Package.fqnSeparator, + Package.vendorModuleNameSeparator + ), + getEvenName(), + getObserverName(), + getObserverClassFqn().concat(Package.fqnSeparator).concat( + ModuleObserverFile.resolveClassNameFromInput(getClassName()) + ) + ), + project + ).generate(NewObserverAction.ACTION_NAME); exit(); } } - private void createUIComponents() { - observerArea = new ComboBox<>(); - - for (final Areas areaEntry : Areas.values()) { - observerArea.addItem(new ComboBoxItemData(areaEntry.toString(), areaEntry.toString())); - } - - final Collection events = FileBasedIndex.getInstance().getAllKeys( - EventNameIndex.KEY, project - ); - - this.eventName = new FilteredComboBox(new ArrayList<>(events)); - } - private boolean validateFields() { final PsiFile[] directoryFiles = getDirectoryFiles(baseDir); @@ -276,10 +285,6 @@ private PsiFile[] getDirectoryFiles(final PsiDirectory targetDirectory) { return directory.getFiles(); } - private String getModuleName() { - return modulePackage.concat(Package.fqnSeparator).concat(moduleName); - } - private String getObserverClassFqn() { final String folderStructureFqn = getDirectoryStructure().replace( Package.V_FILE_SEPARATOR, Package.fqnSeparator @@ -292,4 +297,37 @@ private String getObserverClassFqn() { return getModuleName().concat(Package.fqnSeparator).concat(folderFqn); } + + private void autoCompleteObserverName() { + final String className = getClassName(); + + if (className.isEmpty()) { + return; + } + final String modifiedClassName = ModuleObserverFile.resolveClassNameFromInput(className); + final String classNameInSnakeCase = CamelCaseToSnakeCase.getInstance() + .convert(modifiedClassName); + + final String modulePackageModified = modulePackage.substring(0, 1) + .toLowerCase(Locale.getDefault()) + modulePackage.substring(1); + final String moduleNameModified = moduleName.substring(0, 1) + .toLowerCase(Locale.getDefault()) + moduleName.substring(1); + + observerName.setText( + modulePackageModified + "_" + moduleNameModified + "_" + classNameInSnakeCase + ); + } + + @SuppressWarnings({"PMD.UnusedPrivateMethod"}) + private void createUIComponents() { + observerArea = new ComboBox<>(); + + for (final Areas areaEntry : Areas.values()) { + observerArea.addItem(new ComboBoxItemData(areaEntry.toString(), areaEntry.toString())); + } + final Collection events = FileBasedIndex.getInstance().getAllKeys( + EventNameIndex.KEY, project + ); + this.eventName = new FilteredComboBox(new ArrayList<>(events)); + } } From 69463986bc0d76843eadb193868a4231a2131184 Mon Sep 17 00:00:00 2001 From: bohdan-harniuk Date: Mon, 19 Sep 2022 22:07:27 +0300 Subject: [PATCH 5/5] 1139: Code refactoring --- .../generation/dialog/NewObserverDialog.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java index 91d4185d5..178b97d98 100644 --- a/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java +++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewObserverDialog.java @@ -7,8 +7,10 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.ui.DocumentAdapter; import com.intellij.util.indexing.FileBasedIndex; import com.magento.idea.magento2plugin.actions.context.php.NewObserverAction; @@ -24,6 +26,7 @@ import com.magento.idea.magento2plugin.actions.generation.generator.ModuleObserverGenerator; import com.magento.idea.magento2plugin.actions.generation.generator.ObserverEventsXmlGenerator; import com.magento.idea.magento2plugin.actions.generation.generator.util.DirectoryGenerator; +import com.magento.idea.magento2plugin.lang.roots.MagentoTestSourceFilter; import com.magento.idea.magento2plugin.magento.files.ModuleObserverFile; import com.magento.idea.magento2plugin.magento.packages.Areas; import com.magento.idea.magento2plugin.magento.packages.Package; @@ -36,6 +39,7 @@ import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Locale; import javax.swing.JButton; import javax.swing.JComboBox; @@ -328,6 +332,24 @@ private void createUIComponents() { final Collection events = FileBasedIndex.getInstance().getAllKeys( EventNameIndex.KEY, project ); + // Filter all events declared only for tests. + events.removeIf(event -> { + final Collection files = FileBasedIndex.getInstance() + .getContainingFiles( + EventNameIndex.KEY, + event, + GlobalSearchScope.allScope(project) + ); + final List realObservers = new ArrayList<>(); + + for (final VirtualFile file : files) { + if (!MagentoTestSourceFilter.isTestSources(file, project)) { + realObservers.add(file); + } + } + + return realObservers.isEmpty(); + }); this.eventName = new FilteredComboBox(new ArrayList<>(events)); } }