Add explicit `return null;` statements
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / system / importer / ImportHandler.class.php
CommitLineData
78db8ddf 1<?php
a9229942 2
78db8ddf 3namespace wcf\system\importer;
a9229942 4
78db8ddf 5use wcf\data\object\type\ObjectTypeCache;
e5029272 6use wcf\system\cache\CacheHandler;
0cba1b6e 7use wcf\system\database\exception\DatabaseException;
78db8ddf 8use wcf\system\exception\SystemException;
55ae068a 9use wcf\system\IAJAXInvokeAction;
78db8ddf 10use wcf\system\SingletonFactory;
a9229942 11use wcf\system\user\storage\UserStorageHandler;
78db8ddf
MW
12use wcf\system\WCF;
13
14/**
15 * Handles data import.
a9229942
TD
16 *
17 * @author Marcel Werk
18 * @copyright 2001-2019 WoltLab GmbH
19 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
20 * @package WoltLabSuite\Core\System\Importer
78db8ddf 21 */
a9229942
TD
22class ImportHandler extends SingletonFactory implements IAJAXInvokeAction
23{
24 /**
25 * id map cache
26 * @var array
27 */
28 protected $idMappingCache = [];
29
30 /**
31 * list of available importers
32 * @var array
33 */
34 protected $objectTypes = [];
35
36 /**
37 * list of available importer processors
38 * @var array
39 */
40 protected $importers = [];
41
42 /**
43 * user merge mode
44 * @var int
45 */
46 protected $userMergeMode = 2;
47
48 /**
49 * import hash
50 * @var string
51 */
52 protected $importHash = '';
53
54 /**
55 * list of methods allowed for remote invoke
56 * @var string[]
57 */
58 public static $allowInvoke = ['resetMapping'];
59
60 /**
61 * @inheritDoc
62 */
63 protected function init()
64 {
65 $this->objectTypes = ObjectTypeCache::getInstance()->getObjectTypes('com.woltlab.wcf.importer');
66 }
67
68 /**
69 * Returns a data importer.
70 *
71 * @param string $type
72 * @return IImporter
73 * @throws SystemException
74 */
75 public function getImporter($type)
76 {
77 if (!isset($this->importers[$type])) {
78 if (!isset($this->objectTypes[$type])) {
79 throw new SystemException("unknown importer '" . $type . "'");
80 }
81
82 $this->importers[$type] = $this->objectTypes[$type]->getProcessor();
83 }
84
85 return $this->importers[$type];
86 }
87
88 /**
89 * Returns a new id from id mapping.
90 *
91 * @param string $type
92 * @param mixed $oldID
c0b28aa2 93 * @return int|null
a9229942
TD
94 */
95 public function getNewID($type, $oldID)
96 {
97 if (!$oldID) {
c0b28aa2 98 return null;
a9229942
TD
99 }
100 $objectTypeID = $this->objectTypes[$type]->objectTypeID;
101
102 if (
103 !isset($this->idMappingCache[$objectTypeID])
104 || !\array_key_exists($oldID, $this->idMappingCache[$objectTypeID])
105 ) {
106 $this->idMappingCache[$objectTypeID][$oldID] = null;
107 $importer = $this->getImporter($type);
108 $tableName = $indexName = '';
109 if ($importer->getClassName()) {
110 $tableName = \call_user_func([$importer->getClassName(), 'getDatabaseTableName']);
111 $indexName = \call_user_func([$importer->getClassName(), 'getDatabaseTableIndexName']);
112 }
113
114 $sql = "SELECT import_mapping.newID
115 FROM wcf" . WCF_N . "_import_mapping import_mapping
d3bd0a85
MS
116 " . ($tableName ? "
117 LEFT JOIN " . $tableName . " object_table
118 ON object_table." . $indexName . " = import_mapping.newID
119 " : '') . "
a9229942
TD
120 WHERE import_mapping.importHash = ?
121 AND import_mapping.objectTypeID = ?
122 AND import_mapping.oldID = ?
123 " . ($tableName ? "AND object_table." . $indexName . " IS NOT NULL" : '');
124 $statement = WCF::getDB()->prepareStatement($sql);
125 $statement->execute([$this->importHash, $objectTypeID, $oldID]);
126 $row = $statement->fetchArray();
127 if ($row !== false) {
128 $this->idMappingCache[$objectTypeID][$oldID] = $row['newID'];
129 }
130 }
131
132 return $this->idMappingCache[$objectTypeID][$oldID];
133 }
134
135 /**
136 * Saves an id mapping.
137 *
138 * @param string $type
139 * @param int $oldID
140 * @param int $newID
141 */
142 public function saveNewID($type, $oldID, $newID)
143 {
0cba1b6e
TD
144 static $statement = null;
145
a9229942
TD
146 $objectTypeID = $this->objectTypes[$type]->objectTypeID;
147
0cba1b6e
TD
148 if ($statement === null) {
149 $sql = "INSERT IGNORE INTO wcf" . WCF_N . "_import_mapping
150 (importHash, objectTypeID, oldID, newID)
151 VALUES (?, ?, ?, ?)";
152 $statement = WCF::getDB()->prepareStatement($sql);
153 }
154
155 try {
156 $statement->execute([$this->importHash, $objectTypeID, $oldID, $newID]);
157 } catch (DatabaseException $e) {
158 // Re-prepare the statement once.
159 $sql = "INSERT IGNORE INTO wcf" . WCF_N . "_import_mapping
160 (importHash, objectTypeID, oldID, newID)
161 VALUES (?, ?, ?, ?)";
162 $statement = WCF::getDB()->prepareStatement($sql);
163 $statement->execute([$this->importHash, $objectTypeID, $oldID, $newID]);
164 }
a9229942
TD
165
166 unset($this->idMappingCache[$objectTypeID][$oldID]);
167 }
168
169 /**
170 * Validates accessibility of resetMapping().
171 */
172 public function validateResetMapping()
173 {
174 WCF::getSession()->checkPermissions(['admin.management.canImportData']);
175
176 // reset caches
177 CacheHandler::getInstance()->flushAll();
178 UserStorageHandler::getInstance()->clear();
179 }
180
181 /**
182 * Resets the mapping.
183 */
184 public function resetMapping()
185 {
186 $sql = "DELETE FROM wcf" . WCF_N . "_import_mapping";
187 $statement = WCF::getDB()->prepareStatement($sql);
188 $statement->execute();
189
190 $this->idMappingCache = [];
191 }
192
193 /**
194 * Sets the user merge mode.
195 *
196 * @param int $mode
197 */
198 public function setUserMergeMode($mode)
199 {
200 $this->userMergeMode = $mode;
201 }
202
203 /**
204 * Returns the user merge mode.
205 *
206 * @return int
207 */
208 public function getUserMergeMode()
209 {
210 return $this->userMergeMode;
211 }
212
213 /**
214 * Sets the import hash.
215 *
216 * @param string $hash
217 */
218 public function setImportHash($hash)
219 {
220 $this->importHash = $hash;
221 }
78db8ddf 222}