Skip to content
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

MVP implementation of the New Magento 2 Module action #52

Merged
merged 3 commits into from
Mar 24, 2020
Merged
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
8 changes: 8 additions & 0 deletions resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
@@ -53,6 +53,10 @@
description="Create Magento around plugin method."/>
<add-to-group group-id="PhpGenerateGroup" anchor="last"/>
</group>
<group id="MagentoNewGroup">
<action id="Magento2NewModule" class="com.magento.idea.magento2plugin.actions.generation.NewModuleAction"/>
<add-to-group group-id="NewGroup" anchor="after" relative-to-action="NewDir"/>
</group>

</actions>

@@ -104,6 +108,10 @@
groupName="Magento" enabledByDefault="true" level="ERROR"
implementationClass="com.magento.idea.magento2plugin.inspections.php.PluginInspection"/>
<libraryRoot id=".phpstorm.meta.php" path=".phpstorm.meta.php/" runtime="false"/>

<internalFileTemplate name="Magento Module Composer"/>
<internalFileTemplate name="Magento Module Registration Php"/>
<internalFileTemplate name="Magento Module Xml"/>
</extensions>

<application-components>
17 changes: 17 additions & 0 deletions resources/fileTemplates/internal/Magento Module Composer.json.ft
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "${COMPOSER_PACKAGE_NAME}",
"version": "${MODULE_VERSION}",
"description": "${MODULE_DESCRIPTION}",
"type": "magento2-module",
#if (${DEPENDENCIES}) "require": {
${DEPENDENCIES} }, #end
#if (${LICENSE}) ${LICENSE}, #end
"autoload": {
"files": [
"registration.php"
],
"psr-4": {
"${PACKAGE}\\\\${MODULE_NAME}\\": ""
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php
#parse("PHP File Header.php")

use Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(ComponentRegistrar::MODULE, '${PACKAGE}_${MODULE_NAME}', __DIR__);
10 changes: 10 additions & 0 deletions resources/fileTemplates/internal/Magento Module Xml.xml.ft
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
#if (${SEQUENCES})
<module name="${PACKAGE}_${MODULE_NAME}">
${SEQUENCES}
</module>
#else
<module name="${PACKAGE}_${MODULE_NAME}" />
#end
</config>
File renamed without changes
File renamed without changes
1 change: 1 addition & 0 deletions src/com/magento/idea/magento2plugin/MagentoIcons.java
Original file line number Diff line number Diff line change
@@ -13,4 +13,5 @@
*/
public class MagentoIcons {
public static final Icon WEB_API = IconLoader.getIcon("icons/webapi.png");
public static final Icon MODULE = IconLoader.getIcon("/icons/module.png");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
package com.magento.idea.magento2plugin.actions.generation;

import com.intellij.ide.IdeView;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.magento.idea.magento2plugin.MagentoIcons;
import com.magento.idea.magento2plugin.actions.generation.dialog.NewMagentoModuleDialog;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class NewModuleAction extends com.intellij.openapi.actionSystem.AnAction {
public static String ACTION_NAME = "New Magento 2 Module";
public static String ACTION_DESCRIPTION = "Create a new Magento 2 module";

NewModuleAction() {
super(ACTION_NAME, ACTION_DESCRIPTION, MagentoIcons.MODULE);
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
DataContext dataContext = e.getDataContext();
IdeView view = LangDataKeys.IDE_VIEW.getData(dataContext);
if (view != null) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project != null) {
PsiDirectory initialBaseDir = view.getOrChooseDirectory();
if (initialBaseDir != null) {
this.invoke(project, initialBaseDir, this.getFile(dataContext), view, CommonDataKeys.EDITOR.getData(dataContext));
}
}
}
}

public void invoke(@NotNull Project project, @NotNull PsiDirectory initialBaseDir, @Nullable PsiFile file, @Nullable IdeView view, @Nullable Editor editor) {
NewMagentoModuleDialog.open(project, initialBaseDir, file, view, editor);
}

@Override
public boolean isDumbAware() {
return false;
}

@NotNull
private String getActionName() {
return this.getTemplatePresentation().getText();
}

public PsiFile getFile(DataContext dataContext) {
return CommonDataKeys.PSI_FILE.getData(dataContext);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.magento.idea.magento2plugin.actions.generation.dialog.NewMagentoModuleDialog">
<grid id="cbd77" binding="contentPane" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="10" left="10" bottom="10" right="10"/>
<constraints>
<xy x="48" y="54" width="462" height="297"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="94766" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="1" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<hspacer id="98af6">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
<grid id="9538f" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="true" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="e7465" class="javax.swing.JButton" binding="buttonOK">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="OK"/>
</properties>
</component>
<component id="5723f" class="javax.swing.JButton" binding="buttonCancel">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Cancel"/>
</properties>
</component>
</children>
</grid>
</children>
</grid>
<grid id="e3588" layout-manager="GridLayoutManager" row-count="3" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="ad3ba" class="javax.swing.JTextField" binding="packageName" default-binding="true">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
<clientProperties>
<html.disable class="java.lang.Boolean" value="true"/>
</clientProperties>
</component>
<component id="3fe2b" class="javax.swing.JLabel" binding="packageNameLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Package Name"/>
</properties>
</component>
<component id="e4858" class="javax.swing.JTextField" binding="moduleName">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
<clientProperties>
<html.disable class="java.lang.Boolean" value="true"/>
</clientProperties>
</component>
<component id="22b5e" class="javax.swing.JLabel" binding="moduleNameLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Module Name"/>
</properties>
</component>
<component id="423dc" class="javax.swing.JTextField" binding="moduleVersion">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties>
<text value="1.0.0"/>
</properties>
<clientProperties>
<html.disable class="java.lang.Boolean" value="true"/>
</clientProperties>
</component>
<component id="2af8d" class="javax.swing.JLabel" binding="moduleVersionLabel">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Module Version"/>
</properties>
</component>
</children>
</grid>
<component id="4c5ac" class="javax.swing.JTextArea" binding="moduleDescription">
<constraints>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
<preferred-size width="150" height="50"/>
</grid>
</constraints>
<properties>
<text value="N/A"/>
<toolTipText value="Module Description"/>
</properties>
<clientProperties>
<html.disable class="java.lang.Boolean" value="true"/>
</clientProperties>
</component>
<component id="ec98d" class="javax.swing.JLabel" binding="moduleDescriptionLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Module Description"/>
</properties>
</component>
</children>
</grid>
</form>
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
/*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
package com.magento.idea.magento2plugin.actions.generation.dialog;

import com.intellij.ide.IdeView;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.magento.idea.magento2plugin.actions.generation.NewModuleAction;
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.NewMagentoModuleDialogValidator;
import com.magento.idea.magento2plugin.actions.generation.generator.DirectoryGenerator;
import com.magento.idea.magento2plugin.actions.generation.generator.FileFromTemplateGenerator;
import com.magento.idea.magento2plugin.actions.generation.generator.data.ModuleDirectoriesData;
import com.magento.idea.magento2plugin.magento.files.ComposerJson;
import com.magento.idea.magento2plugin.magento.files.ModuleXml;
import com.magento.idea.magento2plugin.magento.files.RegistrationPhp;
import com.magento.idea.magento2plugin.magento.packages.MagentoPackages;
import com.magento.idea.magento2plugin.util.CamelCaseToHyphen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Properties;

public class NewMagentoModuleDialog extends JDialog {
@NotNull
private final Project project;
@NotNull
private final PsiDirectory initialBaseDir;
@Nullable
private final PsiFile file;
@Nullable
private final IdeView view;
@Nullable
private final Editor editor;
private final DirectoryGenerator directoryGenerator;
private final FileFromTemplateGenerator fileFromTemplateGenerator;
private final NewMagentoModuleDialogValidator validator;
private final CamelCaseToHyphen camelCaseToHyphen;
private JPanel contentPane;
private JButton buttonOK;
private JButton buttonCancel;
private JTextField packageName;
private JLabel packageNameLabel;
private JTextField moduleName;
private JLabel moduleNameLabel;
private JTextArea moduleDescription;
private JLabel moduleDescriptionLabel;
private JTextField moduleVersion;
private JLabel moduleVersionLabel;
private String detectedPackageName;

public NewMagentoModuleDialog(@NotNull Project project, @NotNull PsiDirectory initialBaseDir, @Nullable PsiFile file, @Nullable IdeView view, @Nullable Editor editor) {
this.project = project;
this.initialBaseDir = initialBaseDir;
this.file = file;
this.view = view;
this.editor = editor;
this.directoryGenerator = DirectoryGenerator.getInstance();
this.fileFromTemplateGenerator = FileFromTemplateGenerator.getInstance(project);
this.camelCaseToHyphen = CamelCaseToHyphen.getInstance();
this.validator = NewMagentoModuleDialogValidator.getInstance(this);
detectPackageName(initialBaseDir);
setContentPane(contentPane);
setModal(true);
getRootPane().setDefaultButton(buttonOK);
pushToMiddle();

buttonOK.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onOK();
}
});

buttonCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onCancel();
}
});

setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
onCancel();
}
});

contentPane.registerKeyboardAction(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onCancel();
}
}, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
}

private void detectPackageName(@NotNull PsiDirectory initialBaseDir) {
PsiDirectory parentDir = initialBaseDir.getParent();
if (parentDir != null && parentDir.toString().endsWith(MagentoPackages.PACKAGES_ROOT)) {
packageName.setVisible(false);
packageNameLabel.setVisible(false);
this.detectedPackageName = initialBaseDir.getName();
}
}

private void pushToMiddle() {
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
this.setLocation(dim.width / 2 -this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2);
}

private void onOK() {
if (!validator.validate()) {
return;
}
generateFiles();
this.setVisible(false);
}

private void generateFiles() {
PsiDirectory baseDir = detectedPackageName != null ? this.initialBaseDir.getParent() : this.initialBaseDir;
ModuleDirectoriesData moduleDirectoriesData = directoryGenerator.createModuleDirectories(getPackageName(), getModuleName(), baseDir);
Properties attributes = getAttributes();
PsiFile composerJson = fileFromTemplateGenerator.generate(ComposerJson.getInstance(), attributes, moduleDirectoriesData.getModuleDirectory(), NewModuleAction.ACTION_NAME);
if (composerJson == null) {
return;
}
PsiFile registrationPhp = fileFromTemplateGenerator.generate(RegistrationPhp.getInstance(), attributes, moduleDirectoriesData.getModuleDirectory(), NewModuleAction.ACTION_NAME);
if (registrationPhp == null) {
return;
}
fileFromTemplateGenerator.generate(ModuleXml.getInstance(), attributes, moduleDirectoriesData.getModuleEtcDirectory(), NewModuleAction.ACTION_NAME);
}

public String getPackageName() {
if (detectedPackageName != null) {
return detectedPackageName;
}
return this.packageName.getText().trim();
}

public String getModuleName() {
return this.moduleName.getText().trim();
}

public String getModuleDescription() {
return this.moduleDescription.getText().trim();
}

public String getModuleVersion() {
return this.moduleVersion.getText().trim();
}

private void onCancel() {
this.setVisible(false);
}

public static void open(@NotNull Project project, @NotNull PsiDirectory initialBaseDir, @Nullable PsiFile file, @Nullable IdeView view, @Nullable Editor editor) {
NewMagentoModuleDialog dialog = new NewMagentoModuleDialog(project, initialBaseDir, file, view, editor);
dialog.pack();
dialog.setVisible(true);
}

private Properties getAttributes() {
Properties attributes = new Properties();
this.fillAttributes(attributes);
return attributes;
}

private void fillAttributes(Properties attributes) {
attributes.setProperty("PACKAGE", getPackageName());
attributes.setProperty("MODULE_NAME", getModuleName());
attributes.setProperty("MODULE_DESCRIPTION", getModuleDescription());
attributes.setProperty("COMPOSER_PACKAGE_NAME", getComposerPackageName());
attributes.setProperty("MODULE_VERSION", getModuleVersion());
}

@NotNull
private String getComposerPackageName() {
return camelCaseToHyphen.convert(getPackageName())
.concat("/")
.concat(camelCaseToHyphen.convert(getModuleName()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
package com.magento.idea.magento2plugin.actions.generation.dialog.validator;

import com.magento.idea.magento2plugin.actions.generation.dialog.NewMagentoModuleDialog;
import com.magento.idea.magento2plugin.util.Regex;
import javax.swing.*;

public class NewMagentoModuleDialogValidator {
private static NewMagentoModuleDialogValidator INSTANCE = null;
private NewMagentoModuleDialog dialog;

public static NewMagentoModuleDialogValidator getInstance(NewMagentoModuleDialog dialog) {
if (null == INSTANCE) {
INSTANCE = new NewMagentoModuleDialogValidator();
}
INSTANCE.dialog = dialog;
return INSTANCE;
}

public boolean validate()
{
String errorTitle = "Error";
String packageName = dialog.getPackageName();
if (packageName.length() == 0) {
JOptionPane.showMessageDialog(null, "Package Name must not be empty.", errorTitle, JOptionPane.ERROR_MESSAGE);
return false;
}

if (!packageName.matches(Regex.ALPHANUMERIC)) {
JOptionPane.showMessageDialog(null, "Package Name must contain letters and numbers only.", errorTitle, JOptionPane.ERROR_MESSAGE);
return false;
}

if (!Character.isUpperCase(packageName.charAt(0)) && !Character.isDigit(packageName.charAt(0))) {
JOptionPane.showMessageDialog(null, "Package Name must start from a number or a capital letter", errorTitle, JOptionPane.ERROR_MESSAGE);
return false;
}

String moduleName = dialog.getModuleName();
if (moduleName.length() == 0) {
JOptionPane.showMessageDialog(null, "Module Name must not be empty.", errorTitle, JOptionPane.ERROR_MESSAGE);
return false;
}

if (!moduleName.matches(Regex.ALPHANUMERIC)) {
JOptionPane.showMessageDialog(null, "Module Name must contain letters and numbers only.", errorTitle, JOptionPane.ERROR_MESSAGE);
return false;
}

if (!Character.isUpperCase(moduleName.charAt(0)) && !Character.isDigit(moduleName.charAt(0))) {
JOptionPane.showMessageDialog(null, "Module Name must start from a number or a capital letter", errorTitle, JOptionPane.ERROR_MESSAGE);
return false;
}

if (dialog.getModuleVersion().length() == 0) {
JOptionPane.showMessageDialog(null, "Module Version must not be empty.", errorTitle, JOptionPane.ERROR_MESSAGE);
return false;
}

if (dialog.getModuleDescription().length() == 0) {
JOptionPane.showMessageDialog(null, "Module Version must not be empty.", errorTitle, JOptionPane.ERROR_MESSAGE);
return false;
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
package com.magento.idea.magento2plugin.actions.generation.generator;

import com.intellij.openapi.application.WriteAction;
import com.intellij.psi.PsiDirectory;
import com.magento.idea.magento2plugin.actions.generation.generator.data.ModuleDirectoriesData;
import org.jetbrains.annotations.NotNull;

public class DirectoryGenerator {
private static DirectoryGenerator INSTANCE = null;

public static DirectoryGenerator getInstance() {
if (null == INSTANCE) {
INSTANCE = new DirectoryGenerator();
}
return INSTANCE;
}

public ModuleDirectoriesData createModuleDirectories(@NotNull String packageName, @NotNull String moduleName, @NotNull PsiDirectory baseDirectory){
PsiDirectory packageDirectory = findOrCreateSubdirectory(baseDirectory, packageName);
PsiDirectory moduleDirectory = findOrCreateSubdirectory(packageDirectory, moduleName);
PsiDirectory moduleEtcDirectory = findOrCreateSubdirectory(moduleDirectory, "etc");
return new ModuleDirectoriesData(moduleDirectory, moduleEtcDirectory);
}

public PsiDirectory findOrCreateSubdirectory(@NotNull PsiDirectory parent, @NotNull String subdirName) {
final PsiDirectory sub = parent.findSubdirectory(subdirName);
return sub == null ? WriteAction.compute(() -> parent.createSubdirectory(subdirName)) : sub;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
package com.magento.idea.magento2plugin.actions.generation.generator;

import com.intellij.ide.fileTemplates.DefaultTemplatePropertiesProvider;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.lang.Language;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.util.IncorrectOperationException;
import com.magento.idea.magento2plugin.magento.files.ModuleFileInterface;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

public class FileFromTemplateGenerator {
private static FileFromTemplateGenerator INSTANCE = null;
private Project project;

public static FileFromTemplateGenerator getInstance(Project project) {
if (null == INSTANCE) {
INSTANCE = new FileFromTemplateGenerator();
}
INSTANCE.project = project;
return INSTANCE;
}

@Nullable
public PsiFile generate(@NotNull ModuleFileInterface moduleFile, @NotNull Properties attributes, @NotNull PsiDirectory baseDir, @NotNull String actionName) {
Ref<PsiFile> fileRef = new Ref(null);
Ref<String> exceptionRef = new Ref(null);
String filePath = baseDir.getText().concat("/").concat(moduleFile.getFileName());
CommandProcessor.getInstance().executeCommand(project, () -> {
Runnable run = () -> {
try {
PsiFile file = createFile(moduleFile, filePath, baseDir, attributes);
if (file != null) {
fileRef.set(file);
}
} catch (IncorrectOperationException | IOException var9) {
exceptionRef.set(var9.getMessage());
}

};
ApplicationManager.getApplication().runWriteAction(run);
}, actionName, null);
if (!exceptionRef.isNull()) {
Messages.showErrorDialog(exceptionRef.get(), actionName);
return null;
} else {
return fileRef.get();
}
}

@Nullable
private PsiFile createFile(@NotNull ModuleFileInterface moduleFile, @NotNull String filePath, @NotNull PsiDirectory baseDir, @NotNull Properties attributes) throws IOException, IncorrectOperationException {
List<String> path = StringUtil.split(filePath.replace(File.separator, "/"), "/");
String fileName = path.get(path.size() - 1);
PsiFile fileTemplate = createFileFromTemplate(getTestTemplateManager(), baseDir, moduleFile.getTemplate(), attributes, fileName, moduleFile.getLanguage());
if (fileTemplate == null) {
throw new IncorrectOperationException("Template not found!");
} else {
PsiElement file;

file = baseDir.add(fileTemplate);
if (file instanceof PsiFile) {
return (PsiFile)file;
} else {
return null;
}
}
}

public PsiFile createFileFromTemplate(@NotNull FileTemplateManager templateManager, @NotNull PsiDirectory directory, @NotNull String templateName, @NotNull Properties properties, @NotNull String fileName, @NotNull Language language) throws IOException {
FileTemplate fileTemplate = templateManager.getInternalTemplate(templateName);
fillDefaultProperties(templateManager, properties, directory);
String fileTemplateText = fileTemplate.getText(properties);
PsiFile file = PsiFileFactory.getInstance(project).createFileFromText(fileName, language, fileTemplateText, true, false);
if (fileTemplate.isReformatCode()) {
CodeStyleManager.getInstance(project).reformat(file);
}

return file;
}

public void fillDefaultProperties(@NotNull FileTemplateManager templateManager, @NotNull Properties props, @NotNull PsiDirectory directory) {
Properties hardCodedProperties = templateManager.getDefaultProperties();
Iterator iterator = hardCodedProperties.keySet().iterator();

while(iterator.hasNext()) {
Object propertyKey = iterator.next();
props.setProperty((String)propertyKey, hardCodedProperties.getProperty((String)propertyKey));
}

iterator = DefaultTemplatePropertiesProvider.EP_NAME.getExtensionList().iterator();

while(iterator.hasNext()) {
DefaultTemplatePropertiesProvider provider = (DefaultTemplatePropertiesProvider)iterator.next();
provider.fillProperties(directory, props);
}
}

public FileTemplateManager getTestTemplateManager() {
return FileTemplateManager.getInstance(project);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
package com.magento.idea.magento2plugin.actions.generation.generator.data;

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

public class ModuleDirectoriesData {
@NotNull
private final PsiDirectory moduleDirectory;
@NotNull
private final PsiDirectory moduleEtc;

public ModuleDirectoriesData(@NotNull PsiDirectory moduleDirectory, @NotNull PsiDirectory moduleEtc) {
this.moduleDirectory = moduleDirectory;
this.moduleEtc = moduleEtc;
}

@NotNull
public PsiDirectory getModuleDirectory() {
return moduleDirectory;
}

@NotNull
public PsiDirectory getModuleEtcDirectory() {
return moduleEtc;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
package com.magento.idea.magento2plugin.magento.files;

import com.intellij.json.JsonLanguage;
import com.intellij.lang.Language;

public class ComposerJson implements ModuleFileInterface {
public static String FILE_NAME = "composer.json";
public static String TEMPLATE = "Magento Module Composer";
private static ComposerJson INSTANCE = null;

public static ComposerJson getInstance() {
if (null == INSTANCE) {
INSTANCE = new ComposerJson();
}
return INSTANCE;
}

@Override
public String getFileName() {
return FILE_NAME;
}

@Override
public String getTemplate() {
return TEMPLATE;
}

@Override
public Language getLanguage() {
return JsonLanguage.INSTANCE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
package com.magento.idea.magento2plugin.magento.files;

import com.intellij.lang.Language;

public interface ModuleFileInterface {
public String getFileName();
public String getTemplate();
public Language getLanguage();
}
36 changes: 36 additions & 0 deletions src/com/magento/idea/magento2plugin/magento/files/ModuleXml.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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.intellij.lang.xml.XMLLanguage;

public class ModuleXml implements ModuleFileInterface {
public static String FILE_NAME = "module.xml";
public static String TEMPLATE = "Magento Module Xml";
private static ModuleXml INSTANCE = null;

public static ModuleXml getInstance() {
if (null == INSTANCE) {
INSTANCE = new ModuleXml();
}
return INSTANCE;
}

@Override
public String getFileName() {
return FILE_NAME;
}

@Override
public String getTemplate() {
return TEMPLATE;
}

@Override
public Language getLanguage() {
return XMLLanguage.INSTANCE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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;

public class RegistrationPhp implements ModuleFileInterface {
public static String FILE_NAME = "registration.php";
public static String TEMPLATE = "Magento Module Registration Php";
private static RegistrationPhp INSTANCE = null;

public static RegistrationPhp getInstance() {
if (null == INSTANCE) {
INSTANCE = new RegistrationPhp();
}
return INSTANCE;
}

@Override
public String getFileName() {
return FILE_NAME;
}

@Override
public String getTemplate() {
return TEMPLATE;
}

@Override
public Language getLanguage() {
return PhpLanguage.INSTANCE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
package com.magento.idea.magento2plugin.magento.packages;

public class MagentoPackages {
public static String PACKAGES_ROOT = "app/code";
}
31 changes: 31 additions & 0 deletions src/com/magento/idea/magento2plugin/util/CamelCaseToHyphen.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
package com.magento.idea.magento2plugin.util;

import java.lang.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CamelCaseToHyphen {
private static CamelCaseToHyphen INSTANCE = null;
public static CamelCaseToHyphen getInstance() {
if (null == INSTANCE) {
INSTANCE = new CamelCaseToHyphen();
}
return INSTANCE;
}

public String convert(String string) {
String regex = "(?=[A-Z][a-z])";
String subst = "-";

Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(string);

String result = matcher.replaceAll(subst);

return result.toLowerCase().substring(1);
}
}
11 changes: 11 additions & 0 deletions src/com/magento/idea/magento2plugin/util/Regex.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Copyright © Dmytro Kvashnin. All rights reserved.
* See COPYING.txt for license details.
*/
package com.magento.idea.magento2plugin.util;

public class Regex {

public static final String ALPHANUMERIC
= "[a-zA-Z0-9]*";
}