| Total Complexity | 53 | 
| Total Lines | 264 | 
| Duplicated Lines | 0 % | 
| Changes | 1 | ||
| Bugs | 0 | Features | 0 | 
Complex classes like ActionScheduler often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use ActionScheduler, and based on these observations, apply Extract Interface, too.
| 1 | <?php  | 
            ||
| 10 | abstract class ActionScheduler { | 
            ||
| 11 | private static $plugin_file = '';  | 
            ||
| 12 | /** @var ActionScheduler_ActionFactory */  | 
            ||
| 13 | private static $factory = NULL;  | 
            ||
| 14 | |||
| 15 | 	public static function factory() { | 
            ||
| 16 | 		if ( !isset(self::$factory) ) { | 
            ||
| 17 | self::$factory = new ActionScheduler_ActionFactory();  | 
            ||
| 18 | }  | 
            ||
| 19 | return self::$factory;  | 
            ||
| 20 | }  | 
            ||
| 21 | |||
| 22 | 	public static function store() { | 
            ||
| 23 | return ActionScheduler_Store::instance();  | 
            ||
| 24 | }  | 
            ||
| 25 | |||
| 26 | 	public static function lock() { | 
            ||
| 27 | return ActionScheduler_Lock::instance();  | 
            ||
| 28 | }  | 
            ||
| 29 | |||
| 30 | 	public static function logger() { | 
            ||
| 31 | return ActionScheduler_Logger::instance();  | 
            ||
| 32 | }  | 
            ||
| 33 | |||
| 34 | 	public static function runner() { | 
            ||
| 35 | return ActionScheduler_QueueRunner::instance();  | 
            ||
| 36 | }  | 
            ||
| 37 | |||
| 38 | 	public static function admin_view() { | 
            ||
| 39 | return ActionScheduler_AdminView::instance();  | 
            ||
| 40 | }  | 
            ||
| 41 | |||
| 42 | /**  | 
            ||
| 43 | * Get the absolute system path to the plugin directory, or a file therein  | 
            ||
| 44 | * @static  | 
            ||
| 45 | * @param string $path  | 
            ||
| 46 | * @return string  | 
            ||
| 47 | */  | 
            ||
| 48 | 	public static function plugin_path( $path ) { | 
            ||
| 49 | $base = dirname(self::$plugin_file);  | 
            ||
| 50 | 		if ( $path ) { | 
            ||
| 51 | return trailingslashit($base).$path;  | 
            ||
| 52 | 		} else { | 
            ||
| 53 | return untrailingslashit($base);  | 
            ||
| 54 | }  | 
            ||
| 55 | }  | 
            ||
| 56 | |||
| 57 | /**  | 
            ||
| 58 | * Get the absolute URL to the plugin directory, or a file therein  | 
            ||
| 59 | * @static  | 
            ||
| 60 | * @param string $path  | 
            ||
| 61 | * @return string  | 
            ||
| 62 | */  | 
            ||
| 63 | 	public static function plugin_url( $path ) { | 
            ||
| 64 | return plugins_url($path, self::$plugin_file);  | 
            ||
| 65 | }  | 
            ||
| 66 | |||
| 67 | 	public static function autoload( $class ) { | 
            ||
| 68 | $d = DIRECTORY_SEPARATOR;  | 
            ||
| 69 | $classes_dir = self::plugin_path( 'classes' . $d );  | 
            ||
| 70 | $separator = strrpos( $class, '\\' );  | 
            ||
| 71 | 		if ( false !== $separator ) { | 
            ||
| 72 | 			if ( 0 !== strpos( $class, 'Action_Scheduler' ) ) { | 
            ||
| 73 | return;  | 
            ||
| 74 | }  | 
            ||
| 75 | $class = substr( $class, $separator + 1 );  | 
            ||
| 76 | }  | 
            ||
| 77 | |||
| 78 | 		if ( 'Deprecated' === substr( $class, -10 ) ) { | 
            ||
| 79 | $dir = self::plugin_path( 'deprecated' . $d );  | 
            ||
| 80 | 		} elseif ( self::is_class_abstract( $class ) ) { | 
            ||
| 81 | $dir = $classes_dir . 'abstracts' . $d;  | 
            ||
| 82 | 		} elseif ( self::is_class_migration( $class ) ) { | 
            ||
| 83 | $dir = $classes_dir . 'migration' . $d;  | 
            ||
| 84 | 		} elseif ( 'Schedule' === substr( $class, -8 ) ) { | 
            ||
| 85 | $dir = $classes_dir . 'schedules' . $d;  | 
            ||
| 86 | 		} elseif ( 'Action' === substr( $class, -6 ) ) { | 
            ||
| 87 | $dir = $classes_dir . 'actions' . $d;  | 
            ||
| 88 | 		} elseif ( 'Schema' === substr( $class, -6 ) ) { | 
            ||
| 89 | $dir = $classes_dir . 'schema' . $d;  | 
            ||
| 90 | 		} elseif ( strpos( $class, 'ActionScheduler' ) === 0 ) { | 
            ||
| 91 | $segments = explode( '_', $class );  | 
            ||
| 92 | $type = isset( $segments[ 1 ] ) ? $segments[ 1 ] : '';  | 
            ||
| 93 | |||
| 94 | 			switch ( $type ) { | 
            ||
| 95 | case 'WPCLI':  | 
            ||
| 96 | $dir = $classes_dir . 'WP_CLI' . $d;  | 
            ||
| 97 | break;  | 
            ||
| 98 | case 'DBLogger':  | 
            ||
| 99 | case 'DBStore':  | 
            ||
| 100 | case 'HybridStore':  | 
            ||
| 101 | case 'wpPostStore':  | 
            ||
| 102 | case 'wpCommentLogger':  | 
            ||
| 103 | $dir = $classes_dir . 'data-stores' . $d;  | 
            ||
| 104 | break;  | 
            ||
| 105 | default:  | 
            ||
| 106 | $dir = $classes_dir;  | 
            ||
| 107 | break;  | 
            ||
| 108 | }  | 
            ||
| 109 | 		} elseif ( self::is_class_cli( $class ) ) { | 
            ||
| 110 | $dir = $classes_dir . 'WP_CLI' . $d;  | 
            ||
| 111 | 		} elseif ( strpos( $class, 'CronExpression' ) === 0 ) { | 
            ||
| 112 | $dir = self::plugin_path( 'lib' . $d . 'cron-expression' . $d );  | 
            ||
| 113 | 		} elseif ( strpos( $class, 'WP_Async_Request' ) === 0 ) { | 
            ||
| 114 | $dir = self::plugin_path( 'lib' . $d );  | 
            ||
| 115 | 		} else { | 
            ||
| 116 | return;  | 
            ||
| 117 | }  | 
            ||
| 118 | |||
| 119 | 		if ( file_exists( "{$dir}{$class}.php" ) ) { | 
            ||
| 120 | 			include( "{$dir}{$class}.php" ); | 
            ||
| 121 | return;  | 
            ||
| 122 | }  | 
            ||
| 123 | }  | 
            ||
| 124 | |||
| 125 | /**  | 
            ||
| 126 | * Initialize the plugin  | 
            ||
| 127 | *  | 
            ||
| 128 | * @static  | 
            ||
| 129 | * @param string $plugin_file  | 
            ||
| 130 | */  | 
            ||
| 131 | 	public static function init( $plugin_file ) { | 
            ||
| 132 | self::$plugin_file = $plugin_file;  | 
            ||
| 133 | spl_autoload_register( array( __CLASS__, 'autoload' ) );  | 
            ||
| 134 | |||
| 135 | /**  | 
            ||
| 136 | * Fires in the early stages of Action Scheduler init hook.  | 
            ||
| 137 | */  | 
            ||
| 138 | do_action( 'action_scheduler_pre_init' );  | 
            ||
| 139 | |||
| 140 | require_once( self::plugin_path( 'functions.php' ) );  | 
            ||
| 141 | ActionScheduler_DataController::init();  | 
            ||
| 142 | |||
| 143 | $store = self::store();  | 
            ||
| 144 | $logger = self::logger();  | 
            ||
| 145 | $runner = self::runner();  | 
            ||
| 146 | $admin_view = self::admin_view();  | 
            ||
| 147 | |||
| 148 | // Ensure initialization on plugin activation.  | 
            ||
| 149 | 		if ( ! did_action( 'init' ) ) { | 
            ||
| 150 | add_action( 'init', array( $admin_view, 'init' ), 0, 0 ); // run before $store::init()  | 
            ||
| 151 | add_action( 'init', array( $store, 'init' ), 1, 0 );  | 
            ||
| 152 | add_action( 'init', array( $logger, 'init' ), 1, 0 );  | 
            ||
| 153 | add_action( 'init', array( $runner, 'init' ), 1, 0 );  | 
            ||
| 154 | 		} else { | 
            ||
| 155 | $admin_view->init();  | 
            ||
| 156 | $store->init();  | 
            ||
| 157 | $logger->init();  | 
            ||
| 158 | $runner->init();  | 
            ||
| 159 | }  | 
            ||
| 160 | |||
| 161 | 		if ( apply_filters( 'action_scheduler_load_deprecated_functions', true ) ) { | 
            ||
| 162 | require_once( self::plugin_path( 'deprecated/functions.php' ) );  | 
            ||
| 163 | }  | 
            ||
| 164 | |||
| 165 | 		if ( defined( 'WP_CLI' ) && WP_CLI ) { | 
            ||
| 
                                                                                                    
                        
                         | 
                |||
| 166 | WP_CLI::add_command( 'action-scheduler', 'ActionScheduler_WPCLI_Scheduler_command' );  | 
            ||
| 167 | 			if ( ! ActionScheduler_DataController::is_migration_complete() && Controller::instance()->allow_migration() ) { | 
            ||
| 168 | $command = new Migration_Command();  | 
            ||
| 169 | $command->register();  | 
            ||
| 170 | }  | 
            ||
| 171 | }  | 
            ||
| 172 | |||
| 173 | /**  | 
            ||
| 174 | * Handle WP comment cleanup after migration.  | 
            ||
| 175 | */  | 
            ||
| 176 | 		if ( is_a( $logger, 'ActionScheduler_DBLogger' ) && ActionScheduler_DataController::is_migration_complete() && ActionScheduler_WPCommentCleaner::has_logs() ) { | 
            ||
| 177 | ActionScheduler_WPCommentCleaner::init();  | 
            ||
| 178 | }  | 
            ||
| 179 | |||
| 180 | add_action( 'action_scheduler/migration_complete', 'ActionScheduler_WPCommentCleaner::maybe_schedule_cleanup' );  | 
            ||
| 181 | }  | 
            ||
| 182 | |||
| 183 | /**  | 
            ||
| 184 | * Determine if the class is one of our abstract classes.  | 
            ||
| 185 | *  | 
            ||
| 186 | * @since 3.0.0  | 
            ||
| 187 | *  | 
            ||
| 188 | * @param string $class The class name.  | 
            ||
| 189 | *  | 
            ||
| 190 | * @return bool  | 
            ||
| 191 | */  | 
            ||
| 192 | 	protected static function is_class_abstract( $class ) { | 
            ||
| 193 | static $abstracts = array(  | 
            ||
| 194 | 'ActionScheduler' => true,  | 
            ||
| 195 | 'ActionScheduler_Abstract_ListTable' => true,  | 
            ||
| 196 | 'ActionScheduler_Abstract_QueueRunner' => true,  | 
            ||
| 197 | 'ActionScheduler_Abstract_Schedule' => true,  | 
            ||
| 198 | 'ActionScheduler_Abstract_RecurringSchedule' => true,  | 
            ||
| 199 | 'ActionScheduler_Lock' => true,  | 
            ||
| 200 | 'ActionScheduler_Logger' => true,  | 
            ||
| 201 | 'ActionScheduler_Abstract_Schema' => true,  | 
            ||
| 202 | 'ActionScheduler_Store' => true,  | 
            ||
| 203 | 'ActionScheduler_TimezoneHelper' => true,  | 
            ||
| 204 | );  | 
            ||
| 205 | |||
| 206 | return isset( $abstracts[ $class ] ) && $abstracts[ $class ];  | 
            ||
| 207 | }  | 
            ||
| 208 | |||
| 209 | /**  | 
            ||
| 210 | * Determine if the class is one of our migration classes.  | 
            ||
| 211 | *  | 
            ||
| 212 | * @since 3.0.0  | 
            ||
| 213 | *  | 
            ||
| 214 | * @param string $class The class name.  | 
            ||
| 215 | *  | 
            ||
| 216 | * @return bool  | 
            ||
| 217 | */  | 
            ||
| 218 | 	protected static function is_class_migration( $class ) { | 
            ||
| 219 | static $migration_segments = array(  | 
            ||
| 220 | 'ActionMigrator' => true,  | 
            ||
| 221 | 'BatchFetcher' => true,  | 
            ||
| 222 | 'DBStoreMigrator' => true,  | 
            ||
| 223 | 'DryRun' => true,  | 
            ||
| 224 | 'LogMigrator' => true,  | 
            ||
| 225 | 'Config' => true,  | 
            ||
| 226 | 'Controller' => true,  | 
            ||
| 227 | 'Runner' => true,  | 
            ||
| 228 | 'Scheduler' => true,  | 
            ||
| 229 | );  | 
            ||
| 230 | |||
| 231 | $segments = explode( '_', $class );  | 
            ||
| 232 | $segment = isset( $segments[ 1 ] ) ? $segments[ 1 ] : $class;  | 
            ||
| 233 | |||
| 234 | return isset( $migration_segments[ $segment ] ) && $migration_segments[ $segment ];  | 
            ||
| 235 | }  | 
            ||
| 236 | |||
| 237 | /**  | 
            ||
| 238 | * Determine if the class is one of our WP CLI classes.  | 
            ||
| 239 | *  | 
            ||
| 240 | * @since 3.0.0  | 
            ||
| 241 | *  | 
            ||
| 242 | * @param string $class The class name.  | 
            ||
| 243 | *  | 
            ||
| 244 | * @return bool  | 
            ||
| 245 | */  | 
            ||
| 246 | 	protected static function is_class_cli( $class ) { | 
            ||
| 247 | static $cli_segments = array(  | 
            ||
| 248 | 'QueueRunner' => true,  | 
            ||
| 249 | 'Command' => true,  | 
            ||
| 250 | 'ProgressBar' => true,  | 
            ||
| 251 | );  | 
            ||
| 252 | |||
| 253 | $segments = explode( '_', $class );  | 
            ||
| 254 | $segment = isset( $segments[ 1 ] ) ? $segments[ 1 ] : $class;  | 
            ||
| 255 | |||
| 256 | return isset( $cli_segments[ $segment ] ) && $cli_segments[ $segment ];  | 
            ||
| 257 | }  | 
            ||
| 258 | |||
| 259 | 	final public function __clone() { | 
            ||
| 260 | 		trigger_error("Singleton. No cloning allowed!", E_USER_ERROR); | 
            ||
| 261 | }  | 
            ||
| 262 | |||
| 263 | 	final public function __wakeup() { | 
            ||
| 264 | 		trigger_error("Singleton. No serialization allowed!", E_USER_ERROR); | 
            ||
| 265 | }  | 
            ||
| 266 | |||
| 267 | 	final private function __construct() {} | 
            ||
| 268 | |||
| 269 | /** Deprecated **/  | 
            ||
| 270 | |||
| 271 | 	public static function get_datetime_object( $when = null, $timezone = 'UTC' ) { | 
            ||
| 274 | }  | 
            ||
| 275 | }  | 
            ||
| 276 |