Completed
Push — master ( 84c8d2...736689 )
by Marko
02:14
created

AframeComponentInstaller::install()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 20
Code Lines 12

Duplication

Lines 11
Ratio 55 %

Importance

Changes 0
Metric Value
dl 11
loc 20
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 12
nc 3
nop 2
1
<?php
2
/** @formatter:off
3
 * ******************************************************************
4
 * Created by   Marko Kungla on Jun 26, 2016 - 4:34:50 PM
5
 * Contact      [email protected]
6
 * @copyright   2016 Marko Kungla - https://github.com/mkungla
7
 * @license     The MIT License (MIT)
8
 * 
9
 * @category       AframeVR
10
 * @package        aframe-php
11
 * 
12
 * Lang         PHP (php version >= 7)
13
 * Encoding     UTF-8
14
 * File         AframeComponentInstaller.php
15
 * Code format  PSR-2 and 12
16
 * @link        https://github.com/mkungla/aframe-php
17
 ^ @issues      https://github.com/mkungla/aframe-php/issues
18
 * ********************************************************************
19
 * Contributors:
20
 * @author Marko Kungla <[email protected]>
21
 * ********************************************************************
22
 * Comments:
23
 * @formatter:on */
24
namespace AframeVR\Composer\Installer;
25
26
use Composer\Installer\LibraryInstaller;
27
use Composer\Repository\InstalledRepositoryInterface;
28
use Composer\Package\PackageInterface;
29
30
class AframeComponentInstaller extends LibraryInstaller
31
{
32
33
    const AFRAME_PHP_VERSION = '0.3.0.1';
34
35
    const SUPPORTED_TYPES = array(
36
        'component',
37
        'aframe',
38
        'aframe-component'
39
    );
40
41
    /**
42
     * A-Frame Component vendor
43
     *
44
     * @var string
45
     */
46
    protected $aframe_component_vendor;
47
48
    /**
49
     * A-Frame Component package name
50
     *
51
     * @var string
52
     */
53
    protected $aframe_component_name;
54
55
    /**
56
     * Path to directory of A-Frame assets
57
     *
58
     * @var string
59
     */
60
    protected $public_root;
61
62
    /**
63
     * Path to A-Frame core scripts
64
     *
65
     * @var string
66
     */
67
    protected $public_core_dir;
68
69
    /**
70
     * URI of A-Frame assets relative to your document root
71
     *
72
     * @var string
73
     */
74
    protected $aframe_assets_url = '/aframe';
75
76
    /**
77
     * Decides if the installer supports the given type
78
     * and package.
79
     * We only handle components with name prefix aframe
80
     *
81
     * @param string $package_type            
82
     * @return bool
83
     */
84
    public function supports($package_type)
85
    {
86
        return in_array($package_type, self::SUPPORTED_TYPES);
87
    }
88
89
    /**
90
     * Checks that provided package is installed.
91
     *
92
     * @param InstalledRepositoryInterface $repo
93
     *            repository in which to check
94
     * @param PackageInterface $package
95
     *            package instance
96
     *            
97
     * @return bool
98
     */
99
    public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
100
    {
101
        return parent::isInstalled($repo, $package) && is_dir($this->getComponentPath());
102
    }
103
104
    /**
105
     * Installs specific package.
106
     *
107
     * @param InstalledRepositoryInterface $repo
108
     *            repository in which to check
109
     * @param PackageInterface $package
110
     *            package instance
111
     *            
112
     * @return void
113
     */
114
    public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
115
    {
116
        parent::install($repo, $package);
117
        
118
        $this->initializeVendorDir();
119
        $this->supportedByName($package->getPrettyName());
120
        $this->setComponentPath();
121
        
122 View Code Duplication
        if ($this->supportedByName($package->getPrettyName())) {
123
            $this->io->info(sprintf("Installing A-Frame Component %s", $this->aframe_component_name));
124
            
125
            if (! is_dir($this->getComponentSrcDistPath($package))) {
126
                $this->io->warning(sprintf('A-Frame Component %s can not be used since missing dist directory!', $this->aframe_component_name));
127
            } else {
128
                $this->filesystem->ensureDirectoryExists($this->getComponentPath());
129
                
130
                $this->copy($this->getComponentSrcDistPath($package), $this->getComponentPath());
131
            }
132
        }
133
    }
134
135
    /**
136
     * Updates specific package.
137
     *
138
     * @param InstalledRepositoryInterface $repo
139
     *            repository in which to check
140
     * @param PackageInterface $initial
141
     *            already installed package version
142
     * @param PackageInterface $target
143
     *            updated version
144
     *            
145
     * @throws InvalidArgumentException if $initial package is not installed
146
     * @return void
147
     */
148
    public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
149
    {
150
        parent::update($repo, $initial, $target);
151
        
152
        $this->initializeVendorDir();
153
        $this->supportedByName($target->getPrettyName());
154
        $this->setComponentPath();
155
        
156 View Code Duplication
        if ($this->supportedByName($target->getPrettyName())) {
157
            $this->io->info(sprintf("Updating A-Frame Component %s", $this->aframe_component_name));
158
            if (! is_dir($this->getComponentSrcDistPath($target))) {
159
                $this->io->warning(sprintf('A-Frame Component %s can not be used since missing dist directory!', $this->aframe_component_name));
160
            } else {
161
                $this->filesystem->removeDirectory($this->getComponentPath());
162
                $this->filesystem->ensureDirectoryExists($this->getComponentPath());
163
                $this->copy($this->getComponentSrcDistPath($target), $this->getComponentPath());
164
            }
165
        }
166
    }
167
168
    /**
169
     * Remove the code
170
     *
171
     * @param PackageInterface $package            
172
     * @return void
173
     */
174
    public function removeCode(PackageInterface $package)
175
    {
176
        $this->initializeVendorDir();
177
        $this->supportedByName($package->getPrettyName());
178
        $this->setComponentPath();
179
        
180
        if (is_dir($this->getComponentPath()) && basename($this->getComponentPath()) !== 'component') {
181
            $this->filesystem->removeDirectory($this->getComponentPath());
182
        } else {
183
            $this->io->error($this->getComponentPath());
184
        }
185
        
186
        parent::removeCode($package);
187
    }
188
189
    /**
190
     * Supoorted By Name
191
     *
192
     * Is package supoorted by name. All supported package names shoudl start with aframe
193
     *
194
     * @param string $pretty_name            
195
     * @return bool
196
     */
197
    protected function supportedByName(string $pretty_name)
198
    {
199
        list ($vendor, $package_name) = array_pad(explode('/', $pretty_name, 2), 2, null);
200
        $this->aframe_component_vendor = $vendor;
201
        $this->aframe_component_name = $package_name;
202
        return substr($package_name, 0, 6) === 'aframe' && $package_name !== 'aframe';
203
    }
204
205
    /**
206
     * Get component dist path
207
     *
208
     * @return string
209
     */
210
    protected function getComponentSrcDistPath(PackageInterface $package): string
211
    {
212
        return $this->getInstallPath($package) . DIRECTORY_SEPARATOR . 'dist';
213
    }
214
215
    /**
216
     * Get A-Frame component path
217
     *
218
     * @return string
219
     */
220
    public function getComponentPath()
221
    {
222
        return empty($this->aframe_component_path) ? $this->setComponentPath() : $this->aframe_component_path;
223
    }
224
225
    /**
226
     * Set A-Frame componet public path
227
     *
228
     * @return string
229
     */
230
    protected function setComponentPath()
231
    {
232
        return $this->aframe_component_path = $this->getPublicRoot() . DIRECTORY_SEPARATOR . 'components' . DIRECTORY_SEPARATOR . $this->aframe_component_vendor . DIRECTORY_SEPARATOR . $this->aframe_component_name;
233
    }
234
235
    /**
236
     * Get public path
237
     *
238
     * Path where all package dist files will be saved
239
     *
240
     * @return string $public_path
241
     */
242
    public function getPublicRoot()
243
    {
244
        $this->initializeVendorDir();
245
        return realpath($this->public_root);
246
    }
247
248
    /**
249
     * Get A-Frame assets path
250
     *
251
     * @return string
252
     */
253
    public function getPublicAframeCoreDir()
254
    {
255
        return $this->public_core_dir ?? $this->getPublicRoot() . DIRECTORY_SEPARATOR . 'core';
256
    }
257
258
    /**
259
     * Get Composer Vendor dir
260
     *
261
     * @return string
262
     */
263
    public function getVendorDir()
264
    {
265
        return $this->vendorDir;
266
    }
267
268
    /**
269
     * Get A-Frame core assets source path
270
     *
271
     * @return string
272
     */
273
    public function getAframeCoreSrcDir()
274
    {
275
        return $this->public_src_dir ?? $this->public_src_dir = $this->getVendorDir() . DIRECTORY_SEPARATOR . 'mkungla' . DIRECTORY_SEPARATOR . 'aframe' . DIRECTORY_SEPARATOR . 'dist';
276
    }
277
278
    /**
279
     * Copy directory or files
280
     *
281
     * @param string $source            
282
     * @param string $dest            
283
     * @return bool
284
     */
285
    public function copy(string $source, string $dest)
286
    {
287
        return ! is_dir($source) ? $this->rm($dest) & copy($source, $dest) : $this->copyDir($source, $dest);
288
    }
289
    
290
    /**
291
     * Copy directory
292
     * 
293
     * @param string $source
294
     * @param string $dest
295
     */
296
    private function copyDir(string $source, string $dest)
297
    {
298
        $dir_iterator = new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS);
299
        $iterator = new \RecursiveIteratorIterator($dir_iterator, \RecursiveIteratorIterator::SELF_FIRST);
300
        foreach ($iterator as $item) {
301
            if ($item->isDir()) {
302
                mkdir($dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName(), octdec(str_pad($iterator->getPerms(), 4, 0, STR_PAD_LEFT)));
303
            } else {   
304
                $this->copy($item, $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName());
305
            }
306
        }
307
        return true;
308
    }
309
310
    /**
311
     * Remove files or directories
312
     *
313
     * @param string $pathname            
314
     * @return boolean
315
     */
316
    public function rm(string $pathname)
317
    {
318
        $response = false;
319
        if (is_dir($pathname)) {
320
            
321
            $files = array_diff(scandir($pathname), array(
322
                '.',
323
                '..'
324
            ));
325
            foreach ($files as $file) {
326
                $this->rm("$pathname/$file");
327
            }
328
            
329
            $response = rmdir($pathname);
330
        } elseif (file_exists($pathname)) {
331
            
332
            $response = unlink($pathname);
333
        }
334
        return $response;
335
    }
336
337
    /**
338
     * initializeVendorDir
339
     *
340
     * @return void
341
     */
342
    protected function initializeVendorDir()
343
    {
344
        parent::initializeVendorDir();
345
        $default_public_path = $this->getVendorDir() . DIRECTORY_SEPARATOR . 'mkungla' . DIRECTORY_SEPARATOR . 'aframe-php' . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'aframe';
346
        $this->public_root = $this->composer->getConfig()->get('aframe-dir') ?? $default_public_path;
347
        $this->filesystem->ensureDirectoryExists($this->public_root);
348
        
349
        $this->public_core_dir = $this->public_root . DIRECTORY_SEPARATOR . 'core';
350
        $this->filesystem->ensureDirectoryExists($this->public_core_dir);
351
    }
352
353
    /**
354
     * Set A-Frame assets relative base url
355
     */
356
    public function updateConfig()
357
    {
358
        $this->aframe_assets_url = $this->composer->getConfig()->get('aframe-url') ?? '/aframe';
359
        ;
360
        $composer_json = $this->getVendorDir() . DIRECTORY_SEPARATOR . 'mkungla' . DIRECTORY_SEPARATOR . 'aframe-php' . DIRECTORY_SEPARATOR . 'composer.json';
361
        
362
        if (file_exists($composer_json)) {
363
            $config = json_decode(file_get_contents($composer_json));
364
            $config->config->{'aframe-dir'} = $this->getPublicRoot();
365
            $config->config->{'aframe-url'} = $this->aframe_assets_url;
366
            $config->version = self::AFRAME_PHP_VERSION;
367
            file_put_contents($composer_json, json_encode($config, JSON_PRETTY_PRINT));
368
        }
369
    }
370
}
371