Completed
Push — master ( 32412c...4a6135 )
by Andrii
03:09
created

StartController::requireAll()   C

Complexity

Conditions 9
Paths 25

Size

Total Lines 24
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 29.8773

Importance

Changes 5
Bugs 2 Features 0
Metric Value
c 5
b 2
f 0
dl 0
loc 24
ccs 8
cts 22
cp 0.3636
rs 5.3563
cc 9
eloc 16
nc 25
nop 0
crap 29.8773
1
<?php
2
3
/*
4
 * Task runner, code generator and build tool for easier continuos integration
5
 *
6
 * @link      https://github.com/hiqdev/hidev
7
 * @package   hidev
8
 * @license   BSD-3-Clause
9
 * @copyright Copyright (c) 2015-2016, HiQDev (http://hiqdev.com/)
10
 */
11
12
namespace hidev\controllers;
13
14
use hidev\base\File;
15
use Yii;
16
use yii\base\InvalidParamException;
17
18
/**
19
 * Start goal.
20
 * Chdirs to the project's root directory and loads dependencies and configs.
21
 */
22
class StartController extends CommonController
23
{
24
    const MAIN_CONFIG = '.hidev/config.yml';
25
26
    /**
27
     * @var string absolute path to the project root directory
28
     */
29
    protected $_rootDir;
30
31
    /**
32
     * @var bool hidev already started flag
33
     */
34
    public static $started = false;
35
36
    /**
37
     * Make action.
38
     */
39 3
    public function actionMake()
40
    {
41 3
        $this->getRootDir();
42 3
        $this->takeConfig()->includeConfig(static::MAIN_CONFIG);
43 3
        $this->addAliases();
44 3
        $this->addAutoloader();
45 3
        $this->requireAll();
46 3
        $this->includeAll();
47 3
        $this->loadConfig();
48 3
        $this->takeConfig()->includeConfig(static::MAIN_CONFIG, true);
49 3
        self::$started = true;
50 3
    }
51
52 3
    public function addAutoloader()
53
    {
54 3
        $autoloader = Yii::getAlias('@root/vendor/autoload.php');
55 3
        if (file_exists($autoloader)) {
56
            spl_autoload_unregister(['Yii', 'autoload']);
57
            require $autoloader;
58
            spl_autoload_register(['Yii', 'autoload'], true, true);
59
        }
60 3
    }
61
62
    /**
63
     * Update action.
64
     * @return int exit code
65
     */
66
    public function actionUpdate()
67
    {
68
        return $this->passthru('composer', ['update', '-d', '.hidev', '--prefer-source', '--ansi']);
69
    }
70
71
    /**
72
     * Adds aliases:
73
     * - @root alias to current project root dir
74
     * - current package namespace for it could be used from hidev.
75
     */
76 3
    public function addAliases()
77
    {
78 3
        Yii::setAlias('@root', $this->getRootDir());
79 3
        $config = $this->takeConfig()->rawItem('package');
80 3
        $alias  = strtr($config['namespace'], '\\', '/');
81 3
        if ($alias && !Yii::getAlias('@' . $alias, false)) {
82
            $srcdir = Yii::getAlias('@root/' . ($config['src'] ?: 'src'));
83
            Yii::setAlias($alias, $srcdir);
0 ignored issues
show
Bug introduced by
It seems like $srcdir defined by \Yii::getAlias('@root/' ...onfig['src'] ?: 'src')) on line 82 can also be of type boolean; however, yii\BaseYii::setAlias() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
84
        }
85 3
        $aliases = $this->takeConfig()->rawItem('aliases');
86 3
        if (!empty($aliases) && is_array($aliases)) {
87
            foreach ($aliases as $alias => $path) {
88
                if (!$this->hasAlias($alias)) {
89
                    Yii::setAlias($alias, $path);
90
                }
91
            }
92
        }
93 3
    }
94
95
    public function hasAlias($alias, $exact = true)
0 ignored issues
show
Unused Code introduced by
The parameter $exact is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
96
    {
97
        $pos = strpos($alias, '/');
98
99
        return $pos === false ? isset(Yii::$aliases[$alias]) : isset(Yii::$aliases[substr($alias, 0, $pos)][$alias]);
100
    }
101
102
    /**
103
     * Require all configured requires.
104
     */
105 3
    protected function requireAll()
106
    {
107 3
        $plugins = $this->takeConfig()->rawItem('plugins');
108 3
        $vendors = [];
109 3
        if ($plugins) {
110
            $saved = File::create('.hidev/composer.json')->save(['require' => $plugins]);
111
            if ($saved || !is_dir('.hidev/vendor')) {
112
                $this->runAction('update');
113
            }
114
            $vendors[] = '.hidev/vendor';
115 3
        } elseif ($this->needsComposerInstall()) {
116
            if ($this->passthru('composer', ['install', '--ansi'])) {
117
                throw new InvalidParamException('Failed initialize project with composer install');
118
            }
119
        }
120 3
        if (file_exists('vendor/hiqdev/hidev-config.php')) {
121
            $vendors[] = 'vendor';
122
        }
123 3
        if (!empty($vendors)) {
124
            foreach (array_unique($vendors) as $dir) {
125
                $this->module->loadExtraVendor($dir);
126
            }
127
        }
128 3
    }
129
130 3
    public function needsComposerInstall()
131
    {
132 3
        if (file_exists('vendor')) {
133
            return false;
134
        }
135 3
        if (!file_exists('composer.json')) {
136 3
            return false;
137
        }
138
        $data = File::create('composer.json')->load();
139
        foreach (['require', 'require-dev'] as $key) {
140
            if (isset($data[$key])) {
141
                foreach ($data[$key] as $package => $version) {
142
                    list(, $name) = explode('/', $package);
143
                    if (strncmp($name, 'hidev-', 6) === 0) {
144
                        return true;
145
                    }
146
                }
147
            }
148
        }
149
150
        return false;
151
    }
152
153
    /**
154
     * Include all configs.
155
     */
156 3
    public function includeAll()
157
    {
158 3
        $still = true;
159 3
        while ($still) {
160 3
            $still = false;
161 3
            $include = $this->takeConfig()->rawItem('include');
162 3
            if ($include) {
163
                foreach ($include as $path) {
164
                    $still = $still || $this->takeConfig()->includeConfig($path);
165
                }
166
            }
167 3
        }
168 3
    }
169
170
    /**
171
     * Load project's config if configured.
172
     */
173 3
    public function loadConfig()
174
    {
175 3
        $path = $this->takeConfig()->rawItem('config');
176 3
        if ($path) {
177
            $this->module->loadExtraConfig($path);
178
        }
179 3
    }
180
181
    public function setRootDir($value)
182
    {
183
        $this->_rootDir = $value;
184
    }
185
186 3
    public function getRootDir()
187
    {
188 3
        if ($this->_rootDir === null) {
189 3
            $this->_rootDir = $this->findRootDir();
190 3
        }
191
192 3
        return $this->_rootDir;
193
    }
194
195
    /**
196
     * Chdirs to project's root by looking for config file in the current directory and up.
197
     * @throws InvalidParamException when failed to find
198
     * @return string path to the root directory of hidev project
199
     */
200 3
    protected function findRootDir()
201
    {
202 3
        $configDir = '.hidev';
203 3
        for ($i = 0;$i < 9;++$i) {
204 3
            if (is_dir($configDir)) {
205 3
                return getcwd();
206
            }
207
            chdir('..');
208
        }
209
        throw new InvalidParamException("Not a hidev project (or any of the parent directories).\nUse `hidev init` to initialize hidev project.");
210
    }
211
212
    public function buildRootPath($subpath)
213
    {
214
        return $this->getRootDir() . DIRECTORY_SEPARATOR . $subpath;
215
    }
216
}
217