Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
75.00% |
18 / 24 |
n/a |
0 / 0 |
CRAP | n/a |
0 / 0 |
||
| 1 | <?php |
| 2 | /** |
| 3 | * Search Results block render. |
| 4 | * |
| 5 | * Group-like wrapper that emits `$content` (the serialized inner block |
| 6 | * markup). Each inner result block handles its own state via the |
| 7 | * Interactivity API store; this block contributes only the surrounding |
| 8 | * chrome (block-wrapper attrs derived from color/spacing/border/typography |
| 9 | * supports). |
| 10 | * |
| 11 | * Free-plan attribution: the Jetpack colophon must appear on every |
| 12 | * free-plan results page. If an author has removed the |
| 13 | * `jetpack-search/powered-by` block from the panel (or never had one in |
| 14 | * their pattern), this renderer appends a canonical render of it on the |
| 15 | * way out so the attribution is structurally non-removable. Paid-plan |
| 16 | * sites are unaffected — authors can keep, hide, or delete the block |
| 17 | * freely. |
| 18 | * |
| 19 | * @package automattic/jetpack-search |
| 20 | */ |
| 21 | |
| 22 | namespace Automattic\Jetpack\Search; |
| 23 | |
| 24 | // phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable |
| 25 | |
| 26 | // Author-set post-type scope for this search experience. The constraint |
| 27 | // shape (`{ include: string[], exclude: string[] }`) round-trips through |
| 28 | // `Filter_Post_Type::build_constraint()` for slug sanitization + the live |
| 29 | // searchable-types allowlist, then seeds the `state.staticPostTypes` slot |
| 30 | // the store reads in `fetchResults()`. One writer per page (a search- |
| 31 | // results region is singular by design), so no merge — straight overwrite |
| 32 | // of the slot's deep-merge entry. The block attribute is `postTypeMode` |
| 33 | // (renamed from the helper's neutral `mode` prop to avoid colliding with |
| 34 | // any future generic `mode` attribute on this block). |
| 35 | $scope = Filter_Post_Type::build_constraint( |
| 36 | array( |
| 37 | 'mode' => ( $attributes['postTypeMode'] ?? 'exclude' ) === 'include' ? 'include' : 'exclude', |
| 38 | 'postTypes' => $attributes['postTypes'] ?? array(), |
| 39 | ) |
| 40 | ); |
| 41 | if ( function_exists( 'wp_interactivity_state' ) && ( ! empty( $scope['include'] ) || ! empty( $scope['exclude'] ) ) ) { |
| 42 | wp_interactivity_state( 'jetpack-search', array( 'staticPostTypes' => $scope ) ); |
| 43 | } |
| 44 | |
| 45 | // Results-per-page: author override via `resultsPerPage`, falling back live |
| 46 | // to the site's Reading setting so a later change to `posts_per_page` still |
| 47 | // takes effect on pages that leave this unset. |
| 48 | $results_per_page = Helper::resolve_results_per_page( (int) ( $attributes['resultsPerPage'] ?? 0 ) ); |
| 49 | if ( function_exists( 'wp_interactivity_state' ) ) { |
| 50 | wp_interactivity_state( 'jetpack-search', array( 'resultsPerPage' => $results_per_page ) ); |
| 51 | } |
| 52 | |
| 53 | // Load the WordPress.com Tracks consumer (drains `window._tkq`) so the |
| 54 | // TrainTracks render/interact events the store pushes actually get sent. |
| 55 | // Enqueuing here loads it exactly on pages where the Search blocks render, |
| 56 | // across all blocks experiences. Skipped when tracking is suppressed. |
| 57 | if ( ! Search_Blocks::is_tracking_disabled() ) { |
| 58 | Helper::enqueue_tracks_script(); |
| 59 | } |
| 60 | |
| 61 | $panel_content = $content; // @phan-suppress-current-line PhanUndeclaredGlobalVariable -- $content is provided by WP at block render. |
| 62 | |
| 63 | if ( Search_Blocks::is_free_plan() && false === strpos( $panel_content, 'wp-block-jetpack-search-powered-by' ) ) { |
| 64 | $panel_content .= render_block( |
| 65 | array( |
| 66 | 'blockName' => 'jetpack-search/powered-by', |
| 67 | 'attrs' => array(), |
| 68 | ) |
| 69 | ); |
| 70 | } |
| 71 | ?> |
| 72 | <div <?php echo wp_kses_data( get_block_wrapper_attributes( array( 'class' => 'jetpack-search-search-results' ) ) ); ?>> |
| 73 | <?php |
| 74 | echo $panel_content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Inner block HTML is already escaped by each child block's renderer; auto-injected powered-by output is rendered through render_block() and escaped by its own renderer. |
| 75 | ?> |
| 76 | </div> |