PluginProbe
Import WP – CSV & XML Import Export for WordPress / 2.15.0
Import WP – CSV & XML Import Export for WordPress v2.15.0
2.15.1 2.15.0 2.14.24 2.14.23 2.7.0 2.7.1 2.7.10 2.7.11 2.7.12 2.7.13 2.7.14 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.8.0 2.8.1 2.8.2 2.8.3 2.9.0 2.9.1 All 144 releases
← All changes | class/Common/Importer/State/ImporterState.php +160 -231 2.7.9 → 2.15.0 View file →
@@ -5,26 +5,27 @@
5 5 use ImportWP\Common\Util\Logger;
6 6
7 7 class ImporterState
8 8 {
9 + private $data = [];
9 10 private $importer_id;
10 - private $user;
11 - protected $data;
11 + protected static $object_type = 'importer';
12 12
13 - public function __construct($importer_id, $user)
13 + public function __construct($importer_id, $user = '')
14 14 {
15 15 $this->importer_id = $importer_id;
16 - $this->user = $user;
17 16 }
18 17
19 - public function init($session)
18 + protected function default($session_id)
20 19 {
21 - $state = self::wait_for_lock_and_get_state($this->importer_id, $this->user, [
22 - 'id' => $session,
20 + return [
21 + 'id' => $session_id,
22 + 'status' => 'init',
23 23 'version' => 2,
24 - 'status' => 'init',
24 + 'message' => '',
25 + 'timestamp' => time(),
26 + 'duration' => 0,
25 27 'section' => 'import',
26 - 'message' => '',
27 28 'progress' => [
28 29 'import' => [
29 30 'start' => 0,
30 31 'end' => 0,
@@ -35,27 +36,35 @@
35 36 'end' => 0,
36 37 'current_row' => 0,
37 38 ]
38 39 ],
39 - 'updated' => time(),
40 - 'timestamp' => time(),
41 - 'duration' => 0
42 - ]);
40 + ];
41 + }
43 42
43 + public function init($session_id)
44 + {
45 + // get current or set default to new session_id
46 + $state = self::get_state($this->importer_id);
47 + if (!$state) {
48 + $state = $this->default($session_id);
49 + $this->set_state($this->importer_id, $state);
50 + }
51 +
44 52 if (!$state || !isset($state['status'])) {
45 - throw new \Exception("Invalid importer state");
53 + throw new \Exception(__("Invalid state", 'jc-importer'));
46 54 }
47 55
48 56 $this->populate($state);
49 57
50 - if (!$this->validate($session)) {
51 - throw new \Exception("Importer session has changed");
58 + if (!$this->validate($session_id)) {
59 + throw new \Exception(__("Session has changed", 'jc-importer'));
52 60 }
53 61 }
54 62
55 - public function populate($state)
63 +
64 + public function populate($state_data)
56 65 {
57 - foreach ($state as $name => $value) {
66 + foreach ($state_data as $name => $value) {
58 67 $this->data[$name] = $value;
59 68 }
60 69 }
61 70
@@ -71,29 +80,45 @@
71 80
72 81 return $this->data['status'] == $status;
73 82 }
74 83
75 - public function has_section($section)
84 + public function get_session()
76 85 {
77 - if (!isset($this->data['section'])) {
78 - return false;
86 + return isset($this->data['id']) ? $this->data['id'] : false;
87 + }
88 +
89 + public function update($callback)
90 + {
91 + $raw = [];
92 + if (is_callable($callback)) {
93 + $raw = call_user_func($callback, $this->data);
79 94 }
80 95
81 - if (is_array($section)) {
82 - return in_array($this->data['section'], $section);
83 - }
96 + $this->populate($raw);
84 97
85 - return $this->data['section'] == $section;
86 - }
98 + $this->set_state($this->importer_id, $this->data);
87 99
88 - public function get_session()
89 - {
90 - return isset($this->data['id']) ? $this->data['id'] : false;
100 + return $this;
91 101 }
92 102
93 - public function get_status()
103 + public function error($error)
94 104 {
95 - return isset($this->data['status']) ? $this->data['status'] : false;
105 + $this->update(function ($state) use ($error) {
106 + $state['status'] = 'error';
107 + if (is_wp_error($error)) {
108 + /**
109 + * @var \WP_Error $error
110 + */
111 + $state['message'] = $error->get_error_message();
112 + } else if ($error instanceof \Exception) {
113 + /**
114 + * @var \Exception $error
115 + */
116 + $state['message'] = $error->getMessage();
117 + }
118 + return $state;
119 + });
120 + return $this;
96 121 }
97 122
98 123 public function validate($session_id)
99 124 {
@@ -108,128 +133,19 @@
108 133 {
109 134 return $this->data;
110 135 }
111 136
112 - public function get_importer_id()
137 + public static function wait_for_lock($importer_id, $user, $callback)
113 138 {
114 - return $this->importer_id;
115 - }
116 -
117 - public function get_section()
118 - {
119 - if (!isset($this->data['section'])) {
120 - return false;
139 + $result = null;
140 + if (is_callable($callback)) {
141 + $result = call_user_func($callback);
121 142 }
122 143
123 - return $this->data['section'];
124 - }
125 -
126 - public function get_progress($section = null)
127 - {
128 - if (is_null($section)) {
129 - $section = $this->get_section();
130 - }
131 -
132 - return $this->data['progress'][$section];
133 - }
134 -
135 - /**
136 - * Update live state data using callback
137 - *
138 - * @param Closure[array]:array $state
139 - *
140 - * @return $this
141 - */
142 - public function update($callback)
143 - {
144 - $raw = self::wait_for_lock($this->importer_id, $this->user, function () use ($callback) {
145 - $state = self::get_state($this->importer_id);
146 -
147 - if (is_callable($callback)) {
148 - $state = call_user_func($callback, $state);
149 - }
150 -
151 - self::set_state($this->importer_id, $state);
152 - do_action('iwp/importer/status/save', $state);
153 - return $state;
154 - });
155 -
156 - $this->populate($raw);
157 -
158 - return $this;
159 - }
160 -
161 - /**
162 - * Log fatal error
163 - *
164 - * @param \Exception $error
165 - * @return $this
166 - */
167 - public function error($error)
168 - {
169 - return $this->update(function ($data) use ($error) {
170 -
171 - $data['status'] = 'error';
172 - $data['message'] = $error->getMessage();
173 - $data['duration'] = floatval($data['duration']) + Logger::timer();
174 -
175 - return $data;
176 - });
177 - }
178 -
179 - public static function wait_for_lock($id, $user, $callback)
180 - {
181 -
182 - $start = microtime(true);
183 -
184 - do {
185 - list($has_lock, $result) = self::try_get_lock($id, $user, $callback);
186 - } while (!$has_lock && (microtime(true) - $start < 30));
187 -
188 - if (!$has_lock) {
189 - throw new \Exception("Unable to get lock");
190 - }
191 -
192 144 return $result;
193 145 }
194 146
195 - public static function wait_for_lock_and_get_state($id, $user, $default = false)
196 - {
197 - return self::wait_for_lock($id, $user, function () use ($id, $default) {
198 - return self::get_state($id, $default);
199 - });
200 - }
201 -
202 147 /**
203 - * Get importer lock to update state
204 - *
205 - * @param mixed $user current id
206 - * @param mixed $callback Callback triggered when we have a lock.
207 - * @param int $wait_in_microseconds Time to wait in microseconds before retrying
208 - *
209 - * @return false|array
210 - */
211 - public static function try_get_lock($id, $user, $callback)
212 - {
213 - $has_lock = self::get_lock($id, $user);
214 - if ($has_lock) {
215 -
216 - $result = $has_lock;
217 -
218 - if (is_callable($callback)) {
219 - $result = call_user_func($callback);
220 - }
221 -
222 - self::reset_lock($id);
223 -
224 - return [true, $result];
225 - } else {
226 -
227 - return [false, null];
228 - }
229 - }
230 -
231 - /**
232 148 * Update importer state
233 149 *
234 150 * @param mixed $state State to overwrite
235 151 *
@@ -237,9 +153,10 @@
237 153 */
238 154 public static function set_state($id, $state)
239 155 {
240 156 $state['updated'] = time();
241 - self::update_option('iwp_importer_state_' . $id, maybe_serialize($state));
157 + do_action('iwp/' . static::$object_type . '/status/save', $state);
158 + self::update_option('iwp_' . static::$object_type . '_state_' . $id, maybe_serialize($state));
242 159 }
243 160
244 161 /**
245 162 * Get last importer state
@@ -247,9 +164,9 @@
247 164 * @return array Importer state
248 165 */
249 166 public static function get_state($id, $default = false)
250 167 {
251 - $state = self::get_option('iwp_importer_state_' . $id);
168 + $state = self::get_option('iwp_' . static::$object_type . '_state_' . $id);
252 169 if (!$state) {
253 170 $state = $default;
254 171 if ($state !== false) {
255 172 self::set_state($id, $state);
@@ -258,10 +175,9 @@
258 175
259 176 return $state;
260 177 }
261 178
262 -
263 - public static function get_lock($id, $user, $timeout_in_seconds = 10)
179 + public static function get_option($key, $default = false)
264 180 {
265 181 /**
266 182 * @var \WPDB $wpdb
267 183 */
@@ -266,127 +182,140 @@
266 182 * @var \WPDB $wpdb
267 183 */
268 184 global $wpdb;
269 185
270 - $lock_option_id = sprintf("iwp_importer_lock_%d", $id);
271 - $existing = self::get_option($lock_option_id, false);
186 + $query = $wpdb->prepare("SELECT option_id as id, option_value as `data` FROM {$wpdb->options} WHERE option_name=%s LIMIT 1", [$key]);
272 187
273 - if ($existing !== false) {
274 - if (is_multisite()) {
275 - $query = $wpdb->prepare(
276 - "UPDATE {$wpdb->sitemeta} SET meta_value=%s WHERE site_id=%d AND meta_key=%s AND meta_value=''",
277 - $user,
278 - $wpdb->siteid,
279 - $lock_option_id
280 - );
281 - } else {
282 - $query = $wpdb->prepare(
283 - "UPDATE {$wpdb->options} SET option_value=%s WHERE option_name=%s AND option_value=''",
284 - $user,
285 - $lock_option_id
286 - );
287 - }
288 - } else {
289 - return self::update_option($lock_option_id, '');
188 + $result = $wpdb->get_row($query, ARRAY_A);
189 + if (!$result) {
190 + return $default;
290 191 }
291 192
292 - $result = $wpdb->query($query);
193 + if (is_serialized($result['data'])) {
194 + return unserialize($result['data']);
195 + }
293 196
294 - if ($result) {
197 + return $result['data'];
198 + }
295 199
296 - self::touch_lock($id);
297 - } else {
200 + public static function update_option($key, $value = '')
201 + {
202 + /**
203 + * @var \WPDB $wpdb
204 + */
205 + global $wpdb;
298 206
299 - // Clear lock if timestamp is greater than timeout.
300 - $last_locked_time = (int)self::get_option('iwp_importer_lock_timestamp_' . $id, 0);
301 - if (current_time('timestamp') > $last_locked_time + $timeout_in_seconds) {
302 - self::reset_lock($id);
303 - }
207 + $result = $wpdb->update($wpdb->options, ['option_value' => $value], ['option_name' => $key], ['%s'], ['%s']);
208 + if (intval($result) < 1) {
209 + $result = $wpdb->insert($wpdb->options, ['option_value' => $value, 'option_name' => $key], ['%s', '%s']);
304 210 }
305 211
306 212 return $result;
307 213 }
308 214
309 - public static function reset_lock($id)
215 + public static function clear_options($id)
310 216 {
311 - self::update_option('iwp_importer_lock_' . $id);
312 - self::touch_lock($id);
313 - }
314 217
315 - public static function touch_lock($id)
316 - {
317 - self::update_option('iwp_importer_lock_timestamp_' . $id, current_time('timestamp'));
318 - }
218 + // clear existing
219 + delete_option('iwp_' . static::$object_type . '_config_' . $id);
220 + delete_option('iwp_' . static::$object_type . '_state_' . $id);
221 + delete_option('iwp_' . static::$object_type . '_lock_' . $id);
222 + delete_option('iwp_' . static::$object_type . '_lock_timestamp_' . $id);
223 + delete_option('iwp_' . static::$object_type . '_flag_' . $id);
319 224
320 - public static function get_option($key, $default = false)
321 - {
322 225 /**
323 226 * @var \WPDB $wpdb
324 227 */
325 228 global $wpdb;
229 + $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'iwp\_" . static::$object_type . "\_state\_" . $id . "\_%'");
230 + }
326 231
327 - if (is_multisite()) {
328 - $query = $wpdb->prepare("SELECT meta_id as id, meta_value as data FROM {$wpdb->sitemeta} WHERE site_id=%s AND meta_key=%s LIMIT 1", [$wpdb->siteid, $key]);
329 - } else {
330 - $query = $wpdb->prepare("SELECT option_id as id, option_value as data FROM {$wpdb->options} WHERE option_name=%s LIMIT 1", [$key]);
232 + public function get_section()
233 + {
234 + if (!isset($this->data['section'])) {
235 + return false;
331 236 }
332 237
333 - $result = $wpdb->get_row($query, ARRAY_A);
334 - if (!$result) {
335 - return $default;
238 + return $this->data['section'];
239 + }
240 +
241 + public function get_progress($section = null)
242 + {
243 + if (is_null($section)) {
244 + $section = $this->get_section();
336 245 }
337 246
338 - if (is_serialized($result['data'])) {
339 - return unserialize($result['data']);
247 + return $this->data['progress'][$section];
248 + }
249 +
250 + function update_importer_stats($stats)
251 + {
252 + if (!isset($this->data['stats'])) {
253 + $this->data['stats'] = [
254 + 'inserts' => 0,
255 + 'updates' => 0,
256 + 'deletes' => 0,
257 + 'skips' => 0,
258 + 'errors' => 0,
259 + ];
340 260 }
341 261
342 - return $result['data'];
262 + $this->data['stats']['inserts'] += $stats['inserts'];
263 + $this->data['stats']['updates'] += $stats['updates'];
264 + $this->data['stats']['deletes'] += $stats['deletes'];
265 + $this->data['stats']['skips'] += $stats['skips'];
266 + $this->data['stats']['errors'] += $stats['errors'];
343 267 }
344 268
345 - public static function update_option($key, $value = '')
269 + function get_stats()
346 270 {
347 - /**
348 - * @var \WPDB $wpdb
349 - */
350 - global $wpdb;
271 + if (!isset($this->data['stats'])) {
272 + $this->data['stats'] = [
273 + 'inserts' => 0,
274 + 'updates' => 0,
275 + 'deletes' => 0,
276 + 'skips' => 0,
277 + 'errors' => 0,
278 + ];
279 + }
351 280
352 - $result = self::get_option($key);
281 + return $this->data['stats'];
282 + }
353 283
354 - if (is_multisite()) {
284 + function increment_current_row($section = null)
285 + {
286 + if (is_null($section)) {
287 + $section = $this->get_section();
288 + }
289 + $this->data['progress'][$section]['current_row']++;
290 + }
355 291
356 - if ($result !== false) {
357 - $result = $wpdb->update($wpdb->sitemeta, ['meta_value' => $value], ['meta_key' => $key, 'site_id' => $wpdb->siteid], ['%s'], ['%s', '%s']);
358 - } else {
359 - $result = $wpdb->insert($wpdb->sitemeta, ['meta_value' => $value, 'meta_key' => $key, 'site_id' => $wpdb->siteid], ['%s', '%s', '%s']);
360 - }
361 - } else {
362 - if ($result !== false) {
363 - $result = $wpdb->update($wpdb->options, ['option_value' => $value], ['option_name' => $key], ['%s'], ['%s']);
364 - } else {
365 - $result = $wpdb->insert($wpdb->options, ['option_value' => $value, 'option_name' => $key], ['%s', '%s']);
366 - }
367 - }
292 + static function get_flag($id)
293 + {
294 + return self::get_option('iwp_' . static::$object_type . '_flag_' . $id);
295 + }
368 296
369 - return $result;
297 + static function is_paused($flag)
298 + {
299 + return $flag == 'paused';
370 300 }
371 301
372 - public static function clear_options($id)
302 + static function is_cancelled($flag)
373 303 {
304 + return $flag == 'cancelled';
305 + }
374 306
375 - // clear existing
376 - delete_site_option('iwp_importer_config_' . $id);
377 - delete_site_option('iwp_importer_state_' . $id);
378 - delete_site_option('iwp_importer_lock_' . $id);
379 - delete_site_option('iwp_importer_lock_timestamp_' . $id);
307 + static function set_paused($id)
308 + {
309 + self::update_option('iwp_' . static::$object_type . '_flag_' . $id, 'paused');
310 + }
380 311
381 - /**
382 - * @var \WPDB $wpdb
383 - */
384 - global $wpdb;
312 + static function set_cancelled($id)
313 + {
314 + self::update_option('iwp_' . static::$object_type . '_flag_' . $id, 'cancelled');
315 + }
385 316
386 - if (is_multisite()) {
387 - $wpdb->query("DELETE FROM {$wpdb->sitemeta} WHERE meta_key LIKE 'iwp\_importer\_state\_" . $id . "\_%'");
388 - } else {
389 - $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'iwp\_importer\_state\_" . $id . "\_%'");
390 - }
317 + static function clear_flag($id)
318 + {
319 + self::update_option('iwp_' . static::$object_type . '_flag_' . $id, '');
391 320 }
392 321 }