Skip to content
Merged
Show file tree
Hide file tree
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: 6 additions & 2 deletions .github/workflows/asset.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ on:
jobs:
build:
runs-on: ubuntu-latest
env:
GITHUB_RELEASE_PRERELEASE: ${{ github.event.release.prerelease }}
GITHUB_RELEASE_ID: ${{ github.event.release.id }}
PLUGIN_VERSION: ${{ github.event.release.prerelease && format('{0}-alpha.{1}', github.event.release.tag_name, github.event.release.id) || github.event.release.tag_name }}

steps:
- uses: actions/checkout@v3
Expand All @@ -27,8 +31,8 @@ jobs:
uses: actions/upload-release-asset@v1
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: ./build/distributions/PhpStorm Magento 2 Plugin-${{ github.event.release.tag_name }}.zip
asset_name: PhpStorm Magento 2 Plugin-${{ github.event.release.tag_name }}.zip
asset_path: ./build/distributions/Magento 2 and Adobe Commerce Support-${{ env.PLUGIN_VERSION }}.zip
asset_name: Magento 2 and Adobe Commerce Support-${{ env.PLUGIN_VERSION }}.zip
asset_content_type: application/zip-archive
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4 changes: 3 additions & 1 deletion .github/workflows/gradlepublish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ jobs:
build:

runs-on: ubuntu-latest
env:
GITHUB_RELEASE_PRERELEASE: ${{ github.event.release.prerelease }}
GITHUB_RELEASE_ID: ${{ github.event.release.id }}

steps:
- uses: actions/checkout@v3
Expand All @@ -25,4 +28,3 @@ jobs:
run: ./gradlew publishPlugin -i --no-daemon
env:
MAGENTO_PHPSTORM_intellijPublishToken: ${{ secrets.JET_BRAINS_TOKEN }}
MAGENTO_PHPSTORM_isAlpha: false
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,33 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0).

## 2026.2.0

### Added

- Magento MCP project and generation tools for AI agents. These tools can return the configured Magento root path and generate common Magento scaffolding directly in the opened project, including modules, plugins, observers, CRUD entities, controllers, CLI commands, blocks, view models, and product/category/customer EAV attributes:
`get_magento_root_path`,
`create_magento_module`,
`create_magento_plugin`,
`create_magento_observer`,
`create_magento_entity_crud`,
`create_magento_controller`,
`create_magento_cli_command`,
`create_magento_block`,
`create_magento_view_model`,
`create_magento_product_eav_attribute`,
`create_magento_category_eav_attribute`,
`create_magento_customer_eav_attribute`
- Magento MCP lookup tools for AI agents. These tools help an agent inspect the current project and answer Magento-specific questions by locating modules, DI configuration, plugin interceptions, event observers, layout entities, UI components, and ACL or admin menu declarations:
`find_magento_module`,
`find_di_config_for_class`,
`find_plugins_for_method`,
`find_observers_for_event`,
`find_layout_entities`,
`find_ui_component`,
`find_acl_or_menu`
- Magento MCP CLI environment discovery for AI agents. The `describe_magento_cli_environment` tool exposes project-local wrapper commands, including Mark Shust Docker-style `bin/*` scripts such as `bin/magento` and `bin/n98-magerun2`, so agents can prefer those wrappers over global binaries.

## 2026.1.1

### Added
Expand Down
76 changes: 71 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</p>

<!-- Plugin description -->
# PhpStorm Magento 2 Plugin
# Magento 2 and Adobe Commerce Support

<table align="center" style="border-collapse: collapse; width: 100%; text-align: center;">
<caption style="font-size: 1.2em; margin-bottom: 10px;">
Expand All @@ -20,10 +20,19 @@
<td colspan="3" style="padding: 20px;">
<h3 style="margin: 10px 0;">Support the Project</h3>
<p>If you find this plugin helpful and want to support its development, consider buying the contributors a coffee:</p>
<a href="https://buymeacoffee.com/vitalii_b" style="text-decoration: none;">
<img src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-Donate-orange.svg" alt="Buy Me a Coffee" style="margin: 10px 0;">
<a href="https://buymeacoffee.com/vitalii_b" style="text-decoration: none; color: inherit;">
<pre style="display: inline-block; margin: 10px 0; font-family: monospace;">
( (
) )
........
| |]
\ /
`----'
Buy Me a Coffee
</pre>
</a>
<p style="margin: 10px 0;">Thank you to our sponsors—your support means everything:</p>
<h3 style="margin: 10px 0;">Sponsors</h3>
<p style="margin: 10px 0;">Thank you to our sponsors for supporting the plugin:</p>
<p><strong>Lucas van Staden</strong></p>
<p><strong>Ivan Chepurnyi</strong></p>
<p><strong>Michael Ryvlin</strong></p>
Expand All @@ -40,6 +49,7 @@
* `Navigate to Web API configuration` reference in scope of class/interface and method
* Plugin class methods generation
* Plugin declaration inspection
* Magento-specific MCP tools for AI agents
* RequireJS reference navigation and completion
* MFTF reference navigation and completion
* GraphQL navigation line markers
Expand All @@ -56,7 +66,7 @@

1. Go to `Settings > Preferences` in the PhpStorm IDE
2. Navigate to `Plugins`
3. Click the `Browse repositories...` button and search for "Magento PhpStorm"
3. Click the `Browse repositories...` button and search for "Magento 2 and Adobe Commerce Support"
4. Install the plugin and restart PhpStorm
5. Go to `Settings > Preferences > Languages & Frameworks > PHP > Frameworks > Magento` in the PhpStorm IDE
6. Check `Enable` and click the `OK` button
Expand All @@ -65,6 +75,62 @@

* PhpStorm 2026+

## MCP tools

The plugin exposes a Magento-specific MCP toolset for AI agents inside JetBrains IDEs with MCP support enabled.

Available project and creation tools:

* `get_magento_root_path`: returns the resolved Magento root directory for the current IDE project. Use this when an agent or shell command needs an absolute project path.
* `create_magento_module`: creates a new Magento module with `composer.json`, `registration.php`, and `etc/module.xml`. Pass Magento module parts such as `packageName=Foo` and `moduleName=Bar` to create `Foo_Bar`; the Composer package name is derived automatically as `foo/module-bar`.
* `create_magento_plugin`: creates a plugin class and the matching `di.xml` declaration. `moduleName` must be `Vendor_Module`, `targetClassName` must be an existing PHP FQN such as `Magento\\Catalog\\Api\\ProductRepositoryInterface`, `targetMethodName` is the intercepted method name, and `pluginType` must be `before`, `around`, or `after`.
* `create_magento_observer`: creates an observer class and `events.xml` declaration. `moduleName` must be `Vendor_Module`, `eventName` should be a Magento event such as `catalog_product_save_after`, and `observerClassFqn` should live inside the module namespace, usually under `Observer\\`.
* `create_magento_entity_crud`: scaffolds a Magento CRUD module area including DB schema, model, resource model, collection, repository-related classes, ACL/menu entries, and optional admin UI pieces. `properties` must be a list of `field_name:type` values such as `["title:string", "is_active:bool"]`; the primary ID field is generated automatically.
* `create_magento_controller`: creates a controller class in an editable module. `controllerClassFqn` must be under the module `Controller` namespace, for example `Foo\\Bar\\Controller\\Index\\Index` or `Foo\\Bar\\Controller\\Adminhtml\\Order\\Index`, and `httpMethod` must be `GET`, `POST`, `PUT`, or `DELETE`.
* `create_magento_cli_command`: creates a Symfony console command class and registers it in `etc/di.xml`. `commandClassFqn` usually belongs under `Console\\Command`, and `commandName` should be a Magento CLI command name such as `foo:bar:sync-data`.
* `create_magento_block`: creates a block class under the module `Block\\` namespace, for example `Foo\\Bar\\Block\\Product\\BadgeBlock`.
* `create_magento_view_model`: creates a view model class under the module `ViewModel\\` namespace, for example `Foo\\Bar\\ViewModel\\Product\\BadgeViewModel`.
* `create_magento_product_eav_attribute`: creates a product EAV attribute data patch and optional source model. `attributeCode` must be lower_snake_case, `backendType` and `frontendInput` must be valid Magento attribute types, and `options` may only be used for `select` or `multiselect`.
* `create_magento_category_eav_attribute`: creates a category EAV attribute data patch, `view/adminhtml/ui_component/category_form.xml`, and an optional source model using the same attribute format rules as the product tool.
* `create_magento_customer_eav_attribute`: creates a customer EAV attribute data patch and optional source model using Magento customer attribute rules.

Available query and inspection tools:

* `find_magento_module`: finds modules by exact or partial Magento module name such as `Magento_Catalog`, `Foo_Bar`, `Catalog`, or `Magento_`. Use this to confirm the canonical module name and path before generating code.
* `find_di_config_for_class`: finds `di.xml` declarations related to a PHP FQN or virtual type name such as `Magento\\Catalog\\Model\\Product` or `catalogProductRepository`. Use this to inspect preferences, virtual types, arguments, and related DI wiring before making changes.
* `find_plugins_for_method`: finds plugins for a target class or interface method. Pass a PHP FQN such as `Magento\\Catalog\\Api\\ProductRepositoryInterface` and a bare method name such as `save` or `getById`.
* `find_observers_for_event`: finds observers by full or partial event name such as `catalog_product_save_after` or `product_save` and returns matching `events.xml` declarations.
* `find_layout_entities`: finds layout handles, block names, and container names by exact or partial value such as `catalog_product_view`, `product.info.main`, or `checkout`.
* `find_ui_component`: finds UI component XML definitions by exact or partial component file name such as `product_form`, `sales_order_grid`, or `category_form` without the `.xml` extension.
* `find_acl_or_menu`: finds ACL resource IDs and admin menu entries by exact or partial identifier such as `Magento_Catalog::catalog` or `Foo_Bar::manage_items`.
* `describe_magento_cli_environment`: detects project-local CLI wrappers such as Mark Shust Docker scripts under `bin/`, returns the exact command paths an agent should use, and includes example invocations for Magento CLI, PHP, Composer, and `n98-magerun`.

Notes:

* The IDE MCP server must be enabled in the JetBrains IDE.
* The IDE MCP server entry must be added to the agent MCP configuration.
* MCP tools work against the currently opened IDE project.
* Magento plugin support must be enabled for the project.
* Indexing must be finished before MCP queries and generators can run.
* Category EAV attribute generation creates both the data patch and `view/adminhtml/ui_component/category_form.xml`.
* `describe_magento_cli_environment` detects project-local wrappers such as Mark Shust Docker scripts under `bin/` and returns the exact command paths an agent should use.

### MCP CLI wrapper configuration

If your Magento project uses local wrapper scripts such as Mark Shust Docker commands, configure them in:

`Settings > Languages & Frameworks > PHP > Frameworks > Magento > MCP CLI wrapper candidates`

Use a comma-separated list of relative paths, for example:

`bin/magento, bin/n98-magerun2, bin/cli`

Agent usage pattern:

1. Call `describe_magento_cli_environment`.
2. Use the returned wrapper path exactly, for example `./bin/magento cache:flush` or `./bin/n98-magerun2 sys:info`.
3. Prefer the wrapper over global binaries because these scripts often enter Docker containers or a project-specific runtime.

## Setting up development environment

1. Check out this repository.
Expand Down
29 changes: 24 additions & 5 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,24 @@ plugins {
}

group = providers.gradleProperty("pluginGroup").get()
version = providers.gradleProperty("pluginVersion").get()
val basePluginVersion = providers.gradleProperty("pluginVersion")
val isGithubPrerelease = providers.environmentVariable("GITHUB_RELEASE_PRERELEASE")
.map(String::toBoolean)
.orElse(false)
val effectivePluginVersion = providers.provider {
val pluginVersion = basePluginVersion.get()

if (!isGithubPrerelease.get()) {
pluginVersion
} else {
val releaseId = providers.environmentVariable("GITHUB_RELEASE_ID").orNull
?: throw GradleException("GITHUB_RELEASE_ID is required when publishing a GitHub prerelease.")

"$pluginVersion-alpha.$releaseId"
}
}

version = effectivePluginVersion.get()

kotlin {
jvmToolchain(21)
Expand Down Expand Up @@ -52,7 +69,7 @@ dependencies {

intellijPlatform {
pluginConfiguration {
version = providers.gradleProperty("pluginVersion")
version = effectivePluginVersion

description = providers.fileContents(layout.projectDirectory.file("README.md")).asText.map {
val start = "<!-- Plugin description -->"
Expand All @@ -67,7 +84,7 @@ intellijPlatform {
}

val changelog = project.changelog // local variable for configuration cache compatibility
changeNotes = providers.gradleProperty("pluginVersion").map { pluginVersion ->
changeNotes = basePluginVersion.map { pluginVersion ->
with(changelog) {
renderItem(
(getOrNull(pluginVersion) ?: getUnreleased())
Expand All @@ -92,7 +109,9 @@ intellijPlatform {

publishing {
token = providers.environmentVariable("MAGENTO_PHPSTORM_intellijPublishToken")
channels = providers.gradleProperty("pluginVersion").map { listOf(it.substringAfter('-', "").substringBefore('.').ifEmpty { "default" }) }
channels = effectivePluginVersion.map {
listOf(it.substringAfter('-', "").substringBefore('.').ifEmpty { "default" })
}
}

pluginVerification {
Expand Down Expand Up @@ -175,4 +194,4 @@ kover {
excludedClasses.add("org.apache.velocity.*")
}
}
}
}
6 changes: 3 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
pluginGroup = com.magento.idea.magento2plugin
pluginName = Magento PhpStorm
pluginName = Magento 2 and Adobe Commerce Support
pluginRepositoryUrl = https://github.com/magento/magento2-phpstorm-plugin
pluginVersion = 2026.1.1
pluginVersion = 2026.2.0
pluginSinceBuild = 261.21525.38
pluginUntilBuild = 268.*
platformType = PS
platformVersion = 261.22158.208
platformPlugins = com.intellij.lang.jsgraphql:261.22158.185
platformBundledPlugins = com.intellij.modules.json,com.jetbrains.php,JavaScript,com.intellij.css,org.jetbrains.plugins.yaml,com.intellij.copyright
platformBundledPlugins = com.intellij.modules.json,com.jetbrains.php,JavaScript,com.intellij.css,org.jetbrains.plugins.yaml,com.intellij.copyright,com.intellij.mcpServer
gradleVersion = 9.3.1
kotlin.stdlib.default.dependency = true
org.gradle.configuration-cache = true
Expand Down
2 changes: 1 addition & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* See COPYING.txt for license details.
*/

rootProject.name = "PhpStorm Magento 2 Plugin"
rootProject.name = "Magento 2 and Adobe Commerce Support"

plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
import org.jetbrains.annotations.NotNull;

public class NewEntityAction extends AnAction {
public static final String ACTION_NAME = "Magento 2 Entity";
public static final String ACTION_DESCRIPTION = "Create a new Magento 2 Entity";
public static final String ACTION_NAME = "Magento 2 Entity CRUD";
public static final String ACTION_DESCRIPTION = "Create a new Magento 2 Entity CRUD scaffold";

/**
* Constructor.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public class NewEntityDialog extends AbstractDialog {
private final List<String> properties;
private TableGroupWrapper entityPropertiesTableGroupWrapper;

private static final String ACTION_NAME = "Create Entity";
private static final String ACTION_NAME = "Create Entity CRUD";
private static final String PROPERTY_NAME = "Name";
private static final String PROPERTY_TYPE = "Type";
private static final String ACL_ID = "ACL ID";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<label value=""/>
<text value=""/>
</properties>
</component>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

package com.magento.idea.magento2plugin.actions.generation.dialog.validator.rule;

import com.jetbrains.php.config.PhpLanguageLevel;
import com.jetbrains.php.refactoring.PhpNameUtil;
import org.jetbrains.annotations.NotNull;

Expand All @@ -15,7 +16,7 @@ public class PhpNamespaceNameRule implements ValidationRule {

@Override
public boolean check(final @NotNull String value) {
return PhpNameUtil.isValidNamespaceFullName(value);
return PhpNameUtil.isValidNamespaceFullName(value, PhpLanguageLevel.DEFAULT);
}

public static ValidationRule getInstance() {
Expand Down
Loading
Loading