Completed
Push — master ( 379f2a...89f899 )
by Andrii
03:20
created

StartController::buildRootPath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 2
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
    public function actionMake()
40
    {
41
        $this->getRootDir();
42
        $this->takeConfig()->includeConfig(static::MAIN_CONFIG);
43
        $this->addAliases();
44
        $this->addAutoloader();
45
        $this->requireAll();
46
        $this->includeAll();
47
        $this->loadConfig();
48
        $this->takeConfig()->includeConfig(static::MAIN_CONFIG, true);
49
        self::$started = true;
50
    }
51
52
    public function addAutoloader()
53
    {
54
        $autoloader = Yii::getAlias('@root/vendor/autoload.php');
55
        if (file_exists($autoloader)) {
56
            spl_autoload_unregister(['Yii', 'autoload']);
57
            require $autoloader;
58
            spl_autoload_register(['Yii', 'autoload'], true, true);
59
        }
60
    }
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
    public function addAliases()
77
    {
78
        Yii::setAlias('@root', $this->getRootDir());
79
        $config = $this->takeConfig()->rawItem('package');
80
        $alias  = strtr($config['namespace'], '\\', '/');
81
        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
    }
86
87
    /**
88
     * Require all configured requires.
89
     */
90
    protected function requireAll()
91
    {
92
        $plugins = $this->takeConfig()->rawItem('plugins');
93
        $vendors = [];
94
        if ($plugins) {
95
            $saved = File::create('.hidev/composer.json')->save(['require' => $plugins]);
96
            if ($saved || !is_dir('.hidev/vendor')) {
97
                $this->runAction('update');
98
            }
99
            $vendors[] = '.hidev/vendor';
100
        } elseif ($this->needsComposerInstall()) {
101
            if ($this->passthru('composer', ['install', '--ansi'])) {
102
                throw new InvalidParamException('Failed initialize project with composer install');
103
            }
104
        }
105
        if (file_exists('vendor/hiqdev/hidev-config.php')) {
106
            $vendors[] = 'vendor';
107
        }
108
        if (!empty($vendors)) {
109
            /// backup config then reset with extra config then restore
110
            $config = $this->takeConfig()->getItems();
111
            Yii::$app->clear('config');
112
            foreach (array_unique($vendors) as $dir) {
113
                Yii::$app->loadExtraVendor($dir);
114
            }
115
            $this->takeConfig()->mergeItems($config);
116
        }
117
    }
118
119
    public function needsComposerInstall()
120
    {
121
        if (file_exists('vendor')) {
122
            return false;
123
        }
124
        if (!file_exists('composer.json')) {
125
            return false;
126
        }
127
        $data = File::create('composer.json')->load();
128
        foreach (['require', 'require-dev'] as $key) {
129
            if (isset($data[$key])) {
130
                foreach ($data[$key] as $package => $version) {
131
                    list(, $name) = explode('/', $package);
132
                    if (strncmp($name, 'hidev-', 6) === 0) {
133
                        return true;
134
                    }
135
                }
136
            }
137
        }
138
139
        return false;
140
    }
141
142
    /**
143
     * Include all configs.
144
     */
145
    public function includeAll()
146
    {
147
        $still = true;
148
        while ($still) {
149
            $still = false;
150
            $include = $this->takeConfig()->rawItem('include');
151
            if ($include) {
152
                foreach ($include as $path) {
153
                    $still = $still || $this->takeConfig()->includeConfig($path);
154
                }
155
            }
156
        }
157
    }
158
159
    /**
160
     * Load project's config if configured.
161
     */
162
    public function loadConfig()
163
    {
164
        $path = $this->takeConfig()->rawItem('config');
165
        if ($path) {
166
            Yii::$app->loadExtraConfig($path);
167
        }
168
    }
169
170
    public function setRootDir($value)
171
    {
172
        $this->_rootDir = $value;
173
    }
174
175
    public function getRootDir()
176
    {
177
        if ($this->_rootDir === null) {
178
            $this->_rootDir = $this->findRootDir();
179
        }
180
181
        return $this->_rootDir;
182
    }
183
184
    /**
185
     * Chdirs to project's root by looking for config file in the current directory and up.
186
     * @throws InvalidParamException when failed to find
187
     * @return string path to the root directory of hidev project
188
     */
189
    protected function findRootDir()
190
    {
191
        $configDir = '.hidev';
192
        for ($i = 0;$i < 9;++$i) {
193
            if (is_dir($configDir)) {
194
                return getcwd();
195
            }
196
            chdir('..');
197
        }
198
        throw new InvalidParamException("Not a hidev project (or any of the parent directories).\nUse `hidev init` to initialize hidev project.");
199
    }
200
201
    public function buildRootPath($subpath)
202
    {
203
        return $this->getRootDir() . DIRECTORY_SEPARATOR . $subpath;
204
    }
205
}
206