Skip to content

Commit

Permalink
feat: Add CreateEventListenerIntention
Browse files Browse the repository at this point in the history
  • Loading branch information
shyim committed Oct 4, 2021
1 parent ced2390 commit 5c7cbb1
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 3 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

pluginGroup = com.github.shyim.shopware6
pluginName=shopware6-phpstorm-plugin
pluginVersion=0.0.14
pluginVersion=0.0.15

# See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
# for insight into build numbers and IntelliJ Platform versions.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package de.shyim.shopware6.intentions

import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.OpenFileDescriptor
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.Messages
import com.intellij.openapi.ui.popup.PopupChooserBuilder
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.psi.*
import com.intellij.ui.components.JBList
import com.jetbrains.php.lang.PhpFileType
import com.jetbrains.php.lang.psi.elements.PhpClass
import com.jetbrains.php.roots.PhpNamespaceByFilesProvider
import de.shyim.shopware6.index.dict.ShopwareBundle
import de.shyim.shopware6.templates.ShopwareTemplates
import de.shyim.shopware6.util.ShopwareBundleUtil
import java.awt.Component
import javax.swing.JLabel
import javax.swing.JList

class CreateEventListenerIntention : PsiElementBaseIntentionAction() {
override fun getFamilyName() = "Subscribe to this event using a event listener"
override fun getText() = "Subscribe to this event using a event listener"

override fun isAvailable(project: Project, editor: Editor?, element: PsiElement): Boolean {
if (element.parent !is PhpClass || editor == null) {
return false
}

val phpClass = element.parent as PhpClass
var currentClass = phpClass

while (true) {
if (currentClass.superFQN === null || currentClass.supers.isEmpty()) {
return false
}

if (currentClass.superFQN == "\\Symfony\\Contracts\\EventDispatcher\\Event") {
return true
} else {
currentClass = currentClass.supers[0]
}
}
}

override fun invoke(project: Project, editor: Editor?, element: PsiElement) {
val phpClass = element.parent as PhpClass

val bundleList = ShopwareBundleUtil.getAllBundles(project).filter {
val virtualFile = LocalFileSystem.getInstance().findFileByPath(it.path)!!
val psiFile = PsiManager.getInstance(project).findFile(virtualFile)!!

return@filter psiFile.manager.isInProject(psiFile)
}.sortedBy { shopwareBundle -> shopwareBundle.name }

val jbBundleList = JBList(bundleList)

jbBundleList.cellRenderer = object : JBList.StripedListCellRenderer() {
override fun getListCellRendererComponent(
list: JList<*>?,
value: Any?,
index: Int,
isSelected: Boolean,
cellHasFocus: Boolean
): Component {
val renderer = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus)

if (renderer is JLabel && value is ShopwareBundle) {
renderer.text = value.name
}

return renderer
}
}

PopupChooserBuilder(jbBundleList)
.setTitle("Shopware: Select bundle")
.setItemChoosenCallback {
CommandProcessor.getInstance().executeCommand(project, {
ApplicationManager.getApplication().runWriteAction {
this.createEventListener(
jbBundleList.selectedValue!!,
phpClass.fqn,
project
)
}
}, "Create event listener", null)
}
.createPopup()
.showInBestPositionFor(editor!!)
}

private fun createEventListener(bundle: ShopwareBundle, eventClassName: String, project: Project) {
val classParts = eventClassName.split("\\")
val eventShort = classParts.get(classParts.size - 1)
val className = "${eventShort}Listener"
val classFileName = "${eventShort}Listener.php"

val bundleFile = LocalFileSystem.getInstance().findFileByPath(bundle.path)!!
val bundleFolder = PsiManager.getInstance(project).findFile(bundleFile)!!.containingDirectory
var expectedFolder = bundleFolder.findSubdirectory("EventListener")

if (expectedFolder == null) {
expectedFolder = bundleFolder.createSubdirectory("EventListener")
}

if (expectedFolder.findFile(classFileName) != null) {
Messages.showInfoMessage("File exists", "Error")
return
}

val content = ShopwareTemplates.applyShopwarePHPEventListener(
project, mapOf(
"NAMESPACE" to getNamespaceOfFolder(expectedFolder).replace("\\\\", "\\"),
"EVENT" to eventClassName.substring(1),
"EVENT_SHORT" to eventShort,
"CLASSNAME" to className,
)
)

val factory = PsiFileFactory.getInstance(project)
val file = factory.createFileFromText(classFileName, PhpFileType.INSTANCE, content)
expectedFolder.add(file)

FileEditorManager.getInstance(project)
.openTextEditor(OpenFileDescriptor(project, expectedFolder.findFile(classFileName)!!.virtualFile), true)
?: return
}

private fun getNamespaceOfFolder(folder: PsiDirectory): String {
val namespaces = PhpNamespaceByFilesProvider.INSTANCE.suggestNamespaces(folder)

if (namespaces != null && namespaces.size > 0) {
return namespaces.get(0)
}

val superNamespaces = PhpNamespaceByFilesProvider.INSTANCE.suggestNamespaces(folder.parent!!)

if (superNamespaces != null && superNamespaces.size > 0) {
return superNamespaces.get(0) + "\\\\" + folder.name
}

return ""
}

override fun checkFile(file: PsiFile?): Boolean {
return true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ class ExtendTwigBlockIntention : PsiElementBaseIntentionAction() {
)
}
}, "Extend Twig block", null)
println(jbBundleList.selectedValue)
}
.createPopup()
.showInBestPositionFor(editor)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ class ShopwareTemplates: FileTemplateGroupDescriptorFactory {
pluginGroup.addTemplate(FileTemplateDescriptor(SHOPWARE_CONTRIBUTION_CHANGELOG_TEMPLATE))
}

FileTemplateGroupDescriptor("PP", ShopwareToolBoxIcons.SHOPWARE).let { pluginGroup ->
group.addTemplate(pluginGroup)
pluginGroup.addTemplate(FileTemplateDescriptor(SHOPWARE_PHP_SCHEDULED_TASK))
pluginGroup.addTemplate(FileTemplateDescriptor(SHOPWARE_PHP_SCHEDULED_TASK_HANDLER))
pluginGroup.addTemplate(FileTemplateDescriptor(SHOPWARE_PHP_EVENT_LISTENER))
}

FileTemplateGroupDescriptor("Administration", ShopwareToolBoxIcons.SHOPWARE).let { pluginGroup ->
group.addTemplate(pluginGroup)
pluginGroup.addTemplate(FileTemplateDescriptor(SHOPWARE_ADMIN_VUE_MODULE))
Expand Down Expand Up @@ -50,6 +57,7 @@ class ShopwareTemplates: FileTemplateGroupDescriptorFactory {
const val SHOPWARE_PLUGIN_CONFIG_TEMPLATE = "Shopware Plugin config.xml"
const val SHOPWARE_PHP_SCHEDULED_TASK = "Shopware PHP Scheduled Task.php"
const val SHOPWARE_PHP_SCHEDULED_TASK_HANDLER = "Shopware PHP Scheduled TaskHandler.php"
const val SHOPWARE_PHP_EVENT_LISTENER = "Shopware PHP Event Listener.php"
const val SHOPWARE_PLUGIN_BOOTSTRAP = "Shopware Plugin Bootstrap.php"
const val SHOPWARE_PLUGIN_CHANGELOG = "Shopware Plugin Changelog.md"
const val SHOPWARE_PLUGIN_COMPOSER_JSON = "Shopware Plugin composer.json"
Expand Down Expand Up @@ -156,7 +164,13 @@ class ShopwareTemplates: FileTemplateGroupDescriptorFactory {
fun applyShopwarePluginServicesXml(project: Project, config: NewPluginConfig): String {
return project.applyTemplate(
SHOPWARE_PLUGIN_SERVICES_XML, config.toMap()
);
)
}

fun applyShopwarePHPEventListener(project: Project, config: Map<String, String>): String {
return project.applyTemplate(
SHOPWARE_PHP_EVENT_LISTENER, config
)
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@
<className>de.shyim.shopware6.intentions.ExtendTwigBlockIntention</className>
<category>Shopware</category>
</intentionAction>

<intentionAction>
<className>de.shyim.shopware6.intentions.CreateEventListenerIntention</className>
<category>Shopware</category>
</intentionAction>
</extensions>

<extensions defaultExtensionNs="fr.adrienbrault.idea.symfony2plugin.extension">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace ${NAMESPACE};

use ${EVENT};

class ${CLASSNAME}
{
public function __invoke(${EVENT_SHORT} $event): void
{

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<body>
Create a new Symfony event listener in selected Shopware bundle with the chosen event class
</body>
</html>

0 comments on commit 5c7cbb1

Please sign in to comment.