Passed
Pull Request — develop (#262)
by Felipe
04:12
created

ContainerUtils::__construct()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 53
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 31
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 53
rs 9.424

How to fix   Long Method   

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
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
3
// declare(strict_types=1);
4
5
/**
6
 * PHPPgAdmin vv6.0.0-RC8-16-g13de173f
7
 *
8
 */
0 ignored issues
show
Coding Style introduced by
Additional blank lines found at end of doc comment
Loading history...
9
10
namespace PHPPgAdmin;
11
12
use Psr\Container\ContainerInterface;
13
use Slim\App;
14
15
\defined('BASE_PATH') || \define(BASE_PATH, \dirname(__DIR__, 2));
16
\defined('SUBFOLDER') || \define(
17
    'SUBFOLDER',
18
    \str_replace($_SERVER['DOCUMENT_ROOT'] ?? '', '', BASE_PATH)
19
);
20
\defined('DEBUGMODE') || \define('DEBUGMODE', false);
21
defined('IN_TEST') || define('IN_TEST', false);
22
/**
23
 * @file
24
 * A class that adds convenience methods to the container
25
 */
26
27
/**
28
 * A class that adds convenience methods to the container.
29
 */
30
class ContainerUtils
31
{
32
    use \PHPPgAdmin\Traits\HelperTrait;
33
    /**
34
     * @var string
35
     */
36
    const BASE_PATH = BASE_PATH;
37
    /**
38
     * @var string
39
     */
40
    const SUBFOLDER = SUBFOLDER;
41
    /**
42
     * @var string
43
     */
44
    const DEBUGMODE = DEBUGMODE;
45
46
    /**
47
     * @var ContainerInterface
48
     */
49
    protected $_container;
50
51
    /**
52
     * @var App
53
     */
54
    protected $_app;
55
56
    /**
57
     * @var self
58
     */
59
    protected static $_instance;
60
61
    /**
62
     * Constructor of the ContainerUtils class.
63
     */
64
    public function __construct()
65
    {
66
        $composerinfo = \json_decode(\file_get_contents(BASE_PATH . '/composer.json'));
67
        $appVersion   = $composerinfo->extra->version;
68
69
        $phpMinVer = (\str_replace(['<', '>', '='], '', $composerinfo->require->php));
70
        //$this->prtrace($appVersion);
71
        //$this->dump($composerinfo);
72
        $settings = [
73
            'displayErrorDetails'               => self::DEBUGMODE,
74
            'determineRouteBeforeAppMiddleware' => true,
75
            'base_path'                         => self::BASE_PATH,
76
            'debug'                             => self::DEBUGMODE,
77
78
            // Configuration file version.  If this is greater than that in config.inc.php, then
79
            // the app will refuse to run.  This and $conf['version'] should be incremented whenever
80
            // backwards incompatible changes are made to config.inc.php-dist.
81
            'base_version'                      => 60,
82
            // Application version
83
            'appVersion'                        => 'v' . $appVersion,
84
            // Application name
85
            'appName'                           => 'phpPgAdmin6',
86
87
            // PostgreSQL and PHP minimum version
88
            'postgresqlMinVer'                  => '9.3',
89
            'phpMinVer'                         => $phpMinVer,
90
            'displayErrorDetails'               => self::DEBUGMODE,
91
            'addContentLengthHeader'            => false,
92
        ];
93
94
        if (!self::DEBUGMODE && !IN_TEST) {
95
            $settings['routerCacheFile'] = self::BASE_PATH . '/temp/route.cache.php';
96
        }
97
        $config = [
98
            'msg'       => '',
99
            'appThemes' => [
100
                'default'    => 'Default',
101
                'cappuccino' => 'Cappuccino',
102
                'gotar'      => 'Blue/Green',
103
                'bootstrap'  => 'Bootstrap3',
104
            ],
105
            'settings'  => $settings,
106
        ];
107
108
        $this->_app = new App($config);
109
110
        // Fetch DI Container
111
        $container            = $this->_app->getContainer();
112
        $container['utils']   = $this;
113
        $container['version'] = 'v' . $appVersion;
114
        $container['errors']  = [];
115
116
        $this->_container = $container;
117
    }
118
119
    public static function getContainerInstance()
120
    {
121
        $_instance = self::getInstance();
122
123
        if (!$container = $_instance->_container) {
124
            throw new \Exception('Could not get a container');
125
        }
126
127
        return $container;
128
    }
129
130
    public static function getInstance()
131
    {
132
        if (!self::$_instance) {
133
            self::$_instance = new self();
134
        }
135
136
        return self::$_instance;
137
    }
138
139
    public static function createContainer($conf)
140
    {
141
        $container = self::getContainerInstance();
142
        // Complete missing conf keys
143
        $container['conf'] = static function ($c) use ($conf) {
144
            $display_sizes = $conf['display_sizes'] ?? false;
145
146
            $conf['display_sizes'] = [
147
                'schemas' => (bool) $display_sizes,
148
                'tables'  => (bool) $display_sizes,
149
            ];
150
151
            if (\is_array($display_sizes)) {
152
                $conf['display_sizes'] = [
153
                    'schemas' => $display_sizes['schemas'] ?? \in_array('schemas', $display_sizes, true),
154
                    'tables'  => $display_sizes['tables'] ?? \in_array('tables', $display_sizes, true),
155
                ];
156
            }
157
158
            // Plugins are removed
159
            $conf['plugins'] = [];
160
161
            if (!isset($conf['theme'])) {
162
                $conf['theme'] = 'default';
163
            }
164
165
            foreach ($conf['servers'] as &$server) {
166
                if (!isset($server['port'])) {
167
                    $server['port'] = 5432;
168
                }
169
170
                if (!isset($server['sslmode'])) {
171
                    $server['sslmode'] = 'unspecified';
172
                }
173
            }
174
175
            return $conf;
176
        };
177
        $requestUri = $container->request->getUri() ?? null;
0 ignored issues
show
Bug introduced by
Accessing request on the interface Psr\Container\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
178
179
        if ($requestBasePath = $requestUri->getBasePath() ?? null) {
0 ignored issues
show
Bug introduced by
The method getBasePath() does not exist on null. ( Ignorable by Annotation )

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

179
        if ($requestBasePath = $requestUri->/** @scrutinizer ignore-call */ getBasePath() ?? null) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
180
            $subfolder = $requestBasePath;
181
        } elseif (\PHP_SAPI === 'cli-server') {
182
            $subfolder = '/index.php';
183
        } elseif (isset($conf['subfolder']) && \is_string($conf['subfolder'])) {
184
            $subfolder = $conf['subfolder'];
185
        } else {
186
            $subfolder = \str_replace(
187
                $container->environment->get('DOCUMENT_ROOT'),
188
                '',
189
                \dirname(__DIR__, 2)
190
            );
191
        }
192
193
        $container->subfolder = $subfolder ?? self::SUBFOLDER;
0 ignored issues
show
Bug introduced by
Accessing subfolder on the interface Psr\Container\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
194
        //ddd($container->subfolder);
195
        return [$container, self::$_instance->_app];
196
    }
197
198
    public function maybeRenderIframes($response, $subject, $query_string)
199
    {
200
        $c = self::getContainerInstance();
201
202
        $in_test = $c->view->offsetGet('in_test');
0 ignored issues
show
Bug introduced by
Accessing view on the interface Psr\Container\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
203
204
        if ('1' === $in_test) {
205
            $className  = '\PHPPgAdmin\Controller\\' . \ucfirst($subject) . 'Controller';
206
            $controller = new $className($c);
207
208
            return $controller->render();
209
        }
210
211
        $viewVars = [
212
            'url'            => '/src/views/' . $subject . ($query_string ? '?' . $query_string : ''),
213
            'headertemplate' => 'header.twig',
214
        ];
215
216
        return $c->view->render($response, 'iframe_view.twig', $viewVars);
217
    }
218
219
    /**
220
     * Gets the theme from
221
     * 1. The $_REQUEST global (when it's chosen from start screen)
222
     * 2. Server specific config theme
223
     * 3.- $_SESSION global (subsequent requests after 1.)
224
     * 4.- $_COOKIE global (mostly fallback for $_SESSION after 1.- and 3.-)
225
     * 5.- theme as set in config
226
     * 6.- 'default' theme.
227
     *
228
     * @param <type>     $conf         The conf
0 ignored issues
show
Documentation Bug introduced by
The doc comment <type> at position 0 could not be parsed: Unknown type name '<' at position 0 in <type>.
Loading history...
229
     * @param null|mixed $_server_info
230
     *
231
     * @return string the theme
232
     */
233
    public function getTheme(array $conf, $_server_info = null)
234
    {
235
        $_theme = null;
236
        // List of themes
237
        $themefolders = $this->getThemeFolders();
238
        // Check if theme is in $_REQUEST, $_SESSION or $_COOKIE
239
        // 1.- First priority: $_REQUEST, this happens when you use the selector
240
        if (\array_key_exists('theme', $_REQUEST) &&
241
            \array_key_exists($_REQUEST['theme'], $themefolders)) {
242
            $_theme = $_REQUEST['theme'];
243
        } elseif ( // otherwise, see if there's a theme associated with this particular server
0 ignored issues
show
Coding Style introduced by
First condition of a multi-line IF statement must directly follow the opening parenthesis
Loading history...
244
            null !== $_server_info &&
245
            \array_key_exists('theme', $_server_info) &&
246
            \is_string($_server_info['theme']) &&
247
            \array_key_exists($_COOKIE['ppaTheme'], $themefolders)) {
248
            $_theme = $_server_info['theme'];
249
        } elseif (\array_key_exists('ppaTheme', $_SESSION) &&
250
            \array_key_exists($_SESSION['ppaTheme'], $themefolders)) {
251
            // otherwise check $_SESSION
252
            $_theme = $_SESSION['ppaTheme'];
253
        } elseif (\array_key_exists('ppaTheme', $_SESSION) &&
254
            \array_key_exists($_COOKIE['ppaTheme'], $themefolders)) {
255
            // oterwise check $_COOKIE
256
            $_theme = $_COOKIE['ppaTheme'];
257
        } elseif ( // see if there's a valid theme set in config file
0 ignored issues
show
Coding Style introduced by
First condition of a multi-line IF statement must directly follow the opening parenthesis
Loading history...
258
            \array_key_exists('theme', $conf) &&
259
            \is_string($conf['theme']) &&
260
            \array_key_exists($conf['theme'], $themefolders)) {
261
            $_theme = $conf['theme'];
262
        } else {
263
            // okay then, use default theme
264
            $_theme = 'default';
265
        }
266
267
        return $_theme;
268
    }
269
270
    /**
271
     * Determines the redirection url according to query string.
272
     *
273
     * @return string the redirect url
274
     */
275
    public function getRedirectUrl()
276
    {
277
        $query_string = $this->_container->requestobj->getUri()->getQuery();
0 ignored issues
show
Bug introduced by
Accessing requestobj on the interface Psr\Container\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
278
279
        // if server_id isn't set, then you will be redirected to intro
280
        if (null === $this->_container->requestobj->getQueryParam('server')) {
281
            $destinationurl = \SUBFOLDER . '/src/views/intro';
282
        } else {
283
            // otherwise, you'll be redirected to the login page for that server;
284
            $destinationurl = \SUBFOLDER . '/src/views/login' . ($query_string ? '?' . $query_string : '');
285
        }
286
287
        return $destinationurl;
288
    }
289
290
    /**
291
     * Gets the destination with the last active tab selected for that controller
292
     * Usually used after going through a redirect route.
293
     *
294
     * @param string $subject The subject, usually a view name like 'server' or 'table'
295
     *
296
     * @return string The destination url with last tab set in the query string
297
     */
298
    public function getDestinationWithLastTab($subject)
299
    {
300
        $_server_info = $this->_container->misc->getServerInfo();
0 ignored issues
show
Bug introduced by
Accessing misc on the interface Psr\Container\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
301
        $this->addFlash($subject, 'getDestinationWithLastTab');
302
        //$this->prtrace('$_server_info', $_server_info);
303
        // If username isn't set in server_info, you should login
304
        if (!isset($_server_info['username'])) {
305
            $destinationurl = $this->getRedirectUrl();
306
        } else {
307
            $url = $this->_container->misc->getLastTabURL($subject);
308
            $this->addFlash($url, 'getLastTabURL for ' . $subject);
309
            // Load query vars into superglobal arrays
310
            if (isset($url['urlvars'])) {
311
                $urlvars = [];
312
313
                foreach ($url['urlvars'] as $key => $urlvar) {
314
                    //$this->prtrace($key, $urlvar);
315
                    $urlvars[$key] = \PHPPgAdmin\Decorators\Decorator::get_sanitized_value($urlvar, $_REQUEST);
316
                }
317
                $_REQUEST = \array_merge($_REQUEST, $urlvars);
318
                $_GET     = \array_merge($_GET, $urlvars);
319
            }
320
321
            $actionurl      = \PHPPgAdmin\Decorators\Decorator::actionurl($url['url'], $_GET);
322
            $destinationurl = $actionurl->value($_GET);
323
        }
324
        $destinationurl = \str_replace('views/?', "views/{$subject}?", $destinationurl);
325
        // $this->prtrace('destinationurl for ' . $subject, $destinationurl);
326
        return $destinationurl;
327
    }
328
329
    /**
330
     * Adds an error to the errors array property of the container.
331
     *
332
     * @param string $errormsg The error msg
333
     *
334
     * @return \Slim\Container The app container
335
     */
336
    public function addError($errormsg)
337
    {
338
        $errors   = $this->_container->get('errors');
339
        $errors[] = $errormsg;
340
        $this->_container->offsetSet('errors', $errors);
341
342
        return $this->_container;
343
    }
344
345
    /**
346
     * Traverse THEME_PATH, consider as theme folders those which
347
     * contain a `global.css` stylesheet.
348
     *
349
     * @return array the theme folders
350
     */
351
    private function getThemeFolders()
352
    {
353
        // no THEME_PATH (how?) then return empty array
354
        if (!$gestor = \opendir(THEME_PATH)) {
355
            \closedir($gestor);
0 ignored issues
show
Bug introduced by
It seems like $gestor can also be of type false; however, parameter $dir_handle of closedir() does only seem to accept resource, 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

355
            \closedir(/** @scrutinizer ignore-type */ $gestor);
Loading history...
356
357
            return [];
358
        }
359
        $themefolders = [];
360
361
        /* This is the right way to iterate on a folder */
362
        while (false !== ($foldername = \readdir($gestor))) {
363
            if ('.' === $foldername || '..' === $foldername) {
364
                continue;
365
            }
366
367
            $folderpath = \sprintf('%s%s%s', THEME_PATH, \DIRECTORY_SEPARATOR, $foldername);
368
            $stylesheet = \sprintf('%s%s%s', $folderpath, \DIRECTORY_SEPARATOR, 'global.css');
369
            // if $folderpath if indeed a folder and contains a global.css file, then it's a theme
370
            if (\is_dir($folderpath) &&
371
                \is_file($stylesheet)) {
372
                $themefolders[$foldername] = $folderpath;
373
            }
374
        }
375
376
        \closedir($gestor);
377
378
        return $themefolders;
379
    }
380
}
381