InstallController::doGET()   F
last analyzed

Complexity

Conditions 20
Paths > 20000

Size

Total Lines 205

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 205
rs 0
c 0
b 0
f 0
cc 20
nc 81242
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Alpha\Controller;
4
5
use Alpha\Util\Logging\Logger;
6
use Alpha\Util\Config\ConfigProvider;
7
use Alpha\Util\Http\Response;
8
use Alpha\Util\Service\ServiceFactory;
9
use Alpha\Model\ActiveRecord;
10
use Alpha\Model\Rights;
11
use Alpha\Model\Person;
12
use Alpha\Model\Type\DEnum;
13
use Alpha\Model\Type\DEnumItem;
14
use Alpha\Exception\FailedIndexCreateException;
15
use Alpha\Exception\FailedLookupCreateException;
16
use Alpha\Controller\Front\FrontController;
17
use Alpha\View\View;
18
19
/**
20
 * Controller used install the database.
21
 *
22
 * @since 1.0
23
 *
24
 * @author John Collins <[email protected]>
25
 * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
26
 * @copyright Copyright (c) 2018, John Collins (founder of Alpha Framework).
27
 * All rights reserved.
28
 *
29
 * <pre>
30
 * Redistribution and use in source and binary forms, with or
31
 * without modification, are permitted provided that the
32
 * following conditions are met:
33
 *
34
 * * Redistributions of source code must retain the above
35
 *   copyright notice, this list of conditions and the
36
 *   following disclaimer.
37
 * * Redistributions in binary form must reproduce the above
38
 *   copyright notice, this list of conditions and the
39
 *   following disclaimer in the documentation and/or other
40
 *   materials provided with the distribution.
41
 * * Neither the name of the Alpha Framework nor the names
42
 *   of its contributors may be used to endorse or promote
43
 *   products derived from this software without specific
44
 *   prior written permission.
45
 *
46
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
47
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
48
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
49
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
50
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
51
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
53
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
54
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
56
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
57
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
58
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59
 * </pre>
60
 */
61
class InstallController extends Controller implements ControllerInterface
62
{
63
    /**
64
     * Trace logger.
65
     *
66
     * @var \Alpha\Util\Logging\Logger
67
     *
68
     * @since 1.0
69
     */
70
    private static $logger = null;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
71
72
    /**
73
     * the constructor.
74
     *
75
     * @since 1.0
76
     */
77
    public function __construct()
78
    {
79
        self::$logger = new Logger('InstallController');
80
        self::$logger->debug('>>__construct()');
81
82
        $config = ConfigProvider::getInstance();
83
84
        parent::__construct('Public');
85
86
        // set up the title and meta details
87
        $this->setTitle('Installing '.$config->get('app.title'));
88
89
        self::$logger->debug('<<__construct');
90
    }
91
92
    /**
93
     * Handle GET requests.
94
     *
95
     * @param \Alpha\Util\Http\Request $request
96
     *
97
     * @return \Alpha\Util\Http\Response
98
     *
99
     * @since 1.0
100
     */
101
    public function doGET($request)
102
    {
103
        self::$logger->debug('>>doGET($request=['.var_export($request, true).'])');
104
105
        $config = ConfigProvider::getInstance();
106
107
        $sessionProvider = $config->get('session.provider.name');
108
        $session = ServiceFactory::getInstance($sessionProvider, 'Alpha\Util\Http\Session\SessionProviderInterface');
109
110
        // if there is nobody logged in, we will send them off to the Login controller to do so before coming back here
111
        if ($session->get('currentUser') === false) {
112
            self::$logger->info('Nobody logged in, invoking Login controller...');
113
114
            $controller = new LoginController();
115
            $controller->setName('LoginController');
116
            $controller->setRequest($request);
117
            $controller->setUnitOfWork(array('Alpha\Controller\LoginController', 'Alpha\Controller\InstallController'));
118
119
            self::$logger->debug('<<__construct');
120
121
            return $controller->doGET($request);
122
        }
123
124
        $sessionProvider = $config->get('session.provider.name');
125
        $session = ServiceFactory::getInstance($sessionProvider, 'Alpha\Util\Http\Session\SessionProviderInterface');
126
127
        $body = View::displayPageHead($this);
128
129
        $body .= '<h1>Installing the '.$config->get('app.title').' application</h1>';
130
131
        try {
132
            $body .= $this->createApplicationDirs();
133
        } catch (\Exception $e) {
134
            $body .= View::displayErrorMessage($e->getMessage());
135
            $body .= View::displayErrorMessage('Aborting.');
136
137
            return new Response(500, $body, array('Content-Type' => 'text/html'));
138
        }
139
140
        ActiveRecord::createDatabase();
141
142
        // start a new database transaction
143
        ActiveRecord::begin();
144
145
        /*
146
         * Create DEnum tables
147
         */
148
        $DEnum = new DEnum();
149
        $DEnumItem = new DEnumItem();
150
151
        try {
152
            $body .= '<p>Attempting to create the DEnum tables...';
153
            if (!$DEnum->checkTableExists()) {
154
                $DEnum->makeTable();
155
            }
156
            self::$logger->info('Created the ['.$DEnum->getTableName().'] table successfully');
157
158
            if (!$DEnumItem->checkTableExists()) {
159
                $DEnumItem->makeTable();
160
            }
161
            self::$logger->info('Created the ['.$DEnumItem->getTableName().'] table successfully');
162
163
            $body .= View::displayUpdateMessage('DEnums set up successfully.');
164
        } catch (\Exception $e) {
165
            $body .= View::displayErrorMessage($e->getMessage());
166
            $body .= View::displayErrorMessage('Aborting.');
167
            self::$logger->error($e->getMessage());
168
            ActiveRecord::rollback();
169
170
            return new Response(500, $body, array('Content-Type' => 'text/html'));
171
        }
172
173
        /*
174
         * Loop over each business object in the system, and create a table for it
175
         */
176
        $classNames = ActiveRecord::getRecordClassNames();
177
        $loadedClasses = array();
178
179
        foreach ($classNames as $classname) {
180
            array_push($loadedClasses, $classname);
181
        }
182
183
        foreach ($loadedClasses as $classname) {
184
            try {
185
                $body .= '<p>Attempting to create the table for the class ['.$classname.']...';
186
187
                try {
188
                    $Record = new $classname();
189
190
                    if (!$Record->checkTableExists()) {
191
                        $Record->makeTable();
192
                    } else {
193
                        if ($Record->checkTableNeedsUpdate()) {
194
                            $missingFields = $Record->findMissingFields();
195
196
                            $count = count($missingFields);
197
198
                            for ($i = 0; $i < $count; ++$i) {
199
                                $Record->addProperty($missingFields[$i]);
200
                            }
201
                        }
202
                    }
203
                } catch (FailedIndexCreateException $eice) {
204
                    // this are safe to ignore for now as they will be auto-created later once all of the tables are in place
205
                    self::$logger->warn($eice->getMessage());
206
                } catch (FailedLookupCreateException $elce) {
207
                    // this are safe to ignore for now as they will be auto-created later once all of the tables are in place
208
                    self::$logger->warn($elce->getMessage());
209
                }
210
211
                self::$logger->info('Created the ['.$Record->getTableName().'] table successfully');
212
                $body .= View::displayUpdateMessage('Created the ['.$Record->getTableName().'] table successfully');
213
            } catch (\Exception $e) {
214
                $body .= View::displayErrorMessage($e->getMessage());
215
                $body .= View::displayErrorMessage('Aborting.');
216
                self::$logger->error($e->getMessage());
217
                ActiveRecord::rollback();
218
219
                return new Response(500, $body, array('Content-Type' => 'text/html'));
220
            }
221
        }
222
223
        $body .= View::displayUpdateMessage('All business object tables created successfully!');
224
225
        /*
226
         * Create the Admin and Standard groups
227
         */
228
        $adminGroup = new Rights();
229
        $adminGroup->set('name', 'Admin');
230
        $standardGroup = new Rights();
231
        $standardGroup->set('name', 'Standard');
232
233
        try {
234
            try {
235
                $body .= '<p>Attempting to create the Admin and Standard groups...';
236
                $adminGroup->save();
237
                $standardGroup->save();
238
239
                self::$logger->info('Created the Admin and Standard rights groups successfully');
240
                $body .= View::displayUpdateMessage('Created the Admin and Standard rights groups successfully');
241
            } catch (FailedIndexCreateException $eice) {
242
                // this are safe to ignore for now as they will be auto-created later once all of the tables are in place
243
                self::$logger->warn($eice->getMessage());
244
            } catch (FailedLookupCreateException $elce) {
245
                // this are safe to ignore for now as they will be auto-created later once all of the tables are in place
246
                self::$logger->warn($elce->getMessage());
247
            }
248
        } catch (\Exception $e) {
249
            $body .= View::displayErrorMessage($e->getMessage());
250
            $body .= View::displayErrorMessage('Aborting.');
251
            self::$logger->error($e->getMessage());
252
            ActiveRecord::rollback();
253
254
            return new Response(500, $body, array('Content-Type' => 'text/html'));
255
        }
256
257
        /*
258
         * Save the admin user to the database in the right group
259
         */
260
        try {
261
            try {
262
                $body .= '<p>Attempting to save the Admin account...';
263
                $admin = new Person();
264
                $admin->set('username', 'Admin');
265
                $admin->set('email', $session->get('currentUser')->get('email'));
266
                $admin->set('password', $session->get('currentUser')->get('password'));
267
                $admin->save();
268
                self::$logger->info('Created the admin user account ['.$session->get('currentUser')->get('email').'] successfully');
269
270
                $adminGroup->loadByAttribute('name', 'Admin');
271
272
                $lookup = $adminGroup->getMembers()->getLookup();
273
                $lookup->setValue(array($admin->getID(), $adminGroup->getID()));
274
                $lookup->save();
275
276
                self::$logger->info('Added the admin account to the Admin group successfully');
277
                $body .= View::displayUpdateMessage('Added the admin account to the Admin group successfully');
278
            } catch (FailedIndexCreateException $eice) {
279
                // this are safe to ignore for now as they will be auto-created later once all of the tables are in place
280
                self::$logger->warn($eice->getMessage());
281
            } catch (FailedLookupCreateException $elce) {
282
                // this are safe to ignore for now as they will be auto-created later once all of the tables are in place
283
                self::$logger->warn($elce->getMessage());
284
            }
285
        } catch (\Exception $e) {
286
            $body .= View::displayErrorMessage($e->getMessage());
287
            $body .= View::displayErrorMessage('Aborting.');
288
            self::$logger->error($e->getMessage());
289
            ActiveRecord::rollback();
290
291
            return new Response(500, $body, array('Content-Type' => 'text/html'));
292
        }
293
294
        $body .= '<br><p align="center"><a href="'.FrontController::generateSecureURL('act=Alpha\Controller\ListActiveRecordsController').'">Administration Home Page</a></p><br>';
295
        $body .= View::displayPageFoot($this);
296
297
        // commit
298
        ActiveRecord::commit();
299
300
        self::$logger->info('Finished installation!');
301
        self::$logger->info('Installed the application');
302
        self::$logger->debug('<<doGET');
303
304
        return new Response(200, $body, array('Content-Type' => 'text/html'));
305
    }
306
307
    /**
308
     * Create the directories required by the application.
309
     *
310
     * @return string
311
     *
312
     * @since 2.0
313
     */
314
    public function createApplicationDirs()
315
    {
316
        self::$logger->debug('>>createApplicationDirs()');
317
318
        $config = ConfigProvider::getInstance();
319
320
        $body = '';
321
322
        // set the umask first before attempt mkdir
323
        umask(0);
324
325
        /*
326
         * Create the logs directory, then instantiate a new logger
327
         */
328
        $logsDir = $config->get('app.file.store.dir').'logs';
329
330
        $body .= '<p>Attempting to create the logs directory <em>'.$logsDir.'</em>...';
331
332
        if (!file_exists($logsDir)) {
333
            mkdir($logsDir, 0774);
334
        }
335
336
        self::$logger = new Logger('InstallController');
337
        self::$logger->info('Started installation process!');
338
        self::$logger->info('Logs directory ['.$logsDir.'] successfully created');
339
        $body .= View::displayUpdateMessage('Logs directory ['.$logsDir.'] successfully created');
340
341
        /*
342
         * Create the src directory and sub-directories
343
         */
344
        $srcDir = $config->get('app.root').'src';
345
346
        $body .= '<p>Attempting to create the src directory <em>'.$srcDir.'</em>...';
347
348
        if (!file_exists($srcDir)) {
349
            mkdir($srcDir, 0774);
350
        }
351
352
        self::$logger->info('Source directory ['.$srcDir.'] successfully created');
353
        $body .= View::displayUpdateMessage('Source directory ['.$srcDir.'] successfully created');
354
355
        $srcDir = $config->get('app.root').'src/Model';
356
357
        if (!file_exists($srcDir)) {
358
            mkdir($srcDir, 0774);
359
        }
360
361
        self::$logger->info('Source directory ['.$srcDir.'] successfully created');
362
        $body .= View::displayUpdateMessage('Source directory ['.$srcDir.'] successfully created');
363
364
        $srcDir = $config->get('app.root').'src/View';
365
366
        if (!file_exists($srcDir)) {
367
            mkdir($srcDir, 0774);
368
        }
369
370
        self::$logger->info('Source directory ['.$srcDir.'] successfully created');
371
        $body .= View::displayUpdateMessage('Source directory ['.$srcDir.'] successfully created');
372
373
        /*
374
         * Create the attachments directory
375
         */
376
        $attachmentsDir = $config->get('app.file.store.dir').'attachments';
377
378
        $body .= '<p>Attempting to create the attachments directory <em>'.$attachmentsDir.'</em>...';
379
380
        if (!file_exists($attachmentsDir)) {
381
            mkdir($attachmentsDir, 0774);
382
        }
383
384
        self::$logger->info('Attachments directory ['.$attachmentsDir.'] successfully created');
385
        $body .= View::displayUpdateMessage('Attachments directory ['.$attachmentsDir.'] successfully created');
386
387
        /*
388
         * Create the cache directory and sub-directories
389
         */
390
        $cacheDir = $config->get('app.file.store.dir').'cache';
391
        $filesDir = $config->get('app.file.store.dir').'cache/files';
392
        $imagesDir = $config->get('app.file.store.dir').'cache/images';
393
        $xlsDir = $config->get('app.file.store.dir').'cache/xls';
394
395
        // cache
396
        $body .= '<p>Attempting to create the cache directory <em>'.$cacheDir.'</em>...';
397
        if (!file_exists($cacheDir)) {
398
            mkdir($cacheDir, 0774);
399
        }
400
401
        self::$logger->info('Cache directory ['.$cacheDir.'] successfully created');
402
        $body .= View::displayUpdateMessage('Cache directory ['.$cacheDir.'] successfully created');
403
404
        // cache/files
405
        $body .= '<p>Attempting to create the files cache directory <em>'.$filesDir.'</em>...';
406
        if (!file_exists($filesDir)) {
407
            mkdir($filesDir, 0774);
408
        }
409
410
        self::$logger->info('Cache directory ['.$filesDir.'] successfully created');
411
        $body .= View::displayUpdateMessage('Cache directory ['.$filesDir.'] successfully created');
412
413
        // cache/images
414
        $body .= '<p>Attempting to create the cache directory <em>'.$imagesDir.'</em>...';
415
        if (!file_exists($imagesDir)) {
416
            mkdir($imagesDir, 0774);
417
        }
418
419
        self::$logger->info('Cache directory ['.$imagesDir.'] successfully created');
420
        $body .= View::displayUpdateMessage('Cache directory ['.$imagesDir.'] successfully created');
421
422
        // cache/xls
423
        $body .= '<p>Attempting to create the cache directory <em>'.$xlsDir.'</em>...';
424
        if (!file_exists($xlsDir)) {
425
            mkdir($xlsDir, 0774);
426
        }
427
428
        self::$logger->info('Cache directory ['.$xlsDir.'] successfully created');
429
        $body .= View::displayUpdateMessage('Cache directory ['.$xlsDir.'] successfully created');
430
431
        self::$logger->debug('<<createApplicationDirs');
432
433
        return $body;
434
    }
435
436
    /**
437
     * Custom version of the check rights method that only checks for a session for the config admin username/password,
438
     * when the system database is not set-up.
439
     *
440
     * @return boolean|null
441
     *
442
     * @since 1.0
443
     */
444
    public function checkRights()
445
    {
446
        self::$logger->debug('>>checkRights()');
447
448
        $config = ConfigProvider::getInstance();
449
        $sessionProvider = $config->get('session.provider.name');
450
        $session = ServiceFactory::getInstance($sessionProvider, 'Alpha\Util\Http\Session\SessionProviderInterface');
451
452
        if ($this->getVisibility() == 'Public') {
453
            self::$logger->debug('<<checkRights [true]');
454
455
            return true;
456
        }
457
458
        if (ActiveRecord::isInstalled()) {
459
            self::$logger->debug('<<checkRights [false]');
460
461
            return false;
462
        }
463
464
        // the person is logged in?
465
        if ($session->get('currentUser') !== false) {
466
            if ($session->get('currentUser')->get('email') == $config->get('app.install.username')) {
467
                self::$logger->debug('<<checkRights [true]');
468
469
                return true;
470
            }
471
        }
472
    }
473
}
474