1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @name OpenImporter |
4
|
|
|
* @copyright OpenImporter contributors |
5
|
|
|
* @license BSD https://opensource.org/licenses/BSD-3-Clause |
6
|
|
|
* |
7
|
|
|
* @version 1.0 |
8
|
|
|
* |
9
|
|
|
* This file contains code based on: |
10
|
|
|
* |
11
|
|
|
* Simple Machines Forum (SMF) |
12
|
|
|
* copyright: 2011 Simple Machines (http://www.simplemachines.org) |
13
|
|
|
* license: BSD, See included LICENSE.TXT for terms and conditions. |
14
|
|
|
*/ |
15
|
|
|
|
16
|
|
|
namespace OpenImporter; |
17
|
|
|
|
18
|
|
|
if (!defined('DS')) |
19
|
|
|
{ |
20
|
|
|
define('DS', DIRECTORY_SEPARATOR); |
21
|
|
|
} |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* Object ImportManager loads the main importer. |
25
|
|
|
* It handles all steps to completion. |
26
|
|
|
* |
27
|
|
|
* @todo path_to should be source-specific (i.e. in /Importers/whatever/source_importer.php |
28
|
|
|
* @todo path_from should be destination-specific (i.e. in /Importers/whatever/whatever_importer.php |
29
|
|
|
* |
30
|
|
|
* @class ImportManager |
31
|
|
|
* |
32
|
|
|
*/ |
33
|
|
|
class ImportManager |
34
|
|
|
{ |
35
|
|
|
/** @var \OpenImporter\Importer The importer that will act as interface */ |
36
|
|
|
public $importer; |
37
|
|
|
|
38
|
|
|
/** @var \OpenImporter\Cookie Our cookie settings */ |
39
|
|
|
protected $cookie; |
40
|
|
|
|
41
|
|
|
/** @var \OpenImporter\Configurator The configurator that holds all the settings */ |
42
|
|
|
protected $config; |
43
|
|
|
|
44
|
|
|
/** @var \OpenImporter\Template The template, basically our UI. */ |
45
|
|
|
public $template; |
46
|
|
|
|
47
|
|
|
/** @var \OpenImporter\HttpResponse The response object. */ |
48
|
|
|
protected $response; |
49
|
|
|
|
50
|
|
|
/** @var \OpenImporter\Lang The language object. */ |
51
|
|
|
protected $language; |
52
|
|
|
|
53
|
|
|
/** @var array An array of possible importer scripts */ |
54
|
|
|
public $sources; |
55
|
|
|
|
56
|
|
|
/** @var array Data used by the script and stored in session between reload and the following one */ |
57
|
|
|
public $data = array(); |
58
|
|
|
|
59
|
|
|
/** @var string This is the URL from our Installation. */ |
60
|
|
|
protected $_boardurl = ''; |
61
|
|
|
|
62
|
|
|
/** @var string The database password */ |
63
|
|
|
protected $db_pass = ''; |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* ImportManager constructor. |
67
|
|
|
* Initialize the main Importer object |
68
|
|
|
* |
69
|
|
|
* @param Configurator $config |
70
|
|
|
* @param Importer $importer |
71
|
|
|
* @param Template $template |
72
|
|
|
* @param Cookie $cookie |
73
|
|
|
* @param HttpResponse $response |
74
|
|
|
*/ |
75
|
|
|
public function __construct($config, $importer, $template, $cookie, $response) |
76
|
|
|
{ |
77
|
|
|
global $time_start; |
78
|
|
|
|
79
|
|
|
require_once(BASEDIR . '/OpenImporter/Utils.php'); |
80
|
|
|
|
81
|
|
|
$time_start = time(); |
82
|
|
|
|
83
|
|
|
$this->loadFromSession(); |
84
|
|
|
|
85
|
|
|
$this->config = $config; |
86
|
|
|
$this->importer = $importer; |
87
|
|
|
$this->cookie = $cookie; |
88
|
|
|
$this->template = $template; |
89
|
|
|
$this->response = $response; |
90
|
|
|
$this->language = $importer->lng; |
91
|
|
|
$this->response->lng = $importer->lng; |
92
|
|
|
|
93
|
|
|
$this->_findScript(); |
94
|
|
|
|
95
|
|
|
// The current step - starts at 0. |
96
|
|
|
$_GET['step'] = isset($_GET['step']) ? (int) $_GET['step'] : 0; |
97
|
|
|
$this->response->step = $_GET['step']; |
98
|
|
|
$_REQUEST['start'] = isset($_REQUEST['start']) ? (int) $_REQUEST['start'] : 0; |
99
|
|
|
|
100
|
|
|
$this->loadPass(); |
101
|
|
|
|
102
|
|
|
$this->loadPaths(); |
103
|
|
|
|
104
|
|
|
if (!empty($this->config->script)) |
105
|
|
|
{ |
106
|
|
|
$this->importer->reloadImporter(); |
107
|
|
|
} |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* On close, save our session |
112
|
|
|
*/ |
113
|
|
|
public function __destruct() |
114
|
|
|
{ |
115
|
|
|
$this->saveInSession(); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* Need the db password to do anything useful |
120
|
|
|
*/ |
121
|
|
|
protected function loadPass() |
122
|
|
|
{ |
123
|
|
|
// Check for the password... |
124
|
|
|
if (isset($_POST['db_pass'])) |
125
|
|
|
{ |
126
|
|
|
$this->data['db_pass'] = $_POST['db_pass']; |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
if (isset($this->data['db_pass'])) |
130
|
|
|
{ |
131
|
|
|
$this->db_pass = $this->data['db_pass']; |
132
|
|
|
} |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Load in the source and destination forum paths |
137
|
|
|
*/ |
138
|
|
|
protected function loadPaths() |
139
|
|
|
{ |
140
|
|
|
if (isset($_POST['path_from']) || isset($_POST['path_to'])) |
141
|
|
|
{ |
142
|
|
|
if (isset($_POST['path_from'])) |
143
|
|
|
{ |
144
|
|
|
$this->config->path_from = rtrim($_POST['path_from'], '\\/'); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
if (isset($_POST['path_to'])) |
148
|
|
|
{ |
149
|
|
|
$this->config->path_to = rtrim($_POST['path_to'], '\\/'); |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
$this->data['import_paths'] = array($this->config->path_from, $this->config->path_to); |
153
|
|
|
} |
154
|
|
|
elseif (isset($this->data['import_paths'])) |
155
|
|
|
{ |
156
|
|
|
list ($this->config->path_from, $this->config->path_to) = $this->data['import_paths']; |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
if (!empty($this->data)) |
160
|
|
|
{ |
161
|
|
|
$this->importer->setData($this->data); |
162
|
|
|
} |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Load session data |
167
|
|
|
*/ |
168
|
|
|
protected function loadFromSession() |
169
|
|
|
{ |
170
|
|
|
if (empty($_SESSION['importer_data'])) |
171
|
|
|
{ |
172
|
|
|
return; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
$this->data = $_SESSION['importer_data']; |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Save the session data |
180
|
|
|
*/ |
181
|
|
|
protected function saveInSession() |
182
|
|
|
{ |
183
|
|
|
$_SESSION['importer_data'] = $this->data; |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* Finds the script either in the session or in request |
188
|
|
|
*/ |
189
|
|
|
protected function _findScript() |
190
|
|
|
{ |
191
|
|
|
// Save here, so it doesn't get overwritten when sessions are restarted. |
192
|
|
|
if (isset($_REQUEST['import_script'])) |
193
|
|
|
{ |
194
|
|
|
$this->config->script = (string) $_REQUEST['import_script']; |
195
|
|
|
$this->data['import_script'] = $this->config->script; |
196
|
|
|
} |
197
|
|
|
elseif (isset($this->data['import_script'])) |
198
|
|
|
{ |
199
|
|
|
$this->data['import_script'] = $this->validateScript($this->data['import_script']); |
200
|
|
|
$this->config->script = $this->data['import_script']; |
|
|
|
|
201
|
|
|
} |
202
|
|
|
else |
203
|
|
|
{ |
204
|
|
|
$this->config->script = ''; |
205
|
|
|
$this->data['import_script'] = null; |
206
|
|
|
} |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* Prepares the response to send to the template system |
211
|
|
|
*/ |
212
|
|
|
public function process() |
213
|
|
|
{ |
214
|
|
|
// This is really quite simple; if ?delete is on the URL, delete the importer... |
215
|
|
|
if (isset($_GET['delete'])) |
216
|
|
|
{ |
217
|
|
|
$this->uninstall(); |
218
|
|
|
|
219
|
|
|
$this->response->no_template = true; |
|
|
|
|
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
$this->populateResponseDetails(); |
223
|
|
|
|
224
|
|
|
// An ajax response |
225
|
|
|
if (isset($_GET['xml'])) |
226
|
|
|
{ |
227
|
|
|
$this->response->addHeader('Content-Type', 'text/xml'); |
228
|
|
|
$this->response->is_xml = true; |
229
|
|
|
} |
230
|
|
|
else |
231
|
|
|
{ |
232
|
|
|
$this->template->header(); |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
if (isset($_GET['action']) && $_GET['action'] === 'validate') |
236
|
|
|
{ |
237
|
|
|
$this->validateFields(); |
238
|
|
|
} |
239
|
|
|
elseif (method_exists($this, 'doStep' . $_GET['step'])) |
240
|
|
|
{ |
241
|
|
|
$this->{'doStep' . $_GET['step']}(); |
242
|
|
|
} |
243
|
|
|
else |
244
|
|
|
{ |
245
|
|
|
$this->doStep0(); |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
$this->populateResponseDetails(); |
249
|
|
|
|
250
|
|
|
$this->template->render(); |
251
|
|
|
|
252
|
|
|
if (!isset($_GET['xml'])) |
253
|
|
|
{ |
254
|
|
|
$this->template->footer(); |
255
|
|
|
} |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* Validate the step0 input fields |
260
|
|
|
*/ |
261
|
|
|
protected function validateFields() |
262
|
|
|
{ |
263
|
|
|
$this->_detect_scripts(); |
264
|
|
|
|
265
|
|
|
try |
266
|
|
|
{ |
267
|
|
|
$this->importer->reloadImporter(); |
268
|
|
|
} |
269
|
|
|
catch (\Exception $e) |
270
|
|
|
{ |
271
|
|
|
// Do nothing, let the code die |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
if (isset($_GET['path_to'])) |
275
|
|
|
{ |
276
|
|
|
$this->response->valid = $this->config->destination->checkSettingsPath($_GET['path_to']); |
|
|
|
|
277
|
|
|
} |
278
|
|
|
elseif (isset($_GET['path_from'])) |
279
|
|
|
{ |
280
|
|
|
$this->response->valid = $this->config->source->loadSettings($_GET['path_from'], true); |
|
|
|
|
281
|
|
|
} |
282
|
|
|
else |
283
|
|
|
{ |
284
|
|
|
$this->response->valid = false; |
285
|
|
|
} |
286
|
|
|
} |
287
|
|
|
|
288
|
|
|
protected function populateResponseDetails() |
289
|
|
|
{ |
290
|
|
|
if (isset($this->importer->xml->general->name)) |
291
|
|
|
{ |
292
|
|
|
$this->response->page_title = $this->importer->xml->general->name . ' to ' . $this->config->destination->getName(); |
293
|
|
|
} |
294
|
|
|
else |
295
|
|
|
{ |
296
|
|
|
$this->response->page_title = 'OpenImporter'; |
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
// $this->response->from = $this->importer->settings : null |
300
|
|
|
$this->response->script = $this->config->script; |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
/** |
304
|
|
|
* Deletes the importer files from the server |
305
|
|
|
* |
306
|
|
|
* @todo doesn't know yet about the new structure. |
307
|
|
|
*/ |
308
|
|
|
protected function uninstall() |
309
|
|
|
{ |
310
|
|
|
@unlink(__FILE__); |
311
|
|
|
|
312
|
|
|
if (preg_match('~_importer\.xml$~', $this->data['import_script']) !== 0) |
313
|
|
|
{ |
314
|
|
|
@unlink(BASEDIR . DS . $this->data['import_script']); |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
$this->data['import_script'] = null; |
318
|
|
|
} |
319
|
|
|
|
320
|
|
|
/** |
321
|
|
|
* File validation, existence and format checking |
322
|
|
|
* |
323
|
|
|
* @param string $script |
324
|
|
|
* |
325
|
|
|
* @return bool|mixed |
326
|
|
|
*/ |
327
|
|
|
protected function validateScript($script) |
328
|
|
|
{ |
329
|
|
|
if (empty($script)) |
330
|
|
|
{ |
331
|
|
|
return false; |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
$script = preg_replace('~\.+~', '.', $script); |
335
|
|
|
|
336
|
|
|
if (file_exists(BASEDIR . DS . 'Importers' . DS . $script) |
337
|
|
|
&& preg_match('~_importer\.xml$~', $script) !== 0) |
338
|
|
|
{ |
339
|
|
|
return $script; |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
return false; |
343
|
|
|
} |
344
|
|
|
|
345
|
|
|
/** |
346
|
|
|
* Finds import scripts that we can offer for usage |
347
|
|
|
* |
348
|
|
|
* - checks, if we have already specified an importer script |
349
|
|
|
* - checks the file system for importer definition files |
350
|
|
|
* |
351
|
|
|
* @return boolean |
352
|
|
|
*/ |
353
|
|
|
private function _detect_scripts() |
354
|
|
|
{ |
355
|
|
|
if ($this->config->script !== null) |
356
|
|
|
{ |
357
|
|
|
$this->data['import_script'] = $this->validateScript($this->data['import_script']); |
358
|
|
|
$this->config->script = $this->data['import_script']; |
|
|
|
|
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
$sources = glob(BASEDIR . DS . 'Importers' . DS . '*', GLOB_ONLYDIR); |
362
|
|
|
$count_scripts = 0; |
363
|
|
|
$scripts = array(); |
364
|
|
|
$destination_names = array(); |
365
|
|
|
$from = ''; |
366
|
|
|
foreach ($sources as $source) |
367
|
|
|
{ |
368
|
|
|
$from = basename($source); |
369
|
|
|
$scripts[$from] = array(); |
370
|
|
|
$possible_scripts = glob($source . DS . '*_importer.xml'); |
371
|
|
|
|
372
|
|
|
// Silence simplexml errors |
373
|
|
|
libxml_use_internal_errors(true); |
374
|
|
|
foreach ($possible_scripts as $entry) |
375
|
|
|
{ |
376
|
|
|
// If a script is broken simply skip it. |
377
|
|
|
if (!$xmlObj = simplexml_load_string(file_get_contents($entry), 'SimpleXMLElement', LIBXML_NOCDATA)) |
378
|
|
|
{ |
379
|
|
|
continue; |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
$scripts[$from][] = array('path' => $from . DS . basename($entry), 'name' => (string) $xmlObj->general->name); |
383
|
|
|
$destination_names[$from] = (string) $xmlObj->general->version; |
384
|
|
|
$count_scripts++; |
385
|
|
|
} |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
if (!empty($this->data['import_script'])) |
389
|
|
|
{ |
390
|
|
|
if ($count_scripts > 1) |
391
|
|
|
{ |
392
|
|
|
$this->sources[$from] = $scripts[$from]; |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
return false; |
396
|
|
|
} |
397
|
|
|
|
398
|
|
|
if ($count_scripts === 1) |
399
|
|
|
{ |
400
|
|
|
$this->data['import_script'] = basename($scripts[$from][0]['path']); |
401
|
|
|
if (substr($this->data['import_script'], -4) === '.xml') |
402
|
|
|
{ |
403
|
|
|
try |
404
|
|
|
{ |
405
|
|
|
$this->importer->reloadImporter(); |
406
|
|
|
} |
407
|
|
|
catch (\Exception $e) |
408
|
|
|
{ |
409
|
|
|
$this->data['import_script'] = null; |
410
|
|
|
} |
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
return false; |
414
|
|
|
} |
415
|
|
|
|
416
|
|
|
foreach ($scripts as $key => $val) |
417
|
|
|
{ |
418
|
|
|
usort($scripts[$key], static function ($v1, $v2) |
419
|
|
|
{ |
420
|
|
|
return strcasecmp($v1['name'], $v2['name']); |
421
|
|
|
}); |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
$this->response->use_template = 'select_script'; |
425
|
|
|
$this->response->params_template = array($scripts, $destination_names); |
426
|
|
|
|
427
|
|
|
return true; |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
/** |
431
|
|
|
* Collects all the important things, the importer can't do anything |
432
|
|
|
* without this information. |
433
|
|
|
* |
434
|
|
|
* @param string|null $error_message |
435
|
|
|
* @param object|null|bool $object |
436
|
|
|
* |
437
|
|
|
* @return boolean|null |
438
|
|
|
*/ |
439
|
|
|
public function doStep0($error_message = null, $object = false) |
440
|
|
|
{ |
441
|
|
|
global $oi_import; |
442
|
|
|
|
443
|
|
|
$oi_import = $object ?? false; |
444
|
|
|
$this->cookie->destroy(); |
445
|
|
|
|
446
|
|
|
// Previously imported? we need to clean some variables .. |
447
|
|
|
unset($_SESSION['import_overall'], $_SESSION['import_steps']); |
448
|
|
|
|
449
|
|
|
if ($this->_detect_scripts()) |
450
|
|
|
{ |
451
|
|
|
return true; |
452
|
|
|
} |
453
|
|
|
|
454
|
|
|
try |
455
|
|
|
{ |
456
|
|
|
$this->importer->reloadImporter(); |
457
|
|
|
} |
458
|
|
|
catch (\Exception $e) |
459
|
|
|
{ |
460
|
|
|
$this->response->template_error = true; |
461
|
|
|
$this->response->addErrorParam($e->getMessage()); |
462
|
|
|
} |
463
|
|
|
|
464
|
|
|
// Show the step0 template, used to define source/destination directories |
465
|
|
|
$form = new Form($this->language); |
466
|
|
|
$this->_prepareStep0Form($form); |
467
|
|
|
$this->response->use_template = 'step0'; |
468
|
|
|
$this->response->params_template = array($this, $form); |
469
|
|
|
|
470
|
|
|
// If we have errors, it's the end of the road |
471
|
|
|
if ($error_message !== null) |
472
|
|
|
{ |
473
|
|
|
$this->template->footer(); |
474
|
|
|
exit; |
|
|
|
|
475
|
|
|
} |
476
|
|
|
|
477
|
|
|
return null; |
478
|
|
|
} |
479
|
|
|
|
480
|
|
|
protected function _prepareStep0Form($form) |
481
|
|
|
{ |
482
|
|
|
$form->action_url = $_SERVER['PHP_SELF'] . '?step=1'; |
483
|
|
|
|
484
|
|
|
$this->importer->populateFormFields($form); |
485
|
|
|
|
486
|
|
|
return $form; |
487
|
|
|
} |
488
|
|
|
|
489
|
|
|
protected function testFiles($files, $path) |
490
|
|
|
{ |
491
|
|
|
$files = (array) $files; |
492
|
|
|
|
493
|
|
|
$test = empty($files); |
494
|
|
|
|
495
|
|
|
foreach ($files as $file) |
496
|
|
|
{ |
497
|
|
|
$test |= @file_exists($path . DS . $file); |
498
|
|
|
} |
499
|
|
|
|
500
|
|
|
return $test; |
501
|
|
|
} |
502
|
|
|
|
503
|
|
|
/** |
504
|
|
|
* The important one, transfer the content from the source forum to our |
505
|
|
|
* destination system |
506
|
|
|
* |
507
|
|
|
* @throws \Exception |
508
|
|
|
* |
509
|
|
|
* @return boolean |
510
|
|
|
*/ |
511
|
|
|
public function doStep1() |
512
|
|
|
{ |
513
|
|
|
$this->cookie->set(array($this->config->path_to, $this->config->path_from)); |
514
|
|
|
|
515
|
|
|
$do_steps = $this->step1Progress(); |
516
|
|
|
|
517
|
|
|
try |
518
|
|
|
{ |
519
|
|
|
$this->importer->doStep1($do_steps); |
|
|
|
|
520
|
|
|
} |
521
|
|
|
catch (DatabaseException $e) |
522
|
|
|
{ |
523
|
|
|
$trace = $e->getTrace(); |
524
|
|
|
$this->template->error($e->getMessage(), $trace[0]['args'][1] ?? null, $e->getLine(), $e->getFile()); |
525
|
|
|
|
526
|
|
|
// Forward back to the original caller to terminate the script |
527
|
|
|
throw new \Exception($e->getMessage()); |
528
|
|
|
} |
529
|
|
|
|
530
|
|
|
$_GET['substep'] = 0; |
531
|
|
|
$_REQUEST['start'] = 0; |
532
|
|
|
|
533
|
|
|
return $this->doStep2(); |
534
|
|
|
} |
535
|
|
|
|
536
|
|
|
/** |
537
|
|
|
* Show the progress being made in step 1, the main import process |
538
|
|
|
* |
539
|
|
|
* @return array |
540
|
|
|
*/ |
541
|
|
|
protected function step1Progress() |
542
|
|
|
{ |
543
|
|
|
$_GET['substep'] = isset($_GET['substep']) ? (int) @$_GET['substep'] : 0; |
544
|
|
|
// @TODO: check if this is needed |
545
|
|
|
//$progress = ($_GET['substep'] == 0 ? 1 : $_GET['substep']); |
546
|
|
|
|
547
|
|
|
// Skipping steps? |
548
|
|
|
$do_steps = $_SESSION['do_steps'] ?? array(); |
549
|
|
|
|
550
|
|
|
// Calculate our overall time and create the progress bar |
551
|
|
|
if (!isset($_SESSION['import_overall'])) |
552
|
|
|
{ |
553
|
|
|
list ($_SESSION['import_overall'], $_SESSION['import_steps']) = $this->importer->determineProgress(); |
554
|
|
|
} |
555
|
|
|
|
556
|
|
|
if (!isset($_SESSION['import_progress'])) |
557
|
|
|
{ |
558
|
|
|
$_SESSION['import_progress'] = 0; |
559
|
|
|
} |
560
|
|
|
|
561
|
|
|
return $do_steps; |
562
|
|
|
} |
563
|
|
|
|
564
|
|
|
/** |
565
|
|
|
* We have imported the old database, let's recalculate the forum statistics. |
566
|
|
|
* |
567
|
|
|
* @throws \Exception |
568
|
|
|
* @return boolean |
569
|
|
|
*/ |
570
|
|
|
public function doStep2() |
571
|
|
|
{ |
572
|
|
|
$_GET['step'] = '2'; |
573
|
|
|
$this->response->step = '2'; |
|
|
|
|
574
|
|
|
|
575
|
|
|
$this->template->step2(); |
576
|
|
|
|
577
|
|
|
try |
578
|
|
|
{ |
579
|
|
|
$key = $this->importer->doStep2(); |
580
|
|
|
} |
581
|
|
|
catch (DatabaseException $e) |
582
|
|
|
{ |
583
|
|
|
$trace = $e->getTrace(); |
584
|
|
|
$this->template->error($e->getMessage(), $trace[0]['args'][1] ?? null, $e->getLine(), $e->getFile()); |
585
|
|
|
|
586
|
|
|
// Forward back to the original caller to terminate the script |
587
|
|
|
throw new \Exception($e->getMessage()); |
588
|
|
|
} |
589
|
|
|
|
590
|
|
|
$this->template->status($key + 1, 1, false, true); |
|
|
|
|
591
|
|
|
|
592
|
|
|
return $this->doStep3(); |
593
|
|
|
} |
594
|
|
|
|
595
|
|
|
/** |
596
|
|
|
* We are done :) |
597
|
|
|
* |
598
|
|
|
* @return boolean |
599
|
|
|
*/ |
600
|
|
|
public function doStep3() |
601
|
|
|
{ |
602
|
|
|
$this->importer->doStep3(); |
603
|
|
|
|
604
|
|
|
$writable = (is_writable(BASEDIR) && is_writable(__FILE__)); |
605
|
|
|
|
606
|
|
|
$this->response->use_template = 'step3'; |
607
|
|
|
$this->response->params_template = array($this->importer->xml->general->name, $this->_boardurl, $writable); |
608
|
|
|
|
609
|
|
|
unset ($_SESSION['import_steps'], $_SESSION['import_progress'], $_SESSION['import_overall']); |
610
|
|
|
$this->data = array(); |
611
|
|
|
|
612
|
|
|
return true; |
613
|
|
|
} |
614
|
|
|
} |
615
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.