Skip to content

Commit b4cb960

Browse files
committed
Improve our plugin
1 parent e0279c1 commit b4cb960

File tree

1 file changed

+87
-37
lines changed

1 file changed

+87
-37
lines changed

src/Plugin.php

Lines changed: 87 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
namespace Bugo\Sass;
44

55
use Composer\Composer;
6-
use Composer\EventDispatcher\EventSubscriberInterface;
76
use Composer\IO\IOInterface;
7+
use Composer\Plugin\PluginInterface;
8+
use Composer\EventDispatcher\EventSubscriberInterface;
89
use Composer\Installer\PackageEvent;
10+
use Composer\Script\Event;
11+
use Composer\Script\ScriptEvents;
912
use Composer\Installer\PackageEvents;
10-
use Composer\Plugin\PluginInterface;
13+
use RuntimeException;
1114
use Symfony\Component\Process\Process;
1215

1316
use function copy;
@@ -23,57 +26,69 @@ class Plugin implements PluginInterface, EventSubscriberInterface
2326
{
2427
private const PACKAGE_NAME = 'sass-embedded-php';
2528

26-
private string $packagePath;
29+
private string $packagePath = '';
2730

28-
private string $binDir;
31+
private string $binDir = '';
2932

3033
public function activate(Composer $composer, IOInterface $io): void
3134
{
3235
$config = $composer->getConfig();
3336

34-
$this->packagePath = realpath(__DIR__ . '/../');
37+
$this->packagePath = (string) realpath(__DIR__ . '/../');
3538
$this->binDir = (string) $config->get('bin-dir');
3639
}
3740

38-
public function deactivate(Composer $composer, IOInterface $io): void
39-
{
40-
}
41+
public function deactivate(Composer $composer, IOInterface $io): void {}
4142

42-
public function uninstall(Composer $composer, IOInterface $io): void
43-
{
44-
}
43+
public function uninstall(Composer $composer, IOInterface $io): void {}
4544

46-
/* @uses onPostPackageUpdate */
45+
/* @uses onPackageEvent */
46+
/* @uses onScriptEvent */
4747
public static function getSubscribedEvents(): array
4848
{
4949
return [
50-
PackageEvents::POST_PACKAGE_INSTALL => 'onPostPackageUpdate',
51-
PackageEvents::POST_PACKAGE_UPDATE => 'onPostPackageUpdate',
50+
PackageEvents::POST_PACKAGE_INSTALL => 'onPackageEvent',
51+
PackageEvents::POST_PACKAGE_UPDATE => 'onPackageEvent',
52+
ScriptEvents::POST_AUTOLOAD_DUMP => 'onScriptEvent',
5253
];
5354
}
5455

55-
public function onPostPackageUpdate(PackageEvent $event): void
56+
public function onPackageEvent(PackageEvent $event): void
5657
{
57-
static $alreadyRun = false;
58+
$this->ensureInitializedFromComposer($event->getComposer());
59+
$this->runInstall($event->getIO());
60+
}
5861

59-
if ($alreadyRun) {
60-
return;
62+
public function onScriptEvent(Event $event): void
63+
{
64+
$this->ensureInitializedFromComposer($event->getComposer());
65+
$this->runInstall($event->getIO());
66+
}
67+
68+
private function ensureInitializedFromComposer(?Composer $composer): void
69+
{
70+
if ($this->packagePath === '') {
71+
$this->packagePath = (string) realpath(__DIR__ . '/../');
6172
}
6273

63-
$alreadyRun = true;
74+
if ($composer !== null && $this->binDir === '') {
75+
$this->binDir = (string) $composer->getConfig()->get('bin-dir');
76+
}
77+
}
6478

65-
$this->installNpm($event->getIO());
66-
$this->copyBinary($event->getIO());
79+
private function runInstall(IOInterface $io): void
80+
{
81+
$this->installNpm($io);
82+
$this->copyBinary($io);
6783
}
6884

6985
private function installNpm(IOInterface $io): void
7086
{
71-
if ($this->packagePath === '') {
87+
if ($this->packagePath === '' || ! is_dir($this->packagePath)) {
7288
$io->write(sprintf(
7389
'<warning>[%s]</warning> package directory not found, skipping npm install.',
7490
self::PACKAGE_NAME
7591
));
76-
7792
return;
7893
}
7994

@@ -84,20 +99,31 @@ private function installNpm(IOInterface $io): void
8499
self::PACKAGE_NAME,
85100
$this->packagePath
86101
));
87-
88102
return;
89103
}
90104

91105
$npmBin = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? 'npm.cmd' : 'npm';
92106

93-
$checkNpm = new Process([$npmBin, '--version']);
94-
$checkNpm->run();
95-
if (! $checkNpm->isSuccessful()) {
107+
$check = new Process([$npmBin, '--version']);
108+
$check->setTimeout(10);
109+
110+
try {
111+
$check->run();
112+
} catch (RuntimeException $e) {
96113
$io->write(sprintf(
97-
'<warning>[%s]</warning> npm not found in PATH, skipping npm install.',
98-
self::PACKAGE_NAME
114+
'<warning>[%s]</warning> failed to execute "%s --version": %s',
115+
self::PACKAGE_NAME,
116+
$npmBin,
117+
$e->getMessage()
99118
));
119+
return;
120+
}
100121

122+
if (! $check->isSuccessful()) {
123+
$io->write(sprintf(
124+
'<warning>[%s]</warning> npm not found in PATH or not executable, skipping npm install.',
125+
self::PACKAGE_NAME
126+
));
101127
return;
102128
}
103129

@@ -107,33 +133,49 @@ private function installNpm(IOInterface $io): void
107133
'<info>[%s]</info> node_modules/sass-embedded already exists, skipping npm install.',
108134
self::PACKAGE_NAME
109135
));
110-
111136
return;
112137
}
113138

114139
$process = new Process([$npmBin, 'install'], $this->packagePath);
115-
$process->setTimeout(null);
116-
$process->run(function ($type, $buffer): void { echo $buffer; });
140+
$process->setTimeout(300);
141+
142+
$io->write(sprintf(
143+
'<info>[%s]</info> running "npm install" in %s',
144+
self::PACKAGE_NAME, $this->packagePath
145+
));
146+
147+
$process->run(function (string $type, string $buffer) use ($io): void {
148+
$io->write($buffer);
149+
});
117150

118151
if ($process->isSuccessful()) {
119152
$io->write(sprintf(
120153
'<info>[%s]</info> npm install completed successfully.',
121154
self::PACKAGE_NAME
122155
));
123-
124156
return;
125157
}
126158

127-
$io->write(sprintf('<error>[%s]</error> npm install failed:', self::PACKAGE_NAME));
159+
$io->write(sprintf(
160+
'<error>[%s]</error> npm install failed:',
161+
self::PACKAGE_NAME
162+
));
163+
128164
$io->write($process->getErrorOutput());
129165
}
130166

131167
private function copyBinary(IOInterface $io): void
132168
{
133169
$source = $this->packagePath . '/bin/bridge.js';
134-
$target = $this->binDir . '/bridge.js';
170+
$targetDir = rtrim($this->binDir, '/\\');
171+
$target = $targetDir . DIRECTORY_SEPARATOR . 'bridge.js';
135172

136173
if (! is_file($source)) {
174+
$io->write(sprintf(
175+
'<warning>[%s]</warning> binary not found in package (%s), skipping copy.',
176+
self::PACKAGE_NAME,
177+
$source
178+
));
137179
return;
138180
}
139181

@@ -142,9 +184,17 @@ private function copyBinary(IOInterface $io): void
142184
}
143185

144186
if (@copy($source, $target)) {
145-
$io->write(sprintf('<info>[%s]</info> Binary overwritten: %s', self::PACKAGE_NAME, $target));
187+
$io->write(sprintf(
188+
'<info>[%s]</info> Binary copied: %s',
189+
self::PACKAGE_NAME,
190+
$target
191+
));
146192
} else {
147-
$io->writeError(sprintf('<error>[%s]</error> Failed to copy binary', self::PACKAGE_NAME));
193+
$io->write(sprintf(
194+
'<error>[%s]</error> Failed to copy binary to %s',
195+
self::PACKAGE_NAME,
196+
$target
197+
));
148198
}
149199
}
150200
}

0 commit comments

Comments
 (0)