= self::SECOND_MILESTONE ) { update_option( self::OPTION, 'due-again', false ); } } public static function state(): string { $state = (string) get_option( self::OPTION, '' ); if ( '' === $state ) { // The first look on a site whose orders with designs came before this request existed. $ordered = get_posts( array( 'post_type' => Design_Store::POST_TYPE, 'post_status' => 'private', 'numberposts' => 1, 'fields' => 'ids', 'meta_key' => Design_Store::META_ORDER, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key ) ); $state = $ordered ? 'due' : 'waiting'; update_option( self::OPTION, $state, false ); } return $state; } public static function notice(): void { if ( ! current_user_can( 'manage_woocommerce' ) || 'own' !== Admin_Menu::surface() ) { return; } echo wp_kses_post( self::notice_html() ); } public static function notice_html(): string { $state = self::state(); if ( ! in_array( $state, array( 'due', 'due-again' ), true ) ) { return ''; } $answer = static fn( string $answer ): string => Admin_Menu::action_url( 'printblob_review_request', array( 'answer' => $answer ) ); $later = 'due' === $state ? sprintf( ' %2$s %4$s', esc_url( $answer( 'dismiss' ) ), esc_html__( 'Dismiss', 'printblob' ), esc_url( $answer( 'never' ) ), esc_html__( 'Don’t ask again', 'printblob' ) ) : sprintf( ' %2$s', esc_url( $answer( 'never' ) ), esc_html__( 'Dismiss', 'printblob' ) ); return sprintf( '

%1$s

%3$s%4$s

', 'due' === $state ? esc_html__( 'Your shop has its first order with a PrintBlob design. If PrintBlob is useful to you, a review on WordPress.org helps other shops find it.', 'printblob' ) /* translators: %d: number of orders with designs. */ : esc_html( sprintf( __( 'Your shop has had %d orders with PrintBlob designs. If PrintBlob is useful to you, a review on WordPress.org helps other shops find it.', 'printblob' ), self::SECOND_MILESTONE ) ), esc_url( $answer( 'review' ) ), esc_html__( 'Write a review', 'printblob' ), $later ); } /** * Records the admin's answer. Following a request, "Don't ask again" and dismissing the second request end it for * good; dismissing the first waits for the second milestone, unless the shop has reached it already. * * @param string $answer 'review', 'dismiss' or 'never'. */ public static function answer( string $answer ): void { if ( in_array( $answer, array( 'review', 'never' ), true ) ) { update_option( self::OPTION, 'done', false ); } elseif ( 'dismiss' === $answer ) { $first = 'due' === self::state() && Design_Store::order_count() < self::SECOND_MILESTONE; update_option( self::OPTION, $first ? 'later' : 'done', false ); } } public static function handle(): void { check_admin_referer( 'printblob_review_request' ); Admin_Menu::allow(); $answer = isset( $_GET['answer'] ) ? sanitize_key( wp_unslash( $_GET['answer'] ) ) : ''; self::answer( $answer ); if ( 'review' === $answer ) { wp_redirect( self::REVIEW_URL ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect -- PrintBlob's own page on WordPress.org. exit; } Admin_Menu::back(); } }