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+ }
0 commit comments