Cancelled
Pull Request — develop (#267)
by Felipe
06:23
created

ViewManager::__construct()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 32
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 22
c 1
b 0
f 0
nc 2
nop 3
dl 0
loc 32
rs 9.568
1
<?php
2
3
/**
4
 * PHPPgAdmin v6.0.0-RC9
5
 */
6
7
namespace PHPPgAdmin;
8
9
/**
10
 * @file
11
 * Class to hold various commonly used functions
12
 *
13
 * Id: Misc.php,v 1.171 2008/03/17 21:35:48 ioguix Exp $
14
 */
15
16
/**
17
 * Class to hold various commonly used functions.
18
 *
19
 * Release: Misc.php,v 1.171 2008/03/17 21:35:48 ioguix Exp $
20
 */
21
class ViewManager extends \Slim\Views\Twig
22
{
23
    use \PHPPgAdmin\Traits\HelperTrait;
24
25
    /**
26
     * @var string
27
     */
28
    const BASE_PATH = ContainerUtils::BASE_PATH;
29
30
    /**
31
     * @var string
32
     */
33
    const THEME_PATH = ContainerUtils::THEME_PATH;
34
    /**
35
     * @var string
36
     */
37
    const SUBFOLDER = ContainerUtils::SUBFOLDER;
38
    /**
39
     * @var string
40
     */
41
    const DEBUGMODE = ContainerUtils::DEBUGMODE;
42
43
    public $appLangFiles = [];
44
45
    public $appName = '';
46
47
    public $appVersion = '';
48
49
    public $form = '';
50
51
    public $href = '';
52
53
    public $lang = [];
54
55
    public $conf;
56
57
    public $phpMinVer;
58
59
    public $postgresqlMinVer;
60
61
    public $view;
62
63
    protected $container;
64
65
    private $_connection;
0 ignored issues
show
introduced by
The private property $_connection is not used, and could be removed.
Loading history...
66
67
    private $_no_db_connection = false;
0 ignored issues
show
introduced by
The private property $_no_db_connection is not used, and could be removed.
Loading history...
68
69
    private $_reload_browser = false;
0 ignored issues
show
introduced by
The private property $_reload_browser is not used, and could be removed.
Loading history...
70
71
    private $_data;
0 ignored issues
show
introduced by
The private property $_data is not used, and could be removed.
Loading history...
72
73
    private $_database;
0 ignored issues
show
introduced by
The private property $_database is not used, and could be removed.
Loading history...
74
75
    private $_server_id;
0 ignored issues
show
introduced by
The private property $_server_id is not used, and could be removed.
Loading history...
76
77
    private $_server_info;
0 ignored issues
show
introduced by
The private property $_server_info is not used, and could be removed.
Loading history...
78
79
    private $_error_msg = '';
0 ignored issues
show
introduced by
The private property $_error_msg is not used, and could be removed.
Loading history...
80
81
    private static $instance = null;
0 ignored issues
show
introduced by
The private property $instance is not used, and could be removed.
Loading history...
Coding Style introduced by
Private member variable "instance" must be prefixed with an underscore
Loading history...
82
83
    /**
84
     * @param \Slim\Container $container The container
0 ignored issues
show
Coding Style introduced by
Doc comment for parameter $container does not match actual variable name $path
Loading history...
85
     * @param mixed           $path
0 ignored issues
show
Coding Style introduced by
Doc comment for parameter $path does not match actual variable name $settings
Loading history...
86
     * @param mixed           $settings
0 ignored issues
show
Coding Style introduced by
Doc comment for parameter $settings does not match actual variable name $c
Loading history...
87
     * @param \Slim\Container $c
88
     */
89
    public function __construct($path, $settings, \Slim\Container $c)
90
    {
91
        $this->lang = $c->get('lang');
92
        $this->conf = $c->get('conf');
93
        $this->misc = $c->get('misc');
94
        parent::__construct($path, $settings);
95
        $this->container          = $c;
96
        $environment              = $c->get('environment');
97
        $base_script_trailing_str = \mb_substr($environment['SCRIPT_NAME'], 1);
98
        $request_basepath         = $c['request']->getUri()->getBasePath();
99
        // Instantiate and add Slim specific extension
100
        $basePath = \rtrim(\str_ireplace($base_script_trailing_str, '', $request_basepath), '/');
101
102
        $this->addExtension(new \Slim\Views\TwigExtension($c['router'], $basePath));
103
104
        $this->offsetSet('subfolder', $c->subfolder);
105
        $this->offsetSet('theme', $this->misc->getConf('theme'));
106
        $this->offsetSet('Favicon', $this->icon('Favicon'));
107
        $this->offsetSet('Introduction', $this->icon('Introduction'));
108
        $this->offsetSet('lang', $this->lang);
109
110
        $this->offsetSet('applangdir', $this->lang['applangdir']);
111
112
        $this->offsetSet('appName', $c->get('settings')['appName']);
113
114
        $_theme = $this->getTheme($this->conf, $this->misc->getServerInfo());
115
116
        if (null !== $_theme && isset($_SESSION)) {
117
            /* save the selected theme in cookie for a year */
118
            @\setcookie('ppaTheme', $_theme, \time() + 31536000, '/');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for setcookie(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

118
            /** @scrutinizer ignore-unhandled */ @\setcookie('ppaTheme', $_theme, \time() + 31536000, '/');

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
119
            $_SESSION['ppaTheme'] = $_theme;
120
            $this->misc->setConf('theme', $_theme);
121
        }
122
    }
123
124
    public function maybeRenderIframes($response, $subject, $query_string)
125
    {
126
        $c = $this->getContainer();
127
128
        $in_test = $this->offsetGet('in_test');
129
130
        if ('1' === $in_test) {
131
            $className  = '\PHPPgAdmin\Controller\\' . \ucfirst($subject) . 'Controller';
132
            $controller = new $className($c);
133
134
            return $controller->render();
135
        }
136
137
        $viewVars = [
138
            'url'            => '/src/views/' . $subject . ($query_string ? '?' . $query_string : ''),
139
            'headertemplate' => 'header.twig',
140
        ];
141
142
        return $this->render($response, 'iframe_view.twig', $viewVars);
143
    }
144
145
    /**
146
     * Gets the theme from
147
     * 1. The $_REQUEST global (when it's chosen from start screen)
148
     * 2. Server specific config theme 3.- $_SESSION global (subsequent requests after 1.) 4.- $_COOKIE global (mostly
149
     *    fallback for $_SESSION after 1.- and 3.-) 5.- theme as set in config 6.- 'default' theme.
150
     *
151
     * @param array      $conf         The conf
152
     * @param null|mixed $_server_info
153
     *
154
     * @return string the theme
155
     */
156
    public function getTheme(array $conf, $_server_info = null)
157
    {
158
        $_theme = null;
159
        // List of themes
160
        $themefolders = $this->getThemeFolders();
161
        // Check if theme is in $_REQUEST, $_SESSION or $_COOKIE
162
        // 1.- First priority: $_REQUEST, this happens when you use the selector
163
        if (\array_key_exists('theme', $_REQUEST) &&
164
            \array_key_exists($_REQUEST['theme'], $themefolders)) {
165
            $_theme = $_REQUEST['theme'];
166
        } 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...
167
            null !== $_server_info &&
168
            \array_key_exists('theme', $_server_info) &&
169
            \is_string($_server_info['theme']) &&
170
            \array_key_exists($_COOKIE['ppaTheme'], $themefolders)) {
171
            $_theme = $_server_info['theme'];
172
        } elseif (isset($_SESSION) && \array_key_exists('ppaTheme', $_SESSION) &&
173
            \array_key_exists($_SESSION['ppaTheme'], $themefolders)) {
174
            // otherwise check $_SESSION
175
            $_theme = $_SESSION['ppaTheme'];
176
        } elseif (\array_key_exists('ppaTheme', $_COOKIE) &&
177
            \array_key_exists($_COOKIE['ppaTheme'], $themefolders)) {
178
            // oterwise check $_COOKIE
179
            $_theme = $_COOKIE['ppaTheme'];
180
        } 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...
181
            \array_key_exists('theme', $conf) &&
182
            \is_string($conf['theme']) &&
183
            \array_key_exists($conf['theme'], $themefolders)) {
184
            $_theme = $conf['theme'];
185
        } else {
186
            // okay then, use default theme
187
            $_theme = 'default';
188
        }
189
190
        return $_theme;
191
    }
192
193
    /**
194
     * Sets the form tracking variable.
195
     */
196
    public function setForm()
197
    {
198
        $form = [];
199
200
        if ($this->container->server) {
201
            $form[] = \sprintf(
202
                '<input type="hidden" name="%s" value="%s" />',
203
                'server',
204
                \htmlspecialchars($this->container->server)
205
            );
206
        }
207
208
        if ($this->container->database) {
209
            $form[] = \sprintf(
210
                '<input type="hidden" name="%s" value="%s" />',
211
                'database',
212
                \htmlspecialchars($this->container->database)
213
            );
214
        }
215
216
        if ($this->container->schema) {
217
            $form[] = \sprintf(
218
                '<input type="hidden" name="%s" value="%s" />',
219
                'schema',
220
                \htmlspecialchars($this->container->schema)
221
            );
222
        }
223
        $this->form = \implode("\n", $form);
224
225
        return $this->form;
226
    }
227
228
    /**
229
     * Displays link to the context help.
230
     *
231
     * @param string $str      the string that the context help is related to (already escaped)
232
     * @param string $help     help section identifier
233
     * @param bool   $do_print true to echo, false to return
234
     */
235
    public function printHelp($str, $help = null, $do_print = true)
236
    {
237
        if (null !== $help) {
238
            $helplink = $this->getHelpLink($help);
239
            $str .= '<a class="help" href="' . $helplink . '" title="' . $this->lang['strhelp'] . '" target="phppgadminhelp">';
240
            $str .= $this->lang['strhelpicon'] . '</a>';
241
        }
242
243
        if ($do_print) {
244
            echo $str;
245
        } else {
246
            return $str;
247
        }
248
    }
249
250
    /**
251
     * Gets the help link.
252
     *
253
     * @param string $help The help subject
254
     *
255
     * @return string the help link
256
     */
257
    public function getHelpLink($help)
258
    {
259
        return \htmlspecialchars(
260
            $this->getSubfolder('help?help=') .
261
            \urlencode($help) .
262
            '&server=' .
263
            \urlencode($this->misc->getServerId())
264
        );
265
    }
266
267
    public function icon($icon)
268
    {
269
        if (!\is_string($icon)) {
270
            return '';
271
        }
272
273
        $theme        = $this->conf['theme'];
274
        $path         = 'assets/images/themes';
275
        $default_icon = \sprintf('%s/%s/default/DisconnectedServer.png', self::SUBFOLDER, $path);
276
277
        if (\is_readable(\sprintf('%s/%s/%s/%s.png', self::BASE_PATH, $path, $theme, $icon))) {
278
            return \sprintf('%s/%s/%s/%s.png', self::SUBFOLDER, $path, $theme, $icon);
279
        }
280
281
        if (\is_readable(\sprintf('%s/%s/%s/%s.gif', self::BASE_PATH, $path, $theme, $icon))) {
282
            return \sprintf('%s/%s/%s/%s.gif', self::SUBFOLDER, $path, $theme, $icon);
283
        }
284
285
        if (\is_readable(\sprintf('%s/%s/%s/%s.ico', self::BASE_PATH, $path, $theme, $icon))) {
286
            return \sprintf('%s/%s/%s/%s.ico', self::SUBFOLDER, $path, $theme, $icon);
287
        }
288
289
        if (\is_readable(\sprintf('%s/%s/default/%s.png', self::BASE_PATH, $path, $icon))) {
290
            return \sprintf('%s/%s/default/%s.png', self::SUBFOLDER, $path, $icon);
291
        }
292
293
        if (\is_readable(\sprintf('%s/%s/default/%s.gif', self::BASE_PATH, $path, $icon))) {
294
            return \sprintf('%s/%s/default/%s.gif', self::SUBFOLDER, $path, $icon);
295
        }
296
297
        if (\is_readable(\sprintf('%s/%s/default/%s.ico', self::BASE_PATH, $path, $icon))) {
298
            return \sprintf('%s/%s/default/%s.ico', self::SUBFOLDER, $path, $icon);
299
        }
300
301
        return $default_icon;
302
    }
303
304
    private function getContainer()
305
    {
306
        return $this->container;
307
    }
308
309
    /**
310
     * Traverse THEME_PATH, consider as theme folders those which
311
     * contain a `global.css` stylesheet.
312
     *
313
     * @return array the theme folders
314
     */
315
    private function getThemeFolders()
316
    {
317
        // no THEME_PATH (how?) then return empty array
318
        if (!$gestor = \opendir(self::THEME_PATH)) {
319
            \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

319
            \closedir(/** @scrutinizer ignore-type */ $gestor);
Loading history...
320
321
            return [];
322
        }
323
        $themefolders = [];
324
325
        /* This is the right way to iterate on a folder */
326
        while (false !== ($foldername = \readdir($gestor))) {
327
            if ('.' === $foldername || '..' === $foldername) {
328
                continue;
329
            }
330
331
            $folderpath = \sprintf('%s%s%s', self::THEME_PATH, \DIRECTORY_SEPARATOR, $foldername);
332
            $stylesheet = \sprintf('%s%s%s', $folderpath, \DIRECTORY_SEPARATOR, 'global.css');
333
            // if $folderpath if indeed a folder and contains a global.css file, then it's a theme
334
            if (\is_dir($folderpath) &&
335
                \is_file($stylesheet)) {
336
                $themefolders[$foldername] = $folderpath;
337
            }
338
        }
339
340
        \closedir($gestor);
341
342
        return $themefolders;
343
    }
344
}
345