PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 All 508 releases
jetpack / jetpack_vendor / automattic / jetpack-search / src / search-blocks / blocks / ai-answer / render.php

render.php in Jetpack – WP Security, Backup, Speed, & Growth 16.3, at jetpack_vendor/automattic/jetpack-search/src/search-blocks/blocks/ai-answer/render.php

165 lines 4.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * AI Answer block render.
4 *
5 * Renders the panel scaffold that the Interactivity store hydrates with the
6 * streaming AI answer. Inserting the block is its own opt-in switch — the
7 * `jetpack_search_ai_answers_enabled` option governs the overlay, not the block.
8 *
9 * The gates below (paid Search plan, host AI opt-out, Jetpack AI master
10 * switch) emit nothing when they fail, matching how WordAds / Premium
11 * Content hide on a failed plan check.
12 *
13 * @package automattic/jetpack-search
14 */
15
16 namespace Automattic\Jetpack\Search;
17
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit( 0 );
20 }
21
22 // Paid-plan gate. AI Answer requires Jetpack Search's paid plan; on a free
23 // or no-plan site the block contributes nothing to the page (no panel
24 // scaffold, no `data-wp-interactive` div, no Interactivity hydration). The
25 // editor surface shows an upgrade prompt instead — see `edit.js`.
26 if ( ! Search_Blocks::supports_paid_search() ) {
27 return;
28 }
29
30 // Host-owner AI opt-out (core's wp_supports_ai() / WP_AI_SUPPORT). The overlay
31 // already honors it through the plugin's filter gate; the block must agree.
32 if ( ! AI_Answers::host_allows_ai() ) {
33 return;
34 }
35
36 if ( ! AI_Answers::is_master_enabled() ) {
37 return;
38 }
39
40 // $attributes is injected by WordPress at block-render time via the
41 // `render_callback` include scope; static analysis can't see the binding,
42 // so both phpcs and Phan need a one-line suppression on the next statement.
43 // @phan-suppress-next-line PhanUndeclaredGlobalVariable
44 $attrs = (array) $attributes; // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
45 $heading_raw = trim( (string) ( $attrs['heading'] ?? '' ) );
46 $heading = '' === $heading_raw ? __( 'AI answer', 'jetpack-search-pkg' ) : $heading_raw;
47 $show_citations = ! isset( $attrs['showCitations'] ) || $attrs['showCitations'];
48 $enable_extended = ! isset( $attrs['enableShowMore'] ) || $attrs['enableShowMore'];
49 $wrapper_attrs = get_block_wrapper_attributes(
50 array( 'class' => 'jp-search-answers-panel' )
51 );
52 ?>
53 <div
54 <?php echo wp_kses_data( $wrapper_attrs ); ?>
55 data-wp-interactive="jetpack-search"
56 data-wp-init="callbacks.initializeAiAnswer"
57 data-wp-bind--hidden="state.aiPanelHidden"
58 aria-live="polite"
59 hidden
60 >
61 <h2 class="jp-search-answers-panel__heading"><?php echo esc_html( $heading ); ?></h2>
62
63 <div
64 class="jp-search-answers-panel__loading"
65 data-wp-bind--hidden="!state.aiIsLoading"
66 hidden
67 >
68 <?php esc_html_e( 'Finding an answer', 'jetpack-search-pkg' ); ?>
69 <span class="jp-search-animated-ellipsis" aria-hidden="true">
70 <span></span><span></span><span></span>
71 </span>
72 </div>
73
74 <div
75 class="jp-search-answers-panel__error"
76 role="alert"
77 data-wp-bind--hidden="!state.aiIsError"
78 hidden
79 >
80 <p
81 class="jp-search-answers-panel__error-message"
82 data-wp-text="state.aiErrorPrimary"
83 ></p>
84 <p
85 class="jp-search-answers-panel__error-detail"
86 data-wp-bind--hidden="!state.aiHasErrorDetail"
87 >
88 <span data-wp-text="state.aiErrorDetail"></span>
89 <span data-wp-bind--hidden="!state.aiHasErrorCode">
90 <br />
91 <span data-wp-text="state.aiErrorCodeText"></span>
92 </span>
93 </p>
94 </div>
95
96 <div
97 class="jp-search-answers-panel__content"
98 data-wp-bind--hidden="!state.aiHasContent"
99 hidden
100 >
101 <div
102 class="jp-search-answers-panel__text"
103 data-wp-watch="callbacks.renderAiAnswerHtml"
104 ></div>
105
106 <?php if ( $show_citations ) : ?>
107 <ul
108 class="jp-search-answers-panel__citations"
109 data-wp-bind--hidden="!state.aiHasCitations"
110 hidden
111 >
112 <template
113 data-wp-each--citation="state.aiVisibleCitations"
114 data-wp-each-key="context.citation.key"
115 >
116 <li>
117 <a
118 data-wp-bind--href="context.citation.href"
119 target="_blank"
120 rel="noopener noreferrer"
121 >
122 <span data-wp-text="context.citation.title"></span>
123 <svg
124 width="10"
125 height="10"
126 viewBox="0 0 10 10"
127 fill="none"
128 xmlns="http://www.w3.org/2000/svg"
129 aria-hidden="true"
130 class="jp-search-answers-panel__citation-icon"
131 >
132 <path d="M1 9L9 1M9 1H5M9 1V5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
133 </svg>
134 </a>
135 </li>
136 </template>
137 </ul>
138 <?php endif; ?>
139 </div>
140
141 <p
142 class="jp-search-answers-panel__loading-hint"
143 data-wp-bind--hidden="!state.aiExtendedLoadingHintShown"
144 hidden
145 >
146 <span data-wp-text="state.aiExtendedLoadingText"></span>
147 <span class="jp-search-animated-ellipsis" aria-hidden="true">
148 <span></span><span></span><span></span>
149 </span>
150 </p>
151
152 <?php if ( $enable_extended ) : ?>
153 <button
154 type="button"
155 class="jp-search-answers-panel__toggle"
156 data-wp-bind--hidden="!state.aiShowExtendedButton"
157 data-wp-on--click="actions.showExtendedAiAnswer"
158 hidden
159 >
160 <?php esc_html_e( 'Show more', 'jetpack-search-pkg' ); ?>
161 <span class="jp-search-answers-panel__toggle-icon" aria-hidden="true"></span>
162 </button>
163 <?php endif; ?>
164 </div>
165