10, 'headers' => array( 'Accept' => 'application/json' ), ) ); if ( is_wp_error( $response ) ) { return $response; } if ( 200 !== (int) wp_remote_retrieve_response_code( $response ) ) { return new \WP_Error( 'at_http', __( 'The demo library could not be reached.', 'advanced-testimonial' ) ); } $data = json_decode( wp_remote_retrieve_body( $response ), true ); $data = self::validate_manifest( $data ); if ( is_wp_error( $data ) ) { return $data; } set_transient( self::TRANSIENT, $data, self::CACHE_TTL ); return $data; } /** * Validate the raw manifest and normalise its demos. * * @param mixed $data Decoded JSON. * @return array|\WP_Error */ private static function validate_manifest( $data ) { if ( ! is_array( $data ) || empty( $data['demos'] ) || ! is_array( $data['demos'] ) ) { return new \WP_Error( 'at_manifest', __( 'The demo library response was not valid.', 'advanced-testimonial' ) ); } if ( isset( $data['plugin'] ) && 'advanced-testimonial' !== $data['plugin'] ) { return new \WP_Error( 'at_manifest', __( 'The demo library is for a different plugin.', 'advanced-testimonial' ) ); } $demos = array(); foreach ( $data['demos'] as $demo ) { if ( ! is_array( $demo ) || empty( $demo['id'] ) || empty( $demo['file'] ) ) { continue; } $file = esc_url_raw( $demo['file'] ); if ( ! $file || ! in_array( wp_parse_url( $file, PHP_URL_SCHEME ), array( 'http', 'https' ), true ) ) { continue; } $demos[] = array( 'id' => sanitize_key( $demo['id'] ), 'name' => isset( $demo['name'] ) ? sanitize_text_field( $demo['name'] ) : $demo['id'], 'description' => isset( $demo['description'] ) ? sanitize_text_field( $demo['description'] ) : '', 'version' => isset( $demo['version'] ) ? sanitize_text_field( $demo['version'] ) : '', 'requires' => isset( $demo['requires'] ) ? sanitize_text_field( $demo['requires'] ) : '', 'category' => isset( $demo['category'] ) ? sanitize_text_field( $demo['category'] ) : '', 'tags' => isset( $demo['tags'] ) && is_array( $demo['tags'] ) ? array_map( 'sanitize_text_field', $demo['tags'] ) : array(), 'featured' => ! empty( $demo['featured'] ), 'is_new' => ! empty( $demo['new'] ), 'preview' => isset( $demo['preview'] ) ? esc_url_raw( $demo['preview'] ) : '', 'file' => $file, ); } if ( ! $demos ) { return new \WP_Error( 'at_manifest', __( 'The demo library is empty right now.', 'advanced-testimonial' ) ); } return array( 'schema_version' => isset( $data['schema_version'] ) ? absint( $data['schema_version'] ) : 1, 'demos' => $demos, ); } /** * Render the Demo Library page. * * @return void */ public function page() { // A nonce-protected "Refresh" link bypasses the 6h manifest cache. $refresh = isset( $_GET['at_refresh'], $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_key( wp_unslash( $_GET['_wpnonce'] ) ), 'at_demo_refresh' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nonce verified inline. $manifest = self::get_manifest( $refresh ); $refresh_url = wp_nonce_url( add_query_arg( array( 'post_type' => CPT::POST_TYPE, 'page' => self::PAGE, 'at_refresh' => 1, ), admin_url( 'edit.php' ) ), 'at_demo_refresh' ); ?>
=' ); $haystack = strtolower( trim( $demo['name'] . ' ' . $demo['description'] . ' ' . $demo['category'] . ' ' . implode( ' ', $demo['tags'] ) ) ); ?>
' . sprintf( /* translators: %d: number of imported testimonials. */ esc_html__( 'Demo imported — %d testimonials added. Display them with the block or the [advanced_testimonial] shortcode.', 'advanced-testimonial' ), (int) $count ) . '
' . esc_html__( 'Sorry, that demo could not be imported. Please try again.', 'advanced-testimonial' ) . '