package com.yiistorm.elements; import com.intellij.ide.plugins.PluginManager; import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.progress.util.ProgressIndicatorBase; import com.intellij.openapi.project.DumbModeAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowFactory; import com.intellij.openapi.wm.ex.ProgressIndicatorEx; import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentFactory; import com.yiistorm.forms.NewMigrationForm; import com.yiistorm.helpers.CommonHelper; import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; public class MigrationsToolWindow implements ToolWindowFactory { private Yiic yiic; static final public int ADD_MENUS_BACKGROUND_ACTION = 0; static final public int UPDATE_MIGRAITIONS_MENUS_BACKGROUND_ACTION = 1; static final public int CREATE_MIGRATION_BACKGROUND_ACTION = 2; static final public int APPLY_MIGRATIONS_BACKGROUND_ACTION = 3; static final public int MIGRATE_DOWN_BACKGROUND_ACTION = 4; public static MigrationsToolWindow toolw; private JPanel contentPane; private JTextArea migrateLog; private JBScrollPane scrollpane; private JTextField createMigrationName; private JMenuBar actionMenuBar; private Cursor waitCursor = new Cursor(Cursor.WAIT_CURSOR); private Cursor defaultCursor = new Cursor(Cursor.DEFAULT_CURSOR); private static String OS = System.getProperty("os.name").toLowerCase(); private Project _project; private String yiiFile; private boolean useMigrations; private String yiiProtected; private ArrayList<String> newMigrationsList = new ArrayList<String>(); public boolean NewFormDisplayed = false; final JMenuItem createMenu = new JMenuItem(); final JMenuItem migrateDown = new JMenuItem(); JMenu actionMenu = new JMenu(); NewMigrationForm newMigrationDialog; JPanel buttonsPanel = new JPanel(); private boolean MenusAdded = false; public Project getProject() { return _project; } public String runCommand(String migrateCommand) { try { Process p; String prependPath = CommonHelper.getCommandPrepend(); if (yiiFile == null) { return "Please select yiic path in YiiStorm config."; } prependPath += yiiFile; p = Runtime.getRuntime().exec(prependPath + " " + migrateCommand + " --interactive=0"); //+ "D:\\webservers\\home\\www.rest.lcl\\www\\protected\\" String lineAll = ""; if (p != null) { //p.waitFor(); BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); String line = reader.readLine(); while (line != null) { line = reader.readLine(); if (line == null) { break; } lineAll += line + "\n"; } } return lineAll; } catch (Exception e1) { return "Error! " + e1.getMessage(); } } /** * Update new migrations list * * @param writeLog */ public void updateNewMigrations(boolean writeLog) { updateNewMigrations(writeLog, false); } /** * Update new migrations list * * @param writeLog * @param openFirst */ public void updateNewMigrations(boolean writeLog, boolean openFirst) { String text; if (yiiFile == null) { text = "Please select yiic path in YiiStorm config."; } else { text = this.runCommand("migrate new"); try { Pattern regex = Pattern.compile("\\s+(m\\d+?_.+?)(?:\n|$)", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE | Pattern.MULTILINE); Matcher regexMatcher = regex.matcher(text); newMigrationsList.clear(); while (regexMatcher.find()) { newMigrationsList.add(regexMatcher.group(1)); } if (openFirst) { if (newMigrationsList.size() > 0) { MigrationsToolWindow.toolw.openMigrationFile(newMigrationsList.get(newMigrationsList.size() - 1)); } } } catch (Exception ex) { // Syntax error in the regular expression } } if (writeLog) { setMigrateLogText(text); } } @Override public void createToolWindowContent(Project project, ToolWindow toolWindow) { _project = project; toolw = this; yiic = new Yiic(); PropertiesComponent properties = PropertiesComponent.getInstance(getProject()); yiiFile = properties.getValue("yiicFile"); useMigrations = properties.getBoolean("useYiiMigrations", false); setMigrateLogText(""); contentPane = new JPanel(); contentPane.setLayout(new BorderLayout()); scrollpane = new JBScrollPane(); migrateLog = new JTextArea("Yii migrations"); //migrateLog.setLineWrap(true); migrateLog.setEditable(false); migrateLog.setEnabled(true); scrollpane.setLayout(new ScrollPaneLayout()); scrollpane.getViewport().add(migrateLog); contentPane.add(scrollpane, BorderLayout.CENTER); FlowLayout layout = new FlowLayout(); layout.setAlignment(FlowLayout.LEFT); buttonsPanel.setLayout(layout); actionMenuBar = new JMenuBar(); actionMenuBar.setBackground(new Color(0, 0, 0, 0)); actionMenuBar.setLayout(layout); actionMenuBar.setBorderPainted(false); buttonsPanel.add(actionMenuBar); contentPane.add(buttonsPanel, BorderLayout.NORTH); ContentFactory contentFactory = ContentFactory.SERVICE.getInstance(); Content content = contentFactory.createContent(contentPane, "", false); toolWindow.getContentManager().addContent(content); if (yiiFile != null && yiic.yiicIsRunnable(yiiFile)) { yiiProtected = yiiFile.replaceAll("yiic.(bat|php)$", ""); runBackgroundTask(this.ADD_MENUS_BACKGROUND_ACTION, project); } else { setMigrateLogText("Set path to yiic in project settings -> YiiStorm"); } } public void runBackgroundTask(final int Action, Project project) { final Task.Backgroundable task = new Task.Backgroundable(project, "Yii migrations", false) { @Override public String getProcessId() { return "Yii migrations"; } @Override public DumbModeAction getDumbModeAction() { return DumbModeAction.CANCEL; } public void run(@NotNull final ProgressIndicator indicator) { final Task.Backgroundable this_task = this; ((ProgressIndicatorEx) indicator).addStateDelegate(new ProgressIndicatorBase() { @Override public void cancel() { this_task.onCancel(); } }); switch (Action) { case MigrationsToolWindow.MIGRATE_DOWN_BACKGROUND_ACTION: indicator.setText("Migrating 1 down"); indicator.setFraction(0.1); MigrationsToolWindow.toolw.migrateDown(); indicator.setFraction(0.3); MigrationsToolWindow.toolw.updateNewMigrations(true); indicator.setFraction(0.5); indicator.setText("Updating migrations menu"); MigrationsToolWindow.toolw.fillActionMenu(); indicator.setFraction(0.8); break; case MigrationsToolWindow.ADD_MENUS_BACKGROUND_ACTION: indicator.setText("Updating migrations list"); indicator.setFraction(0.1); MigrationsToolWindow.toolw.updateNewMigrations(true); indicator.setFraction(0.5); MigrationsToolWindow.toolw.addMenus(); indicator.setFraction(0.8); break; case MigrationsToolWindow.UPDATE_MIGRAITIONS_MENUS_BACKGROUND_ACTION: indicator.setText("Updating migrations list"); indicator.setFraction(0.1); MigrationsToolWindow.toolw.updateNewMigrations(true); indicator.setFraction(0.5); indicator.setText("Updating migrations menu"); MigrationsToolWindow.toolw.fillActionMenu(); indicator.setFraction(0.8); break; case MigrationsToolWindow.APPLY_MIGRATIONS_BACKGROUND_ACTION: indicator.setText("Applying migrations list"); indicator.setFraction(0.1); MigrationsToolWindow.toolw.applyMigrations(); indicator.setFraction(0.3); MigrationsToolWindow.toolw.updateNewMigrations(false); indicator.setFraction(0.5); indicator.setText("Updating migrations menu"); MigrationsToolWindow.toolw.fillActionMenu(); indicator.setFraction(0.8); break; case MigrationsToolWindow.CREATE_MIGRATION_BACKGROUND_ACTION: indicator.setText("Creating migration: " + newMigrationDialog.getMigrationName()); indicator.setFraction(0.1); MigrationsToolWindow.toolw.createMigrationByName(newMigrationDialog.getMigrationName()); indicator.setFraction(0.3); MigrationsToolWindow.toolw.updateNewMigrations(false, true); indicator.setFraction(0.5); indicator.setText("Updating migrations menu"); MigrationsToolWindow.toolw.fillActionMenu(); indicator.setFraction(0.8); break; } indicator.stop(); } }; task.setCancelText("Stop processing").queue(); } public void createMigrationByName(String name) { setMigrateLogText(this.runCommand("migrate create " + name)); } public void setMigrateLogText(final String text) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { migrateLog.setText(text); } }); } public ArrayList<String> getMigrationsList() { return newMigrationsList; } public void fillActionMenu() { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { actionMenu.removeAll(); if (newMigrationsList != null && newMigrationsList.size() > 0) { JMenu migrationsMenu = new JMenu("Open new migration"); actionMenu.add(migrationsMenu); for (String migration : newMigrationsList) { final String migrationName = migration; migrationsMenu.add(new JMenuItem(migrationName)); migrationsMenu.getItem(migrationsMenu.getItemCount() - 1).addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { openMigrationFile(migrationName); } }); } } else { JMenuItem noMigration = new JMenuItem("Where no new migrations"); noMigration.setEnabled(false); actionMenu.add(noMigration); } } }); } public void applyMigrations() { String text = this.runCommand("migrate"); setMigrateLogText(text); } public void migrateDown() { String text = this.runCommand("migrate down 1"); setMigrateLogText(text); } /** * Add menu to contentPane */ public void addMenus() { if (MenusAdded) { return; } MenusAdded = true; ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { actionMenu.setToolTipText("New migrations"); actionMenu.setSize(15, 15); ImageIcon icon = new ImageIcon(this.getClass().getResource("/com/yiistorm/images/list.png")); actionMenu.setIcon(icon); actionMenuBar.add(actionMenu); fillActionMenu(); MigrationsToolWindow.addImageButton( buttonsPanel, "Update list", this.getClass().getResource("/com/yiistorm/images/reload.png"), new ActionListener() { @Override public void actionPerformed(ActionEvent e) { runBackgroundTask(MigrationsToolWindow.UPDATE_MIGRAITIONS_MENUS_BACKGROUND_ACTION, _project); } }); //apply migrations MigrationsToolWindow.addImageButton( buttonsPanel, "Migrate up", this.getClass().getResource("/com/yiistorm/images/up.png"), new ActionListener() { @Override public void actionPerformed(ActionEvent e) { runBackgroundTask(MigrationsToolWindow.APPLY_MIGRATIONS_BACKGROUND_ACTION, _project); } }); //migrate down MigrationsToolWindow.addImageButton( buttonsPanel, "Migrate one down", this.getClass().getResource("/com/yiistorm/images/down.png"), new ActionListener() { @Override public void actionPerformed(ActionEvent e) { runBackgroundTask(MigrationsToolWindow.MIGRATE_DOWN_BACKGROUND_ACTION, _project); } }); //create migration MigrationsToolWindow.addImageButton( buttonsPanel, "Create migration", this.getClass().getResource("/com/yiistorm/images/add.png"), new ActionListener() { @Override public void actionPerformed(ActionEvent e) { showCreateForm(); } }); } }); } private static void addImageButton(JPanel panel, String toolTip, URL image, ActionListener listener) { ImageIcon updicon = new ImageIcon(image); JButton updateButton = new JButton(updicon); updateButton.setPressedIcon(updicon); updateButton.setFocusable(false); updateButton.setToolTipText(toolTip); //updateButton.setBorder(BorderFactory.createLineBorder(S)); updateButton.setContentAreaFilled(false); panel.add(updateButton); if (updateButton.getActionListeners().length < 1) { updateButton.addActionListener(listener); } } public void showCreateForm() { final MigrationsToolWindow migrForm = this; if (!NewFormDisplayed) { newMigrationDialog = new NewMigrationForm(migrForm); NewFormDisplayed = true; newMigrationDialog.pack(); newMigrationDialog.setVisible(true); } } public void openMigrationFile(final String name) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { String migrationPath = yiiProtected.replace(_project.getBasePath(), "").replace("\\", "/"); VirtualFile baseDir = _project.getBaseDir(); if (baseDir != null) { VirtualFile migrationsFolder = baseDir.findFileByRelativePath(migrationPath + "migrations/"); if (migrationsFolder != null) { migrationsFolder.refresh(false, true); VirtualFile migrationFile = migrationsFolder.findFileByRelativePath(name + ".php"); //migrationPath + "migrations/" + if (migrationFile != null) { OpenFileDescriptor of = new OpenFileDescriptor(_project, migrationFile); if (of.canNavigate()) { of.navigate(true); } } else { PluginManager.getLogger().error("Migrations file not founded"); } } else { PluginManager.getLogger().error("Migrations folder not founded"); } } } }); } }