Test Failed
Push — master ( 62e8aa...e74fb5 )
by Julien
04:23
created

Bootstrap::setMode()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 5
ccs 0
cts 4
cp 0
crap 6
rs 10
1
<?php
2
3
/**
4
 * This file is part of the Zemit Framework.
5
 *
6
 * (c) Zemit Team <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE.txt
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Zemit;
13
14
use Phalcon\Application\AbstractApplication;
15
use Phalcon\Di;
16
use Phalcon\Di\DiInterface;
17
use Phalcon\Di\FactoryDefault;
18
use Phalcon\Events;
19
use Phalcon\Http\ResponseInterface;
20
use Phalcon\Text;
21
use Zemit\Config\ConfigInterface;
22
use Zemit\Cli\Console;
23
use Zemit\Events\EventsAwareTrait;
24
use Zemit\Mvc\Application;
25
use Zemit\Provider\Config\ServiceProvider as ConfigServiceProvider;
26
use Zemit\Provider\Router\ServiceProvider as RouterServiceProvider;
27
use Zemit\Router\RouterInterface;
0 ignored issues
show
Bug introduced by
The type Zemit\Router\RouterInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
28
use Zemit\Support\Php;
0 ignored issues
show
Bug introduced by
The type Zemit\Support\Php was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
29
use Docopt;
30
31
/**
32
 * Zemit Core's Bootstrap for the MVC Application & CLI Console mode
33
 */
34
class Bootstrap
35
{
36
    use EventsAwareTrait;
37
    
38
    public const MODE_CLI = 'cli';
39
    public const MODE_MVC = 'mvc';
40
    
41
    public const MODE_DEFAULT = self::MODE_MVC;
42
    public const MODE_CONSOLE = self::MODE_CLI;
43
    
44
    public string $mode;
45
    
46
    public ?array $args;
47
    
48
    public DiInterface $di;
49
    
50
    public ConfigInterface $config;
51
    
52
    public RouterInterface $router;
53
    
54
    public ?ResponseInterface $response;
55
    
56
    public string $cliDoc = <<<DOC
57
Zemit CLI
58
59
Usage:
60
  zemit <module> <task> [<action>] [--help | --quiet | --verbose] [--debug] [--format=<format>] [<args>...] [-c <fds>=<value>]
61
  zemit (-h | --help)
62
  zemit (-v | --version)
63
  zemit (-i | --info)
64
65
Options:
66
  -c <key>=<value>        test
67
  -h --help               show this help message
68
  -v --version            print version number
69
  -i --info               print information
70
  -q --quiet              suppress output
71
  -V --verbose            increase verbosity
72
  -d --debug              enable debug mode
73
  --format=<format>       change output returned value format (json, xml, serialized, raw, dump)
74
75
The most commonly used zemit commands are:
76
   deployment             Populate the database
77
DOC;
78
    
79
    /**
80
     * @throws Exception
81
     */
82
    public function __construct(string $mode = null)
83
    {
84
        $this->setMode($mode);
85
        $this->setEventsManager(new Events\Manager());
86
        $this->setDI();
87
        $this->initialize();
88
        $this->registerConfig();
89
        $this->registerServices();
90
        $this->bootServices();
91
        $this->registerModules();
92
        $this->registerRouter();
93
    }
94
    
95
    /**
96
     * Initialisation
97
     */
98
    public function initialize(): void
99
    {
100
    }
101
    
102
    /**
103
     * Set the default DI
104
     */
105
    public function setDI(?DiInterface $di = null): void
106
    {
107
        $di ??= $this->isCli()
108
            ? new FactoryDefault\Cli()
109
            : new FactoryDefault();
110
        
111
        $this->di = $di;
112
        $this->di->setShared('bootstrap', $this);
113
        Di::setDefault($this->di);
114
    }
115
    
116
    public function setMode(?string $mode = null): void
117
    {
118
        $this->mode = $mode ?? (Php::isCli()
119
            ? self::MODE_CLI
120
            : self::MODE_MVC
121
        );
122
    }
123
    
124
    public function getMode(): string
125
    {
126
        return $this->mode;
127
    }
128
    
129
    /**
130
     * Get the default DI
131
     */
132
    public function getDI(): DiInterface
133
    {
134
        return $this->di;
135
    }
136
    
137
    /**
138
     * Set the Config
139
     */
140
    public function setConfig(ConfigInterface $config): void
141
    {
142
        $this->config = $config;
143
    }
144
    
145
    /**
146
     * Get the Config
147
     */
148
    public function getConfig(): ConfigInterface
149
    {
150
        return $this->config;
151
    }
152
    
153
    /**
154
     * Set the MVC or CLI Router
155
     */
156
    public function setRouter(RouterInterface $router): void
157
    {
158
        $this->router = $router;
159
    }
160
    
161
    /**
162
     * Get the MVC or CLI Router
163
     */
164
    public function getRouter(): RouterInterface
165
    {
166
        return $this->router;
167
    }
168
    
169
    /**
170
     * Register Config
171
     */
172
    public function registerConfig(): void
173
    {
174
        if (!$this->di->has('config')) {
175
            $configService = new ConfigServiceProvider($this->di);
176
            $configService->register($this->di);
177
        }
178
        $this->config ??= $this->di->get('config');
179
    }
180
    
181
    /**
182
     * Register Service Providers
183
     * @throws Exception
184
     */
185
    public function registerServices(?array $providers = null): void
186
    {
187
        $providers ??= $this->config->pathToArray('providers') ?? [];
188
        foreach ($providers as $provider) {
189
            $this->di->register(new $provider($this->di));
190
        }
191
    }
192
    
193
    /**
194
     * Register Router
195
     */
196
    public function registerRouter(): void
197
    {
198
        if (!$this->di->has('router')) {
199
            $configService = new RouterServiceProvider($this->di);
200
            $configService->register($this->di);
201
        }
202
        $this->router ??= $this->di->get('router');
203
    }
204
    
205
    /**
206
     * Boot Service Providers
207
     */
208
    public function bootServices(): void
209
    {
210
        $this->di->get('debug');
211
    }
212
    
213
    /**
214
     * Register modules
215
     */
216
    public function registerModules(AbstractApplication $application = null, ?array $modules = null, ?string $defaultModule = null): void
217
    {
218
        $application ??= $this->isMvc()
219
            ? $this->di->get('application')
220
            : $this->di->get('console');
221
        assert($application instanceof AbstractApplication);
222
        
223
        $modules ??= $this->config->pathToArray('modules') ?? [];
224
        $application->registerModules($modules);
225
        
226
        $defaultModule ??= $this->config->path('router.defaults.module');
227
        $application->setDefaultModule($defaultModule);
0 ignored issues
show
Bug introduced by
It seems like $defaultModule can also be of type null; however, parameter $defaultModule of Phalcon\Application\Abst...ion::setDefaultModule() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

227
        $application->setDefaultModule(/** @scrutinizer ignore-type */ $defaultModule);
Loading history...
228
    }
229
    
230
    /**
231
     * Handle cli or mvc application
232
     * @throws \Exception
233
     */
234
    public function run(): ?string
235
    {
236
        $this->fire('beforeRun');
237
        
238
        if ($this->isMvc()) {
239
            
240
            $application = $this->di->get('application');
241
            $content = $this->handleApplication($application);
242
        }
243
        elseif ($this->isCli()) {
244
            
245
            $console = $this->di->get('console');
246
            $content = $this->handleConsole($console);
247
        }
248
        else {
249
            throw new \Exception('Application or Console not found', 404);
250
        }
251
        
252
        $this->fire('afterRun', $content);
253
        
254
        return $content;
255
    }
256
    
257
    /**
258
     * Handle Console (For CLI only)
259
     */
260
    public function handleConsole(Console $console): ?string
261
    {
262
        $response = null;
263
        try {
264
            ob_start();
265
            $console->handle($this->getArgs());
266
            $response = ob_get_clean() ?: null;
267
        }
268
        catch (\Zemit\Exception $e) {
269
            new Cli\ExceptionHandler($e);
270
        }
271
        catch (\Exception $exception) {
272
            new Cli\ExceptionHandler($exception);
273
        }
274
        catch (\Throwable $throwable) {
275
            new Cli\ExceptionHandler($throwable);
276
        }
277
        
278
        return $response;
279
    }
280
    
281
    /**
282
     * Handle Application
283
     * @throws \Exception
284
     */
285
    public function handleApplication(Application $application): string
286
    {
287
        $this->response = $application->handle($_SERVER['REQUEST_URI'] ?? '/') ?: null;
288
        return $this->response ? $this->response->getContent() : '';
289
    }
290
    
291
    /**
292
     * Get & format args from the $this->args property
293
     */
294
    public function getArgs(): array
295
    {
296
        $args = [];
297
        
298
        if ($this->isCli()) {
299
            $argv = array_slice($_SERVER['argv'] ?? [], 1);
300
            $response = (new Docopt())->handle($this->cliDoc, ['argv' => $argv, 'optionsFirst' => true]);
301
            foreach ($response as $key => $value) {
302
                if (preg_match('/(<(.*?)>|\-\-(.*))/', $key, $match)) {
303
                    $key = lcfirst(Text::camelize(Text::uncamelize(array_pop($match))));
304
                    $args[$key] = $value;
305
                }
306
            }
307
        }
308
        
309
        return $args;
310
    }
311
    
312
    /**
313
     * Return true if the bootstrap mode is set to 'cli'
314
     */
315
    public function isCli(): bool
316
    {
317
        return $this->getMode() === self::MODE_CLI;
318
    }
319
    
320
    /**
321
     * Return true if the bootstrap mode is set to 'mvc'
322
     */
323
    public function isMvc(): bool
324
    {
325
        return $this->getMode() === self::MODE_MVC;
326
    }
327
    
328
    /**
329
     * Alias for the ->isCli() method
330
     * @deprecated
331
     */
332
    public function isConsole(): bool
333
    {
334
        return $this->isCli();
335
    }
336
    
337
    /**
338
     * Alias for the ->isMvc() method
339
     * @deprecated
340
     */
341
    public function isDefault(): bool
342
    {
343
        return $this->isMvc();
344
    }
345
}
346