PluginProbe ʕ •ᴥ•ʔ
Strong Testimonials / 3.3.2
Strong Testimonials v3.3.2
3.3.2 3.3.1 trunk 1.0.1 2.30.9 2.31.10 2.32 2.32.1 2.32.2 2.32.3 2.32.4 2.33 2.34 2.35 2.36 2.37 2.38 2.38.1 2.39 2.39.1 2.39.2 2.39.3 2.40.0 2.40.1 2.40.2 2.40.3 2.40.4 2.40.5 2.40.6 2.40.7 2.41.0 2.41.1 2.50.0 2.50.1 2.50.2 2.50.3 2.50.4 2.51.0 2.51.1 2.51.2 2.51.3 2.51.4 2.51.5 2.51.6 2.51.7 2.51.8 2.51.9 3.0.0 3.0.1 3.0.2 3.0.3 3.1.0 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 3.1.19 3.1.2 3.1.20 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.10 3.2.11 3.2.12 3.2.13 3.2.14 3.2.15 3.2.16 3.2.17 3.2.18 3.2.19 3.2.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.3.0
strong-testimonials / admin / class-strong-testimonials-post-editor.php
strong-testimonials / admin Last commit date
challenge 1 year ago css 6 days ago img 1 year ago js 1 month ago menu 1 month ago partials 1 week ago rest-api 6 days ago scss 1 year ago settings 6 days ago uninstall 1 year ago wpchill 1 month ago admin-notices.php 5 months ago admin.php 1 month ago class-strong-testimonials-addons.php 1 month ago class-strong-testimonials-admin-category-list.php 1 year ago class-strong-testimonials-admin-list.php 1 year ago class-strong-testimonials-admin-scripts.php 1 month ago class-strong-testimonials-admin.php 1 month ago class-strong-testimonials-debug.php 5 months ago class-strong-testimonials-exporter.php 1 year ago class-strong-testimonials-help.php 1 year ago class-strong-testimonials-helper.php 1 month ago class-strong-testimonials-list-table.php 1 year ago class-strong-testimonials-lite-vs-pro-page.php 1 month ago class-strong-testimonials-post-editor.php 7 months ago class-strong-testimonials-review.php 1 year ago class-strong-testimonials-updater.php 1 month ago class-strong-testimonials-upsell.php 6 days ago class-strong-views-list-table.php 1 month ago class-walker-strong-category-checklist.php 1 year ago class-walker-strong-form-category-checklist.php 1 year ago class-wpmtst-onboarding.php 1 year ago compat.php 1 year ago custom-fields-ajax.php 1 year ago custom-fields.php 6 days ago form-preview.php 1 year ago view-list-order.php 1 year ago views-ajax.php 1 month ago views-validate.php 1 year ago views.php 1 month ago
class-strong-testimonials-post-editor.php
413 lines
1 <?php
2
3 /**
4 * Class Strong_Testimonials_Post_Editor
5 *
6 * @since 2.28.0
7 */
8 class Strong_Testimonials_Post_Editor {
9
10 /**
11 * Strong_Testimonials_Post_Editor constructor.
12 */
13 public function __construct() {
14 }
15
16 /**
17 * Initialize.
18 */
19 public static function init() {
20 self::add_actions();
21 }
22
23 /**
24 * Add actions and filters.
25 */
26 public static function add_actions() {
27 add_action( 'add_meta_boxes_wpm-testimonial', array( __CLASS__, 'add_meta_boxes' ) );
28 add_action( 'save_post_wpm-testimonial', array( __CLASS__, 'save_details' ) );
29 add_action( 'wp_ajax_wpmtst_edit_rating', array( __CLASS__, 'edit_rating' ) );
30 add_filter( 'wp_insert_post_data', array( __CLASS__, 'prevent_shortcode' ), 10, 2 );
31 }
32
33 /**
34 * Add meta box to the post editor screen.
35 */
36 public static function add_meta_boxes() {
37 add_meta_box(
38 'details',
39 esc_html_x( 'Client Details', 'post editor', 'strong-testimonials' ),
40 array( __CLASS__, 'meta_options' ),
41 'wpm-testimonial',
42 'normal',
43 'high'
44 );
45 }
46
47 /**
48 * Add custom fields to the testimonial editor.
49 */
50 public static function meta_options() {
51 global $post, $pagenow;
52 $post = wpmtst_get_post( $post );
53 $fields = wpmtst_get_custom_fields();
54 $is_new = ( 'post-new.php' === $pagenow );
55 wp_nonce_field( plugin_basename( __FILE__ ), 'wpmtst_metabox_nonce' );
56 ?>
57 <?php do_action( 'wpmtst_before_client_fields_table' ); ?>
58 <table class="options">
59 <tr>
60 <td colspan="2">
61 <p><?php echo esc_html_x( 'To add a photo or logo, use the Featured Image option.', 'post editor', 'strong-testimonials' ); ?></p>
62 </td>
63 </tr>
64 <?php
65 do_action( 'wpmtst_before_client_fields' );
66 foreach ( $fields as $key => $field ) {
67 // TODO Use field property to bypass instead
68 // short-circuit
69 if ( 'category' === strtok( $field['input_type'], '-' ) ) {
70 continue;
71 }
72 ?>
73 <tr>
74 <th>
75 <label for="<?php echo esc_attr( $field['name'] ); ?>">
76 <?php echo wp_kses_post( apply_filters( 'wpmtst_l10n', $field['label'], 'strong-testimonials-form-fields', $field['name'] . ' : label' ) ); ?>
77 </label>
78 </th>
79 <td>
80 <div class="<?php echo esc_attr( $field['input_type'] ); ?>">
81 <?php self::meta_option( $field, $post, $is_new ); ?>
82 </div>
83 </td>
84 </tr>
85 <?php
86 }
87 do_action( 'wpmtst_after_client_fields' );
88 ?>
89 </table>
90 <?php
91 do_action( 'wpmtst_after_client_fields_table' );
92 }
93
94 /**
95 * Input type for a single custom field.
96 *
97 * @since 2.23.0
98 *
99 * @param $field
100 * @param $post
101 * @param $is_new
102 */
103 public static function meta_option( $field, $post, $is_new ) {
104 // Check for callback first.
105 if ( isset( $field['action_input'] ) && $field['action_input'] ) {
106 self::meta_option__action( $field, $post, $is_new );
107 } else {
108 switch ( $field['input_type'] ) {
109 case 'rating':
110 self::meta_option__rating( $field, $post, $is_new );
111 break;
112 case 'url':
113 self::meta_option__url( $field, $post, $is_new );
114 break;
115 case 'checkbox':
116 self::meta_option__checkbox( $field, $post, $is_new );
117 break;
118 case 'shortcode':
119 self::meta_option__shortcode( $field, $post, $is_new );
120 break;
121 case 'textarea':
122 self::meta_option__textarea( $field, $post, $is_new );
123 break;
124 default:
125 self::meta_option__text( $field, $post, $is_new );
126 }
127 }
128 }
129
130 /**
131 * Custom action callback.
132 *
133 * @param $field
134 * @param $post
135 * @param $is_new
136 */
137 private static function meta_option__action( $field, $post, $is_new ) {
138 if ( isset( $field['action_input'] ) && $field['action_input'] ) {
139 do_action( $field['action_input'], $field, $post->{$field['name']} );
140 }
141 }
142
143 /**
144 * Text input.
145 *
146 * @param $field
147 * @param $post
148 * @param $is_new
149 */
150 private static function meta_option__text( $field, $post, $is_new ) {
151 printf( '<input id="%2$s" type="%1$s" class="custom-input" name="custom[%2$s]" value="%3$s">', esc_attr( $field['input_type'] ), esc_attr( $field['name'] ), esc_attr( $post->{$field['name']} ) );
152 }
153
154 /**
155 * Textarea.
156 *
157 * @param $field
158 * @param $post
159 * @param $is_new
160 */
161 private static function meta_option__textarea( $field, $post, $is_new ) {
162 printf(
163 '<textarea id="%1$s" name="custom[%1$s]" class="custom-input">%2$s</textarea>',
164 esc_attr( $field['name'] ),
165 wp_kses_post( $post->{$field['name']} )
166 );
167 }
168
169 /**
170 * URL input.
171 *
172 * @param $field
173 * @param $post
174 * @param $is_new
175 */
176 private static function meta_option__url( $field, $post, $is_new ) {
177 ?>
178 <div class="input-url">
179 <?php printf( '<input id="%2$s" type="%1$s" class="custom-input" name="custom[%2$s]" value="%3$s" size="">', esc_attr( $field['input_type'] ), esc_html( $field['name'] ), esc_attr( $post->{$field['name']} ) ); ?>
180 </div>
181 <div class="input-links">
182 <div class="input-nofollow">
183 <label for="custom_nofollow"><code>rel="nofollow"</code></label>
184 <select id="custom_nofollow" name="custom[nofollow]">
185 <option value="default" <?php selected( $post->nofollow, 'default' ); ?>><?php esc_html_e( 'default', 'strong-testimonials' ); ?></option>
186 <option value="yes" <?php selected( $post->nofollow, 'yes' ); ?>><?php esc_html_e( 'yes', 'strong-testimonials' ); ?></option>
187 <option value="no" <?php selected( $post->nofollow, 'no' ); ?>><?php esc_html_e( 'no', 'strong-testimonials' ); ?></option>
188 </select>
189 </div>
190 <div class="input-noopener">
191 <label for="custom_noopener"><code>rel="noopener"</code></label>
192 <select id="custom_noopener" name="custom[noopener]">
193 <option value="default" <?php selected( $post->noopener, 'default' ); ?>><?php esc_html_e( 'default', 'strong-testimonials' ); ?></option>
194 <option value="yes" <?php selected( $post->noopener, 'yes' ); ?>><?php esc_html_e( 'yes', 'strong-testimonials' ); ?></option>
195 <option value="no" <?php selected( $post->noopener, 'no' ); ?>><?php esc_html_e( 'no', 'strong-testimonials' ); ?></option>
196 </select>
197 </div>
198 <div class="input-noreferrer">
199 <label for="custom_noreferrer"><code>rel="noreferrer"</code></label>
200 <select id="custom_noopener" name="custom[noreferrer]">
201 <option value="default" <?php selected( $post->noreferrer, 'default' ); ?>><?php esc_html_e( 'default', 'strong-testimonials' ); ?></option>
202 <option value="yes" <?php selected( $post->noreferrer, 'yes' ); ?>><?php esc_html_e( 'yes', 'strong-testimonials' ); ?></option>
203 <option value="no" <?php selected( $post->noreferrer, 'no' ); ?>><?php esc_html_e( 'no', 'strong-testimonials' ); ?></option>
204 </select>
205 </div>
206 <?php
207 }
208
209 /**
210 * Checkbox input.
211 *
212 * @param $field
213 * @param $post
214 * @param $is_new
215 */
216 private static function meta_option__checkbox( $field, $post, $is_new ) {
217 printf( '<input id="%2$s" type="%1$s" class="custom-input" name="custom[%2$s]" value="%3$s" %4$s>', esc_attr( $field['input_type'] ), esc_attr( $field['name'] ), 1, checked( $post->{$field['name']}, 1, false ) );
218 }
219
220 /**
221 * Rating input.
222 *
223 * @param $field
224 * @param $post
225 * @param $is_new
226 */
227 private static function meta_option__rating( $field, $post, $is_new ) {
228 $rating = get_post_meta( $post->ID, $field['name'], true );
229 if ( ! $rating || $is_new ) {
230 $rating = 0;
231 }
232 ?>
233 <div class="edit-rating-box hide-if-no-js" data-field="<?php echo esc_attr( $field['name'] ); ?>">
234
235 <?php wp_nonce_field( 'editrating', "edit-{$field['name']}-nonce", false ); ?>
236 <input type="hidden" class="current-rating" value="<?php echo esc_attr( $rating ); ?>">
237
238 <!-- form -->
239 <div class="rating-form" style="<?php echo ( $is_new ) ? 'display: inline-block;' : 'display: none;'; ?>">
240 <span class="inner">
241 <?php wpmtst_star_rating_form( $field, $rating, 'in-metabox', true, 'custom' ); ?>
242 </span>
243 <?php if ( ! $is_new ) : ?>
244 <span class="edit-rating-buttons-2">
245 <button type="button" class="zero button-link"><?php esc_html_e( 'Zero', 'strong-testimonials' ); ?></button>&nbsp;
246 <button type="button" class="save button button-small"><?php esc_html_e( 'OK', 'strong-testimonials' ); ?></button>&nbsp;
247 <button type="button" class="cancel button-link"><?php esc_html_e( 'Cancel', 'strong-testimonials' ); ?></button>
248 </span>
249 <?php endif; ?>
250 </div>
251
252 <!-- display -->
253 <div class="rating-display" style="<?php echo $is_new ? 'display: none;' : 'display: inline-block;'; ?>">
254 <span class="inner">
255 <?php wpmtst_star_rating_display( $rating, 'in-metabox' ); ?>
256 </span>
257
258 <?php if ( ! $is_new ) : ?>
259 <span class="edit-rating-buttons-1">
260 <button type="button" id="" class="edit-rating button button-small hide-if-no-js" aria-label="Edit rating"><?php esc_html_e( 'Edit', 'strong-testimonials' ); ?></button>
261 </span>
262 <?php endif; ?>
263 </div>
264
265 <span class="edit-rating-success"></span>
266
267 </div>
268 <?php
269 }
270
271 /**
272 * Shortcode for custom input.
273 *
274 * @param $field
275 * @param $post
276 * @param $is_new
277 */
278 public static function meta_option__shortcode( $field, $post, $is_new ) {
279 $shortcode = str_replace( array( '[', ']' ), array( '', '' ), $field['shortcode_on_display'] );
280 if ( shortcode_exists( $shortcode ) ) {
281 echo do_shortcode( $field['shortcode_on_display'] );
282 } else {
283 // translators: %s is the shortcode that was not found.
284 echo '<div class="custom-input not-found">' . sprintf( esc_html__( 'shortcode %s not found', 'strong-testimonials' ), '<code>' . esc_html( $field['shortcode_on_display'] ) . '</code>' ) . '</div>';
285 }
286 }
287
288 /**
289 * Save custom fields.
290 *
291 * @since 2.23.2 Delete meta record when rating is zero to allow default display value.
292 */
293 public static function save_details() {
294 if ( ! isset( $_POST['custom'] ) || ! isset( $_POST['post_ID'] ) || ! wp_verify_nonce( $_POST['wpmtst_metabox_nonce'], plugin_basename( __FILE__ ) ) ) {
295 return;
296 }
297
298 $post_id = absint( $_POST['post_ID'] );
299 $custom = $_POST['custom']; // phpcs:ignore sanitization is done underneath ( Data Sanitizationva )
300
301 $custom_fields = wpmtst_get_custom_fields();
302
303 // Construct array of checkbox empty values because blank checkboxes are not POSTed.
304 $checkboxes = array();
305 foreach ( $custom_fields as $key => $field ) {
306 if ( 'checkbox' === $field['input_type'] ) {
307 $checkboxes[ $key ] = 0;
308 }
309 }
310 if ( $checkboxes ) {
311 $custom = array_merge( $checkboxes, $custom );
312 }
313
314 // Determine whether to update or delete.
315 // Similar to wpmtst_ajax_edit_rating() in admin-ajax.php.
316 $custom_fields['nofollow']['input_type'] = '';
317 $custom_fields['noopener']['input_type'] = '';
318 $custom_fields['noreferrer']['input_type'] = '';
319
320 foreach ( $custom as $key => $value ) {
321 $action = 'update';
322 $sanitized_value = '';
323
324 if ( isset( $custom_fields[ $key ] ) ) {
325 if ( 'rating' === $custom_fields[ $key ]['input_type'] && ! $value ) {
326 $action = 'delete';
327 }
328 }
329
330 // Data Sanitizationva
331 if ( isset( $custom_fields[ $key ]['input_type'] ) && 'text' === $custom_fields[ $key ]['input_type'] ) {
332 // Define the allowed HTML tags and their attributes
333 $allowed_html = array(
334 'p' => array( 'style' => array() ),
335 'strong' => array( 'style' => array() ),
336 'span' => array( 'style' => array() ),
337 );
338 $sanitized_value = wp_kses( $value, $allowed_html );
339 } elseif ( isset( $custom_fields[ $key ]['input_type'] ) && 'email' === $custom_fields[ $key ]['input_type'] ) {
340 $sanitized_value = sanitize_email( $value );
341 } elseif ( isset( $custom_fields[ $key ]['input_type'] ) && 'url' === $custom_fields[ $key ]['input_type'] ) {
342 $sanitized_value = esc_url_raw( $value );
343 } else {
344 $sanitized_value = sanitize_text_field( $value );
345 }
346
347 if ( 'update' === $action ) {
348 // empty values replace existing values
349 update_post_meta( $post_id, $key, $sanitized_value );
350 } else {
351 // delete value; e.g. zero rating
352 delete_post_meta( $post_id, $key );
353 }
354 }
355 }
356
357 /**
358 * Prevent use of this plugin's shortcode in a testimonial.
359 *
360 * @since 2.32.2
361 * @param $data
362 * @param $postarr
363 *
364 * @return mixed
365 */
366 public static function prevent_shortcode( $data, $postarr ) {
367 if ( 'wpm-testimonial' === $data['post_type'] ) {
368 $data['post_content'] = preg_replace( '/\[testimonial_view (.*)\]/', '', $data['post_content'] );
369 }
370
371 return $data;
372 }
373
374 /**
375 * Ajax handler to edit a rating.
376 *
377 * @since 2.12.0
378 */
379 public static function edit_rating() {
380
381 $message = '';
382 $post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
383 $rating = isset( $_POST['rating'] ) ? absint( $_POST['rating'] ) : 0;
384 $name = isset( $_POST['field_name'] ) ? sanitize_text_field( wp_unslash( $_POST['field_name'] ) ) : 'rating';
385
386 check_ajax_referer( 'editrating', 'editratingnonce' );
387
388 if ( ! current_user_can( 'edit_post', $post_id ) ) {
389 wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to edit this testimonial.', 'strong-testimonials' ) ) );
390 return;
391 }
392
393 if ( $post_id ) {
394 if ( $rating ) {
395 update_post_meta( $post_id, $name, $rating );
396 } else {
397 delete_post_meta( $post_id, $name );
398 }
399 $message = 'New rating saved';
400 }
401
402 $display = wpmtst_star_rating_display( $rating, 'in-metabox', false );
403 $response = array(
404 'display' => $display,
405 'message' => $message,
406 );
407 echo json_encode( $response );
408 wp_die();
409 }
410 }
411
412 Strong_Testimonials_Post_Editor::init();
413