Completed
Push — master ( feef39...559eef )
by Marko
02:15
created

AframeComponentInstaller::getPublicRoot()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 0
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())) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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())) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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
            $this->io->error($this->aframe_component_vendor);
183
            $this->io->error($this->aframe_component_name);
184
            $this->io->error($this->getComponentPath());
185
        } else {
186
            $this->io->error($this->getComponentPath());
187
        }
188
        
189
        parent::removeCode($package);
190
    }
191
192
    /**
193
     * Supoorted By Name
194
     *
195
     * Is package supoorted by name. All supported package names shoudl start with aframe
196
     *
197
     * @param string $pretty_name            
198
     * @return bool
199
     */
200
    protected function supportedByName(string $pretty_name)
201
    {
202
        list ($vendor, $package_name) = array_pad(explode('/', $pretty_name, 2), 2, null);
203
        $this->aframe_component_vendor = $vendor;
204
        $this->aframe_component_name = $package_name;
205
        return substr($package_name, 0, 6) === 'aframe' && $package_name !== 'aframe';
206
    }
207
208
    /**
209
     * Get component dist path
210
     * 
211
     * @return string
212
     */
213
    protected function getComponentSrcDistPath(PackageInterface $package) : string
214
    {
215
        return $this->getInstallPath($package) . DIRECTORY_SEPARATOR . 'dist';
216
    }
217
    
218
    /**
219
     * Get A-Frame component path
220
     *
221
     * @return string
222
     */
223
    public function getComponentPath()
224
    {
225
        return empty($this->aframe_component_path) ? $this->setComponentPath() : $this->aframe_component_path;
226
    }
227
228
    /**
229
     * Set A-Frame componet public path
230
     *
231
     * @return string
232
     */
233
    protected function setComponentPath()
234
    {
235
        return $this->aframe_component_path = $this->getPublicRoot() . DIRECTORY_SEPARATOR . 'components' . DIRECTORY_SEPARATOR . $this->aframe_component_vendor . DIRECTORY_SEPARATOR . $this->aframe_component_name;
236
    }
237
238
    /**
239
     * Get public path
240
     *
241
     * Path where all package dist files will be saved
242
     *
243
     * @return string $public_path
244
     */
245
    public function getPublicRoot()
246
    {
247
        $this->initializeVendorDir();
248
        return realpath($this->public_root);
249
    }
250
251
    /**
252
     * Get A-Frame assets path
253
     *
254
     * @return string
255
     */
256
    public function getPublicAframeCoreDir()
257
    {
258
        return $this->public_core_dir ?? $this->getPublicRoot() . DIRECTORY_SEPARATOR . 'core';
259
    }
260
261
    /**
262
     * Get Composer Vendor dir
263
     *
264
     * @return string
265
     */
266
    public function getVendorDir()
267
    {
268
        return $this->vendorDir;
269
    }
270
271
    /**
272
     * Get A-Frame core assets source path
273
     *
274
     * @return string
275
     */
276
    public function getAframeCoreSrcDir()
277
    {
278
        return $this->public_src_dir ?? $this->public_src_dir = $this->getVendorDir() . DIRECTORY_SEPARATOR . 'mkungla' . DIRECTORY_SEPARATOR . 'aframe' . DIRECTORY_SEPARATOR . 'dist';
279
    }
280
281
    /**
282
     * Copy directory or files
283
     *
284
     * @param string $source            
285
     * @param string $dest            
286
     */
287
    public function copy(string $source, string $dest)
288
    {
289
        if (! empty($source) && ! empty($dest) && ! is_dir($source)) {
290
            $this->rm($dest);
291
            return copy($source, $dest);
292
        } elseif ((! empty($source) && ! empty($dest)) && is_dir($source)) {
293
            
294
            foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST) as $item) {
295
                if ($item->isDir()) {
296
                    mkdir($dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName(), octdec(str_pad($iterator->getPerms(), 4, 0, STR_PAD_LEFT)));
297
                } else {
298
                    
299
                    $this->copy($item, $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName());
300
                }
301
            }
302
            
303
            return true;
304
        } else
305
            return false;
306
    }
307
308
    /**
309
     * Remove files or directories
310
     *
311
     * @param string $pathname            
312
     * @return boolean
313
     */
314
    public function rm(string $pathname)
315
    {
316
        $response = false;
317
        if (is_dir($pathname)) {
318
            
319
            $files = array_diff(scandir($pathname), array(
320
                '.',
321
                '..'
322
            ));
323
            foreach ($files as $file) {
324
                $this->rm("$pathname/$file");
325
            }
326
            
327
            $response = rmdir($pathname);
328
        } elseif (file_exists($pathname)) {
329
            
330
            $response = unlink($pathname);
331
        }
332
        return $response;
333
    }
334
335
    /**
336
     * initializeVendorDir
337
     *
338
     * @return void
339
     */
340
    protected function initializeVendorDir()
341
    {
342
        parent::initializeVendorDir();
343
        $default_public_path = $this->getVendorDir() . DIRECTORY_SEPARATOR . 'mkungla' . DIRECTORY_SEPARATOR . 'aframe-php' . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'aframe';
344
        $this->public_root = $this->composer->getConfig()->get('aframe-dir') ?? $default_public_path;
345
        $this->filesystem->ensureDirectoryExists($this->public_root);
346
        
347
        $this->public_core_dir = $this->public_root . DIRECTORY_SEPARATOR . 'core';
348
        $this->filesystem->ensureDirectoryExists($this->public_core_dir);
349
    }
350
351
    /**
352
     * Set A-Frame assets relative base url
353
     */
354
    public function updateConfig()
355
    {
356
        $this->aframe_assets_url = $this->composer->getConfig()->get('aframe-url') ?? '/aframe';
357
        ;
358
        $composer_json = $this->getVendorDir() . DIRECTORY_SEPARATOR . 'mkungla' . DIRECTORY_SEPARATOR . 'aframe-php' . DIRECTORY_SEPARATOR . 'composer.json';
359
        
360
        if (file_exists($composer_json)) {
361
            $config = json_decode(file_get_contents($composer_json));
362
            $config->config->{'aframe-dir'} = $this->getPublicRoot();
363
            $config->config->{'aframe-url'} = $this->aframe_assets_url;
364
            $config->version = self::AFRAME_PHP_VERSION;
365
            file_put_contents($composer_json, json_encode($config, JSON_PRETTY_PRINT));
366
        }
367
    }
368
}
369