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