PluginProbe
Redirection / 4.2
Redirection v4.2
5.10.0 5.9.0 5.8.1 5.8.0 3.7.2 3.7.3 4.0 4.0.1 4.1 4.1.1 4.2 4.2.1 4.2.2 4.2.3 4.3 4.3.1 4.3.2 4.3.3 4.4 4.4.1 4.4.2 4.5 4.5.1 4.6.2 4.7.1 All 130 releases
redirection / database / database-status.php

database-status.php in Redirection 4.2, at database/database-status.php

368 lines 9.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class Red_Database_Status {
4 // Used in < 3.7 versions of Redirection, but since migrated to general settings
5 const OLD_DB_VERSION = 'redirection_version';
6 const DB_UPGRADE_STAGE = 'redirection_database_stage';
7
8 const RESULT_OK = 'ok';
9 const RESULT_ERROR = 'error';
10
11 const STATUS_OK = 'ok';
12 const STATUS_NEED_INSTALL = 'need-install';
13 const STATUS_NEED_UPDATING = 'need-update';
14 const STATUS_FINISHED_INSTALL = 'finish-install';
15 const STATUS_FINISHED_UPDATING = 'finish-update';
16
17 private $stage = false;
18 private $stages = [];
19
20 private $status = false;
21 private $result = false;
22 private $reason = false;
23 private $debug = [];
24
25 public function __construct() {
26 $this->status = self::STATUS_OK;
27
28 if ( $this->needs_installing() ) {
29 $this->status = self::STATUS_NEED_INSTALL;
30 } elseif ( $this->needs_updating() ) {
31 $this->status = self::STATUS_NEED_UPDATING;
32 }
33
34 $info = get_option( self::DB_UPGRADE_STAGE );
35 if ( $info ) {
36 $this->stage = isset( $info['stage'] ) ? $info['stage'] : false;
37 $this->stages = isset( $info['stages'] ) ? $info['stages'] : [];
38 $this->status = isset( $info['status'] ) ? $info['status'] : false;
39 }
40 }
41
42 /**
43 * Does the database need install
44 *
45 * @return bool true if needs installing, false otherwise
46 */
47 public function needs_installing() {
48 $settings = red_get_options();
49
50 if ( $settings['database'] === '' && $this->get_old_version() === false ) {
51 return true;
52 }
53
54 return false;
55 }
56
57 /**
58 * Does the current database need updating to the target
59 *
60 * @return bool true if needs updating, false otherwise
61 */
62 public function needs_updating() {
63 // We need updating if we don't need to install, and the current version is less than target version
64 if ( $this->needs_installing() === false && version_compare( $this->get_current_version(), REDIRECTION_DB_VERSION, '<' ) ) {
65 return true;
66 }
67
68 // Also if we're still in the process of upgrading
69 if ( $this->get_current_stage() ) {
70 return true;
71 }
72
73 return false;
74 }
75
76 /**
77 * Get current database version
78 *
79 * @return string Current database version
80 */
81 public function get_current_version() {
82 $settings = red_get_options();
83
84 if ( $settings['database'] !== '' ) {
85 return $settings['database'];
86 } elseif ( $this->get_old_version() !== false ) {
87 $version = $this->get_old_version();
88
89 // Upgrade the old value
90 red_set_options( array( 'database' => $version ) );
91 delete_option( self::OLD_DB_VERSION );
92 $this->clear_cache();
93 return $version;
94 }
95
96 return '';
97 }
98
99 private function get_old_version() {
100 return get_option( self::OLD_DB_VERSION );
101 }
102
103 public function check_tables_exist() {
104 $latest = Red_Database::get_latest_database();
105 $missing = $latest->get_missing_tables();
106
107 // No tables installed - do a fresh install
108 if ( count( $missing ) === count( $latest->get_all_tables() ) ) {
109 delete_option( Red_Database_Status::OLD_DB_VERSION );
110 red_set_options( [ 'database' => '' ] );
111 $this->clear_cache();
112
113 $this->status = self::STATUS_NEED_INSTALL;
114 $this->stop_update();
115 } elseif ( count( $missing ) > 0 && version_compare( $this->get_current_version(), '2.3.3', 'ge' ) ) {
116 // Some tables are missing - try and fill them in
117 $latest->install();
118 }
119 }
120
121 /**
122 * Does the current database support a particular version
123 *
124 * @param string $version Target version
125 * @return bool true if supported, false otherwise
126 */
127 public function does_support( $version ) {
128 return version_compare( $this->get_current_version(), $version, 'ge' );
129 }
130
131 public function is_error() {
132 return $this->result === self::RESULT_ERROR;
133 }
134
135 public function set_error( $error ) {
136 global $wpdb;
137
138 $this->result = self::RESULT_ERROR;
139 $this->reason = str_replace( "\t", ' ', $error );
140
141 if ( $wpdb->last_error ) {
142 $this->debug[] = $wpdb->last_error;
143 }
144
145 $latest = Red_Database::get_latest_database();
146 $this->debug = array_merge( $this->debug, $latest->get_table_schema() );
147 $this->debug[] = 'Stage: ' . $this->get_current_stage();
148 }
149
150 public function set_ok( $reason ) {
151 $this->reason = $reason;
152 $this->result = self::RESULT_OK;
153 $this->debug = [];
154 }
155
156 /**
157 * Stop current upgrade
158 */
159 public function stop_update() {
160 $this->stage = false;
161 $this->stages = [];
162 $this->debug = [];
163
164 delete_option( self::DB_UPGRADE_STAGE );
165 $this->clear_cache();
166 }
167
168 public function finish() {
169 $this->stop_update();
170
171 if ( $this->status === self::STATUS_NEED_INSTALL ) {
172 $this->status = self::STATUS_FINISHED_INSTALL;
173 } elseif ( $this->status === self::STATUS_NEED_UPDATING ) {
174 $this->status = self::STATUS_FINISHED_UPDATING;
175 }
176 }
177
178 /**
179 * Get current upgrade stage
180 * @return string|bool Current stage name, or false if not upgrading
181 */
182 public function get_current_stage() {
183 return $this->stage;
184 }
185
186 /**
187 * Move current stage on to the next
188 */
189 public function set_next_stage() {
190 $stage = $this->get_current_stage();
191
192 if ( $stage ) {
193 $stage = $this->get_next_stage( $stage );
194
195 // Save next position
196 if ( $stage ) {
197 $this->set_stage( $stage );
198 } else {
199 $this->finish();
200 }
201 }
202 }
203
204 /**
205 * Get current upgrade status
206 *
207 * @return array Database status array
208 */
209 public function get_json() {
210 // Base information
211 $result = [
212 'status' => $this->status,
213 'inProgress' => $this->stage !== false,
214 ];
215
216 // Add on version status
217 if ( $this->status === self::STATUS_NEED_INSTALL || $this->status === self::STATUS_NEED_UPDATING ) {
218 $result = array_merge(
219 $result,
220 $this->get_version_upgrade(),
221 [ 'manual' => $this->get_manual_upgrade() ]
222 );
223 }
224
225 // Add on upgrade status
226 if ( $this->is_error() ) {
227 $result = array_merge( $result, $this->get_version_upgrade(), $this->get_progress_status(), $this->get_error_status() );
228 } elseif ( $result['inProgress'] ) {
229 $result = array_merge( $result, $this->get_progress_status() );
230 } elseif ( $this->status === self::STATUS_FINISHED_INSTALL || $this->status === self::STATUS_FINISHED_UPDATING ) {
231 $result['complete'] = 100;
232 $result['reason'] = $this->reason;
233 }
234
235 return $result;
236 }
237
238 private function get_error_status() {
239 return [
240 'reason' => $this->reason,
241 'result' => self::RESULT_ERROR,
242 'debug' => $this->debug,
243 ];
244 }
245
246 private function get_progress_status() {
247 $complete = 0;
248
249 if ( $this->stage ) {
250 $complete = round( ( array_search( $this->stage, $this->stages, true ) / count( $this->stages ) ) * 100, 1 );
251 }
252
253 return [
254 'complete' => $complete,
255 'result' => self::RESULT_OK,
256 'reason' => $this->reason,
257 ];
258 }
259
260 private function get_version_upgrade() {
261 return [
262 'current' => $this->get_current_version() ? $this->get_current_version() : '-',
263 'next' => REDIRECTION_DB_VERSION,
264 'time' => microtime( true ),
265 ];
266 }
267
268 /**
269 * Set the status information for a database upgrade
270 */
271 public function start_install( array $upgrades ) {
272 $this->set_stages( $upgrades );
273 $this->status = self::STATUS_NEED_INSTALL;
274 }
275
276 public function start_upgrade( array $upgrades ) {
277 $this->set_stages( $upgrades );
278 $this->status = self::STATUS_NEED_UPDATING;
279 }
280
281 private function set_stages( array $upgrades ) {
282 $this->stages = [];
283
284 foreach ( $upgrades as $upgrade ) {
285 $upgrader = Red_Database_Upgrader::get( $upgrade );
286 $this->stages = array_merge( $this->stages, array_keys( $upgrader->get_stages() ) );
287 }
288
289 if ( count( $this->stages ) > 0 ) {
290 $this->set_stage( $this->stages[0] );
291 }
292 }
293
294 public function set_stage( $stage ) {
295 $this->stage = $stage;
296 $this->save_details();
297 }
298
299 private function save_details() {
300 update_option( self::DB_UPGRADE_STAGE, [
301 'stage' => $this->stage,
302 'stages' => $this->stages,
303 'status' => $this->status,
304 ] );
305
306 $this->clear_cache();
307 }
308
309 private function get_manual_upgrade() {
310 $queries = [];
311 $database = new Red_Database();
312 $upgraders = $database->get_upgrades_for_version( $this->get_current_version(), false );
313
314 foreach ( $upgraders as $upgrade ) {
315 $upgrade = Red_Database_Upgrader::get( $upgrade );
316
317 $stages = $upgrade->get_stages();
318 foreach ( array_keys( $stages ) as $stage ) {
319 $queries = array_merge( $queries, $upgrade->get_queries_for_stage( $stage ) );
320 }
321 }
322
323 return $queries;
324 }
325
326 private function get_next_stage( $stage ) {
327 $database = new Red_Database();
328 $upgraders = $database->get_upgrades_for_version( $this->get_current_version(), $this->get_current_stage() );
329
330 if ( count( $upgraders ) === 0 ) {
331 $upgraders = $database->get_upgrades_for_version( $this->get_current_version(), false );
332 }
333
334 $upgrader = Red_Database_Upgrader::get( $upgraders[0] );
335
336 // Where are we in this?
337 $pos = array_search( $this->stage, $this->stages, true );
338
339 if ( $pos === count( $this->stages ) - 1 ) {
340 $this->save_db_version( REDIRECTION_DB_VERSION );
341 return false;
342 }
343
344 // Set current DB version
345 $current_stages = array_keys( $upgrader->get_stages() );
346
347 if ( array_search( $this->stage, $current_stages, true ) === count( $current_stages ) - 1 ) {
348 $this->save_db_version( $upgraders[1]['version'] );
349 }
350
351 // Move on to next in current version
352 return $this->stages[ $pos + 1 ];
353 }
354
355 public function save_db_version( $version ) {
356 red_set_options( array( 'database' => $version ) );
357 delete_option( self::OLD_DB_VERSION );
358
359 $this->clear_cache();
360 }
361
362 private function clear_cache() {
363 if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) && function_exists( 'wp_cache_flush' ) ) {
364 wp_cache_flush();
365 }
366 }
367 }
368