1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
<?php
class BaseConfig
{
private static $modulesDone = [];
/**
* @var array key-value-pairs of override vars, can be accessed by hooks
*/
private static $overrides = [];
/**
* Fill the ConfigHolder with values from various hooks, while taking
* into account UUID and IP-address of the client making the current
* HTTP request.
*/
public static function prepareFromRequest()
{
$ip = $_SERVER['REMOTE_ADDR'];
if (substr($ip, 0, 7) === '::ffff:') {
$ip = substr($ip, 7);
}
$uuid = Request::any('uuid', false, 'string');
if ($uuid !== false && strlen($uuid) !== 36) {
$uuid = false;
}
// Handle any hooks by other modules first
// other modules should generally only populate $configVars
foreach (glob('modules/*/baseconfig/getconfig.inc.php') as $file) {
preg_match('#^modules/([^/]+)/#', $file, $out);
ConfigHolder::setContext($out[1]);
self::handleModule($out[1], $ip, $uuid, false);
}
self::commonBase();
}
/**
* Fill the ConfigHolder with data from various hooks that supply
* static overrides for config variables. The overrides can be used
* to make the hooks behave in certain ways, by setting specific values like
* 'locationid'
* @param array $overrides key value pairs of overrides
*/
public static function prepareWithOverrides($overrides)
{
self::$overrides = $overrides;
$ip = $uuid = false;
if (self::hasOverride('ip')) {
$ip = self::getOverride('ip');
}
if (self::hasOverride('uuid')) {
$uuid = self::getOverride('uuid');
}
// Handle only static hooks that don't dynamically generate output
foreach (glob('modules/*/baseconfig/hook.json') as $file) {
preg_match('#^modules/([^/]+)/#', $file, $out);
ConfigHolder::setContext($out[1]);
self::handleModule($out[1], $ip, $uuid, true);
}
self::commonBase();
}
/**
* Just fill the ConfigHolder with the defaults from all the json files
* that define config variables.
*/
public static function prepareDefaults()
{
$defaults = BaseConfigUtil::getVariables();
self::addDefaults($defaults);
}
private static function commonBase()
{
$defaults = BaseConfigUtil::getVariables();
// Dump global config from DB
ConfigHolder::setContext('<global>', function($id) {
return [
'name' => Dictionary::translate('source-global', true),
'locationid' => 0,
];
});
$res = Database::simpleQuery('SELECT setting, value, displayvalue FROM setting_global');
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
if (!isset($defaults[$row['setting']]))
continue; // Setting is not defined in any <module>/baseconfig/settings.json
ConfigHolder::add($row['setting'], $row, -1);
}
// Fallback to default values from json files
self::addDefaults($defaults);
}
private static function addDefaults($defaults)
{
ConfigHolder::setContext('<default>', function($id) {
return [
'name' => Dictionary::translate('source-default', true),
'locationid' => 0,
];
});
foreach ($defaults as $setting => $value) {
ConfigHolder::add($setting, $value['defaultvalue'], -1000);
}
}
private static function handleModule($name, $ip, $uuid, $needJsonHook) // Pass ip and uuid instead of global to make them read only
{
if (isset(self::$modulesDone[$name]))
return;
self::$modulesDone[$name] = true;
// Module has getconfig hook
$file = 'modules/' . $name . '/baseconfig/getconfig.inc.php';
if (!is_file($file))
return;
// We want only static hooks that have a json config (currently used for displaying inheritance tree)
if ($needJsonHook && !is_file('modules/' . $name . '/baseconfig/hook.json'))
return;
// Properly registered and can be activated
$mod = Module::get($name);
if ($mod === false)
return;
if (!$mod->activate(1, false))
return;
// Process dependencies first
foreach ($mod->getDependencies() as $dep) {
self::handleModule($dep, $ip, $uuid, $needJsonHook);
}
ConfigHolder::setContext($name);
(function ($file, $ip, $uuid) {
include_once($file);
})($file, $ip, $uuid);
}
public static function hasOverride($key)
{
return array_key_exists($key, self::$overrides);
}
public static function getOverride($key)
{
return self::$overrides[$key];
}
}
|