register(); if ( is_admin() ) { ( new Settings( $connection ) )->register(); ( new Connect( $connection ) )->register(); // Polled by the status screen while a sync runs. Registered with // the rest of the admin because admin-ajax is an admin request. ( new Progress( $connection ) )->register(); } add_action( self::CRON_HOOK, static function () use ( $connection ): void { ( new Stats( $connection ) )->prune(); } ); // The CLI registers whether or not the site is connected: `wp sharelyai // status` saying "Not connected" is the most useful thing it can say, and // a command that disappears when there is a problem is no diagnostic. Cli::register( $connection ); if ( ! $connection->is_connected() ) { return; } // The statistics table may predate this install's activation — a site // restored from an export, or credentials from wp-config.php on a fresh // database. Cheap: one option read unless the version has moved. Stats::install_table(); self::schedule(); // Sync: the editing hooks, the queue workers, and the CLI. The workers // register whenever the site is connected, because an action queued // before a deactivation has to find its handler when it finally runs. ( new Sync( $connection ) )->register(); Queue::register( $connection ); // The search box, on the theme's own search page. It takes itself out // of the way whenever Sharely cannot answer, so a site with this // registered and a workspace that is down still has working search. ( new Search( $connection ) )->register(); // Ask: the panel, and the one route the browser needs to use it. The // route registers in every context because REST requests are not // `is_admin()` and not the front end either. ( new Rest( $connection ) )->register(); ( new Ask( $connection ) )->register(); // The blocks. Registered on init, in every context: the editor needs // the type to render the placeholder, and the front end needs it to // render the real thing. ( new Blocks( $connection ) )->register(); // What an agent on this site can ask it to do: search, and ask. Only // on WordPress 6.9 and up, where the Abilities API exists; the class // checks and does nothing below that. ( new Abilities( $connection ) )->register(); } /** * On activation. * * Nothing is sent to Sharely and nothing is created there until an * administrator connects the site — a plugin that phoned home on activation * would fail the directory's review, and rightly. Only local tables. */ public static function activate(): void { Stats::install_table(); self::schedule(); } /** * On deactivation: stop working, keep the settings. * * Deactivating is not disconnecting. Settings and statistics survive so * reactivating does not mean connecting again; Disconnect is the deliberate * act that clears them. */ public static function deactivate(): void { wp_clear_scheduled_hook( self::CRON_HOOK ); // Queued work is dropped rather than left to run against a plugin that is // no longer there. Nothing in Sharely changes; the next sync re-sends. ( new Queue() )->cancel_all(); } /** * Makes sure the daily job exists, without duplicating it. * * WP-Cron, not Action Scheduler: this is one small delete a day, and * pulling in a scheduling library for it would be the wrong trade. Sync is * the job that needs Action Scheduler, and it brings its own. */ private static function schedule(): void { if ( ! wp_next_scheduled( self::CRON_HOOK ) ) { wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', self::CRON_HOOK ); } } }