PluginProbe
Redirection / 3.7.2
Redirection v3.7.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 3.7.2, at database/database-status.php

320 lines 8.1 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 return $version;
93 }
94
95 return '';
96 }
97
98 private function get_old_version() {
99 return get_option( self::OLD_DB_VERSION );
100 }
101
102 /**
103 * Does the current database support a particular version
104 *
105 * @param string $version Target version
106 * @return bool true if supported, false otherwise
107 */
108 public function does_support( $version ) {
109 return version_compare( $this->get_current_version(), $version, 'ge' );
110 }
111
112 public function is_error() {
113 return $this->result === self::RESULT_ERROR;
114 }
115
116 public function set_error( $error ) {
117 global $wpdb;
118
119 $this->result = self::RESULT_ERROR;
120 $this->reason = str_replace( "\t", ' ', $error );
121
122 if ( $wpdb->last_error ) {
123 $this->debug[] = $wpdb->last_error;
124 }
125
126 $latest = Red_Database::get_latest_database();
127 $this->debug = array_merge( $this->debug, $latest->get_table_schema() );
128 $this->debug[] = 'Stage: ' . $this->get_current_stage();
129 }
130
131 public function set_ok( $reason ) {
132 $this->reason = $reason;
133 $this->result = self::RESULT_OK;
134 $this->debug = [];
135 }
136
137 /**
138 * Stop current upgrade
139 */
140 public function stop_update() {
141 $this->stage = false;
142 $this->stages = [];
143 $this->debug = [];
144
145 delete_option( self::DB_UPGRADE_STAGE );
146 }
147
148 public function finish() {
149 $this->stop_update();
150
151 if ( $this->status === self::STATUS_NEED_INSTALL ) {
152 $this->status = self::STATUS_FINISHED_INSTALL;
153 } elseif ( $this->status === self::STATUS_NEED_UPDATING ) {
154 $this->status = self::STATUS_FINISHED_UPDATING;
155 }
156 }
157
158 /**
159 * Get current upgrade stage
160 * @return string|bool Current stage name, or false if not upgrading
161 */
162 public function get_current_stage() {
163 return $this->stage;
164 }
165
166 /**
167 * Move current stage on to the next
168 */
169 public function set_next_stage() {
170 $stage = $this->get_current_stage();
171
172 if ( $stage ) {
173 $stage = $this->get_next_stage( $stage );
174
175 // Save next position
176 if ( $stage ) {
177 $this->set_stage( $stage );
178 } else {
179 $this->finish();
180 }
181 }
182 }
183
184 /**
185 * Get current upgrade status
186 *
187 * @return array Database status array
188 */
189 public function get_json() {
190 // Base information
191 $result = [
192 'status' => $this->status,
193 'inProgress' => $this->stage !== false,
194 ];
195
196 // Add on version status
197 if ( $this->status === self::STATUS_NEED_INSTALL || $this->status === self::STATUS_NEED_UPDATING ) {
198 $result = array_merge( $result, $this->get_version_upgrade() );
199 }
200
201 if ( $this->status == self::STATUS_NEED_INSTALL ) {
202 $result['api'] = [
203 REDIRECTION_API_JSON => red_get_rest_api( REDIRECTION_API_JSON ),
204 REDIRECTION_API_JSON_INDEX => red_get_rest_api( REDIRECTION_API_JSON_INDEX ),
205 REDIRECTION_API_JSON_RELATIVE => red_get_rest_api( REDIRECTION_API_JSON_RELATIVE ),
206 ];
207 }
208
209 // Add on upgrade status
210 if ( $this->is_error() ) {
211 $result = array_merge( $result, $this->get_version_upgrade(), $this->get_progress_status(), $this->get_error_status() );
212 } elseif ( $result['inProgress'] ) {
213 $result = array_merge( $result, $this->get_progress_status() );
214 } elseif ( $this->status === self::STATUS_FINISHED_INSTALL || $this->status === self::STATUS_FINISHED_UPDATING ) {
215 $result['complete'] = 100;
216 $result['reason'] = $this->reason;
217 }
218
219 return $result;
220 }
221
222 private function get_error_status() {
223 return [
224 'reason' => $this->reason,
225 'result' => self::RESULT_ERROR,
226 'debug' => $this->debug,
227 ];
228 }
229
230 private function get_progress_status() {
231 $complete = 0;
232
233 if ( $this->stage ) {
234 $complete = round( ( array_search( $this->stage, $this->stages, true ) / count( $this->stages ) ) * 100, 1 );
235 }
236
237 return [
238 'complete' => $complete,
239 'result' => self::RESULT_OK,
240 'reason' => $this->reason,
241 ];
242 }
243
244 private function get_version_upgrade() {
245 return [
246 'current' => $this->get_current_version() ? $this->get_current_version() : '-',
247 'next' => REDIRECTION_DB_VERSION,
248 'time' => microtime( true ),
249 ];
250 }
251
252 /**
253 * Set the status information for a database upgrade
254 */
255 public function start_install( array $upgrades ) {
256 $this->set_stages( $upgrades );
257 $this->status = self::STATUS_NEED_INSTALL;
258 }
259
260 public function start_upgrade( array $upgrades ) {
261 $this->set_stages( $upgrades );
262 $this->status = self::STATUS_NEED_UPDATING;
263 }
264
265 private function set_stages( array $upgrades ) {
266 $this->stages = [];
267
268 foreach ( $upgrades as $upgrade ) {
269 $upgrader = Red_Database_Upgrader::get( $upgrade );
270 $this->stages = array_merge( $this->stages, array_keys( $upgrader->get_stages() ) );
271 }
272
273 if ( count( $this->stages ) > 0 ) {
274 $this->set_stage( $this->stages[0] );
275 }
276 }
277
278 public function set_stage( $stage ) {
279 $this->stage = $stage;
280 $this->save_details();
281 }
282
283 private function save_details() {
284 update_option( self::DB_UPGRADE_STAGE, [
285 'stage' => $this->stage,
286 'stages' => $this->stages,
287 'status' => $this->status,
288 ] );
289 }
290
291 private function get_next_stage( $stage ) {
292 $database = new Red_Database();
293 $upgraders = $database->get_upgrades_for_version( $this->get_current_version(), $this->get_current_stage() );
294 $upgrader = Red_Database_Upgrader::get( $upgraders[0] );
295
296 // Where are we in this?
297 $pos = array_search( $this->stage, $this->stages, true );
298
299 if ( $pos === count( $this->stages ) - 1 ) {
300 $this->save_db_version( REDIRECTION_DB_VERSION );
301 return false;
302 }
303
304 // Set current DB version
305 $current_stages = array_keys( $upgrader->get_stages() );
306
307 if ( array_search( $this->stage, $current_stages, true ) === count( $current_stages ) - 1 ) {
308 $this->save_db_version( $upgraders[1]['version'] );
309 }
310
311 // Move on to next in current version
312 return $this->stages[ $pos + 1 ];
313 }
314
315 private function save_db_version( $version ) {
316 red_set_options( array( 'database' => $version ) );
317 delete_option( self::OLD_DB_VERSION );
318 }
319 }
320