Passed
Push — develop ( c6d385...331c63 )
by Felipe
05:01
created

ContainerUtils::icon()   B

Complexity

Conditions 11
Paths 11

Size

Total Lines 47
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 25
c 0
b 0
f 0
nc 11
nop 1
dl 0
loc 47
rs 7.3166

How to fix   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
/**
4
 * PHPPgAdmin v6.0.0-RC1.
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
class ContainerUtils
18
{
19
    use \PHPPgAdmin\Traits\HelperTrait;
20
21
    protected $container;
22
    /** @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...
23
    protected static $instance;
24
25
    /**
26
     * Constructor of the ContainerUtils class.
27
     *
28
     * @param \Slim\Container $container The app container
29
     */
30
    public function __construct()
31
    {
32
        $composerinfo = json_decode(file_get_contents(BASE_PATH . '/composer.json'));
33
        $appVersion   = $composerinfo->version;
34
35
        $phpMinVer = (str_replace(['<', '>', '='], '', $composerinfo->require->php));
36
        $config    = [
37
            'msg'       => '',
38
            'appThemes' => [
39
                'default'    => 'Default',
40
                'cappuccino' => 'Cappuccino',
41
                'gotar'      => 'Blue/Green',
42
                'bootstrap'  => 'Bootstrap3',
43
            ],
44
            'settings'  => [
45
                'displayErrorDetails'               => DEBUGMODE,
46
                'determineRouteBeforeAppMiddleware' => true,
47
                'base_path'                         => BASE_PATH,
48
                'debug'                             => DEBUGMODE,
49
50
                'routerCacheFile'                   => BASE_PATH . '/temp/route.cache.php',
51
52
                // Configuration file version.  If this is greater than that in config.inc.php, then
53
                // the app will refuse to run.  This and $conf['version'] should be incremented whenever
54
                // backwards incompatible changes are made to config.inc.php-dist.
55
                'base_version'                      => 60,
56
                // Application version
57
                'appVersion'                        => 'v' . $appVersion,
58
                // Application name
59
                'appName'                           => 'phpPgAdmin6',
60
61
                // PostgreSQL and PHP minimum version
62
                'postgresqlMinVer'                  => '9.3',
63
                'phpMinVer'                         => $phpMinVer,
64
                'displayErrorDetails'               => DEBUGMODE,
65
                'addContentLengthHeader'            => false,
66
            ],
67
        ];
68
69
        $this->app = new \Slim\App($config);
70
71
        // Fetch DI Container
72
        $container            = $this->app->getContainer();
73
        $container['utils']   = $this;
74
        $container['version'] = 'v' . $appVersion;
75
        $container['errors']  = [];
76
77
        $this->container = $container;
78
    }
79
80
    public static function createContainer()
81
    {
82
        if (!self::$instance) {
83
            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...
84
        }
85
86
        return [self::$instance->container, self::$instance->app];
87
    }
88
89
    public function icon($icon)
90
    {
91
92
        $conf = $this->container->conf;
0 ignored issues
show
Bug introduced by
Accessing conf on the interface Psr\Container\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
93
        if (is_string($icon)) {
94
            $path = "/assets/images/themes/{$conf['theme']}/{$icon}";
95
            if (file_exists(\BASE_PATH . $path . '.png')) {
96
                return SUBFOLDER . $path . '.png';
97
            }
98
99
            if (file_exists(\BASE_PATH . $path . '.gif')) {
100
                return SUBFOLDER . $path . '.gif';
101
            }
102
103
            if (file_exists(\BASE_PATH . $path . '.ico')) {
104
                return SUBFOLDER . $path . '.ico';
105
            }
106
107
            $path = "/assets/images/themes/default/{$icon}";
108
            if (file_exists(\BASE_PATH . $path . '.png')) {
109
                return SUBFOLDER . $path . '.png';
110
            }
111
112
            if (file_exists(\BASE_PATH . $path . '.gif')) {
113
                return SUBFOLDER . $path . '.gif';
114
            }
115
116
            if (file_exists(\BASE_PATH . $path . '.ico')) {
117
                return SUBFOLDER . $path . '.ico';
118
            }
119
        } else {
120
            // Icon from plugins
121
            $path = "/plugins/{$icon[0]}/images/{$icon[1]}";
122
            if (file_exists(\BASE_PATH . $path . '.png')) {
123
                return SUBFOLDER . $path . '.png';
124
            }
125
126
            if (file_exists(\BASE_PATH . $path . '.gif')) {
127
                return SUBFOLDER . $path . '.gif';
128
            }
129
130
            if (file_exists(\BASE_PATH . $path . '.ico')) {
131
                return SUBFOLDER . $path . '.ico';
132
            }
133
        }
134
135
        return '';
136
    }
137
138
    public function maybeRenderIframes($response, $subject, $query_string)
139
    {
140
        $c       = $this->container;
141
        $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...
142
143
        if ($in_test === '1') {
144
            $className  = '\PHPPgAdmin\Controller\\' . ucfirst($subject) . 'Controller';
145
            $controller = new $className($c);
146
147
            return $controller->render();
148
        }
149
        $viewVars = [
150
            'icon'           => [
151
                'Refresh' => $this->icon('Refresh'),
152
                'Servers' => $this->icon('Servers'),
153
            ],
154
            'url'            => '/src/views/' . $subject . ($query_string ? '?' . $query_string : ''),
155
            'headertemplate' => 'header.twig',
156
        ];
157
158
        return $c->view->render($response, 'main.twig', $viewVars);
159
    }
160
161
    /**
162
     * Gets the theme from
163
     * 1. The $_REQUEST global (when it's chosen from start screen)
164
     * 2. Server specific config theme
165
     * 3.- $_SESSION global (subsequent requests after 1.)
166
     * 4.- $_COOKIE global (mostly fallback for $_SESSION after 1.- and 3.-)
167
     * 5.- theme as set in config
168
     * 6.- 'default' theme.
169
     *
170
     * @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...
171
     * @param null|mixed $_server_info
172
     *
173
     * @return string the theme
174
     */
175
    public function getTheme(array $conf, $_server_info = null)
176
    {
177
        $_theme = null;
178
        // List of themes
179
        $themefolders = $this->getThemeFolders();
180
        // Check if theme is in $_REQUEST, $_SESSION or $_COOKIE
181
        // 1.- First priority: $_REQUEST, this happens when you use the selector
182
        if (array_key_exists('theme', $_REQUEST) &&
183
            array_key_exists($_REQUEST['theme'], $themefolders)) {
184
            $_theme = $_REQUEST['theme'];
185
        } 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...
186
            !is_null($_server_info) &&
187
            array_key_exists('theme', $_server_info) &&
188
            is_string($_server_info['theme']) &&
189
            array_key_exists($_COOKIE['ppaTheme'], $themefolders)) {
190
            $_theme = $_server_info['theme'];
191
        } elseif (array_key_exists('ppaTheme', $_SESSION) &&
192
            array_key_exists($_SESSION['ppaTheme'], $themefolders)) {
193
            // otherwise check $_SESSION
194
            $_theme = $_SESSION['ppaTheme'];
195
        } elseif (array_key_exists('ppaTheme', $_SESSION) &&
196
            array_key_exists($_COOKIE['ppaTheme'], $themefolders)) {
197
            // oterwise check $_COOKIE
198
            $_theme = $_COOKIE['ppaTheme'];
199
        } 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...
200
            array_key_exists('theme', $conf) &&
201
            is_string($conf['theme']) &&
202
            array_key_exists($conf['theme'], $themefolders)) {
203
            $_theme = $conf['theme'];
204
        } else {
205
            // okay then, use default theme
206
            $_theme = 'default';
207
        }
208
209
        return $_theme;
210
    }
211
212
    /**
213
     * Traverse THEME_PATH, consider as theme folders those which
214
     * contain a `global.css` stylesheet.
215
     *
216
     * @return array the theme folders
217
     */
218
    private function getThemeFolders()
219
    {
220
        // no THEME_PATH (how?) then return empty array
221
        if (!$gestor = opendir(THEME_PATH)) {
222
            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

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