WP_REST_Server::CREATABLE, 'callback' => array( $this, 'rest_activate' ), 'permission_callback' => static function () { return current_user_can( 'activate_plugins' ); }, ) ); } /** * What the admin app needs to decide between selling and activating — * and, when Pro is running, showing nothing at all. * * Detection is a constant plus a file check: no get_plugins(), which would * load the whole plugin API into every admin page load. * * @return array{active:bool, installed:bool, canActivate:bool, upgradeUrl:string, showPromo:bool} */ public static function status() { $active = defined( 'OORANK_PRO_VERSION' ); $installed = $active || file_exists( WP_PLUGIN_DIR . '/' . self::PLUGIN_FILE ); return array( 'active' => $active, 'installed' => $installed, 'canActivate' => $installed && ! $active && current_user_can( 'activate_plugins' ), 'upgradeUrl' => self::upgrade_url(), 'showPromo' => self::show_promo(), ); } /** * Whether the admin app may render anything about the add-on at all. * * Off by default: the add-on is not on sale yet, so a card describing it — * whether a pitch or an activate button — advertises a product an owner * cannot buy or trust. Flip it with the filter while working on Pro, and * change the default here once Pro ships. * * @return bool True to render the Pro card. */ private static function show_promo() { /** * Filter whether the Pro card is rendered in the admin app. * * @param bool $show False by default, until the add-on ships. */ return (bool) apply_filters( 'oorank_show_pro_promo', false ); } /** * Where an owner without the add-on is sent to get it. * * Empty by default: there is no landing page to point at, and a hardcoded * destination in a wp.org-hosted plugin is a promise the plugin cannot * keep. The promo card hides its button while this is empty. * * @return string Landing page URL, or an empty string when none is set. */ private static function upgrade_url() { /** * Filter the upgrade destination for the Pro promo card. * * @param string $url Landing page for the Pro add-on. Empty hides * the promo card's button. */ $url = apply_filters( 'oorank_pro_url', '' ); return is_string( $url ) ? esc_url_raw( $url ) : ''; } /** * POST /addon/activate — activate the installed add-on in place. * * @return WP_REST_Response|WP_Error */ public function rest_activate() { if ( defined( 'OORANK_PRO_VERSION' ) ) { return rest_ensure_response( self::status() ); } require_once ABSPATH . 'wp-admin/includes/plugin.php'; if ( ! file_exists( WP_PLUGIN_DIR . '/' . self::PLUGIN_FILE ) ) { return new WP_Error( 'oorank_not_installed', __( 'Oorank Pro is not installed on this site.', 'oorank' ), array( 'status' => 404 ) ); } $activated = activate_plugin( self::PLUGIN_FILE ); if ( is_wp_error( $activated ) ) { return new WP_Error( 'oorank_activate_failed', $activated->get_error_message(), array( 'status' => 500 ) ); } // The add-on booted on this request only if it happened to load before // the REST call; either way it is active from the next page load, so // report that rather than what this process can see. $status = self::status(); $status['active'] = true; $status['installed'] = true; $status['canActivate'] = false; return rest_ensure_response( $status ); } }