Issues (217)

src/classes/ContainerUtils.php (2 issues)

1
<?php
2
3
/**
4
 * PHPPgAdmin 6.1.3
5
 */
6
7
namespace PHPPgAdmin;
8
9
use Psr\Container\ContainerInterface;
10
use Slim\Collection;
11
use Slim\DefaultServicesProvider;
12
13
/**
14
 * @property array $deploy_info
15
 * @property \Slim\Flash\Messages $flash
16
 * @property \GuzzleHttp\Client $fcIntranetClient
17
 * @property \PHPPgAdmin\Misc $misc
18
 * @property \PHPPgAdmin\ViewManager $view
19
 * @property \Slim\Http\Request $request
20
 * @property \Slim\Http\Response $response
21
 * @property string $BASE_PATH
22
 * @property string $THEME_PATH
23
 * @property string $subFolder
24
 * @property bool $DEBUGMODE
25
 * @property bool $IN_TEST
26
 * @property string  $server
27
 * @property string $database
28
 * @property string  $schema
29
 * @property
30
 */
31
class ContainerUtils extends \Slim\Container implements ContainerInterface
32
{
33
    use \PHPPgAdmin\Traits\HelperTrait;
34
35
    /**
36
     * @var null|self
37
     */
38
    private static $instance;
39
40
    /**
41
     * $appInstance.
42
     *
43
     * @var null|\Slim\App
44
     */
45
    private static $appInstance;
46
47
    /**
48
     * Default settings.
49
     *
50
     * @var array
51
     */
52
    private $defaultSettings = [
53
        'httpVersion' => '1.1',
54
        'responseChunkSize' => 4096,
55
        'outputBuffering' => 'append',
56
        'determineRouteBeforeAppMiddleware' => false,
57
        'displayErrorDetails' => false,
58
        'addContentLengthHeader' => true,
59
        'routerCacheFile' => false,
60
    ];
61
62
    /**
63
     * Undocumented variable.
64
     *
65
     * @var array
66
     */
67
    private static $envConfig = [
68
        'BASE_PATH' => '',
69
        'subFolder' => '',
70
        'DEBUGMODE' => false,
71
        'THEME_PATH' => '',
72
    ];
73
74
    /**
75
     * @param array $values the parameters or objects
76
     */
77
    final public function __construct(array $values = [])
78
    {
79
        parent::__construct($values);
80
81
        $userSettings = $values['settings'] ?? [];
82
        $this->registerDefaultServices($userSettings);
83
84
        self::$instance = $this;
85
    }
86
87
    /**
88
     * Gets the subfolder.
89
     *
90
     * @param string $path The path
91
     *
92
     * @return string the subfolder
93
     */
94
    public function getSubfolder(string $path = ''): string
95
    {
96
        return \implode(\DIRECTORY_SEPARATOR, [$this->subFolder, $path]);
97
    }
98
99
    public static function getAppInstance(array $config = []): \Slim\App
100
    {
101
        $config = \array_merge(self::getDefaultConfig($config['debugmode'] ?? false), $config);
102
103
        $container = self::getContainerInstance($config);
104
105
        if (!self::$appInstance) {
106
            self::$appInstance = new \Slim\App($container);
107
        }
108
109
        return self::$appInstance;
110
    }
111
112
    public static function getContainerInstance(array $config = []): self
113
    {
114
        self::$envConfig = [
115
            'msg' => '',
116
            'appThemes' => [
117
                'default' => 'Default',
118
                'cappuccino' => 'Cappuccino',
119
                'gotar' => 'Blue/Green',
120
                'bootstrap' => 'Bootstrap3',
121
            ],
122
            'BASE_PATH' => $config['BASE_PATH'] ?? \dirname(__DIR__, 2),
123
            'subFolder' => $config['subfolder'] ?? '',
124
            'debug' => $config['debugmode'] ?? false,
125
            'THEME_PATH' => $config['theme_path'] ?? \dirname(__DIR__, 2) . '/assets/themes',
126
            'IN_TEST' => $config['IN_TEST'] ?? false,
127
            'webdbLastTab' => [],
128
        ];
129
130
        self::$envConfig = \array_merge(self::$envConfig, $config);
131
132
        if (!self::$instance) {
133
            self::$instance = new static(self::$envConfig);
134
135
            self::$instance
136
                ->withConf(self::$envConfig);
137
138
            $handlers = new ContainerHandlers(self::$instance);
139
            $handlers->setExtra()
140
                ->setMisc()
141
                ->setViews()
142
                ->storeMainRequestParams()
143
                ->setHaltHandler();
144
        }
145
        //ddd($container->subfolder);
146
        return self::$instance;
147
    }
148
149
    /**
150
     * Determines the redirection url according to query string.
151
     *
152
     * @return string the redirect url
153
     */
154
    public function getRedirectUrl()
155
    {
156
        $container = self::getContainerInstance();
157
        $query_string = $container->request->getUri()->getQuery();
158
159
        // if server_id isn't set, then you will be redirected to intro
160
        if (null === $container->request->getQueryParam('server')) {
161
            $destinationurl = self::$envConfig['subFolder'] . '/src/views/intro';
162
        } else {
163
            // otherwise, you'll be redirected to the login page for that server;
164
            $destinationurl = self::$envConfig['subFolder'] . '/src/views/login' . ($query_string ? '?' . $query_string : '');
165
        }
166
167
        return $destinationurl;
168
    }
169
170
    /**
171
     * Adds a flash message to the session that will be displayed on the next request.
172
     *
173
     * @param mixed  $content msg content (can be object, array, etc)
174
     * @param string $key     The key to associate with the message. Defaults to the stack
175
     *                        trace of the closure or method that called addFlassh
176
     */
177
    public function addFlash($content, $key = ''): void
178
    {
179
        if ('' === $key) {
180
            $key = self::getBackTrace();
181
        }
182
        $container = self::getContainerInstance();
183
        // $this->dump(__METHOD__ . ': addMessage ' . $key . '  ' . json_encode($content));
184
        if ($container->flash) {
185
            $container->flash->addMessage($key, $content);
0 ignored issues
show
It seems like $key can also be of type array<string,mixed|string>; however, parameter $key of Slim\Flash\Messages::addMessage() does only seem to accept string, 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

185
            $container->flash->addMessage(/** @scrutinizer ignore-type */ $key, $content);
Loading history...
186
        }
187
    }
188
189
    /**
190
     * Gets the destination with the last active tab selected for that controller
191
     * Usually used after going through a redirect route.
192
     *
193
     * @param string $subject The subject, usually a view name like 'server' or 'table'
194
     *
195
     * @return string The destination url with last tab set in the query string
196
     */
197
    public function getDestinationWithLastTab($subject)
198
    {
199
        $container = self::getContainerInstance();
200
        $_server_info = $container->misc->getServerInfo();
201
        $this->addFlash($subject, 'getDestinationWithLastTab');
202
        //$this->prtrace('$_server_info', $_server_info);
203
        // If username isn't set in server_info, you should login
204
        $url = $container->misc->getLastTabURL($subject) ?? ['url' => 'alldb', 'urlvars' => ['subject' => 'server']];
205
        $destinationurl = $this->getRedirectUrl();
206
207
        if (!isset($_server_info['username'])) {
208
            return $destinationurl;
209
        }
210
211
        if (!\is_array($url)) {
212
            return $this->getRedirectUrl($subject);
0 ignored issues
show
The call to PHPPgAdmin\ContainerUtils::getRedirectUrl() has too many arguments starting with $subject. ( Ignorable by Annotation )

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

212
            return $this->/** @scrutinizer ignore-call */ getRedirectUrl($subject);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
213
        }
214
        $this->addFlash($url, 'getLastTabURL for ' . $subject);
215
        // Load query vars into superglobal arrays
216
        if (isset($url['urlvars'])) {
217
            $urlvars = [];
218
219
            foreach ($url['urlvars'] as $key => $urlvar) {
220
                //$this->prtrace($key, $urlvar);
221
                $urlvars[$key] = \PHPPgAdmin\Decorators\Decorator::get_sanitized_value($urlvar, $_REQUEST);
222
            }
223
            $_REQUEST = \array_merge($_REQUEST, $urlvars);
224
            $_GET = \array_merge($_GET, $urlvars);
225
        }
226
        $actionurl = \PHPPgAdmin\Decorators\Decorator::actionurl($url['url'], $_GET);
227
        $destinationurl = $actionurl->value($_GET);
228
229
        return \str_replace('views/?', "views/{$subject}?", $destinationurl);
230
    }
231
232
    /**
233
     * Adds an error to the errors array property of the container.
234
     *
235
     * @param string $errormsg The error msg
236
     *
237
     * @return\Slim\Container The app container
238
     */
239
    public function addError(string $errormsg): \Slim\Container
240
    {
241
        $container = self::getContainerInstance();
242
        $errors = $container->get('errors');
243
        $errors[] = $errormsg;
244
        $container->offsetSet('errors', $errors);
245
246
        return $container;
247
    }
248
249
    /**
250
     * Returns a string with html <br> variant replaced with a new line.
251
     *
252
     * @param string $msg message to parse (<br> separated)
253
     *
254
     * @return string parsed message (linebreak separated)
255
     */
256
    public static function br2ln($msg)
257
    {
258
        return \str_replace(['<br>', '<br/>', '<br />'], \PHP_EOL, $msg);
259
    }
260
261
    public static function getDefaultConfig(bool $debug = false): array
262
    {
263
        return  [
264
            'settings' => [
265
                'displayErrorDetails' => $debug,
266
                'determineRouteBeforeAppMiddleware' => true,
267
                'base_path' => \dirname(__DIR__, 2),
268
                'debug' => $debug,
269
                'phpMinVer' => '7.2', // PHP minimum version
270
                'addContentLengthHeader' => false,
271
                'appName' => 'PHPPgAdmin6',
272
            ],
273
        ];
274
    }
275
276
    /**
277
     * @param array $conf
278
     */
279
    private function withConf($conf): self
280
    {
281
        $container = self::getContainerInstance();
282
        $conf['plugins'] = [];
283
284
        $container->BASE_PATH = $conf['BASE_PATH'];
285
        $container->subFolder = $conf['subfolder'];
286
        $container->debug = $conf['debugmode'];
287
        $container->THEME_PATH = $conf['theme_path'];
288
        $container->IN_TEST = $conf['IN_TEST'];
289
        $container['errors'] = [];
290
        $container['conf'] = static function (\Slim\Container $c) use ($conf): array {
291
            $display_sizes = $conf['display_sizes'];
292
293
            if (\is_array($display_sizes)) {
294
                $conf['display_sizes'] = [
295
                    'schemas' => (bool) isset($display_sizes['schemas']) && true === $display_sizes['schemas'],
296
                    'tables' => (bool) isset($display_sizes['tables']) && true === $display_sizes['tables'],
297
                ];
298
            } else {
299
                $conf['display_sizes'] = [
300
                    'schemas' => (bool) $display_sizes,
301
                    'tables' => (bool) $display_sizes,
302
                ];
303
            }
304
305
            if (!isset($conf['theme'])) {
306
                $conf['theme'] = 'default';
307
            }
308
309
            foreach ($conf['servers'] as &$server) {
310
                if (!isset($server['port'])) {
311
                    $server['port'] = 5432;
312
                }
313
314
                if (!isset($server['sslmode'])) {
315
                    $server['sslmode'] = 'unspecified';
316
                }
317
            }
318
319
            return $conf;
320
        };
321
322
        $container->subFolder = $conf['subfolder'];
323
324
        return $this;
325
    }
326
327
    /**
328
     * This function registers the default services that Slim needs to work.
329
     *
330
     * All services are shared, they are registered such that the
331
     * same instance is returned on subsequent calls.
332
     *
333
     * @param array $userSettings Associative array of application settings
334
     */
335
    private function registerDefaultServices($userSettings): void
336
    {
337
        $defaultSettings = $this->defaultSettings;
338
339
        /**
340
         * This service MUST return an array or an instance of ArrayAccess.
341
         *
342
         * @return array|ArrayAccess
343
         */
344
        $this['settings'] = static function () use ($userSettings, $defaultSettings): \Slim\Collection {
345
            return new Collection(\array_merge($defaultSettings, $userSettings));
346
        };
347
348
        $defaultProvider = new DefaultServicesProvider();
349
        $defaultProvider->register($this);
350
    }
351
}
352