Skip to content

Commit 1b2fbcc

Browse files
Add yarn installer
1 parent b1db19f commit 1b2fbcc

File tree

3 files changed

+148
-7
lines changed

3 files changed

+148
-7
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ PHP projects mostly are Web-Applications. Many Web-Applications also need a fron
66
modern Web-Development there often a whole build-chain connected to the frontend, so you can compile e.g. your scss, build
77
your JavaScript with webpack and optimize your images.
88

9-
This plugin provides a way to automatically download the right version of node.js and npm as a package. The binaries are
10-
linked to the bin-directory specified in your composer.json.
9+
This plugin provides a way to automatically download and installthe right version of node.js, npm and yarn. The binaries
10+
are linked to the bin-directory specified in your composer.json.
1111

12-
After that your can use node and npm in your scripts.
12+
After that your can use node, npm and yarn in your composer-scripts.
1313

1414
## Setup
1515

@@ -34,7 +34,8 @@ Example composer.json
3434
"extra": {
3535
"mariusbuescher": {
3636
"node-composer": {
37-
"node-version": "4.8.3"
37+
"node-version": "4.8.3",
38+
"yarn-version": "0.22.0"
3839
}
3940
}
4041
}

src/Installer/YarnInstaller.php

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
<?php
2+
3+
namespace MariusBuescher\NodeComposer\Installer;
4+
5+
use Composer\IO\IOInterface;
6+
use MariusBuescher\NodeComposer\InstallerInterface;
7+
use MariusBuescher\NodeComposer\NodeContext;
8+
9+
class YarnInstaller implements InstallerInterface
10+
{
11+
/**
12+
* @var IOInterface
13+
*/
14+
private $io;
15+
16+
/**
17+
* @var NodeContext
18+
*/
19+
private $context;
20+
21+
/**
22+
* NodeDownloader constructor.
23+
* @param IOInterface $io
24+
* @param NodeContext $context
25+
*/
26+
public function __construct(
27+
IOInterface $io,
28+
NodeContext $context
29+
) {
30+
$this->io = $io;
31+
$this->context = $context;
32+
}
33+
34+
/**
35+
* @param string $version
36+
* @throws \InvalidArgumentException
37+
* @return bool
38+
*/
39+
public function install($version)
40+
{
41+
if (!is_string($version)) {
42+
throw new \InvalidArgumentException(
43+
sprintf('Version must be a string, %s given'), gettype($version)
44+
);
45+
}
46+
47+
$output = $return = null;
48+
49+
exec(
50+
$this->context->getBinDir() . DIRECTORY_SEPARATOR . 'npm install --global yarn@' . $version,
51+
$output,
52+
$return
53+
);
54+
55+
if ($return !== 0) {
56+
throw new \RuntimeException('Could not install yarn');
57+
}
58+
59+
$sourceDir = $this->getNpmBinaryPath();
60+
61+
$this->linkExecutables($sourceDir, $this->context->getBinDir());
62+
63+
return true;
64+
}
65+
66+
public function isInstalled()
67+
{
68+
$output = array();
69+
$return = null;
70+
71+
$nodeExecutable = $this->context->getBinDir() . DIRECTORY_SEPARATOR . 'yarn';
72+
73+
exec("$nodeExecutable --version", $output, $return);
74+
75+
if ($return === 0) {
76+
return $output[0];
77+
} else {
78+
return false;
79+
}
80+
}
81+
82+
/**
83+
* @param string $sourceDir
84+
* @param string $targetDir
85+
*/
86+
private function linkExecutables($sourceDir, $targetDir)
87+
{
88+
$yarnPath = realpath($sourceDir . DIRECTORY_SEPARATOR . 'yarn');
89+
$yarnLink = $targetDir . DIRECTORY_SEPARATOR . 'yarn';
90+
91+
if (realpath($yarnLink)) {
92+
unlink($yarnLink);
93+
}
94+
95+
symlink($yarnPath, $yarnLink);
96+
97+
$yarnpkgPath = realpath($sourceDir . DIRECTORY_SEPARATOR . 'yarnpkg');
98+
$yarnpkgLink = $targetDir . DIRECTORY_SEPARATOR . 'yarnpkg';
99+
100+
if (realpath($yarnpkgLink)) {
101+
unlink($yarnpkgLink);
102+
}
103+
104+
symlink($yarnpkgPath, $yarnpkgLink);
105+
}
106+
107+
/**
108+
* @return string
109+
*/
110+
private function getNpmBinaryPath()
111+
{
112+
$output = array();
113+
$return = null;
114+
115+
exec($this->context->getBinDir() . DIRECTORY_SEPARATOR . 'npm -g bin', $output, $return);
116+
117+
if ($return !== 0) {
118+
throw new \RuntimeException('npm must be installed');
119+
}
120+
121+
return $output[0];
122+
}
123+
}

src/NodeComposerPlugin.php

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Composer\Util\RemoteFilesystem;
1313
use MariusBuescher\NodeComposer\Exception\NodeComposerConfigException;
1414
use MariusBuescher\NodeComposer\Installer\NodeInstaller;
15+
use MariusBuescher\NodeComposer\Installer\YarnInstaller;
1516

1617
class NodeComposerPlugin implements PluginInterface, EventSubscriberInterface
1718
{
@@ -69,13 +70,29 @@ public function onPostUpdate(Event $event)
6970
$context
7071
);
7172

72-
$installedVersion = $nodeInstaller->isInstalled();
73+
$installedNodeVersion = $nodeInstaller->isInstalled();
7374

7475
if (
75-
$installedVersion === false ||
76-
strpos($installedVersion, 'v' . $this->config->getNodeVersion()) === false
76+
$installedNodeVersion === false ||
77+
strpos($installedNodeVersion, 'v' . $this->config->getNodeVersion()) === false
7778
) {
7879
$nodeInstaller->install($this->config->getNodeVersion());
7980
}
81+
82+
if ($this->config->getYarnVersion() !== null) {
83+
$yarnInstaller = new YarnInstaller(
84+
$this->io,
85+
$context
86+
);
87+
88+
$installedYarnVersion = $yarnInstaller->isInstalled();
89+
90+
if (
91+
$installedYarnVersion === false ||
92+
strpos($installedYarnVersion, $this->config->getYarnVersion()) === false
93+
) {
94+
$yarnInstaller->install($this->config->getYarnVersion());
95+
}
96+
}
8097
}
8198
}

0 commit comments

Comments
 (0)