LLMS_Update
Database background update abstract class
Contents
Source Source
File: includes/abstracts/abstract.llms.update.php
abstract class LLMS_Update { /** * Array of callable function names (within the class) * that need to be called to complete the update * * If functions are dependent on each other * the functions themselves should schedule additional actions * via $this->schedule_function() upon completion. * * @var array */ protected $functions = array(); /** * Version number of the update * * @var string */ protected $version = ''; /** * Constructor * * @since 3.0.0 * @version 3.3.1 */ public function __construct() { if ( ! defined( 'LLMS_BG_UPDATE_LOG' ) ) { define( 'LLMS_BG_UPDATE_LOG', true ); } $this->add_actions(); $progress = $this->get_progress(); switch ( $progress['status'] ) { // Start the update. case 'pending': $this->start(); break; case 'finished': break; // Check progress. case 'running': default: if ( is_admin() && ! defined( 'DOING_CRON' ) ) { $this->output_progress_notice( $progress ); } $this->check_progress( $progress ); break; } } /** * Add action hooks for each function in the update * * @return void * @since 3.0.0 * @version 3.0.0 */ private function add_actions() { foreach ( $this->functions as $func ) { add_action( $this->get_hook( $func ), array( $this, $func ), 10, 1 ); } } /** * Checks progress of functions within the update * and triggers completion when finished * * @return void * @since 3.0.0 * @version 3.0.0 */ private function check_progress( $progress ) { if ( ! in_array( 'incomplete', array_values( $progress['functions'] ), true ) ) { $this->update_status( 'finished' ); $this->complete(); } else { $vals = array_count_values( $progress['functions'] ); $remaining = isset( $vals['incomplete'] ) ? $vals['incomplete'] : 0; $completed = isset( $vals['done'] ) ? $vals['done'] : 0; $this->log( sprintf( 'Progress: %d completed, %d remaining', $completed, $remaining ) ); } } /** * Called when the queue is emptied for the group * Outputs an admin notice * * @return void * @since 3.0.0 * @version 3.0.0 */ public function complete() { $this->log( sprintf( 'LLMS update tasks completed for version %s', $this->version ) ); LLMS_Install::update_db_version( $this->version ); delete_option( 'llms_update_' . $this->version ); } /** * Adds all functions to the queue * * @return void * @since 3.0.0. * @version 3.0.0. */ private function enqueue() { // Schedule an action for each function. foreach ( $this->functions as $func ) { $this->schedule_function( $func ); } $this->log( sprintf( 'LLMS update tasks enqueued for version %s', $this->version ) ); } /** * Should be called by each update function when it's finished * updates the progress in the functions array * * @param string $function function name * @return void * @since 3.0.0 * @version 3.3.1 */ protected function function_complete( $function ) { $progress = $this->get_progress(); $progress['functions'][ $function ] = 'done'; update_option( 'llms_update_' . $this->version, $progress ); $this->log( sprintf( '%s::%s() is complete', get_class( $this ), $function ) ); } /** * Get the name of the action hook for a given function * * @param string $function name of the function * @return string * @since 3.0.0 * @version 3.0.0 */ private function get_hook( $function ) { return 'llms_update_' . $this->version . '_function_' . $function; } /** * Get data about the progress of an update * * @return array * @since 3.0.0 * @version 3.3.1 */ private function get_progress() { $default = array( 'status' => 'pending', 'functions' => array_fill_keys( $this->functions, 'incomplete' ), ); return get_option( 'llms_update_' . $this->version, $default ); } /** * Schedules a function * * @since 3.0.0 * @since 3.32.0 Update to use latest action-scheduler functions. * * @param string $func Function name / callable. * @param array $args Array of arguments to pass to the function. * @return void */ protected function schedule_function( $func, $args = array() ) { $this->log( sprintf( 'function `%s()` scheduled with arguments: %s', $func, json_encode( $args ) ) ); as_schedule_single_action( time(), $this->get_hook( $func ), $args, 'llms_update_' . $this->version ); } /** * Logs the start of the queue * * @return void * @since 3.0.0 * @version 3.0.0 */ public function start() { $this->log( sprintf( 'LLMS update tasks started for version %s', $this->version ) ); $this->update_status( 'running' ); $this->enqueue(); } /** * Update the progress data to a new status * * @param string $status new status * @return void * @since 3.0.0 * @version 3.0.0 */ private function update_status( $status ) { $p = $this->get_progress(); $p['status'] = $status; update_option( 'llms_update_' . $this->version, $p ); } /** * Log data related to the queue * * @param string $msg message to log * @return void * @since 3.0.0 * @version 3.0.0 */ protected function log( $msg ) { if ( defined( 'LLMS_BG_UPDATE_LOG' ) && LLMS_BG_UPDATE_LOG ) { llms_log( $msg, 'updater' ); } } /** * Output a LifterLMS Admin Notice displaying the progress of the background updates * * @param array $progress progress array from $this->get_progress() * @return void * @since 3.3.1 * @version 3.3.1 */ private function output_progress_notice( $progress ) { $id = 'llms_db_update_notice_' . $this->version; if ( LLMS_Admin_Notices::has_notice( $id ) ) { LLMS_Admin_Notices::delete_notice( $id ); } $vals = array_count_values( $progress['functions'] ); $val = isset( $vals['done'] ) ? $vals['done'] : 0; $max = count( $progress['functions'] ); $width = $val ? ( $val / $max ) * 100 : 0; $html = ' <p>' . sprintf( __( 'LifterLMS Database Upgrade %s Progress Report', 'lifterlms' ), $this->version ) . '</p> <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> <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> '; LLMS_Admin_Notices::add_notice( $id, array( 'dismissible' => false, 'flash' => true, 'html' => $html, 'type' => 'info', ) ); } }
Expand full source code Collapse full source code View on GitHub
Methods Methods
- __construct — Constructor
- add_actions — Add action hooks for each function in the update
- check_progress — Checks progress of functions within the update and triggers completion when finished
- complete — Called when the queue is emptied for the group Outputs an admin notice
- enqueue — Adds all functions to the queue
- function_complete — Should be called by each update function when it's finished updates the progress in the functions array
- get_hook — Get the name of the action hook for a given function
- get_progress — Get data about the progress of an update
- log — Log data related to the queue
- output_progress_notice — Output a LifterLMS Admin Notice displaying the progress of the background updates
- schedule_function — Schedules a function
- start — Logs the start of the queue
- update_status — Update the progress data to a new status
Changelog Changelog
Version | Description |
---|---|
3.32.0 | Update to use latest action-scheduler functions. |
3.0.0 | Introduced. |