Passed
Push — develop ( 3cb944...e03f3c )
by nguereza
02:52
created

MaintenanceCommand   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 233
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 126
c 5
b 0
f 0
dl 0
loc 233
rs 10
wmc 27

6 Methods

Rating   Name   Duplication   Size   Complexity  
A online() 0 18 3
A getPayload() 0 25 4
A status() 0 8 2
A down() 0 19 3
A execute() 0 14 3
C __construct() 0 96 12
1
<?php
2
3
/**
4
 * Platine Framework
5
 *
6
 * Platine Framework is a lightweight, high-performance, simple and elegant
7
 * PHP Web framework
8
 *
9
 * This content is released under the MIT License (MIT)
10
 *
11
 * Copyright (c) 2020 Platine Framework
12
 *
13
 * Permission is hereby granted, free of charge, to any person obtaining a copy
14
 * of this software and associated documentation files (the "Software"), to deal
15
 * in the Software without restriction, including without limitation the rights
16
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
 * copies of the Software, and to permit persons to whom the Software is
18
 * furnished to do so, subject to the following conditions:
19
 *
20
 * The above copyright notice and this permission notice shall be included in all
21
 * copies or substantial portions of the Software.
22
 *
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
 * SOFTWARE.
30
 */
31
32
/**
33
 *  @file MaintenanceCommand.php
34
 *
35
 *  The Maintenance management command class
36
 *
37
 *  @package    Platine\Framework\Console\Command
38
 *  @author Platine Developers team
39
 *  @copyright  Copyright (c) 2020
40
 *  @license    http://opensource.org/licenses/MIT  MIT License
41
 *  @link   https://www.platine-php.com
42
 *  @version 1.0.0
43
 *  @filesource
44
 */
45
46
declare(strict_types=1);
47
48
namespace Platine\Framework\Console\Command;
49
50
use Platine\Config\Config;
51
use Platine\Console\Command\Command;
52
use Platine\Framework\App\Application;
53
use RuntimeException;
54
use Throwable;
55
56
/**
57
 * @class MaintenanceCommand
58
 * @package Platine\Framework\Console\Command
59
 * @template T
60
 */
61
class MaintenanceCommand extends Command
62
{
63
    /**
64
     * The configuration to use
65
     * @var Config<T>
66
     */
67
    protected Config $config;
68
69
    /**
70
     * The Platine Application
71
     * @var Application
72
     */
73
    protected Application $application;
74
75
    /**
76
     * Create new instance
77
     * @param Application $app
78
     * @param Config $config
79
     */
80
    public function __construct(
81
        Application $app,
82
        Config $config
83
    ) {
84
        $this->application = $app;
85
        $this->config = $config;
86
87
        $this->setName('maintenance')
88
             ->setDescription('Command to manage application maintenance');
89
90
        $this->addArgument('type', 'type of action [up|down|status]', 'status', true, true, false, function ($val) {
91
            if (!in_array($val, ['up', 'down', 'status'])) {
92
                throw new RuntimeException(sprintf(
93
                    'Invalid argument type [%s], must be one of [up, down, status]',
94
                    $val
95
                ));
96
            }
97
98
             return $val;
99
        });
100
101
        $this->addOption(
102
            '-t|--template',
103
            'The template that should be rendered for display during maintenance mode',
104
            null,
105
            false,
106
            true
107
        );
108
109
        $this->addOption(
110
            '-r|--retry',
111
            'The number of seconds after which the request may be retried',
112
            3600,
113
            false,
114
            true,
115
            false,
116
            function ($val) {
117
                if (strlen($val) > 0 && (!is_numeric($val) || (int) $val <= 0)) {
118
                    throw new RuntimeException(sprintf(
119
                        'Invalid retry value [%s], must be an integer greather than zero',
120
                        $val
121
                    ));
122
                }
123
124
                return $val;
125
            }
126
        );
127
        $this->addOption(
128
            '-e|--refresh',
129
            'The number of seconds after which the browser may refresh',
130
            3600,
131
            false,
132
            true,
133
            false,
134
            function ($val) {
135
                if (strlen($val) > 0 && (!is_numeric($val) || (int) $val <= 0)) {
136
                    throw new RuntimeException(sprintf(
137
                        'Invalid refresh value [%s], must be an integer greather than zero',
138
                        $val
139
                    ));
140
                }
141
142
                return $val;
143
            }
144
        );
145
        $this->addOption(
146
            '-s|--secret',
147
            'The secret phrase that may be used to bypass maintenance mode',
148
            null,
149
            false,
150
            true
151
        );
152
        $this->addOption(
153
            '-c|--status',
154
            'The status code that should be used when returning the maintenance mode response',
155
            503,
156
            false,
157
            true,
158
            false,
159
            function ($val) {
160
                if (strlen($val) > 0 && (!is_numeric($val) || (int) $val < 200 || (int) $val > 505)) {
161
                    throw new RuntimeException(sprintf(
162
                        'Invalid HTTP status value [%s], must be between 200 and 505',
163
                        $val
164
                    ));
165
                }
166
167
                return $val;
168
            }
169
        );
170
        $this->addOption(
171
            '-m|--message',
172
            'The message that will be shown to user during maintenance mode',
173
            null,
174
            false,
175
            true
176
        );
177
    }
178
179
    /**
180
     * {@inheritdoc}
181
     */
182
    public function execute()
183
    {
184
        $type = $this->getArgumentValue('type');
185
186
        $io = $this->io();
187
        $writer = $io->writer();
188
        $writer->boldYellow('APPLICATION MAINTENANCE MANAGEMENT', true)->eol();
189
190
        if ($type === 'up') {
191
            $this->online();
192
        } elseif ($type === 'down') {
193
            $this->down();
194
        }  {
195
            $this->status();
196
        }
197
    }
198
199
    /**
200
     * Put application online
201
     * @return void
202
     */
203
    public function online(): void
204
    {
205
        $writer = $this->io()->writer();
206
207
        try {
208
            if ($this->application->isInMaintenance() === false) {
209
                $writer->boldRed('Application already online')->eol();
210
                return;
211
            }
212
213
            $this->application->maintenance()->deactivate();
214
215
            $writer->boldGreen('Application is now online')->eol();
216
        } catch (Throwable $ex) {
217
            $writer->boldRed(sprintf(
218
                'Failed to disable maintenance mode: %s.',
219
                $ex->getMessage()
220
            ))->eol();
221
        }
222
    }
223
224
    /**
225
     * Put application in maintenance mode
226
     * @return void
227
     */
228
    public function down(): void
229
    {
230
        $writer = $this->io()->writer();
231
232
        try {
233
            if ($this->application->isInMaintenance()) {
234
                $writer->boldRed('Application is already down.')->eol();
235
                return;
236
            }
237
238
            $data = $this->getPayload();
239
            $this->application->maintenance()->activate($data);
240
241
            $writer->boldGreen('Application is now in maintenance mode.')->eol();
242
        } catch (Throwable $ex) {
243
            $writer->boldRed(sprintf(
244
                'Failed to enable maintenance mode: %s.',
245
                $ex->getMessage()
246
            ))->eol();
247
        }
248
    }
249
250
    /**
251
     * Check application maintenance mode
252
     * @return void
253
     */
254
    public function status(): void
255
    {
256
        $writer = $this->io()->writer();
257
258
        if ($this->application->isInMaintenance()) {
259
            $writer->boldYellow('Application is down.')->eol();
260
        } else {
261
            $writer->boldGreen('Application is online.')->eol();
262
        }
263
    }
264
265
    /**
266
     * Get the payload to be placed in the maintenance file.
267
     * @return array<string, mixed>
268
     */
269
    protected function getPayload(): array
270
    {
271
        $retry = $this->getOptionValue('retry') ?? 3600;
272
        if ($retry) {
273
            $retry = (int) $retry;
274
        }
275
276
        $refresh = $this->getOptionValue('refresh') ?? 3600;
277
        if ($refresh) {
278
            $refresh = (int) $refresh;
279
        }
280
281
        $status = $this->getOptionValue('status') ?? 503;
282
        if ($status) {
283
            $status = (int) $status;
284
        }
285
286
        return [
287
            'except' => $this->config->get('maintenance.url_whitelist', []),
288
            'template' => $this->getOptionValue('template') ?? '',
289
            'retry' => $retry,
290
            'refresh' => $refresh,
291
            'secret' => $this->getOptionValue('secret') ?? '',
292
            'status' => $status,
293
            'message' => $this->getOptionValue('message') ?? '',
294
        ];
295
    }
296
}
297