Completed
Pull Request — master (#148)
by
unknown
02:59
created

Config::getPackageBowerFileContent()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 14
rs 9.4285
cc 3
eloc 9
nc 3
nop 1
1
<?php
2
3
/*
4
 * This file is part of Bowerphp.
5
 *
6
 * (c) Massimiliano Arione <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Bowerphp\Config;
13
14
use Bowerphp\Package\PackageInterface;
15
use Bowerphp\Util\Filesystem;
16
use RuntimeException;
17
18
/**
19
 * Config
20
 */
21
class Config implements ConfigInterface
22
{
23
    protected $cacheDir;
24
    protected $installDir;
25
    protected $filesystem;
26
    protected $basePackagesUrl = 'http://bower.herokuapp.com/packages/';
27
    protected $allPackagesUrl = 'https://bower-component-list.herokuapp.com/';
28
    protected $saveToBowerJsonFile = false;
29
    protected $bowerFileNames = ['bower.json', 'package.json'];
30
    protected $stdBowerFileName = 'bower.json';
31
    protected $scripts = ['preinstall'=>[],'postinstall'=>[],'preuninstall'=>[]];
32
33
    /**
34
     * @param Filesystem $filesystem
35
     */
36
    public function __construct(Filesystem $filesystem)
0 ignored issues
show
Complexity introduced by
This operation has 292 execution paths which exceeds the configured maximum of 200.

A high number of execution paths generally suggests many nested conditional statements and make the code less readible. This can usually be fixed by splitting the method into several smaller methods.

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

Loading history...
Coding Style Naming introduced by
The variable $GLOBALS is not named in camelCase.

This check marks variable names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style introduced by
__construct uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
37
    {
38
        $this->filesystem = $filesystem;
39
        $this->cacheDir = $this->getHomeDir() . '/.cache/bowerphp';
40
        $this->installDir = getcwd() . '/bower_components';
41
        $rc = getcwd() . '/.bowerrc';
42
        if ($this->filesystem->exists($rc)) {
43
            $json = json_decode($this->filesystem->read($rc), true);
44
            if (is_null($json)) {
45
                throw new RuntimeException('Invalid .bowerrc file.');
46
            }
47
            if (isset($json['directory'])) {
48
                $this->installDir = getcwd() . '/' . $json['directory'];
49
            }
50
            if (isset($json['storage']) && isset($json['storage']['packages'])) {
51
                $this->cacheDir = $json['storage']['packages'];
52
            }
53
            if (isset($json['scripts'])){
54
				$this->scripts = (array)$json['scripts']+$this->scripts;
55
			}
56
            if (isset($json['token'])&&!isset($GLOBALS['BOWERPHP_TOKEN'])){
57
				putenv('BOWERPHP_TOKEN='.$json['token']);
58
				$GLOBALS['BOWERPHP_TOKEN'] = $json['token'];
59
			}
60
			
61
        }
62
        
63
        $composer = getcwd() . '/composer.json';
64
        if (!isset($GLOBALS['BOWERPHP_TOKEN'])&&$this->filesystem->exists($composer)) {
65
            $json = json_decode($this->filesystem->read($composer), true);
66
            if (isset($json['config']['github-oauth']['github.com'])){
67
				$token = $json['config']['github-oauth']['github.com'];
68
				putenv('BOWERPHP_TOKEN='.$token);
69
				$GLOBALS['BOWERPHP_TOKEN'] = $token;
70
			}
71
        }
72
    }
73
	
74
	/**
75
     * {@inheritdoc}
76
     */
77
    public function getScripts()
78
    {
79
        return $this->scripts;
80
    }
81
	
82
    /**
83
     * {@inheritdoc}
84
     */
85
    public function getBasePackagesUrl()
86
    {
87
        return $this->basePackagesUrl;
88
    }
89
90
    /**
91
     * {@inheritdoc}
92
     */
93
    public function getAllPackagesUrl()
94
    {
95
        return $this->allPackagesUrl;
96
    }
97
98
    /**
99
     * {@inheritdoc}
100
     */
101
    public function getCacheDir()
102
    {
103
        return $this->cacheDir;
104
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109
    public function getInstallDir()
110
    {
111
        return $this->installDir;
112
    }
113
114
    /**
115
     * {@inheritdoc}
116
     */
117
    public function isSaveToBowerJsonFile()
118
    {
119
        return $this->saveToBowerJsonFile;
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125
    public function setSaveToBowerJsonFile($flag = true)
126
    {
127
        $this->saveToBowerJsonFile = $flag;
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133
    public function initBowerJsonFile(array $params)
134
    {
135
        $file = getcwd() . '/' . $this->stdBowerFileName;
136
        $json = json_encode($this->createAClearBowerFile($params), JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE);
137
138
        return $this->filesystem->write($file, $json);
139
    }
140
141
    /**
142
     * {@inheritdoc}
143
     */
144
    public function updateBowerJsonFile(PackageInterface $package)
145
    {
146
        if (!$this->isSaveToBowerJsonFile()) {
147
            return 0;
148
        }
149
150
        $decode = $this->getBowerFileContent();
151
        $decode['dependencies'][$package->getName()] = $package->getRequiredVersion();
152
        $file = getcwd() . '/' . $this->stdBowerFileName;
153
        $json = json_encode($decode, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE);
154
155
        return $this->filesystem->write($file, $json);
156
    }
157
158
    /**
159
     * {@inheritdoc}
160
     */
161
    public function updateBowerJsonFile2(array $old, array $new)
162
    {
163
        $json = json_encode(array_merge($old, $new), JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE);
164
        $file = getcwd() . '/' . $this->stdBowerFileName;
165
166
        return $this->filesystem->write($file, $json);
167
    }
168
169
    /**
170
     * {@inheritdoc}
171
     */
172
    public function getBowerFileContent()
173
    {
174
        if (!$this->bowerFileExists()) {
175
            throw new RuntimeException('No ' . $this->stdBowerFileName . ' found. You can run "init" command to create it.');
176
        }
177
        $bowerJson = $this->filesystem->read(getcwd() . '/' . $this->stdBowerFileName);
178
        if (empty($bowerJson) || !is_array($decode = json_decode($bowerJson, true))) {
179
            throw new RuntimeException(sprintf('Malformed JSON in %s: %s.', $this->stdBowerFileName, $bowerJson));
180
        }
181
182
        return $decode;
183
    }
184
185
    /**
186
     * {@inheritdoc}
187
     */
188
    public function getOverridesSection()
189
    {
190
        if ($this->bowerFileExists()) {
191
            $bowerData = $this->getBowerFileContent();
192
            if ($bowerData && array_key_exists('overrides', $bowerData)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $bowerData of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
193
                return $bowerData['overrides'];
194
            }
195
        }
196
197
        return [];
198
    }
199
200
    /**
201
     * {@inheritdoc}
202
     */
203
    public function getOverrideFor($packageName)
204
    {
205
        $overrides = $this->getOverridesSection();
206
        if (array_key_exists($packageName, $overrides)) {
207
            return $overrides[$packageName];
208
        }
209
210
        return [];
211
    }
212
213
    /**
214
     * {@inheritdoc}
215
     */
216
    public function getPackageBowerFileContent(PackageInterface $package)
217
    {
218
        $file = $this->getInstallDir() . '/' . $package->getName() . '/.bower.json';
219
        if (!$this->filesystem->exists($file)) {
220
            throw new RuntimeException(sprintf('Could not find .bower.json file for package %s.', $package->getName()));
221
        }
222
        $bowerJson = $this->filesystem->read($file);
223
        $bower = json_decode($bowerJson, true);
224
        if (is_null($bower)) {
225
            throw new RuntimeException(sprintf('Invalid content in .bower.json for package %s.', $package->getName()));
226
        }
227
228
        return $bower;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $bower; (object|integer|double|string|array|boolean) is incompatible with the return type declared by the interface Bowerphp\Config\ConfigIn...PackageBowerFileContent of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
229
    }
230
231
    /**
232
     * {@inheritdoc}
233
     */
234
    public function bowerFileExists()
235
    {
236
        return $this->filesystem->exists(getcwd() . '/' . $this->stdBowerFileName);
237
    }
238
239
    /**
240
     * @param  array $params
241
     * @return array
242
     */
243
    protected function createAClearBowerFile(array $params)
244
    {
245
        $structure = [
246
            'name'    => $params['name'],
247
            'authors' => [
248
                0 => 'Beelab <[email protected]>',
249
                1 => $params['author'],
250
            ],
251
            'private'      => true,
252
            'dependencies' => new \StdClass(),
253
        ];
254
255
        return $structure;
256
    }
257
258
    /**
259
     * @return string
260
     */
261
    protected function getHomeDir()
262
    {
263
        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
264
            $appData = getenv('APPDATA');
265
            if (empty($appData)) {
266
                throw new \RuntimeException('The APPDATA environment variable must be set for bowerphp to run correctly');
267
            }
268
269
            return strtr($appData, '\\', '/');
270
        }
271
        $home = getenv('HOME');
272
        if (empty($home)) {
273
            throw new \RuntimeException('The HOME environment variable must be set for bowerphp to run correctly');
274
        }
275
276
        return rtrim($home, '/');
277
    }
278
}
279