Completed
Branch master (fb685e)
by Marko
02:00
created

AframeComponentInstaller   B

Complexity

Total Complexity 37

Size/Duplication

Total Lines 330
Duplicated Lines 6.67 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
wmc 37
lcom 1
cbo 0
dl 22
loc 330
rs 8.6
c 0
b 0
f 0

16 Methods

Rating   Name   Duplication   Size   Complexity  
A supports() 0 4 1
A isInstalled() 0 4 2
A install() 11 20 3
A update() 11 20 3
A removeCode() 0 17 3
A supportedByName() 0 7 2
A getComponentPath() 0 4 2
A setComponentPath() 0 4 1
A getPublicRoot() 0 5 1
A getPublicAframeCoreDir() 0 4 1
A getVendorDir() 0 4 1
A getAframeCoreSrcDir() 0 4 1
B copy() 0 20 9
A rm() 0 20 4
A initializeVendorDir() 0 10 1
A updateConfig() 0 14 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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 $packageType            
0 ignored issues
show
Bug introduced by
There is no parameter named $packageType. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
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
            $src = $this->getInstallPath($package) . DIRECTORY_SEPARATOR . 'dist';
125
            if (! is_dir($src)) {
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($src, $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($package->getPrettyName());
0 ignored issues
show
Bug introduced by
The variable $package does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

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