|
1 | | -<?php |
2 | | -/** |
3 | | - * Handle background database updates |
4 | | - * |
5 | | - * @package LifterLMS/Abstracts/Classes |
6 | | - * |
7 | | - * @since 3.0.0 |
8 | | - * @version 3.32.0 |
9 | | - */ |
10 | | - |
11 | | -defined( 'ABSPATH' ) || exit; |
12 | | - |
13 | | -/** |
14 | | - * Database background update abstract class |
15 | | - * |
16 | | - * @since 3.0.0 |
17 | | - * @since 3.32.0 Update to use latest action-scheduler functions. |
18 | | - */ |
19 | | -abstract class LLMS_Update { |
20 | | - |
21 | | - /** |
22 | | - * Array of callable function names (within the class) |
23 | | - * that need to be called to complete the update |
24 | | - * |
25 | | - * If functions are dependent on each other |
26 | | - * the functions themselves should schedule additional actions |
27 | | - * via $this->schedule_function() upon completion. |
28 | | - * |
29 | | - * @var array |
30 | | - */ |
31 | | - protected $functions = array(); |
32 | | - |
33 | | - /** |
34 | | - * Version number of the update |
35 | | - * |
36 | | - * @var string |
37 | | - */ |
38 | | - protected $version = ''; |
39 | | - |
40 | | - /** |
41 | | - * Constructor |
42 | | - * |
43 | | - * @since 3.0.0 |
44 | | - * @version 3.3.1 |
45 | | - */ |
46 | | - public function __construct() { |
47 | | - |
48 | | - if ( ! defined( 'LLMS_BG_UPDATE_LOG' ) ) { |
49 | | - define( 'LLMS_BG_UPDATE_LOG', true ); |
50 | | - } |
51 | | - |
52 | | - $this->add_actions(); |
53 | | - |
54 | | - $progress = $this->get_progress(); |
55 | | - |
56 | | - switch ( $progress['status'] ) { |
57 | | - |
58 | | - // Start the update. |
59 | | - case 'pending': |
60 | | - $this->start(); |
61 | | - break; |
62 | | - |
63 | | - case 'finished': |
64 | | - break; |
65 | | - |
66 | | - // Check progress. |
67 | | - case 'running': |
68 | | - default: |
69 | | - if ( is_admin() && ! defined( 'DOING_CRON' ) ) { |
70 | | - $this->output_progress_notice( $progress ); |
71 | | - } |
72 | | - $this->check_progress( $progress ); |
73 | | - break; |
74 | | - |
75 | | - } |
76 | | - } |
77 | | - |
78 | | - /** |
79 | | - * Add action hooks for each function in the update |
80 | | - * |
81 | | - * @return void |
82 | | - * @since 3.0.0 |
83 | | - * @version 3.0.0 |
84 | | - */ |
85 | | - private function add_actions() { |
86 | | - |
87 | | - foreach ( $this->functions as $func ) { |
88 | | - |
89 | | - add_action( $this->get_hook( $func ), array( $this, $func ), 10, 1 ); |
90 | | - |
91 | | - } |
92 | | - } |
93 | | - |
94 | | - /** |
95 | | - * Checks progress of functions within the update |
96 | | - * and triggers completion when finished |
97 | | - * |
98 | | - * @return void |
99 | | - * @since 3.0.0 |
100 | | - * @version 3.0.0 |
101 | | - */ |
102 | | - private function check_progress( $progress ) { |
103 | | - |
104 | | - if ( ! in_array( 'incomplete', array_values( $progress['functions'] ), true ) ) { |
105 | | - |
106 | | - $this->update_status( 'finished' ); |
107 | | - $this->complete(); |
108 | | - |
109 | | - } else { |
110 | | - |
111 | | - $vals = array_count_values( $progress['functions'] ); |
112 | | - $remaining = isset( $vals['incomplete'] ) ? $vals['incomplete'] : 0; |
113 | | - $completed = isset( $vals['done'] ) ? $vals['done'] : 0; |
114 | | - $this->log( sprintf( 'Progress: %d completed, %d remaining', $completed, $remaining ) ); |
115 | | - |
116 | | - } |
117 | | - } |
118 | | - |
119 | | - /** |
120 | | - * Called when the queue is emptied for the group |
121 | | - * Outputs an admin notice |
122 | | - * |
123 | | - * @return void |
124 | | - * @since 3.0.0 |
125 | | - * @version 3.0.0 |
126 | | - */ |
127 | | - public function complete() { |
128 | | - |
129 | | - $this->log( sprintf( 'LLMS update tasks completed for version %s', $this->version ) ); |
130 | | - LLMS_Install::update_db_version( $this->version ); |
131 | | - delete_option( 'llms_update_' . $this->version ); |
132 | | - } |
133 | | - |
134 | | - /** |
135 | | - * Adds all functions to the queue |
136 | | - * |
137 | | - * @return void |
138 | | - * @since 3.0.0. |
139 | | - * @version 3.0.0. |
140 | | - */ |
141 | | - private function enqueue() { |
142 | | - |
143 | | - // Schedule an action for each function. |
144 | | - foreach ( $this->functions as $func ) { |
145 | | - $this->schedule_function( $func ); |
146 | | - } |
147 | | - |
148 | | - $this->log( sprintf( 'LLMS update tasks enqueued for version %s', $this->version ) ); |
149 | | - } |
150 | | - |
151 | | - /** |
152 | | - * Should be called by each update function when it's finished |
153 | | - * updates the progress in the functions array |
154 | | - * |
155 | | - * @param string $function function name |
156 | | - * @return void |
157 | | - * @since 3.0.0 |
158 | | - * @version 3.3.1 |
159 | | - */ |
160 | | - protected function function_complete( $function ) { |
161 | | - |
162 | | - $progress = $this->get_progress(); |
163 | | - $progress['functions'][ $function ] = 'done'; |
164 | | - update_option( 'llms_update_' . $this->version, $progress ); |
165 | | - $this->log( sprintf( '%s::%s() is complete', get_class( $this ), $function ) ); |
166 | | - } |
167 | | - |
168 | | - /** |
169 | | - * Get the name of the action hook for a given function |
170 | | - * |
171 | | - * @param string $function name of the function |
172 | | - * @return string |
173 | | - * @since 3.0.0 |
174 | | - * @version 3.0.0 |
175 | | - */ |
176 | | - private function get_hook( $function ) { |
177 | | - return 'llms_update_' . $this->version . '_function_' . $function; |
178 | | - } |
179 | | - |
180 | | - /** |
181 | | - * Get data about the progress of an update |
182 | | - * |
183 | | - * @return array |
184 | | - * @since 3.0.0 |
185 | | - * @version 3.3.1 |
186 | | - */ |
187 | | - private function get_progress() { |
188 | | - |
189 | | - $default = array( |
190 | | - 'status' => 'pending', |
191 | | - 'functions' => array_fill_keys( $this->functions, 'incomplete' ), |
192 | | - ); |
193 | | - |
194 | | - return get_option( 'llms_update_' . $this->version, $default ); |
195 | | - } |
196 | | - |
197 | | - /** |
198 | | - * Schedules a function |
199 | | - * |
200 | | - * @since 3.0.0 |
201 | | - * @since 3.32.0 Update to use latest action-scheduler functions. |
202 | | - * |
203 | | - * @param string $func Function name / callable. |
204 | | - * @param array $args Array of arguments to pass to the function. |
205 | | - * @return void |
206 | | - */ |
207 | | - protected function schedule_function( $func, $args = array() ) { |
208 | | - $this->log( sprintf( 'function `%s()` scheduled with arguments: %s', $func, json_encode( $args ) ) ); |
209 | | - as_schedule_single_action( time(), $this->get_hook( $func ), $args, 'llms_update_' . $this->version ); |
210 | | - } |
211 | | - |
212 | | - /** |
213 | | - * Logs the start of the queue |
214 | | - * |
215 | | - * @return void |
216 | | - * @since 3.0.0 |
217 | | - * @version 3.0.0 |
218 | | - */ |
219 | | - public function start() { |
220 | | - $this->log( sprintf( 'LLMS update tasks started for version %s', $this->version ) ); |
221 | | - $this->update_status( 'running' ); |
222 | | - $this->enqueue(); |
223 | | - } |
224 | | - |
225 | | - /** |
226 | | - * Update the progress data to a new status |
227 | | - * |
228 | | - * @param string $status new status |
229 | | - * @return void |
230 | | - * @since 3.0.0 |
231 | | - * @version 3.0.0 |
232 | | - */ |
233 | | - private function update_status( $status ) { |
234 | | - |
235 | | - $p = $this->get_progress(); |
236 | | - $p['status'] = $status; |
237 | | - update_option( 'llms_update_' . $this->version, $p ); |
238 | | - } |
239 | | - |
240 | | - /** |
241 | | - * Log data related to the queue |
242 | | - * |
243 | | - * @param string $msg message to log |
244 | | - * @return void |
245 | | - * @since 3.0.0 |
246 | | - * @version 3.0.0 |
247 | | - */ |
248 | | - protected function log( $msg ) { |
249 | | - |
250 | | - if ( defined( 'LLMS_BG_UPDATE_LOG' ) && LLMS_BG_UPDATE_LOG ) { |
251 | | - llms_log( $msg, 'updater' ); |
252 | | - } |
253 | | - } |
254 | | - |
255 | | - |
256 | | - /** |
257 | | - * Output a LifterLMS Admin Notice displaying the progress of the background updates |
258 | | - * |
259 | | - * @param array $progress progress array from $this->get_progress() |
260 | | - * @return void |
261 | | - * @since 3.3.1 |
262 | | - * @version 3.3.1 |
263 | | - */ |
264 | | - private function output_progress_notice( $progress ) { |
265 | | - |
266 | | - $id = 'llms_db_update_notice_' . $this->version; |
267 | | - |
268 | | - if ( LLMS_Admin_Notices::has_notice( $id ) ) { |
269 | | - LLMS_Admin_Notices::delete_notice( $id ); |
270 | | - } |
271 | | - |
272 | | - $vals = array_count_values( $progress['functions'] ); |
273 | | - $val = isset( $vals['done'] ) ? $vals['done'] : 0; |
274 | | - $max = count( $progress['functions'] ); |
275 | | - $width = $val ? ( $val / $max ) * 100 : 0; |
276 | | - $html = ' |
277 | | - '; |
278 | | - /* translators: %s: Database version. */ |
279 | | - $html .= '<p>' . sprintf( __( 'LifterLMS Database Upgrade %s Progress Report', 'lifterlms' ), $this->version ) . '</p> |
280 | | - <div style="background:#efefef;height:18px;margin:0.5em 0;"><div style="background:#ef476f;display:block;height:18px;width:' . $width . '%;"><span style="padding:0 0.5em;color:#fff;">' . $width . '%</span></div></div> |
281 | | - '; |
282 | | - /* translators: %1$s: Opening link tag, %2$s: closing link tag. */ |
283 | | - $html .= '<p><em>' . sprintf( __( 'This completion percentage is an estimate, please be patient and %1$sclick here%2$s for more information.', 'lifterlms' ), '<a href="https://lifterlms.com/docs/lifterlms-database-updates/#upgrade-progress-report" target="_blank">', '</a>' ) . '</em></p> |
284 | | - '; |
285 | | - |
286 | | - LLMS_Admin_Notices::add_notice( |
287 | | - $id, |
288 | | - array( |
289 | | - 'dismissible' => false, |
290 | | - 'flash' => true, |
291 | | - 'html' => $html, |
292 | | - 'type' => 'info', |
293 | | - ) |
294 | | - ); |
295 | | - } |
296 | | -} |
0 commit comments