Passed
Pull Request — master (#701)
by Stefano
03:22
created

Application::addPluginDev()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
c 0
b 0
f 0
dl 0
loc 9
rs 10
cc 2
nc 2
nop 1
1
<?php
2
/**
3
 * BEdita, API-first content management framework
4
 * Copyright 2019 ChannelWeb Srl, Chialab Srl
5
 *
6
 * This file is part of BEdita: you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as published
8
 * by the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
12
 */
13
namespace App;
14
15
use App\Middleware\ProjectMiddleware;
16
use BEdita\I18n\Middleware\I18nMiddleware;
17
use BEdita\WebTools\BaseApplication;
18
use Cake\Core\Configure;
19
use Cake\Core\Configure\Engine\PhpConfig;
20
use Cake\Error\Middleware\ErrorHandlerMiddleware;
21
use Cake\Http\MiddlewareQueue;
22
use Cake\Http\Middleware\CsrfProtectionMiddleware;
23
use Cake\Routing\Middleware\AssetMiddleware;
24
use Cake\Routing\Middleware\RoutingMiddleware;
25
26
/**
27
 * Application class.
28
 */
29
class Application extends BaseApplication
30
{
31
    /**
32
     * Default plugin options
33
     *
34
     * @var array
35
     */
36
    protected const PLUGIN_DEFAULTS = [
37
        'debugOnly' => false,
38
        'autoload' => false,
39
        'bootstrap' => true,
40
        'routes' => true,
41
        'ignoreMissing' => true,
42
    ];
43
44
    /**
45
     * @inheritDoc
46
     */
47
    public function bootstrap(): void
48
    {
49
        parent::bootstrap();
50
        $this->addPlugin('BEdita/WebTools');
51
        $this->addPlugin('BEdita/I18n');
52
    }
53
54
    /**
55
     * Load CLI plugins
56
     *
57
     * @return void
58
     */
59
    protected function bootstrapCli(): void
60
    {
61
        $this->addOptionalPlugin('Bake');
62
        $this->addOptionalPlugin('IdeHelper');
63
        $this->loadPluginsFromConfig();
64
    }
65
66
    /**
67
     * Load plugins from 'Plugins' configuration.
68
     * This method will be invoked by `ProjectMiddleware`.
69
     * Should not be invoked in `bootstrap`, to avoid duplicate plugin bootstratp calls.
70
     *
71
     * @return void
72
     */
73
    public function loadPluginsFromConfig(): void
74
    {
75
        $plugins = (array)Configure::read('Plugins');
76
        foreach ($plugins as $plugin => $options) {
77
            $options = array_merge(static::PLUGIN_DEFAULTS, $options);
78
            if (!$options['debugOnly'] || ($options['debugOnly'] && Configure::read('debug'))) {
79
                $this->addPlugin($plugin, $options);
80
                $this->plugins->get($plugin)->bootstrap($this);
81
            }
82
        }
83
    }
84
85
    /**
86
     * @inheritDoc
87
     */
88
    public function middleware($middlewareQueue): MiddlewareQueue
89
    {
90
        $middlewareQueue
91
            // Catch any exceptions in the lower layers,
92
            // and make an error page/response
93
            ->add(new ErrorHandlerMiddleware(null, Configure::read('Error')))
94
95
            // Load current project configuration if `multiproject` instance
96
            // Manager plugins will also be loaded here via `loadPluginsFromConfig()`
97
            ->add(new ProjectMiddleware($this))
98
99
            // Handle plugin/theme assets like CakePHP normally does.
100
            ->add(new AssetMiddleware([
101
                'cacheTime' => Configure::read('Asset.cacheTime'),
102
            ]))
103
104
            // Add I18n middleware.
105
            ->add(new I18nMiddleware([
106
                'cookie' => Configure::read('I18n.cookie'),
107
                'switchLangUrl' => Configure::read('I18n.switchLangUrl'),
108
            ]))
109
110
            // Add routing middleware.
111
            ->add(new RoutingMiddleware($this))
112
113
            // Csrf Middleware
114
            ->add($this->csrfMiddleware());
115
116
        return $middlewareQueue;
117
    }
118
119
    /**
120
     * Get internal Csrf Middleware
121
     *
122
     * @return \Cake\Http\Middleware\CsrfProtectionMiddleware
123
     */
124
    protected function csrfMiddleware(): CsrfProtectionMiddleware
125
    {
126
        // Csrf Middleware
127
        $csrf = new CsrfProtectionMiddleware(['httponly' => true]);
128
        // Token check will be skipped when callback returns `true`.
129
        $csrf->whitelistCallback(function ($request) {
130
            $actions = (array)Configure::read(sprintf('CsrfExceptions.%s', $request->getParam('controller')));
131
            // Skip token check for API URLs.
132
            if (in_array($request->getParam('action'), $actions)) {
133
                return true;
134
            }
135
        });
136
137
        return $csrf;
138
    }
139
140
    /**
141
     * Load project configuration if corresponding config file is found
142
     *
143
     * @param string|null $project The project name.
144
     * @param string $projectsPath The project configuration files base path.
145
     * @return void
146
     */
147
    public static function loadProjectConfig(?string $project, string $projectsPath): void
148
    {
149
        if (empty($project)) {
150
            return;
151
        }
152
153
        if (file_exists($projectsPath . $project . '.php')) {
154
            Configure::config('projects', new PhpConfig($projectsPath));
155
            Configure::load($project, 'projects');
156
        }
157
    }
158
}
159