1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Utility function for installing the ElkArte db on the GHA test server |
5
|
|
|
* |
6
|
|
|
* @package ElkArte Forum |
7
|
|
|
* @copyright ElkArte Forum contributors |
8
|
|
|
* @license BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file) |
9
|
|
|
* |
10
|
|
|
* @version 2.0 dev |
11
|
|
|
* |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
use ElkArte\ext\Composer\Autoload\ClassLoader; |
15
|
|
|
|
16
|
|
|
global $txt; |
17
|
|
|
|
18
|
|
|
define('BOARDDIR', dirname(__FILE__) . '/..'); |
19
|
|
|
define('CACHEDIR', BOARDDIR . '/cache'); |
20
|
|
|
define('ELK', '1'); |
21
|
|
|
|
22
|
|
|
// Lots of needs |
23
|
|
|
require_once(BOARDDIR . '/sources/Subs.php'); |
24
|
|
|
require_once(BOARDDIR . '/sources/subs/Cache.subs.php'); |
25
|
|
|
require_once(BOARDDIR . '/sources/database/Database.subs.php'); |
26
|
|
|
require_once(BOARDDIR . '/install/installcore.php'); |
27
|
|
|
|
28
|
|
|
// Autoloader |
29
|
|
|
require_once(BOARDDIR . '/sources/ext/ClassLoader.php'); |
30
|
|
|
|
31
|
|
|
// Register our paths to the loader |
32
|
|
|
$loader = new ClassLoader(); |
33
|
|
|
$loader->setPsr4('ElkArte\\', BOARDDIR . '/sources/ElkArte'); |
34
|
|
|
$loader->setPsr4('BBC\\', BOARDDIR . '/sources/ElkArte/BBC'); |
35
|
|
|
$loader->register(); |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Used to install ElkArte SQL files to a database scheme |
39
|
|
|
*/ |
40
|
|
|
class ElkTestingSetup |
41
|
|
|
{ |
42
|
|
|
protected $_db; |
43
|
|
|
protected $_install_instance; |
44
|
|
|
protected $_queries; |
45
|
|
|
protected $_dbserver; |
46
|
|
|
protected $_name; |
47
|
|
|
protected $_user; |
48
|
|
|
protected $_passwd; |
49
|
|
|
|
50
|
|
|
// Initialized from extended class |
51
|
|
|
protected $_db_server; |
52
|
|
|
protected $_db_user; |
53
|
|
|
protected $_db_passwd; |
54
|
|
|
protected $_db_type; |
55
|
|
|
protected $_db_name; |
56
|
|
|
protected $_db_prefix; |
57
|
|
|
protected $_db_table; |
58
|
|
|
protected $_boardurl; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* Runs the query's defined in the install files to the db |
62
|
|
|
*/ |
63
|
|
|
public function run_queries() |
64
|
|
|
{ |
65
|
|
|
$exists = array(); |
66
|
|
|
$success = true; |
67
|
|
|
foreach ($this->_queries['tables'] as $table_method) |
68
|
|
|
{ |
69
|
|
|
$table_name = substr($table_method, 6); |
70
|
|
|
|
71
|
|
|
// Copied from DbTable class |
72
|
|
|
// Strip out the table name, we might not need it in some cases |
73
|
|
|
$real_prefix = preg_match('~^("?)(.+?)\\1\\.(.*?)$~', $this->_db_prefix, $match) === 1 ? $match[3] : $this->_db_prefix; |
74
|
|
|
|
75
|
|
|
// With or without the database name, the fullname looks like this. |
76
|
|
|
$full_table_name = str_replace('{db_prefix}', $real_prefix, $table_name); |
77
|
|
|
|
78
|
|
|
if ($this->_db_table->table_exists($full_table_name)) |
79
|
|
|
{ |
80
|
|
|
$exists[] = $table_method; |
81
|
|
|
continue; |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
$success .= $this->_install_instance->{$table_method}(); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
foreach ($this->_queries['inserts'] as $insert_method) |
88
|
|
|
{ |
89
|
|
|
$table_name = substr($insert_method, 6); |
90
|
|
|
|
91
|
|
|
if (in_array($table_name, $exists)) |
92
|
|
|
{ |
93
|
|
|
continue; |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
$success .= $this->_install_instance->{$insert_method}(); |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
// Errors here are ignored |
100
|
|
|
foreach ($this->_queries['others'] as $other_method) |
101
|
|
|
{ |
102
|
|
|
$success .= $this->_install_instance->{$other_method}(); |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
return $success; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* Loads the query's from the supplied database install file |
110
|
|
|
* |
111
|
|
|
* @param string $sql_file |
112
|
|
|
*/ |
113
|
|
|
public function load_queries($sql_file) |
114
|
|
|
{ |
115
|
|
|
global $txt; |
116
|
|
|
|
117
|
|
|
require_once(BOARDDIR . '/sources/ElkArte/Languages/Install/English.php'); |
118
|
|
|
require_once(BOARDDIR . '/sources/ElkArte/Languages/Index/English.php'); |
119
|
|
|
|
120
|
|
|
$replaces = array( |
121
|
|
|
'{$db_prefix}' => $this->_db_prefix, |
122
|
|
|
'{BOARDDIR}' => BOARDDIR, |
123
|
|
|
'{$boardurl}' => $this->_boardurl, |
124
|
|
|
'{$enableCompressedOutput}' => 0, |
125
|
|
|
'{$databaseSession_enable}' => 1, |
126
|
|
|
'{$current_version}' => CURRENT_VERSION, |
127
|
|
|
'{$current_time}' => time(), |
128
|
|
|
'{$sched_task_offset}' => 82800 + mt_rand(0, 86399), |
129
|
|
|
); |
130
|
|
|
|
131
|
|
|
foreach ($txt as $key => $value) |
132
|
|
|
{ |
133
|
|
|
if (substr($key, 0, 8) == 'default_') |
134
|
|
|
{ |
135
|
|
|
$replaces['{$' . $key . '}'] = $value; |
136
|
|
|
} |
137
|
|
|
} |
138
|
|
|
$replaces['{$default_reserved_names}'] = strtr($replaces['{$default_reserved_names}'], array('\\\\n' => '\\n')); |
139
|
|
|
|
140
|
|
|
$this->_db->skip_next_error(); |
141
|
|
|
$db_wrapper = new DbWrapper($this->_db, $replaces); |
142
|
|
|
$db_table_wrapper = new DbTableWrapper($this->_db_table); |
143
|
|
|
|
144
|
|
|
$current_statement = ''; |
145
|
|
|
$exists = array(); |
146
|
|
|
|
147
|
|
|
require_once($sql_file); |
148
|
|
|
|
149
|
|
|
$class_name = 'InstallInstructions_' . str_replace('-', '_', basename($sql_file, '.php')); |
150
|
|
|
$this->_install_instance = new $class_name($db_wrapper, $db_table_wrapper); |
151
|
|
|
$methods = get_class_methods($this->_install_instance); |
152
|
|
|
|
153
|
|
|
$this->_queries['tables'] = array_filter($methods, function ($method) |
154
|
|
|
{ |
155
|
|
|
return strpos($method, 'table_') === 0; |
156
|
|
|
}); |
157
|
|
|
|
158
|
|
|
$this->_queries['inserts'] = array_filter($methods, function ($method) |
159
|
|
|
{ |
160
|
|
|
return strpos($method, 'insert_') === 0; |
161
|
|
|
}); |
162
|
|
|
|
163
|
|
|
$this->_queries['others'] = array_filter($methods, function ($method) |
164
|
|
|
{ |
165
|
|
|
return substr($method, 0, 2) !== '__' && strpos($method, 'insert_') !== 0 && strpos($method, 'table_') !== 0; |
166
|
|
|
}); |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
/** |
170
|
|
|
* Clear the DB for a new install |
171
|
|
|
*/ |
172
|
|
|
public function clear_tables() |
173
|
|
|
{ |
174
|
|
|
// Get all the tables. |
175
|
|
|
$tables = $this->_db->list_tables($this->_db_name, $this->_db_prefix . '%'); |
176
|
|
|
|
177
|
|
|
// Bu-bye |
178
|
|
|
foreach ($tables as $table) |
179
|
|
|
{ |
180
|
|
|
$this->_db_table->drop_table($table); |
181
|
|
|
} |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* Updates the settings.php file to work with a given install / db scheme |
186
|
|
|
*/ |
187
|
|
|
public function prepare_settings() |
188
|
|
|
{ |
189
|
|
|
$file = file_get_contents(BOARDDIR . '/Settings.php'); |
190
|
|
|
|
191
|
|
|
$file = str_replace( |
192
|
|
|
array( |
193
|
|
|
'$boardurl = \'http://127.0.0.1/elkarte\';', |
194
|
|
|
'$db_type = \'mysql\';', |
195
|
|
|
'$db_name = \'elkarte\';', |
196
|
|
|
'$db_user = \'root\';', |
197
|
|
|
'$db_prefix = \'elkarte_\';', |
198
|
|
|
'$db_passwd = \'\';', |
199
|
|
|
), |
200
|
|
|
array( |
201
|
|
|
'$boardurl = \'' . $this->_boardurl . '\';', |
202
|
|
|
'$db_type = \'' . $this->_db_type . '\';', |
203
|
|
|
'$db_name = \'' . $this->_db_name . '\';', |
204
|
|
|
'$db_user = \'' . $this->_db_user . '\';', |
205
|
|
|
'$db_prefix = \'' . $this->_db_prefix . '\';', |
206
|
|
|
'$db_passwd = \'' . $this->_db_passwd . '\';', |
207
|
|
|
), |
208
|
|
|
$file |
209
|
|
|
); |
210
|
|
|
|
211
|
|
|
if (strpos($file, 'if (file_exist') !== false) |
212
|
|
|
{ |
213
|
|
|
$file = substr($file, 0, strpos($file, 'if (file_exist')); |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
file_put_contents(BOARDDIR . '/Settings.php', $file); |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* Called after db is setup, calls functions to prepare for testing |
221
|
|
|
*/ |
222
|
|
|
public function prepare() |
223
|
|
|
{ |
224
|
|
|
$this->prepare_settings(); |
225
|
|
|
$this->update(); |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* Adds a user, sets time, prepares the forum for phpunit tests |
230
|
|
|
*/ |
231
|
|
|
public function update() |
232
|
|
|
{ |
233
|
|
|
global $settings, $db_type; |
234
|
|
|
global $time_start, $maintenance, $msubject, $mmessage, $mbname, $language; |
235
|
|
|
global $boardurl, $webmaster_email, $cookiename; |
236
|
|
|
global $db_server, $db_name, $db_user, $db_prefix, $db_persist, $db_error_send; |
237
|
|
|
global $modSettings, $context, $user_info, $topic, $board, $txt; |
238
|
|
|
global $ssi_db_user, $scripturl, $ssi_db_passwd, $db_passwd; |
239
|
|
|
global $sourcedir, $boarddir; |
240
|
|
|
|
241
|
|
|
define('SUBSDIR', BOARDDIR . '/sources/subs'); |
242
|
|
|
define('EXTDIR', BOARDDIR . '/sources/ext'); |
243
|
|
|
define('SOURCEDIR', BOARDDIR . '/sources'); |
244
|
|
|
define('LANGUAGEDIR', BOARDDIR . '/themes/default/languages'); |
245
|
|
|
define('ADMINDIR', SOURCEDIR . '/admin'); |
246
|
|
|
define('CONTROLLERDIR', SOURCEDIR . '/controllers'); |
247
|
|
|
define('ADDONSDIR', SOURCEDIR . '/addons'); |
248
|
|
|
|
249
|
|
|
require_once(BOARDDIR . '/Settings.php'); |
250
|
|
|
require_once(SOURCEDIR . '/Subs.php'); |
251
|
|
|
require_once(SOURCEDIR . '/Load.php'); |
252
|
|
|
require_once(SUBSDIR . '/Auth.subs.php'); |
253
|
|
|
require_once(EXTDIR . '/ClassLoader.php'); |
254
|
|
|
require_once(SOURCEDIR . '/database/Database.subs.php'); |
255
|
|
|
|
256
|
|
|
$loader = new ClassLoader(); |
257
|
|
|
$loader->setPsr4('ElkArte\\', SOURCEDIR . '/ElkArte'); |
258
|
|
|
$loader->setPsr4('BBC\\', SOURCEDIR . '/ElkArte/BBC'); |
259
|
|
|
$loader->register(); |
260
|
|
|
|
261
|
|
|
$settings['theme_dir'] = $settings['default_theme_dir'] = BOARDDIR . '/Themes/default'; |
262
|
|
|
$settings['theme_url'] = $settings['default_theme_url'] = $boardurl . '/themes/default'; |
263
|
|
|
|
264
|
|
|
// Create an admin member |
265
|
|
|
$db = database(); |
266
|
|
|
|
267
|
|
|
// Get a security hash for this combination |
268
|
|
|
$password = stripslashes('test_admin_pwd'); |
269
|
|
|
$passwd = validateLoginPassword($password, '', 'test_admin', true); |
270
|
|
|
|
271
|
|
|
$db->insert('', ' |
272
|
|
|
{db_prefix}members', |
273
|
|
|
array( |
274
|
|
|
'member_name' => 'string-25', 'real_name' => 'string-25', 'passwd' => 'string', 'email_address' => 'string', |
275
|
|
|
'id_group' => 'int', 'posts' => 'int', 'date_registered' => 'int', 'hide_email' => 'int', |
276
|
|
|
'password_salt' => 'string', 'lngfile' => 'string', 'avatar' => 'string', |
277
|
|
|
'member_ip' => 'string', 'member_ip2' => 'string', 'buddy_list' => 'string', 'pm_ignore_list' => 'string', |
278
|
|
|
'message_labels' => 'string', 'website_title' => 'string', 'website_url' => 'string', |
279
|
|
|
'signature' => 'string', 'usertitle' => 'string', 'secret_question' => 'string', |
280
|
|
|
'additional_groups' => 'string', 'ignore_boards' => 'string', |
281
|
|
|
), |
282
|
|
|
array( |
283
|
|
|
'test_admin', 'test_admin', $passwd, '[email protected]', |
284
|
|
|
1, 0, time(), 0, |
285
|
|
|
substr(md5(mt_rand()), 0, 4), '', '', |
286
|
|
|
'123.123.123.123', '123.123.123.123', '', '', |
287
|
|
|
'', '', '', |
288
|
|
|
'', '', '', |
289
|
|
|
'', '', |
290
|
|
|
), |
291
|
|
|
array('id_member') |
292
|
|
|
); |
293
|
|
|
|
294
|
|
|
// The old Etc/GMT value is discouraged and does not work in some installs |
295
|
|
|
$timezone_id = 'America/Chicago'; |
296
|
|
|
|
297
|
|
|
if (date_default_timezone_set($timezone_id)) |
298
|
|
|
{ |
299
|
|
|
$db->insert('', |
300
|
|
|
$db_prefix . 'settings', |
301
|
|
|
array( |
302
|
|
|
'variable' => 'string-255', 'value' => 'string-65534', |
303
|
|
|
), |
304
|
|
|
array( |
305
|
|
|
'default_timezone', $timezone_id, |
306
|
|
|
), |
307
|
|
|
array('variable') |
308
|
|
|
); |
309
|
|
|
} |
310
|
|
|
} |
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
class DbWrapper |
314
|
|
|
{ |
315
|
|
|
protected $db = null; |
316
|
|
|
protected $count_mode = false; |
317
|
|
|
protected $replaces = array(); |
318
|
|
|
|
319
|
|
|
public function __construct($db, $replaces) |
320
|
|
|
{ |
321
|
|
|
$this->db = $db; |
322
|
|
|
$this->replaces = $replaces; |
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
public function __call($name, $args) |
326
|
|
|
{ |
327
|
|
|
return call_user_func_array(array($this->db, $name), $args); |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
public function insert() |
331
|
|
|
{ |
332
|
|
|
$args = func_get_args(); |
333
|
|
|
|
334
|
|
|
if ($this->count_mode) |
335
|
|
|
{ |
336
|
|
|
return count($args[3]); |
337
|
|
|
} |
338
|
|
|
|
339
|
|
|
foreach ($args[3] as $key => $data) |
340
|
|
|
{ |
341
|
|
|
foreach ($data as $k => $v) |
342
|
|
|
{ |
343
|
|
|
$args[3][$key][$k] = strtr($v, $this->replaces); |
344
|
|
|
} |
345
|
|
|
} |
346
|
|
|
|
347
|
|
|
call_user_func_array(array($this->db, 'insert'), $args); |
348
|
|
|
|
349
|
|
|
return $this->db->affected_rows(); |
350
|
|
|
} |
351
|
|
|
|
352
|
|
|
public function countMode($on = true) |
353
|
|
|
{ |
354
|
|
|
$this->count_mode = (bool) $on; |
355
|
|
|
} |
356
|
|
|
} |
357
|
|
|
|
358
|
|
|
class DbTableWrapper |
359
|
|
|
{ |
360
|
|
|
protected $db = null; |
361
|
|
|
|
362
|
|
|
public function __construct($db) |
363
|
|
|
{ |
364
|
|
|
$this->db = $db; |
365
|
|
|
} |
366
|
|
|
|
367
|
|
|
public function __call($name, $args) |
368
|
|
|
{ |
369
|
|
|
return call_user_func_array(array($this->db, $name), $args); |
370
|
|
|
} |
371
|
|
|
|
372
|
|
|
public function add_index() |
373
|
|
|
{ |
374
|
|
|
$args = func_get_args(); |
375
|
|
|
|
376
|
|
|
// In this case errors are ignored, so the return is always true |
377
|
|
|
call_user_func_array(array($this->db, 'create_table'), $args); |
378
|
|
|
|
379
|
|
|
return true; |
380
|
|
|
} |
381
|
|
|
} |
382
|
|
|
|