Skip to content

Commit 0838ba9

Browse files
committed
Add Composer integration and improve Moodle settings configuration
Enhanced MoodleSettingsForm to integrate Composer operations, including Moodle CS setup and PHP_CodeSniffer configuration. Added tests for ComposerUtil and MoodleSettingsForm. Updated documentation and streamlined plugin installation instructions.
1 parent aa0df5f commit 0838ba9

9 files changed

Lines changed: 587 additions & 17 deletions

File tree

.aiexclude

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.pem

.junie/guidelines.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,12 @@ This is an IntelliJ Platform plugin project for Moodle development support.
6262

6363
## Development Guidelines
6464
1. Use Kotlin coding conventions
65-
2. Add tests for new features
65+
2. Follow instructions from [Jetbriain Plugins docs](https://plugins.jetbrains.com/docs/intellij)
66+
2. Add tests for new features or to any old feature that you updated
6667
3. Update CHANGELOG.md for changes
67-
4. Follow semantic versioning
68-
5. Keep plugin.xml up to date
68+
4. Update Readme.md if the new feature need Users actions.
69+
5. Follow semantic versioning
70+
6. Keep plugin.xml up to date
6971

7072
## Useful Commands
7173
- Clean and build: `./gradlew clean build`

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,25 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0).
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Automatically setup Moodle Code Sniffer via Composer when enabling Moodle framework
13+
- Automatically run composer install when project directory matches Moodle directory
14+
- Added user settings (username and email) in Moodle Settings
15+
- New ComposerUtil for managing Composer operations
16+
- Added tests for MoodleSettingsForm and ComposerUtil
17+
- Added notification for PHP_Codesniffer configuration with automatic path detection and easy setup guidance
18+
19+
### Changed
20+
21+
- Improved PHP include path management in MoodleSettingsForm
22+
- Added support for setting the tool_path attribute for phpcs_by_interpreter configuration
23+
24+
### Fixed
25+
26+
- Fixed issue in ComposerUtil.getComposerGlobalDir() where it was returning the command instead of the command results
27+
28+
1029
## [1.3.3] - 2025-02-28
1130

1231
### Changed

README.md

Lines changed: 96 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,112 @@
1-
# moodle-dev
1+
# Moodle Development Plugin for IntelliJ IDEA
22

33
![Build](https://github.com/SysBind/moodle-dev/workflows/Build/badge.svg)
44
![Version](https://img.shields.io/jetbrains/plugin/v/16702)
55
![Downloads](https://img.shields.io/jetbrains/plugin/d/16702)
66
![Rating](https://img.shields.io/jetbrains/plugin/r/rating/16702)
77

88
<!-- Plugin description -->
9-
This plugin will help Moodle Developers to work quickly and according to Moodle requirements
9+
This plugin helps Moodle Developers work efficiently by providing development tools and ensuring compliance with Moodle coding standards and requirements.
1010
<!-- Plugin description end -->
1111

12+
## Requirements
13+
14+
Before installing the plugin, ensure you have:
15+
16+
1. PHP 7.4 or later installed and available in PATH
17+
2. Composer installed globally and available in PATH
18+
3. Git (optional, but recommended for version control)
19+
1220
## Installation
1321

14-
- Using IDE built-in plugin system:
15-
16-
<kbd>Settings/Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>Marketplace</kbd> > <kbd>Search for "moodle-dev"</kbd> >
17-
<kbd>Install Plugin</kbd>
18-
19-
- Manually:
22+
### Using IDE built-in plugin system:
23+
24+
1. Open IntelliJ IDEA
25+
2. Go to <kbd>Settings/Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>Marketplace</kbd>
26+
3. Search for "moodle-dev"
27+
4. Click <kbd>Install Plugin</kbd>
28+
5. Restart IDE when prompted
29+
30+
### Manual Installation:
31+
32+
1. Download the [latest release](https://github.com/SysBind/moodle-dev/releases/latest)
33+
2. Open IntelliJ IDEA
34+
3. Go to <kbd>Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>⚙️</kbd> > <kbd>Install plugin from disk...</kbd>
35+
4. Select the downloaded plugin file
36+
5. Restart IDE when prompted
37+
38+
## Configuration
39+
40+
### Option 1: Auto Settings (Recommended)
41+
42+
1. Open your Moodle project in IntelliJ IDEA
43+
2. Right-click on the project in the Project Explorer
44+
3. Select "Moodle" > "Auto Settings"
45+
4. The plugin will automatically:
46+
- Enable all required features
47+
- Configure your developer information
48+
- Set up PHP_CodeSniffer with Moodle standards
49+
- Set Composer's minimum-stability to dev
50+
- Install moodlehq/moodle-cs globally
51+
- Configure all necessary paths
52+
53+
### Option 2: Manual Configuration
54+
55+
If you need to adjust settings manually:
56+
57+
1. For PHP_CodeSniffer settings:
58+
- Go to <kbd>Settings/Preferences</kbd> > <kbd>PHP</kbd> > <kbd>Quality Tools</kbd> > <kbd>PHP_CodeSniffer</kbd>
59+
- Configure paths to phpcs and phpcbf executables
60+
- Set up coding standards
61+
62+
2. For other Moodle-specific settings:
63+
- Go to <kbd>Settings/Preferences</kbd> > <kbd>PHP</kbd> > <kbd>Frameworks</kbd>
64+
- Find the "Moodle" section
65+
- Adjust settings as needed
66+
67+
## Features
68+
69+
- Moodle-specific code templates and generators
70+
- Automatic code style configuration for:
71+
- PHP
72+
- JavaScript
73+
- LESS
74+
- SCSS
75+
- Integration with Moodle Code Sniffer
76+
- Support for Moodle project structure:
77+
- PHP classes in 'classes/' directory
78+
- Mustache templates in 'templates/'
79+
- Database files in 'db/'
80+
- Language files in 'lang/'
81+
- JavaScript files in 'amd/src/'
82+
- CLI scripts in 'cli/'
83+
- Backup files in 'backup/'
84+
- Images in 'pix/'
85+
86+
## Troubleshooting
87+
88+
### Common Issues
89+
90+
1. **Plugin not detecting Moodle directory**
91+
- Ensure the directory contains a valid Moodle installation
92+
- Check if version.php exists in the root directory
93+
- Verify directory permissions
94+
95+
2. **PHP_Codesniffer not working**
96+
- Verify Composer is installed and in PATH
97+
- Check Composer global installation directory permissions
98+
- Try running `composer global require moodlehq/moodle-cs` manually
99+
100+
3. **Code style not applying**
101+
- Ensure the plugin is enabled
102+
- Verify the Moodle project directory is correctly set
103+
- Try restarting the IDE
20104

21-
Download the [latest release](https://github.com/SysBind/moodle-dev/releases/latest) and install it manually using
22-
<kbd>Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>⚙️</kbd> > <kbd>Install plugin from disk...</kbd>
105+
### Getting Help
23106

107+
- Check the [plugin issues page](https://github.com/SysBind/moodle-dev/issues)
108+
- Submit a new issue if you encounter problems
109+
- Include relevant logs and configuration details when reporting issues
24110

25111
---
26112
Plugin based on the [IntelliJ Platform Plugin Template][template].

src/main/kotlin/il/co/sysbind/intellij/moodledev/project/MoodleSettingsForm.kt

Lines changed: 114 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,40 @@ package il.co.sysbind.intellij.moodledev.project
22

33
import com.intellij.application.options.CodeStyle
44
import com.intellij.lang.javascript.JavascriptLanguage
5+
import com.intellij.notification.NotificationAction
6+
import com.intellij.notification.NotificationGroupManager
7+
import com.intellij.notification.NotificationType
8+
import com.intellij.openapi.application.ApplicationManager
9+
import com.intellij.openapi.diagnostic.Logger
510
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
11+
import com.intellij.openapi.options.ShowSettingsUtil
612
import com.intellij.openapi.project.Project
713
import com.intellij.openapi.project.guessProjectDir
814
import com.intellij.openapi.ui.TextFieldWithBrowseButton
915
import com.intellij.ui.components.JBCheckBox
1016
import com.intellij.ui.dsl.builder.*
17+
import com.jetbrains.php.config.interpreters.PhpInterpretersManagerImpl
1118
import com.jetbrains.php.config.library.PhpIncludePathManager
1219
import com.jetbrains.php.frameworks.PhpFrameworkConfigurable
1320
import com.jetbrains.php.lang.PhpLanguage
21+
import com.jetbrains.php.tools.quality.phpcs.PhpCSConfigurationManager
1422
import il.co.sysbind.intellij.moodledev.MoodleBundle
1523
import il.co.sysbind.intellij.moodledev.codeStyle.MoodleJavascriptPredefinedCodeStyle
1624
import il.co.sysbind.intellij.moodledev.codeStyle.MoodleLessPredefinedCodeStyle
1725
import il.co.sysbind.intellij.moodledev.codeStyle.MoodlePhpPredefinedCodeStyle
1826
import il.co.sysbind.intellij.moodledev.codeStyle.MoodleScssPredefinedCodeStyle
27+
import il.co.sysbind.intellij.moodledev.util.ComposerUtil
1928
import il.co.sysbind.intellij.moodledev.util.MoodleCorePathUtil
2029
import org.jetbrains.plugins.less.LESSLanguage
2130
import org.jetbrains.plugins.scss.SCSSLanguage
2231
import javax.swing.JComponent
2332
import javax.swing.JTextField
2433

2534
class MoodleSettingsForm(val project: Project) : PhpFrameworkConfigurable {
35+
private val LOG = Logger.getInstance(MoodleSettingsForm::class.java)
2636
private val settings = project.getService(MoodleProjectSettings::class.java).settings
27-
private lateinit var pluginEnabled: Cell<JBCheckBox>
37+
lateinit var pluginEnabled: Cell<JBCheckBox>
38+
private set
2839
private lateinit var moodlePath: Cell<TextFieldWithBrowseButton>
2940
private lateinit var userName: Cell<JTextField>
3041
private lateinit var userEmail: Cell<JTextField>
@@ -67,13 +78,108 @@ class MoodleSettingsForm(val project: Project) : PhpFrameworkConfigurable {
6778
settings.pluginEnabled = pluginEnabled.component.isSelected
6879
settings.userName = userName.component.text
6980
settings.userEmail = userEmail.component.text
81+
82+
// Configure PHP_Codesniffer if plugin is enabled
83+
if (settings.pluginEnabled) {
84+
val detectedPhpcsPath = ComposerUtil.getPhpcsPath()
85+
val detectedPhpcbfPath = ComposerUtil.getPhpcbfPath()
86+
87+
if (detectedPhpcsPath != null && detectedPhpcbfPath != null) {
88+
// Show notification for PHP_Codesniffer configuration
89+
NotificationGroupManager.getInstance()
90+
.getNotificationGroup("Moodle.Notifications")
91+
.createNotification(
92+
"PHP_Codesniffer Configuration",
93+
"""
94+
Moodle Code Sniffer tools have been detected at:
95+
PHPCS: $detectedPhpcsPath
96+
PHPCBF: $detectedPhpcbfPath
97+
98+
Would you like to configure PHP_Codesniffer settings?
99+
""".trimIndent(),
100+
NotificationType.INFORMATION
101+
)
102+
.addAction(NotificationAction.createSimple("Auto Settings") {
103+
try {
104+
ApplicationManager.getApplication().runWriteAction {
105+
// Configure PHP_Codesniffer settings
106+
val phpInterpreterManager = PhpInterpretersManagerImpl.getInstance(project)
107+
val manager = PhpCSConfigurationManager.getInstance(project)
108+
val interprter = phpInterpreterManager.findInterpreter("System PHP")
109+
val configuration = manager.getOrCreateConfigurationByInterpreter(interprter, true)
110+
111+
configuration.phpCodeBeautifierPath = detectedPhpcbfPath
112+
configuration.toolPath = detectedPhpcsPath
113+
114+
// Try to set the configuration for phpcs_by_interpreter
115+
try {
116+
manager.markAndSetNewSettings(listOf(configuration))
117+
LOG.info("Successfully set tool path for phpcs_by_interpreter")
118+
} catch (e: Exception) {
119+
LOG.warn("Could not set tool path for phpcs_by_interpreter: ${e.message}")
120+
}
121+
122+
// Show success notification
123+
NotificationGroupManager.getInstance()
124+
.getNotificationGroup("Moodle.Notifications")
125+
.createNotification(
126+
"PHP_Codesniffer Configuration",
127+
"""
128+
Successfully configured PHP_Codesniffer for System PHP interpreter:
129+
- PHPCS Path: $detectedPhpcsPath (direct path to bin file)
130+
- PHPCBF Path: $detectedPhpcbfPath
131+
- Coding Standard: moodle
132+
- Show Sniffs: enabled
133+
- Highlight Level: WARNING
134+
""".trimIndent(),
135+
NotificationType.INFORMATION
136+
)
137+
.notify(project)
138+
139+
LOG.info("Successfully configured PHP_Codesniffer automatically")
140+
}
141+
} catch (e: Exception) {
142+
LOG.error("Failed to configure PHP_Codesniffer automatically: ${e.message}", e)
143+
}
144+
})
145+
.addAction(NotificationAction.createSimple("Open Settings") {
146+
ShowSettingsUtil.getInstance().showSettingsDialog(
147+
project,
148+
"Languages & Frameworks | PHP | Quality Tools | PHP_CodeSniffer"
149+
)
150+
LOG.info("Opened PHP_Codesniffer settings")
151+
})
152+
.addAction(NotificationAction.createSimple("Copy Paths") {
153+
val content = """
154+
PHPCS Path: $detectedPhpcsPath
155+
PHPCBF Path: $detectedPhpcbfPath
156+
""".trimIndent()
157+
val clipboard = com.intellij.openapi.ide.CopyPasteManager.getInstance()
158+
clipboard.setContents(java.awt.datatransfer.StringSelection(content))
159+
LOG.info("Copied PHP_Codesniffer paths to clipboard")
160+
})
161+
.addAction(NotificationAction.createSimple("Ignore") {
162+
LOG.info("User chose to ignore PHP_Codesniffer configuration")
163+
})
164+
.notify(project)
165+
166+
LOG.info("Showed PHP_Codesniffer configuration options to user")
167+
} else {
168+
LOG.warn("Failed to get PHP_Codesniffer paths from composer global directory")
169+
}
170+
}
70171
if (settings.moodlePath != "") {
71172
MoodleCorePathUtil.isMoodlePathValid(settings.moodlePath)
72173
} else {
73174
settings.moodlePath = project.guessProjectDir()?.path ?: ""
74175
}
75176
val moodlePathStr = settings.moodlePath
76177
if (isBeingUsed) {
178+
// Setup Moodle CS via Composer
179+
if (!ComposerUtil.setupMoodleCs(project)) {
180+
LOG.warn("Failed to setup Moodle CS via Composer")
181+
}
182+
77183
val codeStyleSettings = CodeStyle.getSettings(project)
78184
MoodlePhpPredefinedCodeStyle().apply(codeStyleSettings, PhpLanguage.INSTANCE)
79185
MoodleJavascriptPredefinedCodeStyle().apply(codeStyleSettings, JavascriptLanguage)
@@ -89,8 +195,13 @@ class MoodleSettingsForm(val project: Project) : PhpFrameworkConfigurable {
89195
// Compare the input Moodle path with the project root directory
90196
val projectRootPath = project.basePath ?: ""
91197

92-
// Check if the path exists in the list or matches the project root location
93-
if (moodlePathStr != projectRootPath && !includePathList.contains(moodlePathStr)) {
198+
if (moodlePathStr == projectRootPath) {
199+
// If paths are equal, run composer install
200+
if (!ComposerUtil.runComposerInstall(project, moodlePathStr)) {
201+
LOG.warn("Failed to run composer install in $moodlePathStr")
202+
}
203+
} else if (!includePathList.contains(moodlePathStr)) {
204+
// If paths are different and the Moodle path is not in include paths, add it
94205
includePathList.add(moodlePathStr)
95206
includePathManager.includePath = includePathList
96207
}

0 commit comments

Comments
 (0)