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

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