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
|
|
|
* There are (4) abstract classes in this file |
16
|
|
|
* - SmfCommonSource, SmfCommonSourceStep1, SmfCommonSourceStep2, SmfCommonSourceStep3 |
17
|
|
|
*/ |
18
|
|
|
|
19
|
|
|
namespace Importers; |
20
|
|
|
|
21
|
|
|
use OpenImporter\Configurator; |
22
|
|
|
use OpenImporter\Database; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* Class SmfCommonSource |
26
|
|
|
* |
27
|
|
|
* The class contains code that allows the Importer to obtain settings |
28
|
|
|
* from software that still has an SMF heritage. |
29
|
|
|
* |
30
|
|
|
* @class SmfCommonSource |
31
|
|
|
*/ |
32
|
|
|
abstract class SmfCommonSource |
33
|
|
|
{ |
34
|
|
|
/** @var string The attachment extension */ |
35
|
|
|
public $attach_extension = ''; |
36
|
|
|
/** @var int */ |
37
|
|
|
public $id_attach; |
38
|
|
|
/** @var string */ |
39
|
|
|
public $attachmentUploadDirs; |
40
|
|
|
/** @var string */ |
41
|
|
|
public $avatarUploadDir; |
42
|
|
|
/** @var string Path to the forum */ |
43
|
|
|
protected $path; |
44
|
|
|
/** @var \OpenImporter\Configurator */ |
45
|
|
|
protected $config; |
46
|
|
|
/** @var \OpenImporter\Database */ |
47
|
|
|
protected $db; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Set the database and configuration to the class |
51
|
|
|
* |
52
|
|
|
* @param Database $db |
53
|
|
|
* @param Configurator $config |
54
|
|
|
*/ |
55
|
|
|
public function setParam($db, $config) |
56
|
|
|
{ |
57
|
|
|
$this->db = $db; |
58
|
|
|
$this->config = $config; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
abstract public function getName(); |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* The path to our destination forum |
65
|
|
|
* |
66
|
|
|
* @param $path |
67
|
|
|
* |
68
|
|
|
* @return bool|string |
69
|
|
|
*/ |
70
|
|
|
public function getDestinationURL($path) |
71
|
|
|
{ |
72
|
|
|
// Cannot find Settings.php? |
73
|
|
|
if (!$this->checkSettingsPath($path)) |
74
|
|
|
{ |
75
|
|
|
return false; |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
// Everything should be alright now... no cross server includes, we hope... |
79
|
|
|
return $this->fetchSetting('boardurl'); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Check that the Settings.php file exists |
84
|
|
|
* |
85
|
|
|
* @param $path |
86
|
|
|
* |
87
|
|
|
* @return bool |
88
|
|
|
*/ |
89
|
|
|
public function checkSettingsPath($path) |
90
|
|
|
{ |
91
|
|
|
$found = file_exists($path . '/Settings.php'); |
92
|
|
|
|
93
|
|
|
if ($found && $this->path === null) |
94
|
|
|
{ |
95
|
|
|
$this->path = $path; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
return $found; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
public function fetchSetting($name) |
102
|
|
|
{ |
103
|
|
|
static $content = null; |
104
|
|
|
|
105
|
|
|
if ($content === null) |
106
|
|
|
{ |
107
|
|
|
$content = file_get_contents($this->path . '/Settings.php'); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
$match = array(); |
111
|
|
|
preg_match('~\$' . $name . '\s*=\s*\'(.*?)\';~', $content, $match); |
112
|
|
|
|
113
|
|
|
return isset($match[1]) ? $match[1] : ''; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
public function getFormFields($path_to = '') |
117
|
|
|
{ |
118
|
|
|
return array( |
119
|
|
|
'id' => 'path_to', |
120
|
|
|
'label' => 'path_to_destination', |
121
|
|
|
'type' => 'text', |
122
|
|
|
'default' => htmlspecialchars($path_to), |
123
|
|
|
'correct' => $this->checkSettingsPath($path_to) ? 'right_path' : 'change_path', |
124
|
|
|
'validate' => true, |
125
|
|
|
); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
public function verifyDbPass($pwd_to_verify) |
129
|
|
|
{ |
130
|
|
|
if ($this->path === null) |
131
|
|
|
{ |
132
|
|
|
return false; |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
$db_passwd = $this->fetchSetting('db_passwd'); |
136
|
|
|
|
137
|
|
|
return $db_passwd === $pwd_to_verify; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
public function dbConnectionData() |
141
|
|
|
{ |
142
|
|
|
if ($this->path === null) |
143
|
|
|
{ |
144
|
|
|
return false; |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
$db_server = $this->fetchSetting('db_server'); |
148
|
|
|
$db_user = $this->fetchSetting('db_user'); |
149
|
|
|
$db_passwd = $this->fetchSetting('db_passwd'); |
150
|
|
|
$db_persist = $this->fetchSetting('db_persist'); |
151
|
|
|
$db_prefix = $this->fetchSetting('db_prefix'); |
152
|
|
|
$db_name = $this->fetchSetting('db_name'); |
153
|
|
|
|
154
|
|
|
return array($db_server, $db_user, $db_passwd, $db_persist, $db_prefix, $db_name); |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
/** |
158
|
|
|
* Helper function for old (SMF) attachments and some new ones |
159
|
|
|
* |
160
|
|
|
* @param string $filename |
161
|
|
|
* @param int $attachment_id |
162
|
|
|
* @param bool $legacy if true returns legacy SMF file name (default true) |
163
|
|
|
* |
164
|
|
|
* @return string |
165
|
|
|
*/ |
166
|
|
|
public function getLegacyAttachmentFilename($filename, $attachment_id, $legacy = true) |
167
|
|
|
{ |
168
|
|
|
$se = array("ä", "ö", "ü", "Ä", "Ö", "Ü", "ß"); |
169
|
|
|
$repl = array("a", "o", "u", "A", "O", "U", "ss"); |
170
|
|
|
$filename = str_replace($se, $repl, $filename); |
171
|
|
|
|
172
|
|
|
// Remove special accented characters - ie. sí (because they won't write to the filesystem well.) |
173
|
|
|
$clean_name = strtr($filename, 'ŠŽšžŸÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜÝàáâãäåçèéêëìíîïñòóôõöøùúûüýÿ', 'SZszYAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy'); |
174
|
|
|
$clean_name = strtr($clean_name, array('Þ' => 'TH', 'þ' => 'th', 'Ð' => 'DH', 'ð' => 'dh', 'ß' => 'ss', 'Œ' => 'OE', 'œ' => 'oe', 'Æ' => 'AE', 'æ' => 'ae', 'µ' => 'u')); |
175
|
|
|
|
176
|
|
|
// Get rid of dots, spaces, and other weird characters. |
177
|
|
|
$clean_name = preg_replace(array('/\s/', '/[^\w_\.\-]/'), array('_', ''), $clean_name); |
178
|
|
|
|
179
|
|
|
if ($legacy) |
180
|
|
|
{ |
181
|
|
|
// @todo not sure about that one |
182
|
|
|
$clean_name = preg_replace('~\.[\.]+~', '.', $clean_name); |
183
|
|
|
|
184
|
|
|
return $attachment_id . '_' . strtr($clean_name, '.', '_') . md5($clean_name); |
185
|
|
|
} |
186
|
|
|
else |
187
|
|
|
{ |
188
|
|
|
return $attachment_id . '_' . strtr($clean_name, '.', '_') . md5($clean_name) . '.' . $this->attach_extension; |
189
|
|
|
} |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
public function getAvatarDir($row) |
193
|
|
|
{ |
194
|
|
|
if ($this->avatarUploadDir === null) |
195
|
|
|
{ |
196
|
|
|
return $this->getAttachDir($row); |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
return $this->avatarUploadDir; |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
public function getAttachDir($row) |
203
|
|
|
{ |
204
|
|
|
$this->specialAttachments(); |
205
|
|
|
|
206
|
|
|
if (!empty($row['id_folder']) && !empty($this->attachmentUploadDirs[$row['id_folder']])) |
207
|
|
|
{ |
208
|
|
|
return $this->attachmentUploadDirs[$row['id_folder']]; |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
return $this->attachmentUploadDirs[1]; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* Determine the source attachment and avatar directories |
216
|
|
|
* |
217
|
|
|
* @param bool $force |
218
|
|
|
*/ |
219
|
|
|
public function specialAttachments($force = false) |
220
|
|
|
{ |
221
|
|
|
$to_prefix = $this->config->to_prefix; |
222
|
|
|
|
223
|
|
|
// If we don't know the attachment or avatar directories |
224
|
|
|
if ($force === true || !isset($this->id_attach, $this->attachmentUploadDirs, $this->avatarUploadDir)) |
225
|
|
|
{ |
226
|
|
|
// Attachment starting id |
227
|
|
|
$result = $this->db->query(" |
228
|
|
|
SELECT MAX(id_attach) + 1 |
229
|
|
|
FROM {$to_prefix}attachments"); |
230
|
|
|
list ($this->id_attach) = $this->db->fetch_row($result); |
231
|
|
|
$this->db->free_result($result); |
232
|
|
|
|
233
|
|
|
// Attachment directories |
234
|
|
|
$result = $this->db->query(" |
235
|
|
|
SELECT value |
236
|
|
|
FROM {$to_prefix}settings |
237
|
|
|
WHERE variable = 'attachmentUploadDir' |
238
|
|
|
LIMIT 1"); |
239
|
|
|
list ($attachmentdir) = $this->db->fetch_row($result); |
240
|
|
|
$attachment_UploadDir = @unserialize($attachmentdir); |
241
|
|
|
$this->attachmentUploadDirs = !empty($attachment_UploadDir) ? $attachment_UploadDir : array(1 => $attachmentdir); |
|
|
|
|
242
|
|
|
|
243
|
|
|
// Avatar directories |
244
|
|
|
$result = $this->db->query(" |
245
|
|
|
SELECT value |
246
|
|
|
FROM {$to_prefix}settings |
247
|
|
|
WHERE variable = 'custom_avatar_dir' |
248
|
|
|
LIMIT 1"); |
249
|
|
|
list ($this->avatarUploadDir) = $this->db->fetch_row($result); |
250
|
|
|
$this->db->free_result($result); |
251
|
|
|
|
252
|
|
|
if (empty($this->avatarUploadDir)) |
253
|
|
|
{ |
254
|
|
|
$this->avatarUploadDir = ''; |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
if (empty($this->id_attach)) |
258
|
|
|
{ |
259
|
|
|
$this->id_attach = 1; |
260
|
|
|
} |
261
|
|
|
} |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
public function getAllAttachDirs() |
265
|
|
|
{ |
266
|
|
|
if ($this->attachmentUploadDirs === null) |
267
|
|
|
{ |
268
|
|
|
$this->specialAttachments(); |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
return $this->attachmentUploadDirs; |
272
|
|
|
} |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* Class SmfCommonSourceStep1 |
277
|
|
|
* |
278
|
|
|
* @class SmfCommonSourceStep1 |
279
|
|
|
*/ |
280
|
|
|
abstract class SmfCommonSourceStep1 extends Step1BaseImporter |
281
|
|
|
{ |
282
|
|
|
public function doSpecialTable($special_table, $params = null) |
283
|
|
|
{ |
284
|
|
|
// Are we doing attachments? They're going to want a few things... |
285
|
|
|
if ($special_table == $this->config->to_prefix . 'attachments' && $params === null) |
286
|
|
|
{ |
287
|
|
|
$this->config->destination->specialAttachments(); |
|
|
|
|
288
|
|
|
|
289
|
|
|
return $params; |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
// Here we have various bits of custom code for some known problems global to all importers. |
293
|
|
|
if ($special_table == $this->config->to_prefix . 'members' && $params !== null) |
294
|
|
|
{ |
295
|
|
|
return $this->specialMembers($params); |
296
|
|
|
} |
297
|
|
|
|
298
|
|
|
return $params; |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
protected function specialMembers($row) |
302
|
|
|
{ |
303
|
|
|
// Let's ensure there are no illegal characters. |
304
|
|
|
$row['member_name'] = preg_replace('/[<>&"\'=\\\]/is', '', $row['member_name']); |
305
|
|
|
$row['real_name'] = trim($row['real_name'], " \t\n\r\x0B\0\xA0"); |
306
|
|
|
|
307
|
|
|
if (strpos($row['real_name'], '<') !== false || strpos($row['real_name'], '>') !== false || strpos($row['real_name'], '& ') !== false) |
308
|
|
|
{ |
309
|
|
|
$row['real_name'] = htmlspecialchars($row['real_name'], ENT_QUOTES); |
310
|
|
|
} |
311
|
|
|
else |
312
|
|
|
{ |
313
|
|
|
$row['real_name'] = strtr($row['real_name'], array('\'' => ''')); |
314
|
|
|
} |
315
|
|
|
|
316
|
|
|
return $row; |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
/** |
320
|
|
|
* Delete any defined db attachments that exist on disk for the source system |
321
|
|
|
*/ |
322
|
|
|
public function removeAttachments() |
323
|
|
|
{ |
324
|
|
|
$to_prefix = $this->config->to_prefix; |
325
|
|
|
|
326
|
|
|
// @todo This should probably be done in chunks too. |
327
|
|
|
// attachment_type = 1 are avatars. |
328
|
|
|
$result = $this->db->query(" |
329
|
|
|
SELECT id_attach, filename, id_folder |
330
|
|
|
FROM {$to_prefix}attachments"); |
331
|
|
|
|
332
|
|
|
while ($row = $this->db->fetch_assoc($result)) |
333
|
|
|
{ |
334
|
|
|
$enc_name = $this->config->destination->getLegacyAttachmentFilename($row['filename'], $row['id_attach'], false); |
335
|
|
|
|
336
|
|
|
$attach_dir = $this->getAttachDir($row); |
337
|
|
|
|
338
|
|
|
if (file_exists($attach_dir . '/' . $enc_name)) |
339
|
|
|
{ |
340
|
|
|
$filename = $attach_dir . '/' . $enc_name; |
341
|
|
|
} |
342
|
|
|
else |
343
|
|
|
{ |
344
|
|
|
// @todo this should not be here I think: it's SMF-specific, while this file shouldn't know anything about the source |
345
|
|
|
$clean_name = $this->config->destination->getLegacyAttachmentFilename($row['filename'], $row['id_attach'], true); |
346
|
|
|
$filename = $attach_dir . '/' . $clean_name; |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
if (is_file($filename)) |
350
|
|
|
{ |
351
|
|
|
@unlink($filename); |
352
|
|
|
} |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
$this->db->free_result($result); |
356
|
|
|
|
357
|
|
|
// This is valid for some of the sources (e.g. Elk/SMF/Wedge), but not for others |
358
|
|
|
if (method_exists($this->config->source, 'getAttachmentDirs')) |
359
|
|
|
{ |
360
|
|
|
$this->createAttachFoldersStructure($this->config->source->getAttachmentDirs()); |
361
|
|
|
} |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
public function getAttachDir($row) |
365
|
|
|
{ |
366
|
|
|
return $this->config->destination->getAttachDir($row); |
367
|
|
|
} |
368
|
|
|
|
369
|
|
|
/** |
370
|
|
|
* Create the destination directory structure for the attachments |
371
|
|
|
* |
372
|
|
|
* @param string[] $folders |
373
|
|
|
* |
374
|
|
|
* @return bool |
375
|
|
|
*/ |
376
|
|
|
protected function createAttachFoldersStructure($folders) |
377
|
|
|
{ |
378
|
|
|
$source_base = $this->guessBase($folders); |
379
|
|
|
$destination_base = $this->guessBase($this->config->destination->getAllAttachDirs()); |
380
|
|
|
|
381
|
|
|
// No idea where to start, better not mess with the filesystem |
382
|
|
|
// Though if $destination_base is empty it *is* a mess. |
383
|
|
|
if (empty($source_base) || empty($destination_base)) |
384
|
|
|
{ |
385
|
|
|
return false; |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
$dest_folders = str_replace($source_base, $destination_base, $folders); |
389
|
|
|
|
390
|
|
|
// Prepare the directory structure |
391
|
|
|
foreach ($dest_folders as $folder) |
392
|
|
|
{ |
393
|
|
|
create_folders_recursive($folder); |
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
// Save the new structure in the database |
397
|
|
|
$this->db->query(" |
398
|
|
|
UPDATE {$this->config->to_prefix}settings |
399
|
|
|
SET value = '" . serialize($dest_folders) . "' |
400
|
|
|
WHERE variable = 'attachmentUploadDir' |
401
|
|
|
LIMIT 1"); |
402
|
|
|
|
403
|
|
|
// Reload the new directories |
404
|
|
|
$this->config->destination->specialAttachments(true); |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
/** |
408
|
|
|
* Determine the base / root folder for attachments |
409
|
|
|
* |
410
|
|
|
* @param string[] $folders |
411
|
|
|
* |
412
|
|
|
* @return bool|string |
413
|
|
|
*/ |
414
|
|
|
protected function guessBase($folders) |
415
|
|
|
{ |
416
|
|
|
foreach ($folders as $folder) |
417
|
|
|
{ |
418
|
|
|
if ($this->isCommon($folder, $folders)) |
419
|
|
|
{ |
420
|
|
|
return $folder; |
421
|
|
|
} |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
foreach ($folders as $folder) |
425
|
|
|
{ |
426
|
|
|
$dir = $folder; |
427
|
|
|
while (strlen($dir) > 4) |
428
|
|
|
{ |
429
|
|
|
$dir = dirname($dir); |
430
|
|
|
if ($this->isCommon($dir, $folders)) |
431
|
|
|
{ |
432
|
|
|
return $dir; |
433
|
|
|
} |
434
|
|
|
} |
435
|
|
|
} |
436
|
|
|
|
437
|
|
|
return false; |
438
|
|
|
} |
439
|
|
|
|
440
|
|
|
protected function isCommon($dir, $folders) |
441
|
|
|
{ |
442
|
|
|
foreach ($folders as $folder) |
443
|
|
|
{ |
444
|
|
|
if (substr($folder, 0, strlen($dir)) !== $dir) |
445
|
|
|
{ |
446
|
|
|
return false; |
447
|
|
|
} |
448
|
|
|
} |
449
|
|
|
|
450
|
|
|
return true; |
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
public function moveAvatar($row, $source, $filename) |
454
|
|
|
{ |
455
|
|
|
$avatar_attach_folder = $this->getAvatarFolderId($row); |
456
|
|
|
|
457
|
|
|
if ($avatar_attach_folder === false) |
458
|
|
|
{ |
459
|
|
|
$extensions = array( |
460
|
|
|
'1' => 'gif', |
461
|
|
|
'2' => 'jpg', |
462
|
|
|
'3' => 'png', |
463
|
|
|
'6' => 'bmp' |
464
|
|
|
); |
465
|
|
|
|
466
|
|
|
$sizes = @getimagesize($source); |
467
|
|
|
$extension = isset($extensions[$sizes[2]]) ? $extensions[$sizes[2]] : 'bmp'; |
468
|
|
|
$file_hash = 'avatar_' . $row['id_member'] . '_' . time() . '.' . $extension; |
469
|
|
|
|
470
|
|
|
$this->db->query(" |
471
|
|
|
UPDATE {$this->config->to_prefix}members |
472
|
|
|
SET avatar = '$file_hash' |
473
|
|
|
WHERE id_member = $row[id_member]"); |
474
|
|
|
|
475
|
|
|
$destination = $this->getAvatarDir($row) . '/' . $file_hash; |
476
|
|
|
|
477
|
|
|
$return = false; |
478
|
|
|
} |
479
|
|
|
else |
480
|
|
|
{ |
481
|
|
|
$file_hash = createAttachmentFileHash($filename); |
482
|
|
|
$id_attach = $this->newIdAttach(); |
483
|
|
|
|
484
|
|
|
$destination = $this->getAvatarDir($row) . '/' . $id_attach . '_' . $file_hash . '.' . $this->config->destination->attach_extension; |
485
|
|
|
|
486
|
|
|
$return = array( |
487
|
|
|
'id_attach' => $id_attach, |
488
|
|
|
'size' => filesize($destination), |
489
|
|
|
'filename' => '\'' . $row['filename'] . '\'', |
490
|
|
|
'file_hash' => '\'' . $file_hash . '\'', |
491
|
|
|
'id_member' => $row['id_member'], |
492
|
|
|
'id_folder' => $avatar_attach_folder, |
493
|
|
|
); |
494
|
|
|
} |
495
|
|
|
|
496
|
|
|
copy_file($source, $destination); |
497
|
|
|
|
498
|
|
|
return $return; |
499
|
|
|
} |
500
|
|
|
|
501
|
|
|
public function getAvatarFolderId($row) |
|
|
|
|
502
|
|
|
{ |
503
|
|
|
// @todo in theory we could be able to find the "current" directory |
504
|
|
|
if ($this->config->destination->avatarUploadDir === null) |
505
|
|
|
{ |
506
|
|
|
return 1; |
507
|
|
|
} |
508
|
|
|
|
509
|
|
|
return false; |
510
|
|
|
} |
511
|
|
|
|
512
|
|
|
public function getAvatarDir($row) |
513
|
|
|
{ |
514
|
|
|
return $this->config->destination->getAvatarDir($row); |
515
|
|
|
} |
516
|
|
|
|
517
|
|
|
public function newIdAttach() |
518
|
|
|
{ |
519
|
|
|
// The one to return |
520
|
|
|
$current = $this->config->destination->id_attach; |
521
|
|
|
|
522
|
|
|
// Increase preparing for the next one |
523
|
|
|
$this->config->destination->id_attach++; |
524
|
|
|
|
525
|
|
|
return $current; |
526
|
|
|
} |
527
|
|
|
} |
528
|
|
|
|
529
|
|
|
/** |
530
|
|
|
* Class SmfCommonSourceStep2 |
531
|
|
|
* |
532
|
|
|
* @class SmfCommonSourceStep2 |
533
|
|
|
*/ |
534
|
|
|
abstract class SmfCommonSourceStep2 extends Step2BaseImporter |
535
|
|
|
{ |
536
|
|
|
abstract public function substep0(); |
537
|
|
|
|
538
|
|
|
public function substep1() |
539
|
|
|
{ |
540
|
|
|
$to_prefix = $this->config->to_prefix; |
541
|
|
|
|
542
|
|
|
$request = $this->db->query(" |
543
|
|
|
SELECT |
544
|
|
|
id_board, MAX(id_msg) AS id_last_msg, MAX(modified_time) AS last_edited |
545
|
|
|
FROM {$to_prefix}messages |
546
|
|
|
GROUP BY id_board"); |
547
|
|
|
$modifyData = array(); |
548
|
|
|
$modifyMsg = array(); |
549
|
|
|
while ($row = $this->db->fetch_assoc($request)) |
550
|
|
|
{ |
551
|
|
|
$this->setBoardProperty($row['id_board'], array('id_last_msg' => $row['id_last_msg'], 'id_msg_updated' => $row['id_last_msg'])); |
552
|
|
|
|
553
|
|
|
$modifyData[$row['id_board']] = array( |
554
|
|
|
'last_msg' => $row['id_last_msg'], |
555
|
|
|
'last_edited' => $row['last_edited'], |
556
|
|
|
); |
557
|
|
|
$modifyMsg[] = $row['id_last_msg']; |
558
|
|
|
} |
559
|
|
|
$this->db->free_result($request); |
560
|
|
|
|
561
|
|
|
// Are there any boards where the updated message is not the last? |
562
|
|
|
if (!empty($modifyMsg)) |
563
|
|
|
{ |
564
|
|
|
$request = $this->db->query(" |
565
|
|
|
SELECT id_board, id_msg, modified_time, poster_time |
566
|
|
|
FROM {$to_prefix}messages |
567
|
|
|
WHERE id_msg IN (" . implode(',', $modifyMsg) . ")"); |
568
|
|
|
while ($row = $this->db->fetch_assoc($request)) |
569
|
|
|
{ |
570
|
|
|
// Have we got a message modified before this was posted? |
571
|
|
|
if (max($row['modified_time'], $row['poster_time']) < $modifyData[$row['id_board']]['last_edited']) |
572
|
|
|
{ |
573
|
|
|
// Work out the ID of the message (This seems long but it won't happen much. |
574
|
|
|
$request2 = $this->db->query(" |
575
|
|
|
SELECT id_msg |
576
|
|
|
FROM {$to_prefix}messages |
577
|
|
|
WHERE modified_time = " . $modifyData[$row['id_board']]['last_edited'] . " |
578
|
|
|
LIMIT 1"); |
579
|
|
|
if ($this->db->num_rows($request2) != 0) |
580
|
|
|
{ |
581
|
|
|
list ($id_msg) = $this->db->fetch_row($request2); |
582
|
|
|
|
583
|
|
|
$this->setBoardProperty($row['id_board'], array('id_msg_updated' => $id_msg)); |
584
|
|
|
} |
585
|
|
|
$this->db->free_result($request2); |
586
|
|
|
} |
587
|
|
|
} |
588
|
|
|
$this->db->free_result($request); |
589
|
|
|
} |
590
|
|
|
} |
591
|
|
|
|
592
|
|
|
protected function setBoardProperty($board, $property, $where = null) |
593
|
|
|
{ |
594
|
|
|
$to_prefix = $this->config->to_prefix; |
595
|
|
|
|
596
|
|
|
$sets = array(); |
597
|
|
|
foreach ($property as $k => $v) |
598
|
|
|
{ |
599
|
|
|
$sets[] = $k . ' = ' . $v; |
600
|
|
|
} |
601
|
|
|
$set = implode(', ', $sets); |
602
|
|
|
|
603
|
|
|
if ($where === null) |
604
|
|
|
{ |
605
|
|
|
if (empty($board)) |
606
|
|
|
{ |
607
|
|
|
return; |
608
|
|
|
} |
609
|
|
|
|
610
|
|
|
$where = "id_board = $board"; |
611
|
|
|
} |
612
|
|
|
|
613
|
|
|
$this->db->query(" |
614
|
|
|
UPDATE {$to_prefix}boards |
615
|
|
|
SET $set |
616
|
|
|
WHERE $where"); |
617
|
|
|
} |
618
|
|
|
|
619
|
|
|
public function substep2() |
620
|
|
|
{ |
621
|
|
|
$to_prefix = $this->config->to_prefix; |
622
|
|
|
|
623
|
|
|
$request = $this->db->query(" |
624
|
|
|
SELECT |
625
|
|
|
id_group |
626
|
|
|
FROM {$to_prefix}membergroups |
627
|
|
|
WHERE min_posts = -1"); |
628
|
|
|
|
629
|
|
|
$all_groups = array(); |
630
|
|
|
while ($row = $this->db->fetch_assoc($request)) |
631
|
|
|
{ |
632
|
|
|
$all_groups[] = $row['id_group']; |
633
|
|
|
} |
634
|
|
|
$this->db->free_result($request); |
635
|
|
|
|
636
|
|
|
$request = $this->db->query(" |
637
|
|
|
SELECT |
638
|
|
|
id_board, member_groups |
639
|
|
|
FROM {$to_prefix}boards |
640
|
|
|
WHERE FIND_IN_SET(0, member_groups)"); |
641
|
|
|
|
642
|
|
|
while ($row = $this->db->fetch_assoc($request)) |
643
|
|
|
{ |
644
|
|
|
$member_groups = "'" . implode(',', array_unique(array_merge($all_groups, explode(',', $row['member_groups'])))) . "'"; |
645
|
|
|
$this->setBoardProperty($row['id_board'], array('member_groups' => $member_groups)); |
646
|
|
|
} |
647
|
|
|
$this->db->free_result($request); |
648
|
|
|
} |
649
|
|
|
|
650
|
|
|
/** |
651
|
|
|
* Fix various system totals |
652
|
|
|
*/ |
653
|
|
|
public function substep3() |
654
|
|
|
{ |
655
|
|
|
$to_prefix = $this->config->to_prefix; |
656
|
|
|
|
657
|
|
|
// Get the number of messages... |
658
|
|
|
$result = $this->db->query(" |
659
|
|
|
SELECT |
660
|
|
|
COUNT(*) AS totalMessages, MAX(id_msg) AS maxMsgID |
661
|
|
|
FROM {$to_prefix}messages"); |
662
|
|
|
$row = $this->db->fetch_assoc($result); |
663
|
|
|
$this->db->free_result($result); |
664
|
|
|
|
665
|
|
|
// Update the latest member. (Highest ID_MEMBER) |
666
|
|
|
$result = $this->db->query(" |
667
|
|
|
SELECT |
668
|
|
|
id_member AS latestMember, real_name AS latestreal_name |
669
|
|
|
FROM {$to_prefix}members |
670
|
|
|
ORDER BY id_member DESC |
671
|
|
|
LIMIT 1"); |
672
|
|
|
|
673
|
|
|
if ($this->db->num_rows($result)) |
674
|
|
|
{ |
675
|
|
|
$row += $this->db->fetch_assoc($result); |
676
|
|
|
} |
677
|
|
|
else |
678
|
|
|
{ |
679
|
|
|
$row += array('latestMember' => '', 'latestreal_name' => ''); |
680
|
|
|
} |
681
|
|
|
|
682
|
|
|
$this->db->free_result($result); |
683
|
|
|
|
684
|
|
|
// Update the member count. |
685
|
|
|
$result = $this->db->query(" |
686
|
|
|
SELECT |
687
|
|
|
COUNT(*) AS totalMembers |
688
|
|
|
FROM {$to_prefix}members"); |
689
|
|
|
$row += $this->db->fetch_assoc($result); |
690
|
|
|
$this->db->free_result($result); |
691
|
|
|
|
692
|
|
|
// Get the number of topics. |
693
|
|
|
$result = $this->db->query(" |
694
|
|
|
SELECT |
695
|
|
|
COUNT(*) AS totalTopics |
696
|
|
|
FROM {$to_prefix}topics"); |
697
|
|
|
$row += $this->db->fetch_assoc($result); |
698
|
|
|
$this->db->free_result($result); |
699
|
|
|
|
700
|
|
|
$this->db->query(" |
701
|
|
|
REPLACE INTO {$to_prefix}settings |
702
|
|
|
(variable, value) |
703
|
|
|
VALUES ('latestMember', '$row[latestMember]'), |
704
|
|
|
('latestreal_name', '$row[latestreal_name]'), |
705
|
|
|
('totalMembers', '$row[totalMembers]'), |
706
|
|
|
('totalMessages', '$row[totalMessages]'), |
707
|
|
|
('maxMsgID', '$row[maxMsgID]'), |
708
|
|
|
('totalTopics', '$row[totalTopics]'), |
709
|
|
|
('disableHashTime', " . (time() + 7776000) . ")"); |
710
|
|
|
} |
711
|
|
|
|
712
|
|
|
/** |
713
|
|
|
* Fix the post-based membergroups |
714
|
|
|
*/ |
715
|
|
|
public function substep4() |
716
|
|
|
{ |
717
|
|
|
$to_prefix = $this->config->to_prefix; |
718
|
|
|
|
719
|
|
|
$request = $this->db->query(" |
720
|
|
|
SELECT |
721
|
|
|
id_group, min_posts |
722
|
|
|
FROM {$to_prefix}membergroups |
723
|
|
|
WHERE min_posts != -1 |
724
|
|
|
ORDER BY min_posts DESC"); |
725
|
|
|
|
726
|
|
|
$post_groups = array(); |
727
|
|
|
$max = $this->db->fetch_assoc($request); |
728
|
|
|
while ($row = $this->db->fetch_assoc($request)) |
729
|
|
|
{ |
730
|
|
|
$post_groups[] = $row; |
731
|
|
|
} |
732
|
|
|
$this->db->free_result($request); |
733
|
|
|
|
734
|
|
|
$case = "CASE WHEN posts > " . $max['min_posts'] . " THEN " . $max['id_group']; |
735
|
|
|
|
736
|
|
|
$first = true; |
737
|
|
|
foreach ($post_groups as $id => $group) |
738
|
|
|
{ |
739
|
|
|
if ($first) |
740
|
|
|
{ |
741
|
|
|
$case .= " WHEN posts BETWEEN " . $group['min_posts'] . " AND " . $max['min_posts'] . " THEN " . $group['id_group']; |
742
|
|
|
$first = false; |
743
|
|
|
} |
744
|
|
|
else |
745
|
|
|
{ |
746
|
|
|
$case .= " WHEN posts BETWEEN " . $group['min_posts'] . " AND " . $post_groups[$id - 1]['min_posts'] . " THEN " . $group['id_group']; |
747
|
|
|
} |
748
|
|
|
} |
749
|
|
|
$case .= " ELSE 4 END"; |
750
|
|
|
|
751
|
|
|
$this->db->query(" |
752
|
|
|
UPDATE {$to_prefix}members |
753
|
|
|
SET id_post_group = $case"); |
754
|
|
|
} |
755
|
|
|
|
756
|
|
|
/** |
757
|
|
|
* Fix the boards total posts and topics. |
758
|
|
|
*/ |
759
|
|
|
public function substep5() |
760
|
|
|
{ |
761
|
|
|
$to_prefix = $this->config->to_prefix; |
762
|
|
|
|
763
|
|
|
$result_topics = $this->db->query(" |
764
|
|
|
SELECT |
765
|
|
|
id_board, COUNT(*) as num_topics |
766
|
|
|
FROM {$to_prefix}topics |
767
|
|
|
GROUP BY id_board"); |
768
|
|
|
|
769
|
|
|
$updates = array(); |
770
|
|
|
while ($row = $this->db->fetch_assoc($result_topics)) |
771
|
|
|
{ |
772
|
|
|
$updates[$row['id_board']] = array( |
773
|
|
|
'num_topics' => $row['num_topics'] |
774
|
|
|
); |
775
|
|
|
} |
776
|
|
|
$this->db->free_result($result_topics); |
777
|
|
|
|
778
|
|
|
// Find how many messages are in the board. |
779
|
|
|
$result_posts = $this->db->query(" |
780
|
|
|
SELECT |
781
|
|
|
id_board, COUNT(*) as num_posts |
782
|
|
|
FROM {$to_prefix}messages |
783
|
|
|
GROUP BY id_board"); |
784
|
|
|
|
785
|
|
|
while ($row = $this->db->fetch_assoc($result_posts)) |
786
|
|
|
{ |
787
|
|
|
$updates[$row['id_board']]['num_posts'] = $row['num_posts']; |
788
|
|
|
} |
789
|
|
|
$this->db->free_result($result_posts); |
790
|
|
|
|
791
|
|
|
// Fix the board's totals. |
792
|
|
|
foreach ($updates as $id_board => $vals) |
793
|
|
|
{ |
794
|
|
|
$this->setBoardProperty($id_board, $vals); |
795
|
|
|
} |
796
|
|
|
} |
797
|
|
|
|
798
|
|
|
public function substep6() |
799
|
|
|
{ |
800
|
|
|
$to_prefix = $this->config->to_prefix; |
801
|
|
|
|
802
|
|
|
while (true) |
803
|
|
|
{ |
804
|
|
|
$resultTopic = $this->db->query(" |
805
|
|
|
SELECT |
806
|
|
|
t.id_topic, COUNT(m.id_msg) AS num_msg |
807
|
|
|
FROM {$to_prefix}topics AS t |
808
|
|
|
LEFT JOIN {$to_prefix}messages AS m ON (m.id_topic = t.id_topic) |
809
|
|
|
GROUP BY t.id_topic |
810
|
|
|
HAVING num_msg = 0 |
811
|
|
|
LIMIT $_REQUEST[start], 200"); |
812
|
|
|
|
813
|
|
|
$numRows = $this->db->num_rows($resultTopic); |
814
|
|
|
|
815
|
|
|
if ($numRows > 0) |
816
|
|
|
{ |
817
|
|
|
$stupidTopics = array(); |
818
|
|
|
while ($topicArray = $this->db->fetch_assoc($resultTopic)) |
819
|
|
|
{ |
820
|
|
|
$stupidTopics[] = $topicArray['id_topic']; |
821
|
|
|
} |
822
|
|
|
$this->db->query(" |
823
|
|
|
DELETE FROM {$to_prefix}topics |
824
|
|
|
WHERE id_topic IN (" . implode(',', $stupidTopics) . ') |
825
|
|
|
LIMIT ' . count($stupidTopics)); |
826
|
|
|
$this->db->query(" |
827
|
|
|
DELETE FROM {$to_prefix}log_topics |
828
|
|
|
WHERE id_topic IN (" . implode(',', $stupidTopics) . ')'); |
829
|
|
|
} |
830
|
|
|
$this->db->free_result($resultTopic); |
831
|
|
|
|
832
|
|
|
if ($numRows < 200) |
833
|
|
|
{ |
834
|
|
|
break; |
835
|
|
|
} |
836
|
|
|
|
837
|
|
|
// @todo this should not deal with $_REQUEST and alike |
838
|
|
|
$_REQUEST['start'] += 200; |
839
|
|
|
pastTime(6); |
840
|
|
|
} |
841
|
|
|
} |
842
|
|
|
|
843
|
|
|
public function substep7() |
844
|
|
|
{ |
845
|
|
|
$to_prefix = $this->config->to_prefix; |
846
|
|
|
|
847
|
|
|
while (true) |
848
|
|
|
{ |
849
|
|
|
$resultTopic = $this->db->query(" |
850
|
|
|
SELECT |
851
|
|
|
t.id_topic, MIN(m.id_msg) AS myid_first_msg, t.id_first_msg, |
852
|
|
|
MAX(m.id_msg) AS myid_last_msg, t.id_last_msg, COUNT(m.id_msg) - 1 AS my_num_replies, |
853
|
|
|
t.num_replies |
854
|
|
|
FROM {$to_prefix}topics AS t |
855
|
|
|
LEFT JOIN {$to_prefix}messages AS m ON (m.id_topic = t.id_topic) |
856
|
|
|
GROUP BY t.id_topic |
857
|
|
|
HAVING id_first_msg != myid_first_msg OR id_last_msg != myid_last_msg OR num_replies != my_num_replies |
858
|
|
|
LIMIT $_REQUEST[start], 200"); |
859
|
|
|
|
860
|
|
|
$numRows = $this->db->num_rows($resultTopic); |
861
|
|
|
|
862
|
|
|
while ($topicArray = $this->db->fetch_assoc($resultTopic)) |
863
|
|
|
{ |
864
|
|
|
$memberStartedID = $this->getMsgMemberID($topicArray['myid_first_msg']); |
865
|
|
|
$memberUpdatedID = $this->getMsgMemberID($topicArray['myid_last_msg']); |
866
|
|
|
|
867
|
|
|
$this->db->query(" |
868
|
|
|
UPDATE {$to_prefix}topics |
869
|
|
|
SET id_first_msg = '$topicArray[myid_first_msg]', |
870
|
|
|
id_member_started = '$memberStartedID', id_last_msg = '$topicArray[myid_last_msg]', |
871
|
|
|
id_member_updated = '$memberUpdatedID', num_replies = '$topicArray[my_num_replies]' |
872
|
|
|
WHERE id_topic = $topicArray[id_topic] |
873
|
|
|
LIMIT 1"); |
874
|
|
|
} |
875
|
|
|
$this->db->free_result($resultTopic); |
876
|
|
|
|
877
|
|
|
if ($numRows < 200) |
878
|
|
|
{ |
879
|
|
|
break; |
880
|
|
|
} |
881
|
|
|
|
882
|
|
|
// @todo this should not deal with $_REQUEST and alike |
883
|
|
|
$_REQUEST['start'] += 100; |
884
|
|
|
pastTime(7); |
885
|
|
|
} |
886
|
|
|
} |
887
|
|
|
|
888
|
|
|
/** |
889
|
|
|
* |
890
|
|
|
* Get the id_member associated with the specified message. |
891
|
|
|
* |
892
|
|
|
* @param int $messageID |
893
|
|
|
* @return int |
894
|
|
|
*/ |
895
|
|
|
protected function getMsgMemberID($messageID) |
896
|
|
|
{ |
897
|
|
|
$to_prefix = $this->config->to_prefix; |
898
|
|
|
|
899
|
|
|
// Find the topic and make sure the member still exists. |
900
|
|
|
$result = $this->db->query(" |
901
|
|
|
SELECT |
902
|
|
|
IFNULL(mem.id_member, 0) |
903
|
|
|
FROM {$to_prefix}messages AS m |
904
|
|
|
LEFT JOIN {$to_prefix}members AS mem ON (mem.id_member = m.id_member) |
905
|
|
|
WHERE m.id_msg = " . (int) $messageID . " |
906
|
|
|
LIMIT 1"); |
907
|
|
|
|
908
|
|
|
if ($this->db->num_rows($result) > 0) |
909
|
|
|
{ |
910
|
|
|
list ($memberID) = $this->db->fetch_row($result); |
911
|
|
|
} |
912
|
|
|
// The message doesn't even exist. |
913
|
|
|
else |
914
|
|
|
{ |
915
|
|
|
$memberID = 0; |
916
|
|
|
} |
917
|
|
|
|
918
|
|
|
$this->db->free_result($result); |
919
|
|
|
|
920
|
|
|
return $memberID; |
921
|
|
|
} |
922
|
|
|
|
923
|
|
|
/** |
924
|
|
|
* Fix the board parents. |
925
|
|
|
*/ |
926
|
|
|
public function substep8() |
927
|
|
|
{ |
928
|
|
|
$to_prefix = $this->config->to_prefix; |
929
|
|
|
|
930
|
|
|
// First, let's get an array of boards and parents. |
931
|
|
|
$request = $this->db->query(" |
932
|
|
|
SELECT |
933
|
|
|
id_board, id_parent, id_cat |
934
|
|
|
FROM {$to_prefix}boards"); |
935
|
|
|
|
936
|
|
|
$child_map = array(); |
937
|
|
|
$cat_map = array(); |
938
|
|
|
while ($row = $this->db->fetch_assoc($request)) |
939
|
|
|
{ |
940
|
|
|
$child_map[$row['id_parent']][] = $row['id_board']; |
941
|
|
|
$cat_map[$row['id_board']] = $row['id_cat']; |
942
|
|
|
} |
943
|
|
|
$this->db->free_result($request); |
944
|
|
|
|
945
|
|
|
// Let's look for any boards with obviously invalid parents... |
946
|
|
|
foreach ($child_map as $parent => $dummy) |
947
|
|
|
{ |
948
|
|
|
if ($parent != 0 && !isset($cat_map[$parent])) |
949
|
|
|
{ |
950
|
|
|
// Perhaps it was supposed to be their id_cat? |
951
|
|
|
foreach ($dummy as $board) |
952
|
|
|
{ |
953
|
|
|
if (empty($cat_map[$board])) |
954
|
|
|
{ |
955
|
|
|
$cat_map[$board] = $parent; |
956
|
|
|
} |
957
|
|
|
} |
958
|
|
|
|
959
|
|
|
$child_map[0] = array_merge(isset($child_map[0]) ? $child_map[0] : array(), $dummy); |
960
|
|
|
unset($child_map[$parent]); |
961
|
|
|
} |
962
|
|
|
} |
963
|
|
|
|
964
|
|
|
// The above id_parents and id_cats may all be wrong; we know id_parent = 0 is right. |
965
|
|
|
$solid_parents = array(array(0, 0)); |
966
|
|
|
$fixed_boards = array(); |
967
|
|
|
while (!empty($solid_parents)) |
968
|
|
|
{ |
969
|
|
|
list ($parent, $level) = array_pop($solid_parents); |
970
|
|
|
if (!isset($child_map[$parent])) |
971
|
|
|
{ |
972
|
|
|
continue; |
973
|
|
|
} |
974
|
|
|
|
975
|
|
|
// Fix all of this board's children. |
976
|
|
|
foreach ($child_map[$parent] as $board) |
977
|
|
|
{ |
978
|
|
|
if ($parent != 0) |
979
|
|
|
{ |
980
|
|
|
$cat_map[$board] = $cat_map[$parent]; |
981
|
|
|
} |
982
|
|
|
|
983
|
|
|
$this->setBoardProperty((int) $board, array('id_parent' => (int) $parent, 'id_cat' => (int) $cat_map[$board], 'child_level' => (int) $level)); |
984
|
|
|
|
985
|
|
|
$fixed_boards[] = $board; |
986
|
|
|
$solid_parents[] = array($board, $level + 1); |
987
|
|
|
} |
988
|
|
|
} |
989
|
|
|
|
990
|
|
|
// Leftovers should be brought to the root. They had weird parents we couldn't find. |
991
|
|
|
if (count($fixed_boards) < count($cat_map)) |
992
|
|
|
{ |
993
|
|
|
$this->setBoardProperty(0, array('child_level' => 0, 'id_parent' => 0, 'child_level' => (int) $level), empty($fixed_boards) ? "1=1" : "id_board NOT IN (" . implode(', ', $fixed_boards) . ")"); |
|
|
|
|
994
|
|
|
} |
995
|
|
|
|
996
|
|
|
$this->fixInexistentCategories($cat_map); |
997
|
|
|
} |
998
|
|
|
|
999
|
|
|
/** |
1000
|
|
|
* Assigns any board belonging to a category that doesn't exist |
1001
|
|
|
* to a newly created category. |
1002
|
|
|
*/ |
1003
|
|
|
protected function fixInexistentCategories($cat_map) |
1004
|
|
|
{ |
1005
|
|
|
$to_prefix = $this->config->to_prefix; |
1006
|
|
|
|
1007
|
|
|
// Last check: any boards not in a good category? |
1008
|
|
|
$request = $this->db->query(" |
1009
|
|
|
SELECT |
1010
|
|
|
id_cat |
1011
|
|
|
FROM {$to_prefix}categories"); |
1012
|
|
|
$real_cats = array(); |
1013
|
|
|
while ($row = $this->db->fetch_assoc($request)) |
1014
|
|
|
{ |
1015
|
|
|
$real_cats[] = $row['id_cat']; |
1016
|
|
|
} |
1017
|
|
|
$this->db->free_result($request); |
1018
|
|
|
|
1019
|
|
|
$fix_cats = array(); |
1020
|
|
|
foreach ($cat_map as $cat) |
1021
|
|
|
{ |
1022
|
|
|
if (!in_array($cat, $real_cats)) |
1023
|
|
|
{ |
1024
|
|
|
$fix_cats[] = $cat; |
1025
|
|
|
} |
1026
|
|
|
} |
1027
|
|
|
|
1028
|
|
|
if (!empty($fix_cats)) |
1029
|
|
|
{ |
1030
|
|
|
$this->db->query(" |
1031
|
|
|
INSERT INTO {$to_prefix}categories |
1032
|
|
|
(name) |
1033
|
|
|
VALUES ('General Category')"); |
1034
|
|
|
$catch_cat = mysqli_insert_id($this->db->con); |
|
|
|
|
1035
|
|
|
|
1036
|
|
|
$this->setBoardProperty(0, array('id_cat' => (int) $catch_cat), "id_cat IN (" . implode(', ', array_unique($fix_cats)) . ")"); |
1037
|
|
|
} |
1038
|
|
|
} |
1039
|
|
|
|
1040
|
|
|
/** |
1041
|
|
|
* Adjust boards and categories orders. |
1042
|
|
|
*/ |
1043
|
|
|
public function substep9() |
1044
|
|
|
{ |
1045
|
|
|
$to_prefix = $this->config->to_prefix; |
1046
|
|
|
|
1047
|
|
|
$request = $this->db->query(" |
1048
|
|
|
SELECT |
1049
|
|
|
c.id_cat, c.cat_order, b.id_board, b.board_order |
1050
|
|
|
FROM {$to_prefix}categories AS c |
1051
|
|
|
LEFT JOIN {$to_prefix}boards AS b ON (b.id_cat = c.id_cat) |
1052
|
|
|
ORDER BY c.cat_order, b.child_level, b.board_order, b.id_board"); |
1053
|
|
|
$cat_order = -1; |
1054
|
|
|
$board_order = -1; |
1055
|
|
|
$curCat = -1; |
1056
|
|
|
while ($row = $this->db->fetch_assoc($request)) |
1057
|
|
|
{ |
1058
|
|
|
if ($curCat != $row['id_cat']) |
1059
|
|
|
{ |
1060
|
|
|
$curCat = $row['id_cat']; |
1061
|
|
|
if (++$cat_order != $row['cat_order']) |
1062
|
|
|
{ |
1063
|
|
|
$this->db->query(" |
1064
|
|
|
UPDATE {$to_prefix}categories |
1065
|
|
|
SET cat_order = $cat_order |
1066
|
|
|
WHERE id_cat = $row[id_cat] |
1067
|
|
|
LIMIT 1"); |
1068
|
|
|
} |
1069
|
|
|
} |
1070
|
|
|
if (!empty($row['id_board']) && ++$board_order != $row['board_order']) |
1071
|
|
|
{ |
1072
|
|
|
$this->setBoardProperty($row['id_board'], array('board_order' => $board_order)); |
1073
|
|
|
} |
1074
|
|
|
} |
1075
|
|
|
$this->db->free_result($request); |
1076
|
|
|
} |
1077
|
|
|
|
1078
|
|
|
/** |
1079
|
|
|
* Fix attachment size, W & H values |
1080
|
|
|
*/ |
1081
|
|
|
public function substep11() |
1082
|
|
|
{ |
1083
|
|
|
$to_prefix = $this->config->to_prefix; |
1084
|
|
|
|
1085
|
|
|
$request = $this->db->query(" |
1086
|
|
|
SELECT |
1087
|
|
|
COUNT(*) |
1088
|
|
|
FROM {$to_prefix}attachments"); |
1089
|
|
|
list ($attachments) = $this->db->fetch_row($request); |
1090
|
|
|
$this->db->free_result($request); |
1091
|
|
|
|
1092
|
|
|
while ($_REQUEST['start'] < $attachments) |
1093
|
|
|
{ |
1094
|
|
|
$request = $this->db->query(" |
1095
|
|
|
SELECT |
1096
|
|
|
id_attach, filename, attachment_type, id_folder |
1097
|
|
|
FROM {$to_prefix}attachments |
1098
|
|
|
WHERE id_thumb = 0 |
1099
|
|
|
AND (RIGHT(filename, 4) IN ('.gif', '.jpg', '.png', '.bmp') OR RIGHT(filename, 5) = '.jpeg') |
1100
|
|
|
AND width = 0 |
1101
|
|
|
AND height = 0 |
1102
|
|
|
LIMIT $_REQUEST[start], 500"); |
1103
|
|
|
|
1104
|
|
|
if ($this->db->num_rows($request) == 0) |
1105
|
|
|
{ |
1106
|
|
|
break; |
1107
|
|
|
} |
1108
|
|
|
|
1109
|
|
|
while ($row = $this->db->fetch_assoc($request)) |
1110
|
|
|
{ |
1111
|
|
|
$filename = $this->avatarFullPath($row); |
1112
|
|
|
|
1113
|
|
|
// Probably not one of the imported ones, then? |
1114
|
|
|
if (!file_exists($filename)) |
1115
|
|
|
{ |
1116
|
|
|
continue; |
1117
|
|
|
} |
1118
|
|
|
|
1119
|
|
|
$size = @getimagesize($filename); |
1120
|
|
|
$filesize = @filesize($filename); |
1121
|
|
|
if (!empty($size) && !empty($size[0]) && !empty($size[1]) && !empty($filesize)) |
1122
|
|
|
{ |
1123
|
|
|
$this->db->query(" |
1124
|
|
|
UPDATE {$to_prefix}attachments |
1125
|
|
|
SET |
1126
|
|
|
size = " . (int) $filesize . ", |
1127
|
|
|
width = " . (int) $size[0] . ", |
1128
|
|
|
height = " . (int) $size[1] . " |
1129
|
|
|
WHERE id_attach = $row[id_attach] |
1130
|
|
|
LIMIT 1"); |
1131
|
|
|
} |
1132
|
|
|
} |
1133
|
|
|
$this->db->free_result($request); |
1134
|
|
|
|
1135
|
|
|
// More? |
1136
|
|
|
// We can't keep importing the same files over and over again! |
1137
|
|
|
$_REQUEST['start'] += 500; |
1138
|
|
|
pastTime(11); |
1139
|
|
|
} |
1140
|
|
|
} |
1141
|
|
|
|
1142
|
|
|
protected function avatarFullPath($row) |
1143
|
|
|
{ |
1144
|
|
|
$dir = $this->config->destination->getAvatarDir($row); |
1145
|
|
|
|
1146
|
|
|
if ($row['attachment_type'] == 1) |
1147
|
|
|
{ |
1148
|
|
|
// @todo Honestly I'm not sure what the final name looks like |
1149
|
|
|
// I'm pretty sure there could be at least three options: |
1150
|
|
|
// 1) filename |
1151
|
|
|
// 2) avatar_{id_member}_{time()}.{file_extension} |
1152
|
|
|
// 3) {id_attach}_{file_hash}.{->attach_extension} |
1153
|
|
|
$filename = $row['filename']; |
1154
|
|
|
} |
1155
|
|
|
else |
1156
|
|
|
{ |
1157
|
|
|
$filename = $this->config->destination->getLegacyAttachmentFilename($row['filename'], $row['id_attach']); |
1158
|
|
|
} |
1159
|
|
|
|
1160
|
|
|
return $dir . '/' . $filename; |
1161
|
|
|
} |
1162
|
|
|
} |
1163
|
|
|
|
1164
|
|
|
/** |
1165
|
|
|
* Class SmfCommonSourceStep3 |
1166
|
|
|
* |
1167
|
|
|
* @class SmfCommonSourceStep3 |
1168
|
|
|
*/ |
1169
|
|
|
abstract class SmfCommonSourceStep3 extends Step3BaseImporter |
1170
|
|
|
{ |
1171
|
|
|
public function run($import_script) |
1172
|
|
|
{ |
1173
|
|
|
$to_prefix = $this->config->to_prefix; |
1174
|
|
|
|
1175
|
|
|
// add some importer information. |
1176
|
|
|
$this->db->query(" |
1177
|
|
|
REPLACE INTO {$to_prefix}settings (variable, value) |
1178
|
|
|
VALUES ('import_time', " . time() . "), |
1179
|
|
|
('enable_password_conversion', '1'), |
1180
|
|
|
('imported_from', '" . $import_script . "')"); |
1181
|
|
|
} |
1182
|
|
|
} |
1183
|
|
|
|
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.