config = new Config(); $this->audit = new Audit(); $this->taxonomy = new Taxonomy( $this->config ); $this->workflow = new Workflow( $this->config ); $this->statuses = new Statuses( $this->config, $this->workflow ); $this->transitions = new Transitions( $this->workflow, $this->audit, $this->config ); $this->rest = new Rest( $this->transitions, $this->workflow ); $this->editor_ui = new Admin\EditorUi( $this->workflow, $this->transitions ); $recipients = new Notifications\Recipients( $this->workflow ); $mailer = new Notifications\Mailer(); $this->review_queue = new Notifications\ReviewQueue( $this->config, $this->workflow ); $this->notifications = new Notifications\Notifications( $this->config, $this->workflow, $recipients, $mailer, $this->review_queue ); $this->escalation = new Escalation\Escalation( $this->config, $this->workflow, $recipients, $mailer ); $this->sections = new Permissions\Sections( $this->config ); $this->scoping = new Permissions\Scoping( $this->config, $this->sections ); $this->user_assignment = new Permissions\UserAssignment( $this->sections ); $this->settings = new Admin\Settings( $this->config, $this->workflow, $this->statuses, $this->audit ); $this->history = new Admin\History( $this->workflow, $this->audit ); } /** * Boot: register runtime hooks. Called on plugins_loaded. * * @return void */ public function boot() { // Translations load automatically for plugins hosted on WordPress.org // since WordPress 4.6, so no text domain is registered manually here. $this->taxonomy->register_hooks(); $this->statuses->register_hooks(); $this->transitions->register_hooks(); $this->rest->register_hooks(); $this->notifications->register_hooks(); $this->escalation->register_hooks(); $this->sections->register_hooks(); $this->scoping->register_hooks(); add_action( 'admin_init', array( $this, 'maybe_upgrade_database' ) ); if ( is_admin() ) { $this->editor_ui->register_hooks(); $this->history->register_hooks(); $this->review_queue->register_hooks(); $this->user_assignment->register_hooks(); $this->settings->register_hooks(); } /** * Fires after the workflow plugin has booted its services. * * @param Plugin $plugin The plugin container. */ do_action( 'ostew/booted', $this ); } /** * Activation: create the audit table, seed the default config, stamp versions. * * @return void */ public static function activate() { $plugin = self::instance(); $plugin->audit->create_table(); $plugin->config->seed(); $plugin->taxonomy->register(); // ensure taxonomy exists this request. $plugin->taxonomy->insert_default_terms(); // Record the statuses this configuration defines, so that a later edit which // drops one can still be reconciled against the content holding it. $plugin->config->remember_statuses( $plugin->config->custom_statuses_in( $plugin->config->all() ) ); update_option( 'ostew_db_version', OSTEW_DB_VERSION ); /* * Schedule the escalation scan. * * Deactivation clears the schedule, so a plain "an hour from now" here meant * that toggling the plugin silently pushed the next scan back by up to an * hour — worst when it was about to run. Deactivation now records when the * scan was due; if that moment has not passed, it is honoured. */ if ( ! wp_next_scheduled( Escalation\Escalation::CRON_HOOK ) ) { $pending = (int) get_option( self::PENDING_SCAN_OPTION, 0 ); $first = ( $pending > time() ) ? $pending : self::next_hour_boundary(); wp_schedule_event( $first, 'hourly', Escalation\Escalation::CRON_HOOK ); } delete_option( self::PENDING_SCAN_OPTION ); // Rewrite rules aren't needed yet (no public statuses), but flush defensively. flush_rewrite_rules(); } /** * Bring the audit table up to the current schema. * * Activation is not enough on its own: updating an installed plugin does not * re-run the activation hook, so without this an existing install would keep * an out-of-date table. dbDelta is idempotent, and only runs when the stored * version is behind. * * @return void */ public function maybe_upgrade_database() { $stored = (int) get_option( 'ostew_db_version', 0 ); if ( $stored >= (int) OSTEW_DB_VERSION ) { return; } $this->audit->create_table(); update_option( 'ostew_db_version', OSTEW_DB_VERSION ); } /** * The next whole hour, as a Unix timestamp. * * @return int */ public static function next_hour_boundary() { $now = time(); return (int) ( ( (int) floor( $now / HOUR_IN_SECONDS ) + 1 ) * HOUR_IN_SECONDS ); } /** * Deactivation: non-destructive. Clears scheduled events only; data is kept. * * @return void */ public static function deactivate() { // Remember when the scan was due, so reactivating does not move it. $next = wp_next_scheduled( Escalation\Escalation::CRON_HOOK ); if ( $next ) { update_option( self::PENDING_SCAN_OPTION, (int) $next, false ); } wp_clear_scheduled_hook( 'ostew_escalation_scan' ); flush_rewrite_rules(); } }