PluginProbe
Blocks – Reusable Content, Shortcodes & Site Variables / trunk
Blocks – Reusable Content, Shortcodes & Site Variables vtrunk
26.09.03.15 26.08.31.21 26.08.22.20 26.08.22.22 26.08.22.17 26.08.22.13 26.08.21.19 26.08.07.23 26.07.19.14 26.07.13.21 26.07.13.17 26.07.12.13 026.07.07.21 026.07.05.18 026.06.26.20 026.06.26.21 026.06.08.20 026.05.13.14 026.04.29.10 trunk 026.02.22.22 026.03.16.23 026.04.23.13
blocks / src / Settings / FieldRenderer.php

FieldRenderer.php in Blocks – Reusable Content, Shortcodes & Site Variables trunk, at src/Settings/FieldRenderer.php

253 lines 12.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace RenzoJohnson\Blocks\Settings;
6
7 use RenzoJohnson\Blocks\Security\SecretStore;
8
9 \defined( 'ABSPATH' ) || exit;
10
11 final class FieldRenderer {
12 public function __construct(
13 private readonly \Blocks_Settings_Repository $settings,
14 private readonly SecretStore $secrets,
15 ) {
16 }
17
18 public function render_section( SectionDefinition $section ): void {
19 if ( $section->honeypot_description ) {
20 $this->render_honeypot_description();
21 return;
22 }
23
24 foreach ( $section->description_paragraphs as $paragraph ) {
25 ?>
26 <p><?php echo \esc_html( $paragraph ); ?></p>
27 <?php
28 }
29 }
30
31 public function render( FieldDefinition $field ): void {
32 match ( $field->type ) {
33 FieldType::Checkbox => $this->render_checkbox( $field ),
34 FieldType::Image => $this->render_image( $field ),
35 FieldType::Number => $this->render_number( $field ),
36 FieldType::Product => $this->render_product( $field ),
37 FieldType::Secret => $this->render_secret( $field ),
38 FieldType::Select => $this->render_select( $field ),
39 FieldType::SupportHours => $this->render_support_hours( $field ),
40 FieldType::Text => $this->render_text( $field ),
41 FieldType::Textarea => $this->render_textarea( $field ),
42 };
43 }
44
45 private function render_text( FieldDefinition $field ): void {
46 $setting = $field->primary();
47 $type = isset( $field->render_args['type'] ) && \is_string( $field->render_args['type'] ) ? $field->render_args['type'] : 'text';
48 $placeholder = isset( $field->render_args['placeholder'] ) && \is_string( $field->render_args['placeholder'] ) ? $field->render_args['placeholder'] : '';
49 ?>
50 <div class="blocks-variable-field">
51 <input
52 type="<?php echo \esc_attr( $type ); ?>"
53 id="<?php echo \esc_attr( $setting->option_name ); ?>"
54 name="<?php echo \esc_attr( $setting->option_name ); ?>"
55 value="<?php echo \esc_attr( $this->settings->get_string( $setting->option_name, (string) $setting->default_value ) ); ?>"
56 class="regular-text"
57 placeholder="<?php echo \esc_attr( $placeholder ); ?>"
58 />
59 <?php $this->render_variable_control( $setting ); ?>
60 </div>
61 <?php $this->render_description( $field ); ?>
62 <?php
63 }
64
65 private function render_textarea( FieldDefinition $field ): void {
66 $setting = $field->primary();
67 ?>
68 <div class="blocks-variable-field blocks-variable-field-textarea">
69 <textarea
70 id="<?php echo \esc_attr( $setting->option_name ); ?>"
71 name="<?php echo \esc_attr( $setting->option_name ); ?>"
72 rows="3"
73 cols="50"
74 class="large-text"
75 ><?php echo \esc_textarea( $this->settings->get_string( $setting->option_name, (string) $setting->default_value ) ); ?></textarea>
76 <?php $this->render_variable_control( $setting ); ?>
77 </div>
78 <?php $this->render_description( $field ); ?>
79 <?php
80 }
81
82 private function render_checkbox( FieldDefinition $field ): void {
83 $setting = $field->primary();
84 $value = $this->settings->get_bool( $setting->option_name, (bool) $setting->default_value );
85 ?>
86 <label for="<?php echo \esc_attr( $setting->option_name ); ?>">
87 <input
88 type="checkbox"
89 id="<?php echo \esc_attr( $setting->option_name ); ?>"
90 name="<?php echo \esc_attr( $setting->option_name ); ?>"
91 value="1"
92 <?php \checked( $value ); ?>
93 />
94 <?php echo \esc_html( $field->description ); ?>
95 </label>
96 <?php
97 $this->render_doc_link( $field );
98 }
99
100 /**
101 * Render a field's documentation link outside its label, so following the
102 * link does not toggle the control it sits beside.
103 */
104 private function render_doc_link( FieldDefinition $field ): void {
105 if ( '' === $field->doc_url || '' === $field->doc_label ) {
106 return;
107 }
108 ?>
109 <a href="<?php echo \esc_url( $field->doc_url ); ?>" target="_blank" rel="noopener noreferrer"><?php echo \esc_html( $field->doc_label ); ?></a>
110 <?php
111 }
112
113 private function render_number( FieldDefinition $field ): void {
114 $setting = $field->primary();
115 $min = $this->scalar_arg( $field, 'min', 0 );
116 $max = $this->scalar_arg( $field, 'max', 9999 );
117 $step = $this->scalar_arg( $field, 'step', 1 );
118 ?>
119 <input
120 type="number"
121 id="<?php echo \esc_attr( $setting->option_name ); ?>"
122 name="<?php echo \esc_attr( $setting->option_name ); ?>"
123 value="<?php echo \esc_attr( (string) $this->settings->get_int( $setting->option_name, (int) $setting->default_value ) ); ?>"
124 min="<?php echo \esc_attr( (string) $min ); ?>"
125 max="<?php echo \esc_attr( (string) $max ); ?>"
126 step="<?php echo \esc_attr( (string) $step ); ?>"
127 class="small-text"
128 />
129 <?php $this->render_description( $field ); ?>
130 <?php
131 }
132
133 private function render_select( FieldDefinition $field ): void {
134 $setting = $field->primary();
135 $options = isset( $field->render_args['options'] ) && \is_array( $field->render_args['options'] ) ? $field->render_args['options'] : array();
136 $value = $this->settings->get_string( $setting->option_name, (string) $setting->default_value );
137 ?>
138 <select id="<?php echo \esc_attr( $setting->option_name ); ?>" name="<?php echo \esc_attr( $setting->option_name ); ?>">
139 <?php foreach ( $options as $key => $label ) : ?>
140 <?php if ( \is_scalar( $key ) && \is_scalar( $label ) ) : ?>
141 <option value="<?php echo \esc_attr( (string) $key ); ?>" <?php \selected( $value, (string) $key ); ?>><?php echo \esc_html( (string) $label ); ?></option>
142 <?php endif; ?>
143 <?php endforeach; ?>
144 </select>
145 <?php $this->render_description( $field ); ?>
146 <?php
147 }
148
149 private function render_image( FieldDefinition $field ): void {
150 $setting = $field->primary();
151 $attachment_id = $this->settings->get_int( $setting->option_name );
152 $image_url = $this->settings->get_image_url( $setting->option_name, 'medium' );
153 $hidden_class = '' !== $image_url ? '' : ' blocks-hidden';
154 ?>
155 <div class="blocks-variable-field blocks-variable-field-image">
156 <div class="blocks-image-field" data-option="<?php echo \esc_attr( $setting->option_name ); ?>">
157 <input type="hidden" id="<?php echo \esc_attr( $setting->option_name ); ?>" name="<?php echo \esc_attr( $setting->option_name ); ?>" value="<?php echo \esc_attr( (string) $attachment_id ); ?>" class="blocks-image-id" />
158 <div class="blocks-image-preview<?php echo \esc_attr( $hidden_class ); ?>"><img src="<?php echo \esc_url( $image_url ); ?>" alt="" /></div>
159 <p class="blocks-image-buttons">
160 <button type="button" class="button blocks-upload-image"><?php \esc_html_e( 'Select Image', 'blocks' ); ?></button>
161 <button type="button" class="button blocks-remove-image<?php echo \esc_attr( $hidden_class ); ?>"><?php \esc_html_e( 'Remove', 'blocks' ); ?></button>
162 </p>
163 </div>
164 <?php $this->render_variable_control( $setting ); ?>
165 </div>
166 <?php
167 }
168
169 private function render_secret( FieldDefinition $field ): void {
170 $setting = $field->primary();
171 $has_secret = $this->secrets->has( $setting->option_name );
172 $status_id = $setting->option_name . '-status';
173 ?>
174 <div class="blocks-secret-field" data-has-secret="<?php echo $has_secret ? '1' : '0'; ?>" data-saved-label="<?php echo \esc_attr__( 'Saved and encrypted.', 'blocks' ); ?>" data-replace-label="<?php echo \esc_attr__( 'Enter a replacement, then save changes.', 'blocks' ); ?>" data-remove-label="<?php echo \esc_attr__( 'The secret will be removed when you save changes.', 'blocks' ); ?>" data-remove-button-label="<?php echo \esc_attr__( 'Remove', 'blocks' ); ?>" data-undo-button-label="<?php echo \esc_attr__( 'Undo remove', 'blocks' ); ?>">
175 <input type="password" id="<?php echo \esc_attr( $setting->option_name ); ?>" name="<?php echo \esc_attr( $setting->option_name ); ?>" value="" class="regular-text" autocomplete="new-password" aria-describedby="<?php echo \esc_attr( $status_id ); ?>" placeholder="<?php echo \esc_attr( $has_secret ? \__( 'Encrypted secret saved', 'blocks' ) : \__( 'Enter API secret', 'blocks' ) ); ?>" <?php \disabled( $has_secret ); ?> />
176 <input type="hidden" class="blocks-secret-clear" name="<?php echo \esc_attr( $setting->option_name ); ?>_clear" value="0" />
177 <?php if ( $has_secret ) : ?>
178 <button type="button" class="button blocks-secret-replace"><?php \esc_html_e( 'Replace', 'blocks' ); ?></button>
179 <button type="button" class="button-link-delete blocks-secret-remove"><?php \esc_html_e( 'Remove', 'blocks' ); ?></button>
180 <?php endif; ?>
181 <span id="<?php echo \esc_attr( $status_id ); ?>" class="blocks-secret-status" aria-live="polite"><?php echo \esc_html( $has_secret ? \__( 'Saved and encrypted.', 'blocks' ) : \__( 'No secret saved.', 'blocks' ) ); ?></span>
182 </div>
183 <?php $this->render_description( $field ); ?>
184 <?php
185 }
186
187 private function render_support_hours( FieldDefinition $field ): void {
188 $start = $field->settings[0];
189 $end = $field->settings[1];
190 ?>
191 <input type="number" id="<?php echo \esc_attr( $start->option_name ); ?>" name="<?php echo \esc_attr( $start->option_name ); ?>" value="<?php echo \esc_attr( (string) $this->settings->get_int( $start->option_name, (int) $start->default_value ) ); ?>" min="0" max="23" step="1" style="width: 70px;" />
192 <span><?php \esc_html_e( 'to', 'blocks' ); ?></span>
193 <input type="number" id="<?php echo \esc_attr( $end->option_name ); ?>" name="<?php echo \esc_attr( $end->option_name ); ?>" value="<?php echo \esc_attr( (string) $this->settings->get_int( $end->option_name, (int) $end->default_value ) ); ?>" min="0" max="23" step="1" style="width: 70px;" />
194 <span><?php \esc_html_e( 'hours', 'blocks' ); ?></span>
195 <p class="description"><?php \esc_html_e( 'Hours 0-23. Set both to 0 for closed days.', 'blocks' ); ?></p>
196 <?php
197 }
198
199 private function render_product( FieldDefinition $field ): void {
200 $setting = $field->primary();
201 $product_id = $this->settings->get_int( $setting->option_name );
202 $label = '';
203 if ( 0 < $product_id && \function_exists( 'wc_get_product' ) ) {
204 $product = \wc_get_product( $product_id );
205 if ( $product instanceof \WC_Product ) {
206 /* translators: 1: product formatted name, 2: variation count. */
207 $label = \sprintf( \__( '%1$s (%2$d variations)', 'blocks' ), $product->get_formatted_name(), \count( $product->get_children() ) );
208 }
209 }
210 ?>
211 <select id="<?php echo \esc_attr( $setting->option_name ); ?>" name="<?php echo \esc_attr( $setting->option_name ); ?>" class="wc-product-search" style="width: 50%;" data-placeholder="<?php \esc_attr_e( 'Search for a product&hellip;', 'blocks' ); ?>" data-action="woocommerce_json_search_products" data-allow_clear="true" data-limit="50">
212 <?php
213 if ( 0 < $product_id && '' !== $label ) :
214 ?>
215 <option value="<?php echo \esc_attr( (string) $product_id ); ?>" selected="selected"><?php echo \esc_html( $label ); ?></option><?php endif; ?>
216 </select>
217 <?php $this->render_description( $field ); ?>
218 <?php
219 }
220
221 private function render_variable_control( SettingDefinition $setting ): void {
222 $public_token = PublicTokenRegistry::for_option( $setting->option_name );
223 if ( null === $public_token ) {
224 return;
225 }
226
227 $token = '{{blocks:' . $public_token . '}}';
228 ?>
229 <span class="blocks-variable-token"><code><?php echo \esc_html( $token ); ?></code><button type="button" class="button blocks-copy-variable" data-token="<?php echo \esc_attr( $token ); ?>" aria-label="<?php echo \esc_attr( \sprintf( /* translators: %s: public variable token. */ \__( 'Copy %s', 'blocks' ), $token ) ); ?>"><span class="dashicons dashicons-admin-page" aria-hidden="true"></span></button></span>
230 <?php
231 }
232
233 private function render_description( FieldDefinition $field ): void {
234 if ( '' !== $field->description ) {
235 ?>
236 <p class="description"><?php echo \esc_html( $field->description ); ?></p>
237 <?php
238 }
239 }
240
241 private function render_honeypot_description(): void {
242 ?>
243 <p><?php \esc_html_e( 'When enabled, Blocks automatically injects the hidden honeypot and optional timing fields into every Contact Form 7 form. No form shortcode is required.', 'blocks' ); ?></p>
244 <?php
245 }
246
247 private function scalar_arg( FieldDefinition $field, string $name, int $default_value ): int|float|string {
248 $value = $field->render_args[ $name ] ?? $default_value;
249
250 return \is_int( $value ) || \is_float( $value ) || \is_string( $value ) ? $value : $default_value;
251 }
252 }
253