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