PluginProbe
Import WP – CSV & XML Import Export for WordPress / trunk
Import WP – CSV & XML Import Export for WordPress vtrunk
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 trunk 0.1.6 All 142 releases
jc-importer / class / Common / Runner / Runner.php

Runner.php in Import WP – CSV & XML Import Export for WordPress trunk, at class/Common/Runner/Runner.php

214 lines 6.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace ImportWP\Common\Runner;
4
5 use ImportWP\Common\Properties\Properties;
6 use ImportWP\Common\Util\Logger;
7
8 abstract class Runner
9 {
10 /**
11 * @var Properties
12 */
13 protected $properties;
14
15 /**
16 * @var int
17 */
18 protected $memory_limit;
19
20 /**
21 * @var boolean
22 */
23 protected $is_timeout = false;
24
25 protected $object_type = 'importer';
26
27 /**
28 * @param Properties $properties
29 */
30 public function __construct($properties)
31 {
32 $this->properties = $properties;
33 }
34
35 abstract function process_row($id, $user, $state, $session, $section, $progress);
36 abstract function setup($state, $state_data, $config, $user, $id);
37
38 /**
39 * @param int $id
40 * @param string $user
41 * @param RunnerState $state
42 */
43 public function process($id, $user, $state)
44 {
45 $time_limit = $this->properties->get_setting('timeout');
46 Logger::info('time_limit ' . $time_limit . 's');
47
48 $start = microtime(true);
49 $max_record_time = 0;
50 $memory_max_usage = 0;
51 $i = 0;
52
53 $this->try_process_dangling_state($id, $user, $state, $user);
54
55 $config = get_option('iwp_' . $this->object_type . '_config_' . $id, []);
56
57 while (
58 ($i == 0 || (
59 ($time_limit === 0 || $this->has_enough_time($start, $time_limit, $max_record_time))
60 && $this->has_enough_memory($memory_max_usage))
61 )
62 && $state
63 && $state->is_resumable()
64 ) {
65
66 $memory_usage = $this->get_memory_usage();
67
68 $this->is_timeout = false;
69
70 $state = $state->update(function ($state_data) use ($state, $config, $user, $id) {
71 return $this->setup($state, $state_data, $config, $user, $id);
72 });
73
74 if (!$state || $this->is_timeout || !$state->is_running()) {
75 break;
76 }
77
78 $record_time = microtime(true);
79 $this->process_row($id, $user, $state, $state->get_session(), $state->get_section(), $state->get_progress());
80
81 $max_record_time = max($max_record_time, microtime(true) - $record_time);
82
83 if (!wp_using_ext_object_cache()) {
84 wp_cache_flush();
85 }
86
87 // keep track of largest memory change
88 $memory_delta = $this->get_memory_usage() - $memory_usage;
89 if ($memory_delta > $memory_max_usage) {
90 $memory_max_usage = $memory_delta;
91 }
92
93 $i++;
94 }
95 }
96
97 /**
98 * @param string $user
99 * @param RunnerState $state
100 */
101 public function try_process_dangling_state($id, $user, $state, $user_to_check = null)
102 {
103 $dangling = $this->has_dangling_state($id, $user_to_check);
104 if (!empty($dangling)) {
105 $fixed = 0;
106 foreach ($dangling as $dangling_id) {
107
108 // TODO: Should the option be renamed to the current user first? to make sure its not ran multiple times.
109 // TODO: status should not be overwritten like this.
110 $GLOBALS['wp_object_cache']->delete($dangling_id, 'options');
111 $status = get_option($dangling_id);
112 if ($status && $status['last_modified'] < current_time('timestamp') - 30) {
113
114 Logger::write('try_import_dangling_rows -id=' . $id . ' -user=' . $user . ' -dangling=' . $dangling_id);
115
116 $GLOBALS['wp_object_cache']->delete($dangling_id, 'options');
117 $status['last_modified'] = current_time('timestamp');
118 update_option($dangling_id, $status);
119
120
121 $this->process_row($id, $user, $state, $state->get_session(), $status['section'], $status['progress'][$status['section']]);
122 delete_site_option($dangling_id);
123 $fixed++;
124 }
125 }
126
127 if ($fixed !== count($dangling)) {
128 // escape due to dangling records that have not timed out
129 return false;
130 }
131 }
132
133 return true;
134 }
135
136 function has_dangling_state($id, $user = null)
137 {
138 /**
139 * @var \WPDB $wpdb
140 */
141 global $wpdb;
142
143 $key_prefix = 'iwp\_' . $this->object_type . '\_state';
144 $query = "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '{$key_prefix}\_{$id}\_";
145
146 if (!empty($user)) {
147 $query .= $user;
148 } else {
149 $query .= '%';
150 }
151
152 $query .= "'";
153
154 $option_names = $wpdb->get_col($query);
155 return $option_names;
156 }
157
158
159
160 function has_enough_time($start, $time_limit, $max_record_time)
161 {
162 return (microtime(true) - $start) < $time_limit - $max_record_time;
163 }
164
165 function get_memory_usage()
166 {
167 return memory_get_usage(true);
168 }
169
170 function has_enough_memory($memory_max_usage)
171 {
172 $limit = $this->get_memory_limit();
173
174 // Has unlimited memory
175 if ($limit == '-1') {
176 return true;
177 }
178
179 $limit *= 0.9;
180 $current_usage = $this->get_memory_usage();
181
182 if ($current_usage + $memory_max_usage < $limit) {
183 return true;
184 }
185
186 Logger::error(sprintf("Not Enough Memory left to use %s, %s/%s", Logger::formatBytes($memory_max_usage, 2), Logger::formatBytes($current_usage, 2), Logger::formatBytes($limit, 2)));
187
188 return false;
189 }
190
191 function get_memory_limit($force = false)
192 {
193 if ($force || is_null($this->memory_limit)) {
194
195 $memory_limit = ini_get('memory_limit');
196 if (preg_match('/^(\d+)(.)$/', $memory_limit, $matches)) {
197 if ($matches[2] == 'G') {
198 $memory_limit = $matches[1] * 1024 * 1024 * 1024; // nnnM -> nnn MB
199 } elseif ($matches[2] == 'M') {
200 $memory_limit = $matches[1] * 1024 * 1024; // nnnM -> nnn MB
201 } else if ($matches[2] == 'K') {
202 $memory_limit = $matches[1] * 1024; // nnnK -> nnn KB
203 }
204 }
205
206 $this->memory_limit = $memory_limit;
207
208 Logger::info('memory_limit ' . $this->memory_limit . ' bytes');
209 }
210
211 return $this->memory_limit;
212 }
213 }
214