1 | <?php |
||||
2 | /** |
||||
3 | * Config file management |
||||
4 | */ |
||||
5 | |||||
6 | declare(strict_types=1); |
||||
7 | |||||
8 | namespace PhpMyAdmin\Config; |
||||
9 | |||||
10 | use PhpMyAdmin\Config; |
||||
11 | use PhpMyAdmin\Core; |
||||
12 | use PhpMyAdmin\Current; |
||||
13 | |||||
14 | use function __; |
||||
15 | use function _pgettext; |
||||
16 | use function array_diff; |
||||
17 | use function array_flip; |
||||
18 | use function array_keys; |
||||
19 | use function array_merge; |
||||
20 | use function count; |
||||
21 | use function is_array; |
||||
22 | use function preg_replace; |
||||
23 | |||||
24 | /** |
||||
25 | * Config file management class. |
||||
26 | * Stores its data in $_SESSION |
||||
27 | */ |
||||
28 | class ConfigFile |
||||
29 | { |
||||
30 | /** |
||||
31 | * Stores default phpMyAdmin config |
||||
32 | * |
||||
33 | * @see Settings |
||||
34 | * |
||||
35 | * @var mixed[] |
||||
36 | */ |
||||
37 | private array $defaultCfg; |
||||
38 | |||||
39 | /** |
||||
40 | * Stores allowed values for non-standard fields |
||||
41 | * |
||||
42 | * @var array<string, string|mixed[]> |
||||
43 | */ |
||||
44 | private array $cfgDb; |
||||
45 | |||||
46 | /** |
||||
47 | * Whether we are currently working in PMA Setup context |
||||
48 | */ |
||||
49 | private bool $isInSetup; |
||||
50 | |||||
51 | /** |
||||
52 | * Keys which will be always written to config file |
||||
53 | * |
||||
54 | * @var mixed[] |
||||
55 | */ |
||||
56 | private array $persistKeys = []; |
||||
57 | |||||
58 | /** |
||||
59 | * Changes keys while updating config in {@link updateWithGlobalConfig()} |
||||
60 | * or reading by {@link getConfig()} or {@link getConfigArray()} |
||||
61 | * |
||||
62 | * @var mixed[] |
||||
63 | */ |
||||
64 | private array $cfgUpdateReadMapping = []; |
||||
65 | |||||
66 | /** |
||||
67 | * Key filter for {@link set()} |
||||
68 | */ |
||||
69 | private array|null $setFilter = null; |
||||
70 | |||||
71 | /** |
||||
72 | * Instance id (key in $_SESSION array, separate for each server - |
||||
73 | * ConfigFile{server id}) |
||||
74 | */ |
||||
75 | private string $id; |
||||
76 | |||||
77 | /** |
||||
78 | * @param mixed[]|null $baseConfig base configuration read from |
||||
79 | {@link PhpMyAdmin\Config::$base_config}, |
||||
80 | use only when not in PMA Setup |
||||
81 | Stores original PMA config, not modified by user preferences |
||||
82 | */ |
||||
83 | 72 | public function __construct(private array|null $baseConfig = null) |
|||
84 | { |
||||
85 | // load default config values |
||||
86 | 72 | $settings = new Settings([]); |
|||
87 | 72 | $this->defaultCfg = $settings->asArray(); |
|||
88 | |||||
89 | // load additional config information |
||||
90 | 72 | $this->cfgDb = $this->getAllowedValues(); |
|||
91 | 72 | $this->isInSetup = $baseConfig === null; |
|||
92 | 72 | $this->id = 'ConfigFile' . Current::$server; |
|||
93 | 72 | if (isset($_SESSION[$this->id])) { |
|||
94 | 4 | return; |
|||
95 | } |
||||
96 | |||||
97 | 72 | $_SESSION[$this->id] = []; |
|||
98 | } |
||||
99 | |||||
100 | /** |
||||
101 | * Sets names of config options which will be placed in config file even if |
||||
102 | * they are set to their default values (use only full paths) |
||||
103 | * |
||||
104 | * @param mixed[] $keys the names of the config options |
||||
105 | */ |
||||
106 | 8 | public function setPersistKeys(array $keys): void |
|||
107 | { |
||||
108 | // checking key presence is much faster than searching so move values |
||||
109 | // to keys |
||||
110 | 8 | $this->persistKeys = array_flip($keys); |
|||
111 | } |
||||
112 | |||||
113 | /** |
||||
114 | * Returns flipped array set by {@link setPersistKeys()} |
||||
115 | * |
||||
116 | * @return mixed[] |
||||
117 | */ |
||||
118 | public function getPersistKeysMap(): array |
||||
119 | { |
||||
120 | return $this->persistKeys; |
||||
121 | } |
||||
122 | |||||
123 | /** |
||||
124 | * By default ConfigFile allows setting of all configuration keys, use |
||||
125 | * this method to set up a filter on {@link set()} method |
||||
126 | * |
||||
127 | * @param mixed[]|null $keys array of allowed keys or null to remove filter |
||||
128 | */ |
||||
129 | 4 | public function setAllowedKeys(array|null $keys): void |
|||
130 | { |
||||
131 | 4 | if ($keys === null) { |
|||
0 ignored issues
–
show
introduced
by
Loading history...
|
|||||
132 | 4 | $this->setFilter = null; |
|||
133 | |||||
134 | 4 | return; |
|||
135 | } |
||||
136 | |||||
137 | // checking key presence is much faster than searching so move values |
||||
138 | // to keys |
||||
139 | 4 | $this->setFilter = array_flip($keys); |
|||
140 | } |
||||
141 | |||||
142 | /** |
||||
143 | * Sets path mapping for updating config in |
||||
144 | * {@link updateWithGlobalConfig()} or reading |
||||
145 | * by {@link getConfig()} or {@link getConfigArray()} |
||||
146 | * |
||||
147 | * @param mixed[] $mapping Contains the mapping of "Server/config options" |
||||
148 | * to "Server/1/config options" |
||||
149 | */ |
||||
150 | 4 | public function setCfgUpdateReadMapping(array $mapping): void |
|||
151 | { |
||||
152 | 4 | $this->cfgUpdateReadMapping = $mapping; |
|||
153 | } |
||||
154 | |||||
155 | /** |
||||
156 | * Resets configuration data |
||||
157 | */ |
||||
158 | 8 | public function resetConfigData(): void |
|||
159 | { |
||||
160 | 8 | $_SESSION[$this->id] = []; |
|||
161 | } |
||||
162 | |||||
163 | /** |
||||
164 | * Sets configuration data (overrides old data) |
||||
165 | * |
||||
166 | * @param mixed[] $cfg Configuration options |
||||
167 | */ |
||||
168 | 72 | public function setConfigData(array $cfg): void |
|||
169 | { |
||||
170 | 72 | $_SESSION[$this->id] = $cfg; |
|||
171 | } |
||||
172 | |||||
173 | /** |
||||
174 | * Sets config value |
||||
175 | */ |
||||
176 | 56 | public function set(string $path, mixed $value, string|null $canonicalPath = null): void |
|||
177 | { |
||||
178 | 56 | if ($canonicalPath === null) { |
|||
179 | 52 | $canonicalPath = $this->getCanonicalPath($path); |
|||
180 | } |
||||
181 | |||||
182 | 56 | if ($this->setFilter !== null && ! isset($this->setFilter[$canonicalPath])) { |
|||
183 | 4 | return; |
|||
184 | } |
||||
185 | |||||
186 | // if the path isn't protected it may be removed |
||||
187 | 56 | if (isset($this->persistKeys[$canonicalPath])) { |
|||
188 | 4 | Core::arrayWrite($path, $_SESSION[$this->id], $value); |
|||
189 | |||||
190 | 4 | return; |
|||
191 | } |
||||
192 | |||||
193 | 56 | $defaultValue = $this->getDefault($canonicalPath); |
|||
194 | 56 | if ($this->isInSetup) { |
|||
195 | // remove if it has a default value or is empty |
||||
196 | 52 | $removePath = $value === $defaultValue || empty($value) && empty($defaultValue); |
|||
197 | } else { |
||||
198 | // get original config values not overwritten by user |
||||
199 | // preferences to allow for overwriting options set in |
||||
200 | // config.inc.php with default values |
||||
201 | 4 | $instanceDefaultValue = Core::arrayRead($canonicalPath, $this->baseConfig); |
|||
0 ignored issues
–
show
It seems like
$this->baseConfig can also be of type null ; however, parameter $array of PhpMyAdmin\Core::arrayRead() does only seem to accept array , 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
Loading history...
|
|||||
202 | // remove if it has a default value and base config (config.inc.php) |
||||
203 | // uses default value |
||||
204 | 4 | $removePath = $value === $defaultValue && $instanceDefaultValue === $defaultValue; |
|||
205 | } |
||||
206 | |||||
207 | 56 | if ($removePath) { |
|||
208 | 20 | Core::arrayRemove($path, $_SESSION[$this->id]); |
|||
209 | |||||
210 | 20 | return; |
|||
211 | } |
||||
212 | |||||
213 | 48 | Core::arrayWrite($path, $_SESSION[$this->id], $value); |
|||
214 | } |
||||
215 | |||||
216 | /** |
||||
217 | * Flattens multidimensional array, changes indices to paths |
||||
218 | * (eg. 'key/subkey'). |
||||
219 | * |
||||
220 | * @param mixed[] $array Multidimensional array |
||||
221 | * @param string $prefix Prefix |
||||
222 | * |
||||
223 | * @return mixed[] |
||||
224 | */ |
||||
225 | 36 | private function getFlatArray(array $array, string $prefix = ''): array |
|||
226 | { |
||||
227 | 36 | $result = []; |
|||
228 | 36 | foreach ($array as $key => $value) { |
|||
229 | 28 | if (is_array($value) && ! isset($value[0])) { |
|||
230 | 16 | $result += $this->getFlatArray($value, $prefix . $key . '/'); |
|||
231 | } else { |
||||
232 | 28 | $result[$prefix . $key] = $value; |
|||
233 | } |
||||
234 | } |
||||
235 | |||||
236 | 36 | return $result; |
|||
237 | } |
||||
238 | |||||
239 | /** |
||||
240 | * Returns default config in a flattened array |
||||
241 | * |
||||
242 | * @return mixed[] |
||||
243 | */ |
||||
244 | 4 | public function getFlatDefaultConfig(): array |
|||
245 | { |
||||
246 | 4 | return $this->getFlatArray($this->defaultCfg); |
|||
247 | } |
||||
248 | |||||
249 | /** |
||||
250 | * Updates config with values read from given array |
||||
251 | * (config will contain differences to defaults from {@see \PhpMyAdmin\Config\Settings}). |
||||
252 | * |
||||
253 | * @param mixed[] $cfg Configuration |
||||
254 | */ |
||||
255 | 12 | public function updateWithGlobalConfig(array $cfg): void |
|||
256 | { |
||||
257 | // load config array and flatten it |
||||
258 | 12 | $flatConfig = $this->getFlatArray($cfg); |
|||
259 | |||||
260 | // save values map for translating a few user preferences paths, |
||||
261 | // should be complemented by code reading from generated config |
||||
262 | // to perform inverse mapping |
||||
263 | 12 | foreach ($flatConfig as $path => $value) { |
|||
264 | 12 | if (isset($this->cfgUpdateReadMapping[$path])) { |
|||
265 | 4 | $path = $this->cfgUpdateReadMapping[$path]; |
|||
266 | } |
||||
267 | |||||
268 | 12 | $this->set($path, $value, $path); |
|||
269 | } |
||||
270 | } |
||||
271 | |||||
272 | /** |
||||
273 | * Returns config value or $default if it's not set |
||||
274 | * |
||||
275 | * @param string $path Path of config file |
||||
276 | * @param mixed $default Default values |
||||
277 | */ |
||||
278 | 16 | public function get(string $path, mixed $default = null): mixed |
|||
279 | { |
||||
280 | 16 | return Core::arrayRead($path, $_SESSION[$this->id], $default); |
|||
281 | } |
||||
282 | |||||
283 | /** |
||||
284 | * Returns default config value or $default it it's not set ie. it doesn't |
||||
285 | * exist in {@see \PhpMyAdmin\Config\Settings} ($cfg). |
||||
286 | * |
||||
287 | * @param string $canonicalPath Canonical path |
||||
288 | * @param mixed $default Default value |
||||
289 | */ |
||||
290 | 64 | public function getDefault(string $canonicalPath, mixed $default = null): mixed |
|||
291 | { |
||||
292 | 64 | return Core::arrayRead($canonicalPath, $this->defaultCfg, $default); |
|||
293 | } |
||||
294 | |||||
295 | /** |
||||
296 | * Returns config value, if it's not set uses the default one; returns |
||||
297 | * $default if the path isn't set and doesn't contain a default value |
||||
298 | * |
||||
299 | * @param string $path Path |
||||
300 | * @param mixed $default Default value |
||||
301 | */ |
||||
302 | 4 | public function getValue(string $path, mixed $default = null): mixed |
|||
303 | { |
||||
304 | 4 | $v = Core::arrayRead($path, $_SESSION[$this->id]); |
|||
305 | 4 | if ($v !== null) { |
|||
306 | 4 | return $v; |
|||
307 | } |
||||
308 | |||||
309 | 4 | $path = $this->getCanonicalPath($path); |
|||
310 | |||||
311 | 4 | return $this->getDefault($path, $default); |
|||
312 | } |
||||
313 | |||||
314 | /** |
||||
315 | * Returns canonical path |
||||
316 | * |
||||
317 | * @param string $path Path |
||||
318 | */ |
||||
319 | 60 | public function getCanonicalPath(string $path): string |
|||
320 | { |
||||
321 | 60 | return preg_replace('#^Servers/([\d]+)/#', 'Servers/1/', $path); |
|||
322 | } |
||||
323 | |||||
324 | /** |
||||
325 | * Returns config database entry for $path |
||||
326 | * |
||||
327 | * @param string $path path of the variable in config db |
||||
328 | * @param mixed $default default value |
||||
329 | */ |
||||
330 | 4 | public function getDbEntry(string $path, mixed $default = null): mixed |
|||
331 | { |
||||
332 | 4 | return Core::arrayRead($path, $this->cfgDb, $default); |
|||
333 | } |
||||
334 | |||||
335 | /** |
||||
336 | * Returns server count |
||||
337 | */ |
||||
338 | 4 | public function getServerCount(): int |
|||
339 | { |
||||
340 | 4 | return isset($_SESSION[$this->id]['Servers']) |
|||
341 | 4 | ? count($_SESSION[$this->id]['Servers']) |
|||
342 | 4 | : 0; |
|||
343 | } |
||||
344 | |||||
345 | /** |
||||
346 | * Returns server list |
||||
347 | * |
||||
348 | * @return mixed[] |
||||
349 | */ |
||||
350 | 4 | public function getServers(): array |
|||
351 | { |
||||
352 | 4 | return $_SESSION[$this->id]['Servers'] ?? []; |
|||
353 | } |
||||
354 | |||||
355 | /** |
||||
356 | * Returns DSN of given server |
||||
357 | * |
||||
358 | * @param int $server server index |
||||
359 | */ |
||||
360 | 4 | public function getServerDSN(int $server): string |
|||
361 | { |
||||
362 | 4 | if (! isset($_SESSION[$this->id]['Servers'][$server])) { |
|||
363 | 4 | return ''; |
|||
364 | } |
||||
365 | |||||
366 | 4 | $path = 'Servers/' . $server; |
|||
367 | 4 | $dsn = 'mysqli://'; |
|||
368 | 4 | if ($this->getValue($path . '/auth_type') === 'config') { |
|||
369 | 4 | $dsn .= $this->getValue($path . '/user'); |
|||
370 | 4 | if (! empty($this->getValue($path . '/password'))) { |
|||
371 | 4 | $dsn .= ':***'; |
|||
372 | } |
||||
373 | |||||
374 | 4 | $dsn .= '@'; |
|||
375 | } |
||||
376 | |||||
377 | 4 | if ($this->getValue($path . '/host') !== 'localhost') { |
|||
378 | 4 | $dsn .= $this->getValue($path . '/host'); |
|||
379 | 4 | $port = $this->getValue($path . '/port'); |
|||
380 | 4 | if ($port) { |
|||
381 | 4 | $dsn .= ':' . $port; |
|||
382 | } |
||||
383 | } else { |
||||
384 | 4 | $dsn .= $this->getValue($path . '/socket'); |
|||
385 | } |
||||
386 | |||||
387 | 4 | return $dsn; |
|||
388 | } |
||||
389 | |||||
390 | /** |
||||
391 | * Returns server name |
||||
392 | * |
||||
393 | * @param int $id server index |
||||
394 | */ |
||||
395 | 4 | public function getServerName(int $id): string |
|||
396 | { |
||||
397 | 4 | if (! isset($_SESSION[$this->id]['Servers'][$id])) { |
|||
398 | 4 | return ''; |
|||
399 | } |
||||
400 | |||||
401 | 4 | $verbose = $this->get('Servers/' . $id . '/verbose'); |
|||
402 | 4 | if (! empty($verbose)) { |
|||
403 | 4 | return $verbose; |
|||
404 | } |
||||
405 | |||||
406 | 4 | $host = $this->get('Servers/' . $id . '/host'); |
|||
407 | |||||
408 | 4 | return empty($host) ? 'localhost' : $host; |
|||
409 | } |
||||
410 | |||||
411 | /** |
||||
412 | * Removes server |
||||
413 | * |
||||
414 | * @param int $server server index |
||||
415 | */ |
||||
416 | 4 | public function removeServer(int $server): void |
|||
417 | { |
||||
418 | 4 | if (! isset($_SESSION[$this->id]['Servers'][$server])) { |
|||
419 | return; |
||||
420 | } |
||||
421 | |||||
422 | 4 | $lastServer = $this->getServerCount(); |
|||
423 | |||||
424 | /** @infection-ignore-all */ |
||||
425 | 4 | for ($i = $server; $i < $lastServer; $i++) { |
|||
426 | 4 | $_SESSION[$this->id]['Servers'][$i] = $_SESSION[$this->id]['Servers'][$i + 1]; |
|||
427 | } |
||||
428 | |||||
429 | 4 | unset($_SESSION[$this->id]['Servers'][$lastServer]); |
|||
430 | |||||
431 | 4 | if (! isset($_SESSION[$this->id]['ServerDefault']) || $_SESSION[$this->id]['ServerDefault'] != $lastServer) { |
|||
432 | 4 | return; |
|||
433 | } |
||||
434 | |||||
435 | 4 | unset($_SESSION[$this->id]['ServerDefault']); |
|||
436 | } |
||||
437 | |||||
438 | /** |
||||
439 | * Returns configuration array (full, multidimensional format) |
||||
440 | * |
||||
441 | * @return mixed[] |
||||
442 | */ |
||||
443 | 40 | public function getConfig(): array |
|||
444 | { |
||||
445 | 40 | $c = $_SESSION[$this->id]; |
|||
446 | 40 | foreach ($this->cfgUpdateReadMapping as $mapTo => $mapFrom) { |
|||
447 | // if the key $c exists in $map_to |
||||
448 | 4 | if (Core::arrayRead($mapTo, $c) === null) { |
|||
449 | 4 | continue; |
|||
450 | } |
||||
451 | |||||
452 | Core::arrayWrite($mapTo, $c, Core::arrayRead($mapFrom, $c)); |
||||
453 | Core::arrayRemove($mapFrom, $c); |
||||
454 | } |
||||
455 | |||||
456 | 40 | return $c; |
|||
457 | } |
||||
458 | |||||
459 | /** |
||||
460 | * Returns configuration array (flat format) |
||||
461 | * |
||||
462 | * @return mixed[] |
||||
463 | */ |
||||
464 | 20 | public function getConfigArray(): array |
|||
465 | { |
||||
466 | 20 | $c = $this->getFlatArray($_SESSION[$this->id]); |
|||
467 | |||||
468 | 20 | $persistKeys = array_diff( |
|||
469 | 20 | array_keys($this->persistKeys), |
|||
470 | 20 | array_keys($c), |
|||
471 | 20 | ); |
|||
472 | 20 | foreach ($persistKeys as $k) { |
|||
473 | 8 | $c[$k] = $this->getDefault($this->getCanonicalPath($k)); |
|||
474 | } |
||||
475 | |||||
476 | 20 | foreach ($this->cfgUpdateReadMapping as $mapTo => $mapFrom) { |
|||
477 | if (! isset($c[$mapFrom])) { |
||||
478 | continue; |
||||
479 | } |
||||
480 | |||||
481 | $c[$mapTo] = $c[$mapFrom]; |
||||
482 | unset($c[$mapFrom]); |
||||
483 | } |
||||
484 | |||||
485 | 20 | return $c; |
|||
486 | } |
||||
487 | |||||
488 | /** |
||||
489 | * Database with allowed values for configuration stored in the $cfg array, |
||||
490 | * used by setup script and user preferences to generate forms. |
||||
491 | * |
||||
492 | * Value meaning: |
||||
493 | * array - select field, array contains allowed values |
||||
494 | * string - type override |
||||
495 | * |
||||
496 | * @return array<string, string|mixed[]> |
||||
497 | */ |
||||
498 | 72 | public function getAllowedValues(): array |
|||
499 | { |
||||
500 | 72 | $config = Config::getInstance(); |
|||
0 ignored issues
–
show
The function
PhpMyAdmin\Config::getInstance() has been deprecated: Use dependency injection instead.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.
Loading history...
|
|||||
501 | |||||
502 | 72 | return [ |
|||
503 | 72 | 'Servers' => [ |
|||
504 | 72 | 1 => [ |
|||
505 | 72 | 'port' => 'integer', |
|||
506 | 72 | 'auth_type' => ['config', 'http', 'signon', 'cookie'], |
|||
507 | 72 | 'AllowDeny' => ['order' => ['', 'deny,allow', 'allow,deny', 'explicit']], |
|||
508 | 72 | 'only_db' => 'array', |
|||
509 | 72 | ], |
|||
510 | 72 | ], |
|||
511 | 72 | 'RecodingEngine' => ['auto', 'iconv', 'mb', 'none'], |
|||
512 | 72 | 'OBGzip' => ['auto', true, false], |
|||
513 | 72 | 'MemoryLimit' => 'short_string', |
|||
514 | 72 | 'NavigationLogoLinkWindow' => ['main', 'new'], |
|||
515 | 72 | 'NavigationTreeDefaultTabTable' => [ |
|||
516 | // fields list |
||||
517 | 72 | 'structure' => __('Structure'), |
|||
518 | // SQL form |
||||
519 | 72 | 'sql' => __('SQL'), |
|||
520 | // search page |
||||
521 | 72 | 'search' => __('Search'), |
|||
522 | // insert row page |
||||
523 | 72 | 'insert' => __('Insert'), |
|||
524 | // browse page |
||||
525 | 72 | 'browse' => __('Browse'), |
|||
526 | 72 | ], |
|||
527 | 72 | 'NavigationTreeDefaultTabTable2' => [ |
|||
528 | //don't display |
||||
529 | 72 | '' => '', |
|||
530 | // fields list |
||||
531 | 72 | 'structure' => __('Structure'), |
|||
532 | // SQL form |
||||
533 | 72 | 'sql' => __('SQL'), |
|||
534 | // search page |
||||
535 | 72 | 'search' => __('Search'), |
|||
536 | // insert row page |
||||
537 | 72 | 'insert' => __('Insert'), |
|||
538 | // browse page |
||||
539 | 72 | 'browse' => __('Browse'), |
|||
540 | 72 | ], |
|||
541 | 72 | 'NavigationTreeDbSeparator' => 'short_string', |
|||
542 | 72 | 'NavigationTreeTableSeparator' => 'short_string', |
|||
543 | 72 | 'NavigationWidth' => 'integer', |
|||
544 | 72 | 'TableNavigationLinksMode' => ['icons' => __('Icons'), 'text' => __('Text'), 'both' => __('Both')], |
|||
545 | 72 | 'MaxRows' => [25, 50, 100, 250, 500], |
|||
546 | 72 | 'Order' => ['ASC', 'DESC', 'SMART'], |
|||
547 | 72 | 'RowActionLinks' => [ |
|||
548 | 72 | 'none' => __('Nowhere'), |
|||
549 | 72 | 'left' => __('Left'), |
|||
550 | 72 | 'right' => __('Right'), |
|||
551 | 72 | 'both' => __('Both'), |
|||
552 | 72 | ], |
|||
553 | 72 | 'TablePrimaryKeyOrder' => ['NONE' => __('None'), 'ASC' => __('Ascending'), 'DESC' => __('Descending')], |
|||
554 | 72 | 'ProtectBinary' => [false, 'blob', 'noblob', 'all'], |
|||
555 | 72 | 'CharEditing' => ['input', 'textarea'], |
|||
556 | 72 | 'TabsMode' => ['icons' => __('Icons'), 'text' => __('Text'), 'both' => __('Both')], |
|||
557 | 72 | 'PDFDefaultPageSize' => [ |
|||
558 | 72 | 'A3' => 'A3', |
|||
559 | 72 | 'A4' => 'A4', |
|||
560 | 72 | 'A5' => 'A5', |
|||
561 | 72 | 'letter' => 'letter', |
|||
562 | 72 | 'legal' => 'legal', |
|||
563 | 72 | ], |
|||
564 | 72 | 'ActionLinksMode' => ['icons' => __('Icons'), 'text' => __('Text'), 'both' => __('Both')], |
|||
565 | 72 | 'GridEditing' => [ |
|||
566 | 72 | 'click' => __('Click'), |
|||
567 | 72 | 'double-click' => __('Double click'), |
|||
568 | 72 | 'disabled' => __('Disabled'), |
|||
569 | 72 | ], |
|||
570 | 72 | 'RelationalDisplay' => ['K' => __('key'), 'D' => __('display column')], |
|||
571 | 72 | 'DefaultTabServer' => [ |
|||
572 | // the welcome page (recommended for multiuser setups) |
||||
573 | 72 | 'welcome' => __('Welcome'), |
|||
574 | // list of databases |
||||
575 | 72 | 'databases' => __('Databases'), |
|||
576 | // runtime information |
||||
577 | 72 | 'status' => __('Status'), |
|||
578 | // MySQL server variables |
||||
579 | 72 | 'variables' => __('Variables'), |
|||
580 | // user management |
||||
581 | 72 | 'privileges' => __('Privileges'), |
|||
582 | 72 | ], |
|||
583 | 72 | 'DefaultTabDatabase' => [ |
|||
584 | // tables list |
||||
585 | 72 | 'structure' => __('Structure'), |
|||
586 | // SQL form |
||||
587 | 72 | 'sql' => __('SQL'), |
|||
588 | // search query |
||||
589 | 72 | 'search' => __('Search'), |
|||
590 | // operations on database |
||||
591 | 72 | 'operations' => __('Operations'), |
|||
592 | 72 | ], |
|||
593 | 72 | 'DefaultTabTable' => [ |
|||
594 | // fields list |
||||
595 | 72 | 'structure' => __('Structure'), |
|||
596 | // SQL form |
||||
597 | 72 | 'sql' => __('SQL'), |
|||
598 | // search page |
||||
599 | 72 | 'search' => __('Search'), |
|||
600 | // insert row page |
||||
601 | 72 | 'insert' => __('Insert'), |
|||
602 | // browse page |
||||
603 | 72 | 'browse' => __('Browse'), |
|||
604 | 72 | ], |
|||
605 | 72 | 'InitialSlidersState' => ['open' => __('Open'), 'closed' => __('Closed'), 'disabled' => __('Disabled')], |
|||
606 | 72 | 'FirstDayOfCalendar' => [ |
|||
607 | 72 | 1 => _pgettext('Week day name', 'Monday'), |
|||
608 | 72 | 2 => _pgettext('Week day name', 'Tuesday'), |
|||
609 | 72 | 3 => _pgettext('Week day name', 'Wednesday'), |
|||
610 | 72 | 4 => _pgettext('Week day name', 'Thursday'), |
|||
611 | 72 | 5 => _pgettext('Week day name', 'Friday'), |
|||
612 | 72 | 6 => _pgettext('Week day name', 'Saturday'), |
|||
613 | 72 | 7 => _pgettext('Week day name', 'Sunday'), |
|||
614 | 72 | ], |
|||
615 | 72 | 'SendErrorReports' => [ |
|||
616 | 72 | 'ask' => __('Ask before sending error reports'), |
|||
617 | 72 | 'always' => __('Always send error reports'), |
|||
618 | 72 | 'never' => __('Never send error reports'), |
|||
619 | 72 | ], |
|||
620 | 72 | 'DefaultForeignKeyChecks' => [ |
|||
621 | 72 | 'default' => __('Server default'), |
|||
622 | 72 | 'enable' => __('Enable'), |
|||
623 | 72 | 'disable' => __('Disable'), |
|||
624 | 72 | ], |
|||
625 | |||||
626 | 72 | 'Import' => [ |
|||
627 | 72 | 'format' => [ |
|||
628 | // CSV |
||||
629 | 72 | 'csv', |
|||
630 | // DocSQL |
||||
631 | 72 | 'docsql', |
|||
632 | // CSV using LOAD DATA |
||||
633 | 72 | 'ldi', |
|||
634 | // SQL |
||||
635 | 72 | 'sql', |
|||
636 | 72 | ], |
|||
637 | 72 | 'charset' => array_merge([''], $config->settings['AvailableCharsets'] ?? []), |
|||
638 | 72 | 'sql_compatibility' => [ |
|||
639 | 72 | 'NONE', |
|||
640 | 72 | 'ANSI', |
|||
641 | 72 | 'DB2', |
|||
642 | 72 | 'MAXDB', |
|||
643 | 72 | 'MYSQL323', |
|||
644 | 72 | 'MYSQL40', |
|||
645 | 72 | 'MSSQL', |
|||
646 | 72 | 'ORACLE', |
|||
647 | // removed; in MySQL 5.0.33, this produces exports that |
||||
648 | // can't be read by POSTGRESQL (see our bug #1596328) |
||||
649 | //'POSTGRESQL', |
||||
650 | 72 | 'TRADITIONAL', |
|||
651 | 72 | ], |
|||
652 | 72 | 'csv_terminated' => 'short_string', |
|||
653 | 72 | 'csv_enclosed' => 'short_string', |
|||
654 | 72 | 'csv_escaped' => 'short_string', |
|||
655 | 72 | 'ldi_terminated' => 'short_string', |
|||
656 | 72 | 'ldi_enclosed' => 'short_string', |
|||
657 | 72 | 'ldi_escaped' => 'short_string', |
|||
658 | 72 | 'ldi_local_option' => ['auto', true, false], |
|||
659 | 72 | ], |
|||
660 | |||||
661 | 72 | 'Export' => [ |
|||
662 | 72 | '_sod_select' => [ |
|||
663 | 72 | 'structure' => __('structure'), |
|||
664 | 72 | 'data' => __('data'), |
|||
665 | 72 | 'structure_and_data' => __('structure and data'), |
|||
666 | 72 | ], |
|||
667 | 72 | 'method' => [ |
|||
668 | 72 | 'quick' => __('Quick - display only the minimal options to configure'), |
|||
669 | 72 | 'custom' => __('Custom - display all possible options to configure'), |
|||
670 | 72 | 'custom-no-form' => __('Custom - like above, but without the quick/custom choice'), |
|||
671 | 72 | ], |
|||
672 | 72 | 'format' => [ |
|||
673 | 72 | 'codegen', |
|||
674 | 72 | 'csv', |
|||
675 | 72 | 'excel', |
|||
676 | 72 | 'htmlexcel', |
|||
677 | 72 | 'htmlword', |
|||
678 | 72 | 'latex', |
|||
679 | 72 | 'ods', |
|||
680 | 72 | 'odt', |
|||
681 | 72 | 'pdf', |
|||
682 | 72 | 'sql', |
|||
683 | 72 | 'texytext', |
|||
684 | 72 | 'xml', |
|||
685 | 72 | 'yaml', |
|||
686 | 72 | ], |
|||
687 | 72 | 'compression' => ['none', 'zip', 'gzip'], |
|||
688 | 72 | 'charset' => array_merge([''], $config->settings['AvailableCharsets'] ?? []), |
|||
689 | 72 | 'sql_compatibility' => [ |
|||
690 | 72 | 'NONE', |
|||
691 | 72 | 'ANSI', |
|||
692 | 72 | 'DB2', |
|||
693 | 72 | 'MAXDB', |
|||
694 | 72 | 'MYSQL323', |
|||
695 | 72 | 'MYSQL40', |
|||
696 | 72 | 'MSSQL', |
|||
697 | 72 | 'ORACLE', |
|||
698 | // removed; in MySQL 5.0.33, this produces exports that |
||||
699 | // can't be read by POSTGRESQL (see our bug #1596328) |
||||
700 | //'POSTGRESQL', |
||||
701 | 72 | 'TRADITIONAL', |
|||
702 | 72 | ], |
|||
703 | 72 | 'codegen_format' => ['#', 'NHibernate C# DO', 'NHibernate XML'], |
|||
704 | 72 | 'csv_separator' => 'short_string', |
|||
705 | 72 | 'csv_terminated' => 'short_string', |
|||
706 | 72 | 'csv_enclosed' => 'short_string', |
|||
707 | 72 | 'csv_escaped' => 'short_string', |
|||
708 | 72 | 'csv_null' => 'short_string', |
|||
709 | 72 | 'excel_null' => 'short_string', |
|||
710 | 72 | 'excel_edition' => [ |
|||
711 | 72 | 'win' => 'Windows', |
|||
712 | 72 | 'mac_excel2003' => 'Excel 2003 / Macintosh', |
|||
713 | 72 | 'mac_excel2008' => 'Excel 2008 / Macintosh', |
|||
714 | 72 | ], |
|||
715 | 72 | 'sql_structure_or_data' => [ |
|||
716 | 72 | 'structure' => __('structure'), |
|||
717 | 72 | 'data' => __('data'), |
|||
718 | 72 | 'structure_and_data' => __('structure and data'), |
|||
719 | 72 | ], |
|||
720 | 72 | 'sql_type' => ['INSERT', 'UPDATE', 'REPLACE'], |
|||
721 | 72 | 'sql_insert_syntax' => [ |
|||
722 | 72 | 'complete' => __('complete inserts'), |
|||
723 | 72 | 'extended' => __('extended inserts'), |
|||
724 | 72 | 'both' => __('both of the above'), |
|||
725 | 72 | 'none' => __('neither of the above'), |
|||
726 | 72 | ], |
|||
727 | 72 | 'htmlword_structure_or_data' => [ |
|||
728 | 72 | 'structure' => __('structure'), |
|||
729 | 72 | 'data' => __('data'), |
|||
730 | 72 | 'structure_and_data' => __('structure and data'), |
|||
731 | 72 | ], |
|||
732 | 72 | 'htmlword_null' => 'short_string', |
|||
733 | 72 | 'ods_null' => 'short_string', |
|||
734 | 72 | 'odt_null' => 'short_string', |
|||
735 | 72 | 'odt_structure_or_data' => [ |
|||
736 | 72 | 'structure' => __('structure'), |
|||
737 | 72 | 'data' => __('data'), |
|||
738 | 72 | 'structure_and_data' => __('structure and data'), |
|||
739 | 72 | ], |
|||
740 | 72 | 'texytext_structure_or_data' => [ |
|||
741 | 72 | 'structure' => __('structure'), |
|||
742 | 72 | 'data' => __('data'), |
|||
743 | 72 | 'structure_and_data' => __('structure and data'), |
|||
744 | 72 | ], |
|||
745 | 72 | 'texytext_null' => 'short_string', |
|||
746 | 72 | ], |
|||
747 | |||||
748 | 72 | 'Console' => [ |
|||
749 | 72 | 'Mode' => ['info', 'show', 'collapse'], |
|||
750 | 72 | 'OrderBy' => ['exec', 'time', 'count'], |
|||
751 | 72 | 'Order' => ['asc', 'desc'], |
|||
752 | 72 | ], |
|||
753 | |||||
754 | /** |
||||
755 | * Basic validator assignments (functions from libraries/config/Validator.php |
||||
756 | * and 'window.validators' object in js/config.js) |
||||
757 | * Use only full paths and form ids |
||||
758 | */ |
||||
759 | 72 | '_validators' => [ |
|||
760 | 72 | 'Console/Height' => 'validateNonNegativeNumber', |
|||
761 | 72 | 'CharTextareaCols' => 'validatePositiveNumber', |
|||
762 | 72 | 'CharTextareaRows' => 'validatePositiveNumber', |
|||
763 | 72 | 'ExecTimeLimit' => 'validateNonNegativeNumber', |
|||
764 | 72 | 'Export/sql_max_query_size' => 'validatePositiveNumber', |
|||
765 | 72 | 'FirstLevelNavigationItems' => 'validatePositiveNumber', |
|||
766 | 72 | 'ForeignKeyMaxLimit' => 'validatePositiveNumber', |
|||
767 | 72 | 'Import/csv_enclosed' => [['validateByRegex', '/^.?$/']], |
|||
768 | 72 | 'Import/csv_escaped' => [['validateByRegex', '/^.$/']], |
|||
769 | 72 | 'Import/csv_terminated' => [['validateByRegex', '/^.$/']], |
|||
770 | 72 | 'Import/ldi_enclosed' => [['validateByRegex', '/^.?$/']], |
|||
771 | 72 | 'Import/ldi_escaped' => [['validateByRegex', '/^.$/']], |
|||
772 | 72 | 'Import/ldi_terminated' => [['validateByRegex', '/^.$/']], |
|||
773 | 72 | 'Import/skip_queries' => 'validateNonNegativeNumber', |
|||
774 | 72 | 'InsertRows' => 'validatePositiveNumber', |
|||
775 | 72 | 'NumRecentTables' => 'validateNonNegativeNumber', |
|||
776 | 72 | 'NumFavoriteTables' => 'validateNonNegativeNumber', |
|||
777 | 72 | 'LimitChars' => 'validatePositiveNumber', |
|||
778 | 72 | 'LoginCookieValidity' => 'validatePositiveNumber', |
|||
779 | 72 | 'LoginCookieStore' => 'validateNonNegativeNumber', |
|||
780 | 72 | 'MaxDbList' => 'validatePositiveNumber', |
|||
781 | 72 | 'MaxNavigationItems' => 'validatePositiveNumber', |
|||
782 | 72 | 'MaxCharactersInDisplayedSQL' => 'validatePositiveNumber', |
|||
783 | 72 | 'MaxRows' => 'validatePositiveNumber', |
|||
784 | 72 | 'MaxSizeForInputField' => 'validatePositiveNumber', |
|||
785 | 72 | 'MinSizeForInputField' => 'validateNonNegativeNumber', |
|||
786 | 72 | 'MaxTableList' => 'validatePositiveNumber', |
|||
787 | 72 | 'MemoryLimit' => [['validateByRegex', '/^(-1|(\d+(?:[kmg])?))$/i']], |
|||
788 | 72 | 'NavigationTreeDisplayItemFilterMinimum' => 'validatePositiveNumber', |
|||
789 | 72 | 'NavigationTreeTableLevel' => 'validatePositiveNumber', |
|||
790 | 72 | 'NavigationWidth' => 'validateNonNegativeNumber', |
|||
791 | 72 | 'QueryHistoryMax' => 'validatePositiveNumber', |
|||
792 | 72 | 'RepeatCells' => 'validateNonNegativeNumber', |
|||
793 | 72 | 'Server' => 'validateServer', |
|||
794 | 72 | 'Server_pmadb' => 'validatePMAStorage', |
|||
795 | 72 | 'Servers/1/port' => 'validatePortNumber', |
|||
796 | 72 | 'Servers/1/hide_db' => 'validateRegex', |
|||
797 | 72 | 'TextareaCols' => 'validatePositiveNumber', |
|||
798 | 72 | 'TextareaRows' => 'validatePositiveNumber', |
|||
799 | 72 | 'TrustedProxies' => 'validateTrustedProxies', |
|||
800 | 72 | ], |
|||
801 | |||||
802 | /** |
||||
803 | * Additional validators used for user preferences |
||||
804 | */ |
||||
805 | 72 | '_userValidators' => [ |
|||
806 | 72 | 'MaxDbList' => [['validateUpperBound', 'value:MaxDbList']], |
|||
807 | 72 | 'MaxTableList' => [['validateUpperBound', 'value:MaxTableList']], |
|||
808 | 72 | 'QueryHistoryMax' => [['validateUpperBound', 'value:QueryHistoryMax']], |
|||
809 | 72 | ], |
|||
810 | 72 | ]; |
|||
811 | } |
||||
812 | } |
||||
813 |