status = $status; } /** * Register hooks. * * @return void */ public function init() { add_action( 'admin_notices', array( $this, 'render' ) ); add_action( 'admin_post_' . self::ACTION_COMPLETE, array( $this, 'handle_completion' ) ); } /** * Render the notice on the Aisthetix settings page for connected stores. * * @return void */ public function render() { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only page routing. $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; if ( Settings::PAGE_SLUG !== $page || ! current_user_can( 'manage_woocommerce' ) || ! $this->should_render() ) { return; } $this->render_completion_error(); ?>
is_completed(); } /** * Whether the merchant explicitly confirmed completion. * * @return bool */ public function is_completed() { $state = get_option( self::OPTION_STATE, array() ); if ( is_array( $state ) && ! empty( $state['completed'] ) ) { return true; } $status = $this->status->get(); return ! empty( $status['review']['completed'] ); } /** * Persist the merchant's explicit confirmation. * * Kept separate from the review URL so opening WordPress.org can never hide * the notice. * * @return void */ public function mark_completed() { update_option( self::OPTION_STATE, array( 'completed' => true ) ); } /** * Record completion with Core, then mirror it locally after Core confirms. * * @return bool Whether Core accepted the completion. */ public function complete_with_core() { $response = wp_remote_post( Plugin::brain_url() . '/api/storefront/review', array( 'timeout' => 10, 'headers' => array( 'X-Aisthetix-Secret' => Plugin::secret_key(), 'Accept' => 'application/json', 'Content-Type' => 'application/json', ), 'body' => wp_json_encode( array( 'action' => 'completed' ) ), ) ); if ( is_wp_error( $response ) || 200 !== (int) wp_remote_retrieve_response_code( $response ) ) { return false; } $data = json_decode( wp_remote_retrieve_body( $response ), true ); if ( ! is_array( $data ) || true !== ( $data['ok'] ?? null ) ) { return false; } $this->mark_completed(); return true; } /** * Handle the nonce-protected completion confirmation. * * @return void */ public function handle_completion() { $this->guard_action(); if ( ! $this->complete_with_core() ) { $this->redirect_back( self::ERROR_NOTICE ); return; } $this->redirect_back(); } /** Render a retryable error after Core declines the completion request. */ private function render_completion_error() { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only notice flag set by our own redirect. $notice = isset( $_GET['aisthetix_review_notice'] ) ? sanitize_text_field( wp_unslash( $_GET['aisthetix_review_notice'] ) ) : ''; if ( self::ERROR_NOTICE !== $notice ) { return; } ?>