App::Main()   F
last analyzed

Complexity

Conditions 45
Paths > 20000

Size

Total Lines 288
Code Lines 170

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 45
eloc 170
nc 84021
nop 0
dl 0
loc 288
rs 2
c 0
b 0
f 0

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 FFCMS;
4
5
use FFMVC\Helpers;
6
7
/**
8
 * fat-free framework application
9
 *
10
 * @author Vijay Mahrra <[email protected]>
11
 * @copyright (c) Copyright 2013 Vijay Mahrra
12
 * @license GPLv3 (http://www.gnu.org/licenses/gpl-3.0.html)
13
 */
14
class App
15
{
16
    /**
17
     * Application-wide dependencies are injected
18
     *
19
     * @param \Log $logger
20
     * @param \DB\SQL $db
21
     * @param null|\DB\SQL\Session $session
22
     */
23
    public function __construct(\Log $logger, \DB\SQL $db, \DB\SQL\Session $session = null)
24
    {
25
        // single instances to registry
26
        \Registry::set('logger', $logger);
27
        \Registry::set('db', $db);
28
        \Registry::set('session', $session); // needed for CSRF
29
    }
30
31
32
    /**
33
     * Helper to automatically load base config values for keys from the database
34
     * and cache them
35
     *
36
     * @param \Base $f3
37
     * @return array $cfg
38
     */
39
    protected static function loadConfigData(\Base $f3): array
40
    {
41
        $keysToLoad = [];
42
        foreach ($f3->get('cfg.keys') as $k => $v) {
43
            if (is_array($v)) {
44
                $keysToLoad = array_merge($keysToLoad, $v);
45
            }
46
        }
47
48
        $cache = \Cache::instance();
49
        $key = 'cfg-' . md5(join('-', array_keys($keysToLoad)));
50
        if (!$cache->exists($key, $cfg)) {
51
            // now set the value of cfg to the keys we want to load
52
            $configDataModel = \FFCMS\Models\ConfigData::instance();
53
            $cfg = $configDataModel->getValues($keysToLoad);
54
            $cache->set($key, $cfg, $f3->get('ttl.cfg'));
55
        }
56
57
        // cfg.keys.* are no longer required as we know which ones to load in now
58
        $f3->clear('cfg.keys');
59
60
        // replace cfg with values loaded in
61
        $f3->set('cfg', $cfg);
62
63
        return $cfg;
64
    }
65
66
67
    /**
68
     * The main application to run after environment is loaded
69
     */
70
    public function Main()
71
    {
72
        $f3 = \Base::instance();
73
74
        // specify keys of rows in config_data table to load in from .ini files
75
        $f3->set('cfg.keys.load', $f3->get('cfg.keys.load'));
76
77
        // is the url under /api ?
78
        $api = '/api' == substr($f3->get('PATH'), 0, 4);
79
        $f3->set('api', $api);
80
        $language = $f3->get('LANG');
81
82
        // set the assets dir
83
        $f3->set('assets.dir', realpath($f3->get('assets.dir')));
84
85
        // do not use sessions for api calls
86
        if ($f3->get('CLI') ||  $api) {
87
            if (session_status() !== PHP_SESSION_NONE) {
88
                session_write_close();
89
            }
90
        } elseif (session_status() == PHP_SESSION_NONE) {
91
            session_start();
92
93
            // this is an array so not in registry
94
            $f3->set('notifications', $f3->get('SESSION.notifications'));
95
            $f3->set('uuid', $f3->get('SESSION.uuid')); // logged-in user id
96
97
            // initialise gettext
98
            // override language from request
99
            $language = $f3->get('REQUEST.language');
100
            if (!empty($language)) {
101
                $f3->set('SESSION.language', $language);
102
            }
103
104
            // get language from session if set
105
            if (empty($language)) {
106
                $language = $f3->get('SESSION.language');
107
            }
108
        }
109
110
        // enable gettext if set
111
        if (!empty($f3->get('app.gettext'))) {
112
            // will now fall back to client browser language
113
            $language = empty($language) ? substr($f3->get('LANGUAGE'), 0, 2) : $language;
114
            // use LANG because f3 appends to LANGUAGE when setting
115
            $f3->set('LANG', $language);
116
            putenv('LANG=' . $language);
117
            setlocale(LC_ALL, $language);
118
            $domain = 'messages';
119
            bindtextdomain($domain, $f3->get('HOMEDIR') . '/app/i18n');
120
            bind_textdomain_codeset($domain, 'UTF-8');
121
            textdomain($domain);
122
        }
123
124
            // load cli routes and finish
125
        if ($f3->get('CLI')) {
126
            $f3->route('GET /docs/@page', function ($f3, array $params) {
127
                $filename = '../docs/'.strtoupper($params['page']).'.md';
128
                if (!file_exists($filename)) {
129
                    echo "Documentation Error!\n\nNo such document exists!\n";
130
                    return;
131
                } else {
132
                    echo $f3->read($filename);
133
                }
134
            });
135
136
            // load cli config keys
137
            $f3->set('cfg.keys.cli', $f3->get('cfg.keys.cli'));
138
            self::loadConfigData($f3);
139
140
            // @see http://fatfreeframework.com/routing-engine
141
            //load routes from ini file
142
            $f3->config('config/routes-cli.ini');
143
            $f3->run();
144
            return;
145
        }
146
147
        // web start
148
149
        // user feedback messages helper, inisialise so methods can be called statically
150
        $notifications = Helpers\Notifications::instance();
151
        $notifications->init();
152
153
        // Use https://github.com/filp/whoops if debug level is 4
154
        $debug = $f3->get('DEBUG');
155
156
        if (!$api && $debug == 4) {
157
            $whoops = new \Whoops\Run;
158
            $whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
159
            $whoops->register();
160
        }
161
162
        // custom error handler if debugging
163
        $f3->set('ONERROR',
164
            function () use ($f3) {
165
            $logger = \Registry::get('logger');
166
            if (is_object($logger)) {
167
                $logger->write(print_r($f3->get('ERROR')), $f3->get('log.date'));
168
            }
169
170
            // recursively clear existing output buffers:
171
            while (ob_get_level()) {
172
                ob_end_clean();
173
            }
174
175
            $debug = $f3->get('DEBUG');
176
            $api = !empty($f3->get('api'));
177
            $language = $f3->get('LANG');
178
            $e = $f3->get('ERROR');
179
180
            if (!$api && $e['code'] == '404') {
181
                $error_template = 'templates/' . $language . '/website/error/404.phtml';
182
                if (!file_exists($error_template)) {
183
                    $error_template = 'templates/en/website/error/404.phtml';
184
                }
185
                include_once $error_template;
186
            } else {
187
                if (!$api) {
188
                    $error_template = 'templates/' . $language . '/website/error/error.phtml';
189
                    if (!file_exists($error_template)) {
190
                        $error_template = 'templates/en/website/error/error.phtml';
191
                    }
192
193
                    $debug_template = 'templates/' . $language . '/website/error/error.phtml';
194
                    if (!file_exists($debug_template)) {
195
                        $debug_template = 'templates/en/website/error/debug.phtml';
196
                    }
197
198
                    include_once ('production' == $f3->get('app.env') && $debug < 1) ? $error_template
199
                                : $debug_template;
200
                } else {
201
                    $response = Helpers\Response::instance();
202
203
                    $data = [
204
                        'method' => $f3->get('VERB')
205
                    ];
206
207
                    $data['error'] = [
208
                        'code' => substr($f3->snakecase(str_replace(' ', '',
209
                                    $e['status'])), 0),
210
                        'description' => $e['code'] . ' ' . $e['text']
211
                    ];
212
                    if ($debug > 2) {
213
                        $data['error']['trace'] = $f3->trace(null,false);
214
                    }
215
                    $params = ['http_status' => $e['code']];
216
                    $response->json($data, $params);
217
                }
218
            }
219
            // http://php.net/manual/en/function.ob-end-flush.php
220
            while (@ob_end_flush());
221
        });
222
223
        // clean ALL incoming user input by default
224
        $request = [];
225
        $utf = \UTF::instance();
226
        foreach (['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'COOKIE'] as $var) {
227
            $f3->copy($var, $var . '_UNCLEAN');
228
            $input = $f3->get($var);
229
            if (is_array($input) && count($input)) {
230
                $cleaned = [];
231
                foreach ($input as $k => $v) {
232
                    $cleaned[strtolower($utf->trim($f3->clean($k)))] = $f3->recursive($v, function ($v) use ($f3, $utf) {
233
                        return $utf->trim($f3->clean($v));
234
                    });
235
                }
236
                ksort($cleaned);
237
                $request = array_merge_recursive($request, $cleaned);
238
                $f3->set($var, $cleaned);
239
            }
240
        }
241
242
        unset($cleaned);
243
244
        // we don't want to include the session name in the request data
245
        $session_name = strtolower(session_name());
246
        if (array_key_exists($session_name, $request)) {
247
            unset($request[$session_name]);
248
        }
249
250
        ksort($request);
251
        $f3->copy('REQUEST', 'REQUEST_UNCLEAN');
252
        $f3->set('REQUEST', $request);
253
        unset($request);
254
255
        // get the access token and basic auth and set it in REQUEST.access_token
256
        $token = $f3->get('REQUEST.access_token');
257
        foreach ($f3->get('SERVER') as $k => $header) {
258
            if ($utf->stristr($k, 'authorization') !== false) {
259
                if (preg_match('/Bearer\s+(?P<access_token>.+)$/i', $header, $matches)) {
260
                    $token = $matches['access_token'];
261
                } elseif (preg_match('/Basic\s+(?P<data>.+)$/i', $header, $matches)) {
262
                    $data = preg_split('/:/', base64_decode($matches['data']));
263
264
                    $f3->mset([
265
                        'SERVER.PHP_AUTH_USER' => $data[0],
266
                        'SERVER.PHP_AUTH_PW' => $data[1],
267
                        'REQUEST.PHP_AUTH_USER' => $data[0],
268
                        'REQUEST.PHP_AUTH_PW' => $data[1]
269
                    ]);
270
                }
271
            }
272
        }
273
        if (!empty($token)) {
274
            $f3->set('REQUEST.access_token', $token);
275
        }
276
277
        // load /api/* routes and finish
278
        if (!empty($api)) {
279
280
            // load api config keys
281
            $f3->set('cfg.keys.api', $f3->get('cfg.keys.api'));
282
            self::loadConfigData($f3);
283
284
            $f3->config('config/routes-api.ini');
285
            $f3->run();
286
            return;
287
        }
288
289
        $f3->route('GET /docs/@page', function ($f3, array $params) {
290
291
            $filename = '../docs/'.strtoupper($params['page']).'.md';
292
293
            if (!file_exists($filename)) {
294
                $html = '<h1>Documentation Error</h1><p>No such document exists!</p>';
295
                $f3->status(404);
296
            } else {
297
                $html = \Markdown::instance()->convert($f3->read($filename));
298
            }
299
300
            $f3->set('html', $html);
301
            echo \View::instance()->render('/markdown-template.phtml');
302
303
        }, $f3->get('ttl.doc'));
304
305
        // @see http://fatfreeframework.com/optimization
306
        $f3->route('GET /minify/@type',
307
            function ($f3) {
308
                    $path = realpath(dirname(__FILE__) . '/../www/');
309
                    $files = str_replace('../', '', $f3->get('GET.files')); // close potential hacking attempts
310
                    echo \Web::instance()->minify($files, null, true, $path);
311
            },
312
            $f3->get('ttl.minify')
313
        );
314
315
        // load language-based routes, default english
316
        $f3->config('config/routes-en.ini');
317
        $file = 'config/routes-' . $language  . '.ini';
318
        if (file_exists($file)) {
319
            $f3->config($file);
320
        }
321
322
        // auto-load config keys for www and cms (if needed)
323
        $f3->set('cfg.keys.www', $f3->get('cfg.keys.www'));
324
        $cms = '/cms' == substr($f3->get('PATH'), 3, 5);
325
        if ($cms) {
326
            $f3->set('cfg.keys.cms',$f3->get('cfg.keys.cms'));
327
        }
328
        self::loadConfigData($f3);
329
330
        // load page slugs from cache and create routes after
331
        $cache = \Cache::instance();
332
        $key = 'page-slugs';
333
        if (!$cache->exists($key, $slugs)) {
334
            $db = \Registry::get('db');
335
            $data = $db->exec('SELECT slug, CONCAT("/", language, path, slug) AS path FROM pages');
336
            if (!empty($data)) {
337
                foreach ($data as $row) {
338
                    $slugs[$row['slug']] = $f3->fixslashes($row['path']);
339
                }
340
            }
341
            $cache->set($key, $slugs, $f3->get('ttl.cfg'));
342
        }
343
344
        // create routes for slugged pages
345
        if (!empty($slugs)) {
346
            $lang = $f3->get('LANG');
0 ignored issues
show
Unused Code introduced by
$lang is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
347
            $existingRoutes = array_keys($f3->ROUTES);
348
            foreach ($slugs as $path) {
349
                if (in_array($path, $existingRoutes)) {
350
                    continue;
351
                }
352
                $f3->route('GET ' . $path, 'FFCMS\Controllers\Page->page');
353
            }
354
        }
355
356
        $f3->run();
357
    }
358
}
359