Passed
Push — develop ( 9a1b4d...3be2c9 )
by Felipe
03:49
created

ContainerUtils::createContainer()   B

Complexity

Conditions 7
Paths 2

Size

Total Lines 39
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 21
nc 2
nop 1
dl 0
loc 39
rs 8.6506
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * PHPPgAdmin v6.0.0-RC8
5
 */
6
7
namespace PHPPgAdmin;
8
9
/**
10
 * @file
11
 * A class that adds convenience methods to the container
12
 */
13
14
/**
15
 * A class that adds convenience methods to the container.
16
 *
17
 * @package PHPPgAdmin
18
 */
19
class ContainerUtils
20
{
21
    use \PHPPgAdmin\Traits\HelperTrait;
22
23
    protected $container;
24
    /** @var Connector */
0 ignored issues
show
Bug introduced by
The type PHPPgAdmin\Connector was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
25
    protected static $instance;
26
27
    /**
28
     * Constructor of the ContainerUtils class.
29
     *
30
     * @param \Slim\Container $container The app container
31
     */
32
    public function __construct()
33
    {
34
        $composerinfo = json_decode(file_get_contents(BASE_PATH.'/composer.json'));
35
        $appVersion   = $composerinfo->version;
36
37
        $phpMinVer = (str_replace(['<', '>', '='], '', $composerinfo->require->php));
38
        //$this->prtrace($appVersion);
39
        //$this->dump($composerinfo);
40
41
        $config = [
42
            'msg'       => '',
43
            'appThemes' => [
44
                'default'    => 'Default',
45
                'cappuccino' => 'Cappuccino',
46
                'gotar'      => 'Blue/Green',
47
                'bootstrap'  => 'Bootstrap3',
48
            ],
49
            'settings'  => [
50
                'displayErrorDetails'               => DEBUGMODE,
51
                'determineRouteBeforeAppMiddleware' => true,
52
                'base_path'                         => BASE_PATH,
53
                'debug'                             => DEBUGMODE,
54
55
                // 'routerCacheFile'                   => BASE_PATH . '/temp/route.cache.php',
56
57
                // Configuration file version.  If this is greater than that in config.inc.php, then
58
                // the app will refuse to run.  This and $conf['version'] should be incremented whenever
59
                // backwards incompatible changes are made to config.inc.php-dist.
60
                'base_version'                      => 60,
61
                // Application version
62
                'appVersion'                        => 'v'.$appVersion,
63
                // Application name
64
                'appName'                           => 'phpPgAdmin6',
65
66
                // PostgreSQL and PHP minimum version
67
                'postgresqlMinVer'                  => '9.3',
68
                'phpMinVer'                         => $phpMinVer,
69
                'displayErrorDetails'               => DEBUGMODE,
70
                'addContentLengthHeader'            => false,
71
            ],
72
        ];
73
74
        $this->app = new \Slim\App($config);
75
76
        // Fetch DI Container
77
        $container            = $this->app->getContainer();
78
        $container['utils']   = $this;
79
        $container['version'] = 'v'.$appVersion;
80
        $container['errors']  = [];
81
82
        $this->container = $container;
83
    }
84
85
    public static function createContainer($conf)
86
    {
87
        if (!self::$instance) {
88
            self::$instance = new self();
0 ignored issues
show
Documentation Bug introduced by
It seems like new self() of type PHPPgAdmin\ContainerUtils is incompatible with the declared type PHPPgAdmin\Connector of property $instance.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
89
        }
90
91
        // Complete missing conf keys
92
        self::$instance->container['conf'] = function ($c) use ($conf) {
93
            $display_sizes = $conf['display_sizes'] ?? false;
94
95
            $conf['display_sizes'] = [
96
                'schemas' => (bool) $display_sizes,
97
                'tables'  => (bool) $display_sizes,
98
            ];
99
            if (is_array($display_sizes)) {
100
                $conf['display_sizes'] = [
101
                    'schemas' => $display_sizes['schemas'] ?? in_array('schemas', $display_sizes, true),
102
                    'tables'  => $display_sizes['tables'] ?? in_array('tables', $display_sizes, true),
103
                ];
104
            }
105
106
            // Plugins are removed
107
            $conf['plugins'] = [];
108
            if (!isset($conf['theme'])) {
109
                $conf['theme'] = 'default';
110
            }
111
            foreach ($conf['servers'] as &$server) {
112
                if (!isset($server['port'])) {
113
                    $server['port'] = 5432;
114
                }
115
                if (!isset($server['sslmode'])) {
116
                    $server['sslmode'] = 'unspecified';
117
                }
118
            }
119
120
            return $conf;
121
        };
122
123
        return [self::$instance->container, self::$instance->app];
124
    }
125
126
    public function maybeRenderIframes($response, $subject, $query_string)
127
    {
128
        $c       = $this->container;
129
        $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...
130
131
        if ($in_test === '1') {
132
            $className  = '\PHPPgAdmin\Controller\\'.ucfirst($subject).'Controller';
133
            $controller = new $className($c);
134
135
            return $controller->render();
136
        }
137
138
        $viewVars = [
139
            'url'            => '/src/views/'.$subject.($query_string ? '?'.$query_string : ''),
140
            'headertemplate' => 'header.twig',
141
        ];
142
143
        return $c->view->render($response, 'iframe_view.twig', $viewVars);
144
    }
145
146
    /**
147
     * Gets the theme from
148
     * 1. The $_REQUEST global (when it's chosen from start screen)
149
     * 2. Server specific config theme
150
     * 3.- $_SESSION global (subsequent requests after 1.)
151
     * 4.- $_COOKIE global (mostly fallback for $_SESSION after 1.- and 3.-)
152
     * 5.- theme as set in config
153
     * 6.- 'default' theme.
154
     *
155
     * @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...
156
     * @param null|mixed $_server_info
157
     *
158
     * @return string the theme
159
     */
160
    public function getTheme(array $conf, $_server_info = null)
161
    {
162
        $_theme = null;
163
        // List of themes
164
        $themefolders = $this->getThemeFolders();
165
        // Check if theme is in $_REQUEST, $_SESSION or $_COOKIE
166
        // 1.- First priority: $_REQUEST, this happens when you use the selector
167
        if (array_key_exists('theme', $_REQUEST) &&
168
            array_key_exists($_REQUEST['theme'], $themefolders)) {
169
            $_theme = $_REQUEST['theme'];
170
        } 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...
171
            !is_null($_server_info) &&
172
            array_key_exists('theme', $_server_info) &&
173
            is_string($_server_info['theme']) &&
174
            array_key_exists($_COOKIE['ppaTheme'], $themefolders)) {
175
            $_theme = $_server_info['theme'];
176
        } elseif (array_key_exists('ppaTheme', $_SESSION) &&
177
            array_key_exists($_SESSION['ppaTheme'], $themefolders)) {
178
            // otherwise check $_SESSION
179
            $_theme = $_SESSION['ppaTheme'];
180
        } elseif (array_key_exists('ppaTheme', $_SESSION) &&
181
            array_key_exists($_COOKIE['ppaTheme'], $themefolders)) {
182
            // oterwise check $_COOKIE
183
            $_theme = $_COOKIE['ppaTheme'];
184
        } 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...
185
            array_key_exists('theme', $conf) &&
186
            is_string($conf['theme']) &&
187
            array_key_exists($conf['theme'], $themefolders)) {
188
            $_theme = $conf['theme'];
189
        } else {
190
            // okay then, use default theme
191
            $_theme = 'default';
192
        }
193
194
        return $_theme;
195
    }
196
197
    /**
198
     * Traverse THEME_PATH, consider as theme folders those which
199
     * contain a `global.css` stylesheet.
200
     *
201
     * @return array the theme folders
202
     */
203
    private function getThemeFolders()
204
    {
205
        // no THEME_PATH (how?) then return empty array
206
        if (!$gestor = opendir(THEME_PATH)) {
207
            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

207
            closedir(/** @scrutinizer ignore-type */ $gestor);
Loading history...
208
209
            return [];
210
        }
211
        $themefolders = [];
212
213
        /* This is the right way to iterate on a folder */
214
        while (false !== ($foldername = readdir($gestor))) {
215
            if ($foldername == '.' || $foldername == '..') {
216
                continue;
217
            }
218
219
            $folderpath = sprintf('%s%s%s', THEME_PATH, DIRECTORY_SEPARATOR, $foldername);
220
            $stylesheet = sprintf('%s%s%s', $folderpath, DIRECTORY_SEPARATOR, 'global.css');
221
            // if $folderpath if indeed a folder and contains a global.css file, then it's a theme
222
            if (is_dir($folderpath) &&
223
                is_file($stylesheet)) {
224
                $themefolders[$foldername] = $folderpath;
225
            }
226
        }
227
228
        closedir($gestor);
229
230
        return $themefolders;
231
    }
232
233
    /**
234
     * Determines the redirection url according to query string.
235
     *
236
     * @return string the redirect url
237
     */
238
    public function getRedirectUrl()
239
    {
240
        $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...
241
242
        // if server_id isn't set, then you will be redirected to intro
243
        if ($this->container->requestobj->getQueryParam('server') === null) {
244
            $destinationurl = \SUBFOLDER.'/src/views/intro';
245
        } else {
246
            // otherwise, you'll be redirected to the login page for that server;
247
            $destinationurl = \SUBFOLDER.'/src/views/login'.($query_string ? '?'.$query_string : '');
248
        }
249
250
        return $destinationurl;
251
    }
252
253
    /**
254
     * Gets the destination with the last active tab selected for that controller
255
     * Usually used after going through a redirect route.
256
     *
257
     * @param string $subject The subject, usually a view name like 'server' or 'table'
258
     *
259
     * @return string The destination url with last tab set in the query string
260
     */
261
    public function getDestinationWithLastTab($subject)
262
    {
263
        $_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...
264
        $this->addFlash($subject, 'getDestinationWithLastTab');
265
        //$this->prtrace('$_server_info', $_server_info);
266
        // If username isn't set in server_info, you should login
267
        if (!isset($_server_info['username'])) {
268
            $destinationurl = $this->getRedirectUrl();
269
        } else {
270
            $url = $this->container->misc->getLastTabURL($subject);
271
            $this->addFlash($url, 'getLastTabURL for '.$subject);
272
            // Load query vars into superglobal arrays
273
            if (isset($url['urlvars'])) {
274
                $urlvars = [];
275
                foreach ($url['urlvars'] as $key => $urlvar) {
276
                    //$this->prtrace($key, $urlvar);
277
                    $urlvars[$key] = \PHPPgAdmin\Decorators\Decorator::get_sanitized_value($urlvar, $_REQUEST);
278
                }
279
                $_REQUEST = array_merge($_REQUEST, $urlvars);
280
                $_GET     = array_merge($_GET, $urlvars);
281
            }
282
283
            $actionurl      = \PHPPgAdmin\Decorators\Decorator::actionurl($url['url'], $_GET);
284
            $destinationurl = $actionurl->value($_GET);
285
        }
286
        $destinationurl = str_replace('views/?', "views/{$subject}?", $destinationurl);
287
        // $this->prtrace('destinationurl for ' . $subject, $destinationurl);
288
        return $destinationurl;
289
    }
290
291
    /**
292
     * Adds an error to the errors array property of the container.
293
     *
294
     * @param string $errormsg The error msg
295
     *
296
     * @return \Slim\Container The app container
297
     */
298
    public function addError($errormsg)
299
    {
300
        $errors   = $this->container->get('errors');
301
        $errors[] = $errormsg;
302
        $this->container->offsetSet('errors', $errors);
303
304
        return $this->container;
305
    }
306
}
307