Skip to content

Commit 14b149e

Browse files
committed
Enhance Composer handling with improved fallbacks and logging
Added fallback to default Composer directories and Windows-specific .bat extension detection for better cross-platform compatibility. Improved error handling, output trimming, and logging in Composer operations. Updated documentation to reflect new behaviors and troubleshooting steps.
1 parent e8214dd commit 14b149e

4 files changed

Lines changed: 125 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0).
1515
- New ComposerUtil for managing Composer operations
1616
- Added tests for MoodleSettingsForm and ComposerUtil
1717
- Added notification for PHP_Codesniffer configuration with automatic path detection and easy setup guidance
18+
- Added fallback to default Composer directories when command-line detection fails
19+
- Added Windows compatibility with automatic detection of .bat extensions for executables
1820

1921
### Changed
2022

2123
- Improved PHP include path management in MoodleSettingsForm
2224
- Added support for setting the tool_path attribute for phpcs_by_interpreter configuration
25+
- Updated platform version from 251.23536.39 to 251.23774.350
26+
- Updated handlebars plugin version from 251.23536.38 to 251.23774.318
27+
- Enhanced error handling and logging in Composer operations
28+
- Improved verification of Moodle CS installation
2329

2430
### Fixed
2531

2632
- Fixed issue in ComposerUtil.getComposerGlobalDir() where it was returning the command instead of the command results
33+
- Fixed path handling in getPhpcsPath() and getPhpcbfPath() for cross-platform compatibility
34+
- Fixed output handling in getComposerGlobalDir() by properly trimming whitespace and newlines
2735

2836

2937
## [1.3.3] - 2025-02-28

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,18 @@ If you need to adjust settings manually:
9696
- Verify Composer is installed and in PATH
9797
- Check Composer global installation directory permissions
9898
- Try running `composer global require moodlehq/moodle-cs` manually
99+
- For Windows users, the plugin now automatically detects .bat extensions for executables
99100

100101
3. **Code style not applying**
101102
- Ensure the plugin is enabled
102103
- Verify the Moodle project directory is correctly set
103104
- Try restarting the IDE
104105

106+
4. **Composer operations failing**
107+
- The plugin now includes improved error handling and fallback mechanisms
108+
- Default Composer directories are checked if the command-line detection fails
109+
- More detailed logs are available for troubleshooting
110+
105111
### Getting Help
106112

107113
- Check the [plugin issues page](https://github.com/SysBind/moodle-dev/issues)

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ pluginUntilBuild = 251.*
1212

1313
# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
1414
platformType = PS
15-
platformVersion = 251.23536.39
15+
platformVersion = 251.23774.350
1616

1717
# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
1818
# Example: platformPlugins = com.jetbrains.php:203.4449.22, org.intellij.scala:2023.3.27@EAP
19-
platformPlugins = com.dmarcotte.handlebars:251.23536.38
19+
platformPlugins = com.dmarcotte.handlebars:251.23774.318
2020
# Example: platformBundledPlugins = com.intellij.java
2121
platformBundledPlugins = com.jetbrains.php, JavaScript, org.jetbrains.plugins.less, org.jetbrains.plugins.sass
2222
# Gradle Releases -> https://github.com/gradle/gradle/releases

src/main/kotlin/il/co/sysbind/intellij/moodledev/util/ComposerUtil.kt

Lines changed: 109 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,61 @@ object ComposerUtil {
3737
processHandler.waitFor()
3838

3939
if (processHandler.exitCode == 0 && output.isNotEmpty()) {
40-
composerGlobalDir = output.toString()
40+
// Clean up the output - remove any extra whitespace or newlines
41+
composerGlobalDir = output.toString().trim()
42+
LOG.debug("Found composer global directory: $composerGlobalDir")
4143
return composerGlobalDir
44+
} else {
45+
LOG.warn("Composer command exited with code ${processHandler.exitCode} or empty output")
4246
}
4347
} catch (e: Exception) {
4448
LOG.error("Failed to get composer global directory: ${e.message}", e)
4549
}
50+
51+
// Fallback to default locations if composer command fails
52+
val userHome = System.getProperty("user.home")
53+
val possibleLocations = listOf(
54+
"$userHome/.composer", // Linux/Mac
55+
"$userHome/AppData/Roaming/Composer" // Windows
56+
)
57+
58+
for (location in possibleLocations) {
59+
val dir = java.io.File(location)
60+
if (dir.exists() && dir.isDirectory) {
61+
LOG.debug("Using fallback composer global directory: $location")
62+
composerGlobalDir = location
63+
return composerGlobalDir
64+
}
65+
}
66+
67+
LOG.warn("Could not determine composer global directory")
4668
return null
4769
}
4870

4971
fun getPhpcsPath(): String? {
50-
return getComposerGlobalDir()?.let { "$it/vendor/bin/phpcs" }
72+
return getComposerGlobalDir()?.let {
73+
val path = java.io.File(it, "vendor/bin/phpcs")
74+
if (System.getProperty("os.name").lowercase().contains("windows")) {
75+
// On Windows, the executable might have a .bat extension
76+
if (java.io.File("${path}.bat").exists()) {
77+
return@let "${path}.bat"
78+
}
79+
}
80+
path.absolutePath
81+
}
5182
}
5283

5384
fun getPhpcbfPath(): String? {
54-
return getComposerGlobalDir()?.let { "$it/vendor/bin/phpcbf" }
85+
return getComposerGlobalDir()?.let {
86+
val path = java.io.File(it, "vendor/bin/phpcbf")
87+
if (System.getProperty("os.name").lowercase().contains("windows")) {
88+
// On Windows, the executable might have a .bat extension
89+
if (java.io.File("${path}.bat").exists()) {
90+
return@let "${path}.bat"
91+
}
92+
}
93+
path.absolutePath
94+
}
5595
}
5696

5797
fun runComposerInstall(project: Project, directory: String): Boolean {
@@ -90,20 +130,82 @@ object ComposerUtil {
90130
}
91131

92132
fun setupMoodleCs(project: Project): Boolean {
133+
LOG.debug("Setting up Moodle CS...")
134+
135+
// First check if phpcs and phpcbf already exist
136+
val phpcsPath = getPhpcsPath()
137+
val phpcbfPath = getPhpcbfPath()
138+
139+
if (phpcsPath != null && phpcbfPath != null) {
140+
val phpcsFile = java.io.File(phpcsPath)
141+
val phpcbfFile = java.io.File(phpcbfPath)
142+
143+
if (phpcsFile.exists() && phpcbfFile.exists()) {
144+
LOG.debug("PHPCS and PHPCBF already exist, checking if moodle standard is available")
145+
146+
// Check if moodle standard is available
147+
try {
148+
val commandLine = GeneralCommandLine(phpcsPath)
149+
commandLine.addParameters(listOf("-i"))
150+
151+
val output = StringBuilder()
152+
val processHandler = OSProcessHandler(commandLine)
153+
processHandler.addProcessListener(object : ProcessAdapter() {
154+
override fun onTextAvailable(event: ProcessEvent, outputType: Key<*>) {
155+
output.append(event.text)
156+
}
157+
})
158+
159+
processHandler.startNotify()
160+
processHandler.waitFor()
161+
162+
if (processHandler.exitCode == 0 && output.toString().lowercase().contains("moodle")) {
163+
LOG.debug("Moodle standard is already available")
164+
return true
165+
}
166+
} catch (e: Exception) {
167+
LOG.warn("Failed to check if moodle standard is available: ${e.message}")
168+
// Continue with setup
169+
}
170+
}
171+
}
172+
93173
try {
94174
// Set minimum-stability to dev
175+
LOG.debug("Setting composer minimum-stability to dev")
95176
if (!executeComposerCommand(project, listOf("global", "config", "minimum-stability", "dev"))) {
96-
LOG.error("Failed to set composer minimum-stability to dev")
97-
return false
177+
LOG.warn("Failed to set composer minimum-stability to dev, but continuing with installation")
98178
}
99179

100180
// Install moodlehq/moodle-cs
181+
LOG.debug("Installing moodlehq/moodle-cs")
101182
if (!executeComposerCommand(project, listOf("global", "require", "moodlehq/moodle-cs"))) {
102183
LOG.error("Failed to install moodlehq/moodle-cs")
103-
return false
184+
185+
// Try alternative approach - install with --dev flag
186+
LOG.debug("Trying alternative approach with --dev flag")
187+
if (!executeComposerCommand(project, listOf("global", "require", "--dev", "moodlehq/moodle-cs"))) {
188+
LOG.error("Failed to install moodlehq/moodle-cs with --dev flag")
189+
return false
190+
}
104191
}
105192

106-
return true
193+
// Verify installation
194+
val newPhpcsPath = getPhpcsPath()
195+
val newPhpcbfPath = getPhpcbfPath()
196+
197+
if (newPhpcsPath != null && newPhpcbfPath != null) {
198+
val newPhpcsFile = java.io.File(newPhpcsPath)
199+
val newPhpcbfFile = java.io.File(newPhpcbfPath)
200+
201+
if (newPhpcsFile.exists() && newPhpcbfFile.exists()) {
202+
LOG.debug("Successfully installed PHPCS and PHPCBF")
203+
return true
204+
}
205+
}
206+
207+
LOG.warn("PHPCS or PHPCBF not found after installation")
208+
return false
107209
} catch (e: Exception) {
108210
LOG.error("Error setting up Moodle CS: ${e.message}", e)
109211
return false

0 commit comments

Comments
 (0)