Passed
Pull Request — develop (#340)
by Felipe
04:56
created

ViewManager::getControllerClassName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
/**
4
 * PHPPgAdmin 6.0.0
5
 */
6
7
namespace PHPPgAdmin;
8
9
10
/**
11
 * @file
12
 * Class to hold various commonly used functions
13
 *
14
 * Id: Misc.php,v 1.171 2008/03/17 21:35:48 ioguix Exp $
15
 */
16
17
/**
18
 * Class to hold various commonly used functions.
19
 *
20
 * Release: Misc.php,v 1.171 2008/03/17 21:35:48 ioguix Exp $
21
 */
22
class ViewManager extends \Slim\Views\Twig
23
{
24
    use \PHPPgAdmin\Traits\HelperTrait;
25
26
27
28
 
29
30
31
    /**
32
     * @var array
33
     */
34
    public $appLangFiles = [];
35
36
    /**
37
     * @var string
38
     */
39
    public $appName = '';
40
41
    /**
42
     * @var string
43
     */
44
    public $appVersion = '';
45
46
    /**
47
     * @var string
48
     */
49
    public $form = '';
50
51
    /**
52
     * @var string
53
     */
54
    public $href = '';
55
56
    /**
57
     * @var array
58
     */
59
    public $lang = [];
60
61
    /**
62
     * @var array
63
     */
64
    public $conf;
65
66
    /**
67
     * @var string
68
     * @psalm-suppress PropertyNotSetInConstructor
69
     */
70
    public $phpMinVer;
71
72
    /**
73
     * @var string
74
     * @psalm-suppress PropertyNotSetInConstructor
75
     */
76
    public $postgresqlMinVer;
77
78
    /**
79
     * @var \PHPPgAdmin\Misc
80
     */
81
    public $misc;
82
83
    /**
84
     * @var \PHPPgAdmin\ContainerUtils
85
     */
86
    protected $container;
87
88
    private $_connection;
0 ignored issues
show
introduced by
The private property $_connection is not used, and could be removed.
Loading history...
89
90
    /**
91
     * @var bool
92
     */
93
    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...
94
95
    /**
96
     * @var bool
97
     */
98
    private $_reload_browser = false;
0 ignored issues
show
introduced by
The private property $_reload_browser is not used, and could be removed.
Loading history...
99
100
    private $_data;
0 ignored issues
show
introduced by
The private property $_data is not used, and could be removed.
Loading history...
101
102
    private $_database;
0 ignored issues
show
introduced by
The private property $_database is not used, and could be removed.
Loading history...
103
104
    /**
105
     * @var string
106
     */
107
    private $_server_id;
0 ignored issues
show
introduced by
The private property $_server_id is not used, and could be removed.
Loading history...
108
109
    private $_server_info;
0 ignored issues
show
introduced by
The private property $_server_info is not used, and could be removed.
Loading history...
110
111
    /**
112
     * @var string
113
     */
114
    private $_error_msg = '';
0 ignored issues
show
introduced by
The private property $_error_msg is not used, and could be removed.
Loading history...
115
116
    /**
117
     * Undocumented variable.
118
     *
119
     * @var self
120
     */
121
    private static $instance;
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...
122
123
    /**
124
     * @param \PHPPgAdmin\ContainerUtils $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...
125
     * @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...
126
     * @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...
127
     * @param \PHPPgAdmin\ContainerUtils $c
128
     */
129
    public function __construct($path, $settings, \PHPPgAdmin\ContainerUtils $c)
130
    {
131
        $this->lang = $c->get('lang');
132
        $this->conf = $c->get('conf');
133
        $this->misc = $c->get('misc');
134
        parent::__construct($path, $settings);
135
        $this->container = $c;
136
        $environment = $c->get('environment');
137
        $base_script_trailing_str = \mb_substr($environment['SCRIPT_NAME'], 1);
138
        $request_basepath = $c['request']->getUri()->getBasePath();
139
        // Instantiate and add Slim specific extension
140
        $basePath = \rtrim(\str_ireplace($base_script_trailing_str, '', $request_basepath), '/');
141
142
        $this->addExtension(new \Slim\Views\TwigExtension($c['router'], $basePath));
143
144
        $this->offsetSet('subfolder', \containerInstance()->subFolder);
145
        $this->offsetSet('theme', $this->misc->getConf('theme'));
146
        $this->offsetSet('Favicon', $this->icon('Favicon'));
147
        $this->offsetSet('Introduction', $this->icon('Introduction'));
148
        $this->offsetSet('lang', $this->lang);
149
150
        $this->offsetSet('applangdir', $this->lang['applangdir']);
151
152
        $this->offsetSet('appName', $c->get('settings')['appName']);
153
154
        $_theme = $this->getTheme($this->conf, $this->misc->getServerInfo());
155
156
        if (isset($_SESSION) && !isset($_SESSION['ppaTheme'])) {
157
            /* save the selected theme in cookie for a year */
158
            \setcookie('ppaTheme', $_theme, \time() + 31536000, '/');
159
            $_SESSION['ppaTheme'] = $_theme;
160
            $this->misc->setConf('theme', $_theme);
161
        }
162
    }
163
164
    public function maybeRenderIframes(\Slim\Http\Response $response, string $subject, string $query_string): \Slim\Http\Response
165
    {
166
        $c = $this->getContainer();
167
168
        $in_test = $this->offsetGet('in_test');
169
170
        if ('1' === $in_test) {
171
            $className = self::getControllerClassName($subject);
172
            $controller = new $className($c);
173
174
            return $controller->render();
175
        }
176
177
        $viewVars = [
178
            'url' => '/src/views/' . $subject . ($query_string ? '?' . $query_string : ''),
179
            'headertemplate' => 'header.twig',
180
        ];
181
182
        return $this->render($response, 'iframe_view.twig', $viewVars);
183
    }
184
185
    /**
186
     * Gets the theme from
187
     * 1. The $_REQUEST global (when it's chosen from start screen)
188
     * 2. Server specific config theme 3.- $_SESSION global (subsequent requests after 1.) 4.- $_COOKIE global (mostly
189
     *    fallback for $_SESSION after 1.- and 3.-) 5.- theme as set in config 6.- 'default' theme.
190
     *
191
     * @param array      $conf         The conf
192
     * @param null|mixed $_server_info
193
     *
194
     * @return string the theme
195
     */
196
    public function getTheme(array $conf, $_server_info = null)
197
    {
198
        $_theme = 'default';
199
        // List of themes
200
        $themefolders = $this->getThemeFolders();
201
        // Check if theme is in $_REQUEST, $_SESSION or $_COOKIE
202
        // 1.- First priority: $_REQUEST, this happens when you use the selector
203
        if (\array_key_exists('theme', $_REQUEST) &&
204
            \array_key_exists($_REQUEST['theme'], $themefolders)) {
205
            $_theme = $_REQUEST['theme'];
206
        } 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...
207
            null !== $_server_info &&
208
            \array_key_exists('theme', $_server_info) &&
209
            \is_string($_server_info['theme']) &&
210
            \array_key_exists($_COOKIE['ppaTheme'], $themefolders)) {
211
            $_theme = $_server_info['theme'];
212
        } elseif (isset($_SESSION) && \array_key_exists('ppaTheme', $_SESSION) &&
213
            \array_key_exists($_SESSION['ppaTheme'], $themefolders)) {
214
            // otherwise check $_SESSION
215
            $_theme = $_SESSION['ppaTheme'];
216
        } elseif (\array_key_exists('ppaTheme', $_COOKIE) &&
217
            \array_key_exists($_COOKIE['ppaTheme'], $themefolders)) {
218
            // oterwise check $_COOKIE
219
            $_theme = $_COOKIE['ppaTheme'];
220
        } 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...
221
            \array_key_exists('theme', $conf) &&
222
            \is_string($conf['theme']) &&
223
            \array_key_exists($conf['theme'], $themefolders)) {
224
            $_theme = $conf['theme'];
225
        }
226
227
        return $_theme;
228
    }
229
230
    /**
231
     * Sets the form tracking variable.
232
     */
233
    public function setForm(): string
234
    {
235
        $form = [];
236
237
        if ($this->container->server) {
238
            $form[] = \sprintf(
239
                '<input type="hidden" name="%s" value="%s" />',
240
                'server',
241
                \htmlspecialchars($this->container->server)
242
            );
243
        }
244
245
        if ($this->container->database) {
246
            $form[] = \sprintf(
247
                '<input type="hidden" name="%s" value="%s" />',
248
                'database',
249
                \htmlspecialchars($this->container->database)
250
            );
251
        }
252
253
        if ($this->container->schema) {
254
            $form[] = \sprintf(
255
                '<input type="hidden" name="%s" value="%s" />',
256
                'schema',
257
                \htmlspecialchars($this->container->schema)
258
            );
259
        }
260
        $this->form = \implode("\n", $form);
261
262
        return $this->form;
263
    }
264
265
    /**
266
     * Displays link to the context help.
267
     *
268
     * @param string $str      the string that the context help is related to (already escaped)
269
     * @param string $help     help section identifier
270
     * @param bool   $do_print true to echo, false to return
271
     *
272
     * @return string|void
273
     */
274
    public function printHelp($str, $help = null, $do_print = true)
275
    {
276
        if (null !== $help) {
277
            $helplink = $this->getHelpLink($help);
278
            $str .= '<a class="help" href="' . $helplink . '" title="' . $this->lang['strhelp'] . '" target="phppgadminhelp">';
279
            $str .= $this->lang['strhelpicon'] . '</a>';
280
        }
281
282
        if ($do_print) {
283
            echo $str;
284
        } else {
285
            return $str;
286
        }
287
    }
288
289
    /**
290
     * Gets the help link.
291
     *
292
     * @param string $help The help subject
293
     *
294
     * @return string the help link
295
     */
296
    public function getHelpLink($help)
297
    {
298
        return \htmlspecialchars(
299
            $this->container->getSubfolder('help?help=') .
300
            \urlencode($help) .
301
            '&server=' .
302
            \urlencode($this->misc->getServerId())
303
        );
304
    }
305
306
    /**
307
     * @param string $icon
308
     *
309
     * @return string
310
     */
311
    public function icon($icon = ''): string
312
    {
313
        $icon = (string) ($icon ?? '');
314
315
        $theme = $this->conf['theme'];
316
        $path = 'assets/images/themes';
317
        $default_icon = \sprintf('%s/%s/default/DisconnectedServer.png', \containerInstance()->subFolder, $path);
318
319
        if (\is_readable(\sprintf('%s/%s/%s/%s.png', \containerInstance()->BASE_PATH, $path, $theme, $icon))) {
320
            return \sprintf('%s/%s/%s/%s.png', \containerInstance()->subFolder, $path, $theme, $icon);
321
        }
322
323
        if (\is_readable(\sprintf('%s/%s/%s/%s.gif', \containerInstance()->BASE_PATH, $path, $theme, $icon))) {
324
            return \sprintf('%s/%s/%s/%s.gif', \containerInstance()->subFolder, $path, $theme, $icon);
325
        }
326
327
        if (\is_readable(\sprintf('%s/%s/%s/%s.ico', \containerInstance()->BASE_PATH, $path, $theme, $icon))) {
328
            return \sprintf('%s/%s/%s/%s.ico', \containerInstance()->subFolder, $path, $theme, $icon);
329
        }
330
331
        if (\is_readable(\sprintf('%s/%s/default/%s.png', \containerInstance()->BASE_PATH, $path, $icon))) {
332
            return \sprintf('%s/%s/default/%s.png', \containerInstance()->subFolder, $path, $icon);
333
        }
334
335
        if (\is_readable(\sprintf('%s/%s/default/%s.gif', \containerInstance()->BASE_PATH, $path, $icon))) {
336
            return \sprintf('%s/%s/default/%s.gif', \containerInstance()->subFolder, $path, $icon);
337
        }
338
339
        if (\is_readable(\sprintf('%s/%s/default/%s.ico', \containerInstance()->BASE_PATH, $path, $icon))) {
340
            return \sprintf('%s/%s/default/%s.ico', \containerInstance()->subFolder, $path, $icon);
341
        }
342
343
        return $default_icon;
344
    }
345
346
    /**
347
     * Undocumented function.
348
     *
349
     * @param string $subject
350
     * @psalm-suppress LessSpecificReturnStatement
0 ignored issues
show
Coding Style introduced by
Tag @psalm-suppress cannot be grouped with parameter tags in a doc comment
Loading history...
351
     * @psalm-suppress MoreSpecificReturnType
0 ignored issues
show
Coding Style introduced by
Tag @psalm-suppress cannot be grouped with parameter tags in a doc comment
Loading history...
352
     *
353
     * @return class-string
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
354
     */
355
    private static function getControllerClassName(string $subject): string
356
    {
357
        return '\PHPPgAdmin\Controller\\' . \ucfirst($subject) . 'Controller';
358
    }
359
360
    private function getContainer(): \PHPPgAdmin\ContainerUtils
361
    {
362
        return $this->container;
363
    }
364
365
    /**
366
     * Traverse THEME_PATH, consider as theme folders those which
367
     * contain a `global.css` stylesheet.
368
     *
369
     * @return array the theme folders
370
     */
371
    private function getThemeFolders(): array
372
    {
373
        // no THEME_PATH (how?) then return empty array
374
        if (!$gestor = \opendir(containerInstance()->THEME_PATH)) {
375
            \closedir($gestor);
376
377
            return [];
378
        }
379
        $themefolders = [];
380
381
        /* This is the right way to iterate on a folder */
382
        while (false !== ($foldername = \readdir($gestor))) {
383
            if ('.' === $foldername || '..' === $foldername) {
384
                continue;
385
            }
386
387
            $folderpath = \sprintf('%s%s%s', \containerInstance()->THEME_PATH, \DIRECTORY_SEPARATOR, $foldername);
388
            $stylesheet = \sprintf('%s%s%s', $folderpath, \DIRECTORY_SEPARATOR, 'global.css');
389
            // if $folderpath if indeed a folder and contains a global.css file, then it's a theme
390
            if (\is_dir($folderpath) &&
391
                \is_file($stylesheet)) {
392
                $themefolders[$foldername] = $folderpath;
393
            }
394
        }
395
396
        \closedir($gestor);
397
398
        return $themefolders;
399
    }
400
}
401