PluginProbe
Property Hive / 2.3.0
Property Hive v2.3.0
2.3.0 2.2.6 2.2.5 2.2.4 2.2.3 2.2.2 1.4.46 1.4.47 1.4.48 1.4.49 1.4.5 1.4.50 1.4.51 1.4.52 1.4.53 1.4.54 1.4.55 1.4.56 1.4.57 1.4.58 1.4.59 1.4.6 1.4.60 1.4.61 1.4.62 All 260 releases
propertyhive / includes / admin / settings / class-ph-settings-frontend.php

class-ph-settings-frontend.php in Property Hive 2.3.0, at includes/admin/settings/class-ph-settings-frontend.php

1,822 lines 81.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // phpcs:set WordPress.Security.ValidatedSanitizedInput customSanitizingFunctions[] ph_clean
3 // ph_clean() recursively sanitizes text; presence, shape and unslashing checks remain separate.
4
5 /**
6 * PropertyHive Frontend Settings
7 *
8 * @author PropertyHive
9 * @category Admin
10 * @package PropertyHive/Admin
11 * @version 1.0.0
12 */
13
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit; // Exit if accessed directly
16 }
17
18 if ( ! class_exists( 'PH_Settings_Frontend' ) ) :
19
20 /**
21 * PH_Settings_Frontend.
22 */
23 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- Legacy public global class PH_Settings_Frontend; preserving the existing PH_* class name is required for plugin and extension compatibility.
24 class PH_Settings_Frontend extends PH_Settings_Page {
25
26 /**
27 * Constructor.
28 */
29 public function __construct() {
30 $this->id = 'frontend';
31 $this->label = __( 'Frontend', 'propertyhive' );
32
33 add_action( 'admin_init', array( $this, 'check_for_reset_search_form') );
34 add_action( 'admin_init', array( $this, 'check_for_delete_search_form') );
35
36 add_filter( 'propertyhive_settings_tabs_array', array( $this, 'add_settings_page' ), 16 );
37 add_action( 'propertyhive_sections_' . $this->id, array( $this, 'output_sections' ) );
38 add_action( 'propertyhive_settings_' . $this->id, array( $this, 'output' ) );
39 add_action( 'propertyhive_settings_save_' . $this->id, array( $this, 'save' ) );
40
41 add_action( 'propertyhive_admin_field_search_forms_table', array( $this, 'search_forms_table' ) );
42 add_action( 'propertyhive_admin_field_search_form_fields', array( $this, 'search_form_fields' ) );
43 }
44
45 public function check_for_reset_search_form()
46 {
47 if ( isset($_GET['action']) && $_GET['action'] == 'resetsearchform' && isset($_GET['id']) && is_string($_GET['id']) && $_GET['id'] != '' )
48 {
49 if ( ! current_user_can( 'manage_options' ) )
50 {
51 wp_die( esc_html__( 'Sorry, you are not allowed to do this.', 'propertyhive' ) );
52 }
53
54 $request_id = sanitize_text_field( wp_unslash( $_GET['id'] ) );
55 check_admin_referer( 'ph_reset_search_form_' . $request_id );
56
57 $current_settings = get_option( 'propertyhive_template_assistant', array() );
58
59 $current_id = sanitize_title( $request_id );
60
61 $existing_search_forms = ( (isset($current_settings['search_forms'])) ? $current_settings['search_forms'] : array() );
62
63 if ( !isset($existing_search_forms[$current_id]) )
64 {
65 die("Trying to reset a non-existant search form. Please go back and try again");
66 }
67
68 if ( isset($existing_search_forms[$current_id]) )
69 {
70 $existing_search_forms[$current_id] = array();
71 }
72
73 $current_settings['search_forms'] = $existing_search_forms;
74
75 update_option( 'propertyhive_template_assistant', $current_settings );
76 }
77 }
78
79 public function check_for_delete_search_form()
80 {
81 if ( isset($_GET['action']) && $_GET['action'] == 'deletesearchform' && isset($_GET['id']) && is_string($_GET['id']) && $_GET['id'] != '' && $_GET['id'] != 'default' )
82 {
83 if ( ! current_user_can( 'manage_options' ) )
84 {
85 wp_die( esc_html__( 'Sorry, you are not allowed to do this.', 'propertyhive' ) );
86 }
87
88 $request_id = sanitize_text_field( wp_unslash( $_GET['id'] ) );
89 check_admin_referer( 'ph_delete_search_form_' . $request_id );
90
91 $current_settings = get_option( 'propertyhive_template_assistant', array() );
92
93 $current_id = sanitize_title( $request_id );
94
95 $existing_search_forms = ( (isset($current_settings['search_forms'])) ? $current_settings['search_forms'] : array() );
96
97 if ( !isset($existing_search_forms[$current_id]) )
98 {
99 die("Trying to delete a non-existant search form. Please go back and try again");
100 }
101
102 if ( isset($existing_search_forms[$current_id]) )
103 {
104 unset($existing_search_forms[$current_id]);
105 }
106
107 $current_settings['search_forms'] = $existing_search_forms;
108
109 update_option( 'propertyhive_template_assistant', $current_settings );
110 }
111 }
112
113 /**
114 * Get sections.
115 *
116 * @return array
117 */
118 public function get_sections() {
119 $sections = array(
120 '' => __( 'Search Results', 'propertyhive' ),
121 'search-forms' => __( 'Search Forms', 'propertyhive' ),
122 'flags' => __( 'Flags', 'propertyhive' ),
123 );
124
125 return apply_filters( 'propertyhive_get_sections_' . $this->id, $sections );
126 }
127
128 /**
129 * Get settings array.
130 *
131 * @return array
132 */
133 public function get_settings() {
134
135 $current_settings = get_option( 'propertyhive_template_assistant', array() );
136
137 $settings = array(
138
139 array( 'title' => __( 'Search Results Page Layout', 'propertyhive' ), 'type' => 'title', 'desc' => '', 'id' => 'template_assistant_search_results_settings' )
140
141 );
142
143 $settings[] = array(
144 'title' => __( 'Default Sort Order', 'propertyhive' ),
145 'id' => 'search_result_default_order',
146 'type' => 'select',
147 'default' => ( isset($current_settings['search_result_default_order']) ? $current_settings['search_result_default_order'] : ''),
148 'options' => array(
149 '' => 'Price Descending (' . __( 'default', 'propertyhive') . ')',
150 'price-asc' => 'Price Ascending',
151 'date' => 'Date Added',
152 )
153 );
154
155 $settings[] = array(
156 'title' => __( 'Properties Per Row', 'propertyhive' ),
157 'id' => 'search_result_columns',
158 'type' => 'select',
159 'default' => ( isset($current_settings['search_result_columns']) ? $current_settings['search_result_columns'] : '1'),
160 'options' => array(
161 '1' => '1 (' . __( 'default', 'propertyhive') . ')',
162 '2' => '2',
163 '3' => '3',
164 '4' => '4',
165 )
166 );
167
168 $settings[] = array(
169 'title' => __( 'Result Layout', 'propertyhive' ),
170 'id' => 'search_result_layout',
171 'type' => 'select',
172 'default' => ( isset($current_settings['search_result_layout']) ? $current_settings['search_result_layout'] : '1'),
173 'options' => array(
174 '1' => 'List Layout 1 (default)',
175 '2' => 'List Layout 2 (card)',
176 )
177 );
178
179 $search_result_fields = array( 'price', 'floor_area', 'summary', 'actions' );
180 if ( isset($current_settings['search_result_fields']) && is_array($current_settings['search_result_fields']) )
181 {
182 if ( !empty($current_settings['search_result_fields']) )
183 {
184 $search_result_fields = $current_settings['search_result_fields'];
185 }
186 else
187 {
188 $search_result_fields = array();
189 }
190 }
191
192 $fields = array(
193 array( 'id' => 'price', 'label' => 'Price / Rent' ),
194 array( 'id' => 'floor_area', 'label' => 'Floor Area (commercial only)' ),
195 array( 'id' => 'summary', 'label' => 'Summary Description' ),
196 array( 'id' => 'actions', 'label' => 'Actions (i.e. More Details Button)' ),
197 array( 'id' => 'rooms', 'label' => 'Rooms Counts' ),
198 array( 'id' => 'availability', 'label' => 'Availability' ),
199 array( 'id' => 'property_type', 'label' => 'Property Type' ),
200 array( 'id' => 'available_date', 'label' => 'Available Date (lettings only)' ),
201 );
202 $custom_field_selected = false;
203 if ( isset($current_settings['custom_fields']) && is_array($current_settings['custom_fields']) && !empty($current_settings['custom_fields']) )
204 {
205 $label = '<select name="search_result_fields_custom_field"><option value="">Custom Field...</option>';
206 foreach ( $current_settings['custom_fields'] as $custom_field )
207 {
208 $label .= '<option value="custom_field' . $custom_field['field_name'] . '"';
209 if ( in_array('custom_field' . $custom_field['field_name'], $search_result_fields) )
210 {
211 $label .= ' selected';
212 $custom_field_selected = true;
213 }
214 $label .= '>' . $custom_field['field_label'] . '</option>';
215 }
216 $label .= '</select>';
217
218 $fields[] = array( 'id' => 'custom_field', 'label' => $label );
219 }
220
221 // Need to sort order to match what's saved
222 foreach ( $search_result_fields as $j => $search_result_field )
223 {
224 foreach ( $fields as $i => $field )
225 {
226 if ( $field['id'] == $search_result_field || ( $field['id'] == 'custom_field' && substr($search_result_field, 0, 12) == 'custom_field' ) )
227 {
228 $fields[$i]['order'] = $j;
229 }
230 }
231 }
232 foreach ( $fields as $i => $field )
233 {
234 if ( !isset($field['order']) )
235 {
236 $fields[$i]['order'] = $i + 99;
237 }
238 }
239
240 // order $fields by 'order' key
241 $sorter = array();
242 $ret = array();
243 reset($fields);
244 foreach ($fields as $ii => $va)
245 {
246 $sorter[$ii] = $va['order'];
247 }
248 asort($sorter);
249 foreach ($sorter as $ii => $va)
250 {
251 $ret[$ii] = $fields[$ii];
252 }
253 $fields = $ret;
254
255 $html = '<span class="form-field-options" id="sortable_options">';
256 foreach ( $fields as $field )
257 {
258 $html .= '<span style="display:block; padding:3px 0;">
259 <i class="fa fa-reorder" style="cursor:pointer; opacity:0.3"></i> &nbsp;
260 <input type="checkbox" name="search_result_fields[]" value="' . $field['id'] . '"';
261 if ( in_array($field['id'], $search_result_fields) || ( $field['id'] == 'custom_field' && $custom_field_selected ) )
262 {
263 $html .= ' checked';
264 }
265 $html .= '>
266 ' . $field['label'] . '
267 </span>';
268 }
269 $html .= '</span>
270
271 <script>
272 jQuery(document).ready(function($)
273 {
274 $( "#sortable_options" )
275 .sortable({
276 axis: "y",
277 handle: "i",
278 stop: function( event, ui )
279 {
280 // IE doesn\'t register the blur when sorting
281 // so trigger focusout handlers to remove .ui-state-focus
282 //ui.item.children( "h3" ).triggerHandler( "focusout" );
283
284 // Refresh accordion to handle new order
285 //$( this ).accordion( "refresh" );
286 },
287 update: function( event, ui )
288 {
289 // Update hidden fields
290 var fields_order = $(this).sortable(\'toArray\');
291
292 //$(\'#active_fields_order\').val( fields_order.join("|") );
293 }
294 });
295 });
296 </script>';
297
298 $settings[] = array(
299 'title' => __( 'Fields Shown', 'propertyhive' ),
300 'type' => 'html',
301 'html' => $html
302 );
303
304 if ( get_option('propertyhive_images_stored_as', '') != 'urls' )
305 {
306 $image_sizes = get_intermediate_image_sizes();
307 $image_size_options = array();
308 foreach ( $image_sizes as $image_size )
309 {
310 $image_size_options[$image_size] = $image_size;
311 }
312
313 $settings[] = array(
314 'title' => __( 'Image Size Used', 'propertyhive' ),
315 'id' => 'search_result_image_size',
316 'type' => 'select',
317 'default' => ( isset($current_settings['search_result_image_size']) ? $current_settings['search_result_image_size'] : 'medium'),
318 'options' => $image_size_options
319 );
320 }
321
322 $columns_1_css = file_get_contents(PH()->plugin_path() . '/assets/css/search-results-layouts/columns-1.css');
323 $columns_2_css = file_get_contents(PH()->plugin_path() . '/assets/css/search-results-layouts/columns-2.css');
324 $columns_3_css = file_get_contents(PH()->plugin_path() . '/assets/css/search-results-layouts/columns-3.css');
325 $columns_4_css = file_get_contents(PH()->plugin_path() . '/assets/css/search-results-layouts/columns-4.css');
326 $layout_1_css = '';
327 $layout_2_css = file_get_contents(PH()->plugin_path() . '/assets/css/search-results-layouts/content-property-2.css');
328
329 $settings[] = array(
330 'title' => __( 'Customise CSS', 'propertyhive' ),
331 'id' => 'search_result_css',
332 'type' => 'textarea',
333 'default' => ( isset($current_settings['search_result_css']) ? $current_settings['search_result_css'] : $columns_1_css . "\n\n" . $layout_1_css ),
334 'css' => 'height:200px;width:100%;',
335 );
336
337 if ( isset($current_settings['search_result_css']) && trim($current_settings['search_result_css']) != '' )
338 {
339 $settings[] = array(
340 'type' => 'html',
341 'html' => '<div id="change_warning" style="display:none; color:#900">
342 By changing the options above the CSS been regenerated. Please note that this will overwrite any customisations you\'ve previously made to the CSS.
343 </div>'
344 );
345 }
346
347 $settings[] = array(
348 'title' => __( 'Apply CSS To All Pages', 'propertyhive' ),
349 'id' => 'search_result_css_all_pages',
350 'type' => 'checkbox',
351 'default' => isset($current_settings['search_result_css_all_pages']) && $current_settings['search_result_css_all_pages'] == 'yes' ? 'yes' : '',
352 );
353
354 $settings[] = array(
355 'type' => 'html',
356 'html' => '<script>
357
358 jQuery(document).ready(function()
359 {
360 jQuery(\'#search_result_columns\').change(function()
361 {
362 generate_search_results_css();
363 });
364 jQuery(\'#search_result_layout\').change(function()
365 {
366 generate_search_results_css();
367 });
368 });
369
370 function generate_search_results_css()
371 {
372 jQuery(\'#search_result_css\').val(\'\');
373
374 jQuery(\'#change_warning\').slideDown();
375
376 var columns_css = \'\';
377 var layout_css = \'\';
378 switch ( jQuery(\'#search_result_columns\').val() )
379 {
380 case \'1\':
381 {
382 columns_css = "' . str_replace(array("\r\n", "\n"), '\n', $columns_1_css) . '";
383 break;
384 }
385 case \'2\':
386 {
387 columns_css = "' . str_replace(array("\r\n", "\n"), '\n', $columns_2_css) . '";
388 break;
389 }
390 case \'3\':
391 {
392 columns_css = "' . str_replace(array("\r\n", "\n"), '\n', $columns_3_css) . '";
393 break;
394 }
395 case \'4\':
396 {
397 columns_css = "' . str_replace(array("\r\n", "\n"), '\n', $columns_4_css) . '";
398 break;
399 }
400 }
401
402 switch ( jQuery(\'#search_result_layout\').val() )
403 {
404 case \'1\':
405 {
406 layout_css = "' . str_replace(array("\r\n", "\n"), '\n', $layout_1_css) . '";
407 break;
408 }
409 case \'2\':
410 {
411 layout_css = "' . str_replace(array("\r\n", "\n"), '\n', $layout_2_css) . '";
412 break;
413 }
414 }
415
416 jQuery(\'#search_result_css\').val( columns_css + "\n\n" + layout_css );
417 }
418
419 </script>'
420 );
421
422 $settings[] = array( 'type' => 'sectionend', 'id' => 'template_assistant_search_results_settings');
423
424 return apply_filters( 'propertyhive_get_settings_' . $this->id, $settings );
425 }
426
427 public function get_search_forms_settings()
428 {
429 $current_settings = get_option( 'propertyhive_template_assistant', array() );
430
431 $settings = array(
432
433 array( 'title' => __( 'Search Forms', 'propertyhive' ), 'type' => 'title', 'desc' => '', 'id' => 'template_assistant_search_forms_settings' )
434
435 );
436
437 $settings[] = array(
438 'type' => 'search_forms_table',
439 );
440
441 $settings[] = array( 'type' => 'sectionend', 'id' => 'template_assistant_search_forms_settings');
442
443 return $settings;
444 }
445
446 public function get_search_form_settings()
447 {
448 global $current_section;
449
450 wp_enqueue_script( 'jquery-ui-accordion' );
451 wp_enqueue_script( 'jquery-ui-sortable' );
452
453 $current_settings = get_option( 'propertyhive_template_assistant', array() );
454
455 if ( !isset($current_settings['search_forms']) )
456 {
457 $current_settings['search_forms'] = array();
458 }
459 if ( !isset($current_settings['search_forms']['default']) )
460 {
461 $current_settings['search_forms']['default'] = array();
462 }
463
464 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only selection of a search-form editor; save() verifies its settings nonce and capability before writes.
465 $current_id = ( isset( $_REQUEST['id'] ) && is_string( $_REQUEST['id'] ) ) ? sanitize_title( wp_unslash( $_REQUEST['id'] ) ) : '';
466
467 $search_form_details = array();
468
469 if ($current_id != '')
470 {
471 $search_forms = $current_settings['search_forms'];
472
473 if (isset($search_forms[$current_id]))
474 {
475 $search_form_details = $search_forms[$current_id];
476 }
477 else
478 {
479 die('Trying to edit a search form which does not exist. Please go back and try again.');
480 }
481 }
482
483 $settings = array(
484
485 array( 'title' => ( $current_section == 'addsearchform' ? __( 'Add Search Form', 'propertyhive' ) : __( 'Edit Search Form', 'propertyhive' ) ), 'type' => 'title', 'desc' => '', 'id' => 'searchforms' ),
486
487 );
488
489 $custom_attributes = array();
490 if ($current_id == 'default' || $current_section == 'editsearchform')
491 {
492 $custom_attributes['disabled'] = 'disabled';
493 }
494
495 $settings[] = array(
496 'title' => __( 'ID', 'propertyhive' ),
497 'id' => 'form_id',
498 'default' => ( (isset($current_id)) ? $current_id : ''),
499 'type' => 'text',
500 'desc_tip' => false,
501 'custom_attributes' => $custom_attributes
502 );
503
504 $settings[] = array(
505 'type' => 'search_form_fields',
506 );
507
508 $settings[] = array( 'type' => 'sectionend', 'id' => 'searchforms');
509
510 return $settings;
511 }
512
513 /**
514 * Output list of search forms
515 *
516 * @access public
517 * @return void
518 */
519 public function search_forms_table() {
520 global $wpdb, $post;
521 ?>
522 <tr valign="top">
523 <th scope="row" class="titledesc">
524 &nbsp;
525 </th>
526 <td class="forminp forminp-button">
527 <a href="<?php echo esc_url(admin_url( 'admin.php?page=ph-settings&tab=frontend&section=addsearchform' )); ?>" class="button alignright"><?php echo esc_html(__( 'Add New Search Form', 'propertyhive' )); ?></a>
528 </td>
529 </tr>
530 <tr valign="top">
531 <th scope="row" class="titledesc"><?php esc_html_e( 'Search Forms', 'propertyhive' ) ?></th>
532 <td class="forminp">
533 <table class="ph_portals widefat" cellspacing="0">
534 <thead>
535 <tr>
536 <th class="id"><?php esc_html_e( 'ID', 'propertyhive' ); ?></th>
537 <th class="shortcode"><?php esc_html_e( 'Shortcode', 'propertyhive' ); ?></th>
538 <th class="settings">&nbsp;</th>
539 </tr>
540 </thead>
541 <tbody>
542 <?php
543
544 $current_settings = get_option( 'propertyhive_template_assistant', array() );
545 $search_forms = array();
546 if ($current_settings !== FALSE)
547 {
548 if (isset($current_settings['search_forms']))
549 {
550 $search_forms = $current_settings['search_forms'];
551 }
552 }
553
554 if ( !isset($search_forms['default']) )
555 {
556 $search_forms['default'] = array();
557 }
558
559 if (!empty($search_forms))
560 {
561 foreach ( $search_forms as $id => $search_form )
562 {
563 $edit_url = admin_url( 'admin.php?page=ph-settings&tab=frontend&section=editsearchform&id=' . $id );
564
565 $reset_url = wp_nonce_url(
566 admin_url( 'admin.php?page=ph-settings&tab=frontend&section=search-forms&action=resetsearchform&id=' . $id ),
567 'ph_reset_search_form_' . $id
568 );
569
570 echo '<tr>';
571 echo '<td class="id">' . esc_html( $id ) . '</td>';
572 echo '<td class="shortcode"><pre style="background:#EEE; padding:5px; display:inline">[property_search_form id="' . esc_attr( $id ) . '"]</pre></td>';
573 echo '<td class="settings">
574 <a class="button" href="' . esc_url( $edit_url ) . '">' . esc_html__( 'Edit Fields', 'propertyhive' ) . '</a>
575 <a class="button" href="' . esc_url( $reset_url ) . '">' . esc_html__( 'Reset To Default Fields', 'propertyhive' ) . '</a>';
576
577 if ( $id != 'default' )
578 {
579 $delete_url = wp_nonce_url(
580 admin_url( 'admin.php?page=ph-settings&tab=frontend&section=search-forms&action=deletesearchform&id=' . $id ),
581 'ph_delete_search_form_' . $id
582 );
583
584 echo '
585 <a class="button" href="' . esc_url( $delete_url ) . '" onclick="return confirm(\'Are you sure you wish to delete this search form?\');">' . esc_html__( 'Delete', 'propertyhive' ) . '</a>
586 ';
587 }
588
589 echo '</td>';
590 echo '</tr>';
591 }
592 }
593 else
594 {
595 echo '<tr>';
596 echo '<td align="center" colspan="3">' . esc_html(__( 'No search forms exist', 'propertyhive' )) . '</td>';
597 echo '</tr>';
598 }
599 ?>
600 </tbody>
601 </table>
602 </td>
603 </tr>
604 <tr valign="top">
605 <th scope="row" class="titledesc">
606 &nbsp;
607 </th>
608 <td class="forminp forminp-button">
609 <a href="<?php echo esc_url(admin_url( 'admin.php?page=ph-settings&tab=frontend&section=addsearchform' )); ?>" class="button alignright"><?php echo esc_html(__( 'Add New Search Form', 'propertyhive' )); ?></a>
610 </td>
611 </tr>
612 <?php
613 }
614
615 private function output_search_form_field( $id, $field )
616 {
617 echo '
618 <div class="group" id="' . esc_attr( $id ) . '">
619 <h3>' . esc_html( trim( $id, '_' ) ) . '</h3>
620 <div>';
621
622 if ( 'department' === $id )
623 {
624 echo '<p><label for="type_'. esc_attr( $id ) .'">Type:</label> <select name="type[' . esc_attr( $id ) . ']" id="type_'. esc_attr( $id ) .'">
625 <option value="radio"' . ( ( !isset($field['type']) || ( isset($field['type']) && $field['type'] == 'radio' ) ) ? ' selected' : '' ) . '>Radio Buttons</option>
626 <option value="select"' . ( ( isset($field['type']) && $field['type'] == 'select' ) ? ' selected' : '' ) . '>Dropdown</option>
627 ' . ( ( isset($field['type']) && $field['type'] != 'select' && $field['type'] != 'radio' ) ? '<option value="' . esc_attr( $field['type'] ) . '" selected>' . esc_attr( $field['type'] ) . '</option>' : '' ) . '
628 </select></p>';
629 }
630 else
631 {
632 echo '<input type="hidden" name="type[' . esc_attr( $id ) . ']" id="type_'. esc_attr( $id ) .'" value="' . ( ( isset($field['type']) ) ? esc_attr( $field['type'] ) : '' ) . '">';
633 }
634
635 echo ' <p><label for="show_label_'. esc_attr( $id ) .'">Show Label:</label> <input type="checkbox" name="show_label[' . esc_attr( $id ) . ']" id="show_label_'. esc_attr( $id ) .'" value="1"' . ( ( isset($field['show_label']) && $field['show_label'] === true ) ? ' checked' : '' ) . '></p>
636
637 <p><label for="label_'. esc_attr( $id ) .'">Label:</label> <input type="text" name="label[' . esc_attr( $id ) . ']" id="label_'. esc_attr( $id ) .'" value="' . ( ( isset($field['label']) ) ? esc_attr( $field['label'] ) : '' ) . '"></p>
638
639 <p><label for="before_'. esc_attr( $id ) .'">Before:</label> <input type="text" name="before[' . esc_attr( $id ) . ']" id="before_'. esc_attr( $id ) .'" value="' . ( ( isset($field['before']) ) ? esc_attr($field['before']) : '' ) . '"></p>
640
641 <p><label for="after_'. esc_attr( $id ) .'">After:</label> <input type="text" name="after[' . esc_attr( $id ) . ']" id="after_'. esc_attr( $id ) .'" value="' . ( ( isset($field['after']) ) ? esc_attr($field['after']) : '' ) . '"></p>';
642
643 if (
644 isset( $field['type'] ) &&
645 in_array( $field['type'], array( 'text', 'email', 'date', 'number', 'password' ), true )
646 )
647 {
648 echo '
649 <p><label for="placeholder_'. esc_attr( $id ) .'">Placeholder:</label> <input type="text" name="placeholder[' . esc_attr( $id ) . ']" id="placeholder_'. esc_attr( $id ) .'" value="' . ( ( isset($field['placeholder']) ) ? esc_attr($field['placeholder']) : '' ) . '"></p>
650 ';
651 }
652
653 if (
654 isset( $field['type'] ) &&
655 in_array( $field['type'], array( 'slider' ), true )
656 )
657 {
658 echo '
659 <p><label for="min_'. esc_attr( $id ) .'">Min:</label> <input type="number" name="min[' . esc_attr( $id ) . ']" id="min_'. esc_attr( $id ) .'" value="' . ( ( isset($field['min']) ) ? esc_attr($field['min']) : '0' ) . '"></p>
660 ';
661
662 echo '
663 <p><label for="max_'. esc_attr( $id ) .'">Max:</label> <input type="number" name="max[' . esc_attr( $id ) . ']" id="max_'. esc_attr( $id ) .'" value="' . ( ( isset($field['max']) ) ? esc_attr($field['max']) : '' ) . '"></p>
664 ';
665
666 echo '
667 <p><label for="step_'. esc_attr( $id ) .'">Step:</label> <input type="number" name="step[' . esc_attr( $id ) . ']" id="step_'. esc_attr( $id ) .'" value="' . ( ( isset($field['step']) ) ? esc_attr($field['step']) : '1' ) . '"></p>
668 ';
669 }
670
671 if (
672 isset( $field['type'] ) &&
673 in_array( $field['type'], array( 'office' ), true )
674 )
675 {
676 echo '
677 <p><label for="blank_option_'. esc_attr( $id ) .'">Blank Option:</label> <input type="text" name="blank_option[' . esc_attr( $id ) . ']" id="blank_option_'. esc_attr( $id ) .'" value="' . ( ( isset($field['blank_option']) ) ? esc_attr($field['blank_option']) : esc_attr__( 'No Preference', 'propertyhive' ) ) . '"></p>
678 ';
679 }
680
681 if (
682 taxonomy_exists( $id ) ||
683 (
684 isset( $field['custom_field'] ) &&
685 true === $field['custom_field'] &&
686 isset( $field['type'] ) &&
687 'select' === $field['type']
688 )
689 )
690 {
691 echo '
692 <p><label for="blank_option_'. esc_attr( $id ) .'">Blank Option:</label> <input type="text" name="blank_option[' . esc_attr( $id ) . ']" id="blank_option_'. esc_attr( $id ) .'" value="' . ( ( isset($field['blank_option']) ) ? esc_attr($field['blank_option']) : esc_attr__( 'No Preference', 'propertyhive' ) ) . '"></p>
693 ';
694
695 if (
696 taxonomy_exists( $id ) &&
697 in_array(
698 $id,
699 apply_filters(
700 'propertyhive_template_assistant_multi_level_taxonomy_fields',
701 array( 'property_type', 'commercial_property_type', 'location' )
702 ),
703 true
704 )
705 )
706 {
707 echo '
708 <p><label for="parent_terms_only_'. esc_attr( $id ) .'">Top-Level Terms Only:</label> <input type="checkbox" name="parent_terms_only[' . esc_attr( $id ) . ']" id="parent_terms_only_'. esc_attr( $id ) .'" value="yes"' . ( ( isset($field['parent_terms_only']) && $field['parent_terms_only'] === true ) ? ' checked' : '' ) . '></p>
709 ';
710
711 echo '
712 <p><label for="hide_empty_'. esc_attr( $id ) .'">Hide Terms With No Properties Assigned:</label> <input type="checkbox" name="hide_empty[' . esc_attr( $id ) . ']" id="hide_empty_'. esc_attr( $id ) .'" value="yes"' . ( ( isset($field['hide_empty']) && $field['hide_empty'] === true ) ? ' checked' : '' ) . '></p>
713 ';
714 }
715
716 if (
717 taxonomy_exists( $id ) &&
718 in_array(
719 $id,
720 apply_filters(
721 'propertyhive_template_assistant_dynamic_population_taxonomy_fields',
722 array( 'location' )
723 ),
724 true
725 )
726 )
727 {
728 echo '
729 <p><label for="dynamic_population_'. esc_attr( $id ) .'">Dynamically Populate Cascading Dropdowns:</label> <input type="checkbox" name="dynamic_population[' . esc_attr( $id ) . ']" id="dynamic_population_'. esc_attr( $id ) .'" value="yes"' . ( ( isset($field['dynamic_population']) && $field['dynamic_population'] === true ) ? ' checked' : '' ) . '></p>
730 ';
731 }
732
733 echo '
734 <p><label for="multiselect_'. esc_attr( $id ) .'">Multi-Select:</label> <input type="checkbox" name="multiselect[' . esc_attr( $id ) . ']" id="multiselect_'. esc_attr( $id ) .'" value="yes"' . ( ( isset($field['multiselect']) && $field['multiselect'] === true ) ? ' checked' : '' ) . '></p>
735 ';
736 }
737
738 if ( 'office' === $id )
739 {
740 echo '
741 <p><label for="multiselect_'. esc_attr( $id ) .'">Multi-Select:</label> <input type="checkbox" name="multiselect[' . esc_attr( $id ) . ']" id="multiselect_'. esc_attr( $id ) .'" value="yes"' . ( ( isset($field['multiselect']) && $field['multiselect'] === true ) ? ' checked' : '' ) . '></p>
742 ';
743 }
744
745 if (
746 isset( $field['options'] ) &&
747 ! taxonomy_exists( $id ) &&
748 (
749 ! isset( $field['custom_field'] ) ||
750 false === $field['custom_field']
751 )
752 )
753 {
754 echo '<p><label>Options: ';
755
756 echo '<a href="" class="add-search-form-field-option" id="add_search_form_field_option_' . esc_attr( $id ) . '">Add Option</a>';
757
758 echo '</label><br>';
759
760 echo '<span class="form-field-options" id="sortable_options_' . esc_attr( $id ) . '">';
761 $i = 0;
762 foreach ( $field['options'] as $key => $value )
763 {
764 echo '<span style="display:block"><i class="fa fa-reorder" style="cursor:pointer; opacity:0.3"></i> ';
765 echo '<input type="text" name="option_keys[' . esc_attr( $id ) . '][]" value="' . esc_attr( $key ) . '">';
766 echo '<input type="text" name="options_values[' . esc_attr( $id ) . '][]" value="' . esc_attr( $value ) . '">';
767 echo '</span>';
768 }
769
770 echo '</span>';
771 echo '</p>';
772 ?>
773 <script>
774 jQuery(document).ready(function($)
775 {
776 $( document.getElementById( <?php echo wp_json_encode( 'sortable_options_' . $id, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT ); ?> ) )
777 .sortable({
778 axis: "y",
779 handle: "i",
780 stop: function( event, ui )
781 {
782 // IE doesn't register the blur when sorting
783 // so trigger focusout handlers to remove .ui-state-focus
784 //ui.item.children( "h3" ).triggerHandler( "focusout" );
785
786 // Refresh accordion to handle new order
787 //$( this ).accordion( "refresh" );
788 },
789 update: function( event, ui )
790 {
791 // Update hidden fields
792 var fields_order = $(this).sortable('toArray');
793
794 //$('#active_fields_order').val( fields_order.join("|") );
795 }
796 });
797 });
798 </script>
799 <?php
800 }
801
802 echo '</div>
803 </div>';
804 }
805
806 /**
807 * Output list of search form active/inactive fields
808 *
809 * @access public
810 * @return void
811 */
812 public function search_form_fields() {
813 global $wpdb, $post;
814
815 $current_settings = get_option( 'propertyhive_template_assistant', array() );
816
817 if ( !isset($current_settings['search_forms']) )
818 {
819 $current_settings['search_forms'] = array();
820 }
821 if ( !isset($current_settings['search_forms']['default']) )
822 {
823 $current_settings['search_forms']['default'] = array();
824 }
825
826 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only selection of a search-form editor; save() verifies its settings nonce and capability before writes.
827 $current_id = ( isset( $_REQUEST['id'] ) && is_string( $_REQUEST['id'] ) ) ? sanitize_title( wp_unslash( $_REQUEST['id'] ) ) : '';
828
829 $search_form_details = array();
830
831 if ($current_id != '')
832 {
833 $search_forms = $current_settings['search_forms'];
834
835 if (isset($search_forms[$current_id]))
836 {
837 $search_form_details = $search_forms[$current_id];
838 }
839 else
840 {
841 die('Trying to edit search form which does not exist. Please go back and try again.');
842 }
843 }
844
845 $all_fields = ph_get_search_form_fields();
846 $all_fields['address_keyword'] = array(
847 'type' => 'text',
848 'label' => __( 'Location', 'propertyhive' ),
849 'show_label' => true,
850 'before' => '<div class="control control-address_keyword">'
851 );
852 if ( class_exists('PH_Radial_Search') )
853 {
854 $all_fields['radius'] = array(
855 'type' => 'select',
856 'label' => __( 'Radius', 'propertyhive' ),
857 'show_label' => true,
858 'before' => '<div class="control control-radius">',
859 'options' => array(
860 '' => __( 'This Area Only', 'propertyhive' ),
861 '1' => __( 'Within 1 Mile', 'propertyhive' ),
862 '2' => __( 'Within 2 Miles', 'propertyhive' ),
863 '3' => __( 'Within 3 Miles', 'propertyhive' ),
864 '5' => __( 'Within 5 Miles', 'propertyhive' ),
865 '10' => __( 'Within 10 Miles', 'propertyhive' ),
866 )
867 );
868 }
869 $all_fields['location'] = array(
870 'type' => 'location',
871 'label' => __( 'Location', 'propertyhive' ),
872 'show_label' => true,
873 'before' => '<div class="control control-location">'
874 );
875 $all_fields['parking'] = array(
876 'type' => 'parking',
877 'label' => __( 'Parking', 'propertyhive' ),
878 'show_label' => true,
879 'before' => '<div class="control control-parking residential-only">'
880 );
881 $all_fields['outside_space'] = array(
882 'type' => 'outside_space',
883 'label' => __( 'Outside Space', 'propertyhive' ),
884 'show_label' => true,
885 'before' => '<div class="control control-outside_space residential-only">'
886 );
887 $all_fields['availability'] = array(
888 'type' => 'availability',
889 'label' => __( 'Status', 'propertyhive' ),
890 'show_label' => true,
891 'before' => '<div class="control control-availability">'
892 );
893 $all_fields['marketing_flag'] = array(
894 'type' => 'marketing_flag',
895 'label' => __( 'Marketing Flag', 'propertyhive' ),
896 'show_label' => true,
897 'before' => '<div class="control control-marketing_flag">'
898 );
899 $all_fields['tenure'] = array(
900 'type' => 'tenure',
901 'label' => __( 'Tenure', 'propertyhive' ),
902 'show_label' => true,
903 'before' => '<div class="control control-tenure residential-only">'
904 );
905 $all_fields['commercial_tenure'] = array(
906 'type' => 'commercial_tenure',
907 'label' => __( 'Commercial Tenure', 'propertyhive' ),
908 'show_label' => true,
909 'before' => '<div class="control control-commercial_tenure commercial-only">'
910 );
911 $all_fields['commercial_for_sale_to_rent'] = array(
912 'type' => 'select',
913 'label' => __( 'For Sale / To Rent', 'propertyhive' ),
914 'show_label' => true,
915 'before' => '<div class="control control-commercial_for_sale_to_rent commercial-only">',
916 'options' => array(
917 '' => __( 'No Preference', 'propertyhive' ),
918 'for_sale' => __( 'For Sale', 'propertyhive' ),
919 'to_rent' => __( 'To Rent', 'propertyhive' ),
920 )
921 );
922
923 $prices = array(
924 '' => __( 'No preference', 'propertyhive' ),
925 '100000' => '£100,000',
926 '200000' => '£200,000',
927 '300000' => '£300,000',
928 '400000' => '£400,000',
929 '500000' => '£500,000',
930 '750000' => '£750,000',
931 );
932 $all_fields['commercial_minimum_price'] = array(
933 'type' => 'select',
934 'label' => __( 'Minimum Price', 'propertyhive' ),
935 'show_label' => true,
936 'before' => '<div class="control control-commercial_minimum_price commercial-sales-only">',
937 'options' => $prices
938 );
939 $all_fields['commercial_maximum_price'] = array(
940 'type' => 'select',
941 'label' => __( 'Maximum Price', 'propertyhive' ),
942 'show_label' => true,
943 'before' => '<div class="control control-commercial_maximum_price commercial-sales-only">',
944 'options' => $prices
945 );
946
947 $prices = array(
948 '' => __( 'No preference', 'propertyhive' ),
949 '500' => '£500',
950 '750' => '£750',
951 '1000' => '£1,000',
952 '1500' => '£1,500',
953 '2000' => '£2,000',
954 '3000' => '£3,000',
955 );
956 $all_fields['commercial_minimum_rent'] = array(
957 'type' => 'select',
958 'label' => __( 'Minimum Rent', 'propertyhive' ),
959 'show_label' => true,
960 'before' => '<div class="control control-commercial_minimum_rent commercial-lettings-only">',
961 'options' => $prices
962 );
963 $all_fields['commercial_maximum_rent'] = array(
964 'type' => 'select',
965 'label' => __( 'Maximum Rent', 'propertyhive' ),
966 'show_label' => true,
967 'before' => '<div class="control control-commercial_maximum_rent commercial-lettings-only">',
968 'options' => $prices
969 );
970
971 $all_fields['sale_by'] = array(
972 'type' => 'sale_by',
973 'label' => __( 'Sale By', 'propertyhive' ),
974 'show_label' => true,
975 'before' => '<div class="control control-sale_by">'
976 );
977 $all_fields['furnished'] = array(
978 'type' => 'furnished',
979 'label' => __( 'Furnished', 'propertyhive' ),
980 'show_label' => true,
981 'before' => '<div class="control control-furnished lettings-only">'
982 );
983
984 $price_ranges = array(
985 '' => __( 'No preference', 'propertyhive' ),
986 '100000-200000' => '£100,000 - £200,000',
987 '200000-300000' => '£200,000 - £300,000',
988 '300000-400000' => '£300,000 - £400,000',
989 '400000-500000' => '£400,000 - £500,000',
990 '500000-750000' => '£500,000 - £750,000',
991 '750000-1000000' => '£750,000 - £1,000,000',
992 );
993
994 $all_fields['price_range'] = array(
995 'type' => 'select',
996 'label' => __( 'Price', 'propertyhive' ),
997 'show_label' => true,
998 'before' => '<div class="control control-price-range sales-only">',
999 'options' => $price_ranges
1000 );
1001
1002 $all_fields['price_slider'] = array(
1003 'type' => 'slider',
1004 'label' => __( 'Price', 'propertyhive' ),
1005 'show_label' => true,
1006 'before' => '<div class="control control-price-slider sales-only">',
1007 'min' => '0',
1008 'max' => '1000000',
1009 'step' => '10000',
1010 );
1011
1012 $rent_ranges = array(
1013 '' => __( 'No preference', 'propertyhive' ),
1014 '100-200' => '£100 - £200 PCM',
1015 '200-300' => '£200 - £300 PCM',
1016 '300-400' => '£300 - £400 PCM',
1017 '400-500' => '£400 - £500 PCM',
1018 '500-750' => '£500 - £750 PCM',
1019 '750-1000' => '£750 - £1,000 PCM',
1020 );
1021
1022 $all_fields['rent_range'] = array(
1023 'type' => 'select',
1024 'label' => __( 'Rent', 'propertyhive' ),
1025 'show_label' => true,
1026 'before' => '<div class="control control-rent-range lettings-only">',
1027 'options' => $rent_ranges
1028 );
1029
1030 $all_fields['rent_slider'] = array(
1031 'type' => 'slider',
1032 'label' => __( 'Rent', 'propertyhive' ),
1033 'show_label' => true,
1034 'before' => '<div class="control control-rent-slider lettings-only">',
1035 'min' => '0',
1036 'max' => '1000',
1037 'step' => '100',
1038 );
1039
1040 $bedrooms = array(
1041 '' => __( 'No preference', 'propertyhive' ),
1042 '1' => '1',
1043 '2' => '2',
1044 '3' => '3',
1045 '4' => '4',
1046 '5' => '5',
1047 );
1048
1049 $all_fields['bedrooms'] = array(
1050 'type' => 'select',
1051 'label' => __( 'Bedrooms', 'propertyhive' ),
1052 'show_label' => true,
1053 'before' => '<div class="control control-bedrooms residential-only">',
1054 'options' => $bedrooms
1055 );
1056
1057 $all_fields['maximum_bedrooms'] = array(
1058 'type' => 'select',
1059 'label' => __( 'Max Beds', 'propertyhive' ),
1060 'show_label' => true,
1061 'before' => '<div class="control control-maximum_bedrooms residential-only">',
1062 'options' => $bedrooms
1063 );
1064
1065 $bathrooms = array(
1066 '' => __( 'No preference', 'propertyhive' ),
1067 '1' => '1',
1068 '2' => '2',
1069 '3' => '3',
1070 '4' => '4',
1071 '5' => '5',
1072 );
1073
1074 $all_fields['minimum_bathrooms'] = array(
1075 'type' => 'select',
1076 'label' => __( 'Min Bathrooms', 'propertyhive' ),
1077 'show_label' => true,
1078 'before' => '<div class="control control-minimum_bathrooms residential-only">',
1079 'options' => $bathrooms
1080 );
1081 $all_fields['maximum_bathrooms'] = array(
1082 'type' => 'select',
1083 'label' => __( 'Max Bathrooms', 'propertyhive' ),
1084 'show_label' => true,
1085 'before' => '<div class="control control-maximum_bathrooms residential-only">',
1086 'options' => $bathrooms
1087 );
1088
1089 $reception_rooms = array(
1090 '' => __( 'No preference', 'propertyhive' ),
1091 '1' => '1',
1092 '2' => '2',
1093 '3' => '3',
1094 '4' => '4',
1095 '5' => '5',
1096 );
1097
1098 $all_fields['minimum_reception_rooms'] = array(
1099 'type' => 'select',
1100 'label' => __( 'Min Receptions', 'propertyhive' ),
1101 'show_label' => true,
1102 'before' => '<div class="control control-minimum_reception_rooms residential-only">',
1103 'options' => $reception_rooms
1104 );
1105 $all_fields['maximum_reception_rooms'] = array(
1106 'type' => 'select',
1107 'label' => __( 'Max Receptions', 'propertyhive' ),
1108 'show_label' => true,
1109 'before' => '<div class="control control-maximum_reception_rooms residential-only">',
1110 'options' => $reception_rooms
1111 );
1112
1113 $all_fields['bedrooms_slider'] = array(
1114 'type' => 'slider',
1115 'label' => __( 'Bedrooms', 'propertyhive' ),
1116 'show_label' => true,
1117 'before' => '<div class="control control-bedrooms-slider residential-only">',
1118 'min' => '0',
1119 'max' => '10',
1120 );
1121 $all_fields['available_date_from'] = array(
1122 'type' => 'date',
1123 'label' => __( 'Available From', 'propertyhive' ),
1124 'show_label' => true,
1125 'before' => '<div class="control control-available_date_from lettings-only">'
1126 );
1127
1128 $all_fields['office'] = array(
1129 'type' => 'office',
1130 'label' => __( 'Office', 'propertyhive' ),
1131 'show_label' => true,
1132 'before' => '<div class="control control-office">'
1133 );
1134
1135 $all_fields['keyword'] = array(
1136 'type' => 'text',
1137 'label' => __( 'Keyword', 'propertyhive' ),
1138 'show_label' => true,
1139 'before' => '<div class="control control-keyword">'
1140 );
1141
1142 if ( get_option('propertyhive_features_type') == 'checkbox' )
1143 {
1144 $all_fields['property_feature'] = array(
1145 'type' => 'property_feature',
1146 'label' => __( 'Property Features', 'propertyhive' ),
1147 'show_label' => true,
1148 'before' => '<div class="control control-property_feature">',
1149 'multiselect' => true,
1150 );
1151 }
1152
1153 $all_fields = apply_filters( 'propertyhive_search_form_all_fields', $all_fields );
1154
1155 $currencies = array(
1156 '' => '',
1157 'GBP' => 'GBP',
1158 'EUR' => 'EUR',
1159 'USD' => 'USD',
1160 );
1161
1162 $all_fields['currency'] = array(
1163 'type' => 'select',
1164 'label' => __( 'Currency', 'propertyhive' ),
1165 'show_label' => true,
1166 'before' => '<div class="control control-currency">',
1167 'options' => $currencies
1168 );
1169
1170 $date_added_days = array(
1171 '' => __( 'No preference', 'propertyhive' ),
1172 '1' => 'Last 24 Hours',
1173 '3' => 'Last 3 Days',
1174 '7' => 'Last 7 Days',
1175 '14' => 'Last 14 Days',
1176 );
1177
1178 $all_fields['date_added'] = array(
1179 'type' => 'select',
1180 'show_label' => true,
1181 'label' => __( 'Date Added', 'propertyhive' ),
1182 'options' => $date_added_days
1183 );
1184
1185 $form_controls = ph_get_search_form_fields();
1186 $active_fields = apply_filters( 'propertyhive_search_form_fields_' . $current_id, $form_controls );
1187
1188 // Add any additional fields
1189 if ( isset($current_settings['custom_fields']) && !empty($current_settings['custom_fields']) )
1190 {
1191 foreach ( $current_settings['custom_fields'] as $id => $custom_field )
1192 {
1193 $field_type = 'text';
1194 if ( isset($custom_field['field_type']) )
1195 {
1196 switch ( $custom_field['field_type'] )
1197 {
1198 case 'select':
1199 case 'multiselect':
1200 {
1201 $field_type = 'select';
1202 break;
1203 }
1204 case 'checkbox':
1205 {
1206 $field_type = 'checkbox';
1207 break;
1208 }
1209 }
1210
1211 }
1212
1213 $all_fields[$custom_field['field_name']] = array(
1214 'type' => $field_type,
1215 'label' => $custom_field['field_label'],
1216 'show_label' => true,
1217 'before' => '<div class="control control-' . trim( $custom_field['field_name'], '_' ) . '">',
1218 'custom_field' => true,
1219 );
1220
1221 if ( isset($active_fields[$custom_field['field_name']]) )
1222 {
1223 $active_fields[$custom_field['field_name']]['custom_field'] = true;
1224 }
1225 }
1226 }
1227
1228 $inactive_fields = array();
1229 foreach ( $all_fields as $id => $field )
1230 {
1231 if ( !isset($active_fields[$id]) )
1232 {
1233 if ( isset($search_form_details['inactive_fields'][$id]) && !empty($search_form_details['inactive_fields'][$id]) )
1234 {
1235 $field = array_merge($field, $search_form_details['inactive_fields'][$id]);
1236 }
1237 $inactive_fields[$id] = $field;
1238 }
1239 }
1240 ?>
1241 <tr valign="top">
1242 <th scope="row" class="titledesc"><?php esc_html_e( 'Active Fields', 'propertyhive' ) ?></th>
1243 <td class="forminp">
1244 <div id="sortable1" class="connectedSortable" style="min-height:30px;">
1245 <?php
1246 foreach ( $active_fields as $id => $field )
1247 {
1248 if ( isset( $field['type'] ) && $field['type'] == 'hidden' ) { continue; }
1249
1250 $this->output_search_form_field( $id, $field );
1251 }
1252 ?>
1253 </div>
1254 </td>
1255 </tr>
1256 <tr valign="top">
1257 <th scope="row" class="titledesc"><?php esc_html_e( 'Inactive Fields', 'propertyhive' ) ?></th>
1258 <td class="forminp">
1259 <div id="sortable2" class="connectedSortable" style="min-height:30px;">
1260 <?php
1261 if ( !class_exists('PH_Radial_Search') )
1262 {
1263 // Show radial search with link to buy add on
1264 echo '<div class="group" id="radius-placeholder">
1265 <h3>radius</h3>
1266 <div class="">This field requires the <a href="https://wp-property-hive.com/addons/radial-search/" target="_blank">Radial Search add on</a></div>
1267 </div>';
1268 }
1269 foreach ( $inactive_fields as $id => $field )
1270 {
1271 if ( isset( $field['type'] ) && $field['type'] == 'hidden' ) { continue; }
1272
1273 $this->output_search_form_field( $id, $field );
1274 }
1275 ?>
1276 </div>
1277 </td>
1278 </tr>
1279
1280 <input type="hidden" name="active_fields_order" id="active_fields_order" value="<?php
1281 $field_ids = array();
1282 foreach ( $active_fields as $id => $field )
1283 {
1284 $field_ids[] = $id;
1285 }
1286 echo esc_attr( implode("|", $field_ids) );
1287 ?>">
1288 <input type="hidden" name="inactive_fields_order" id="inactive_fields_order" value="<?php
1289 $field_ids = array();
1290 foreach ( $inactive_fields as $id => $field )
1291 {
1292 $field_ids[] = $id;
1293 }
1294 echo esc_attr( implode("|", $field_ids) );
1295 ?>">
1296
1297 <script>
1298 jQuery(document).ready(function($)
1299 {
1300 $( "#sortable1" )
1301 .accordion({
1302 collapsible: true,
1303 active: false,
1304 header: "> div > h3",
1305 heightStyle: "content"
1306 })
1307 .sortable({
1308 axis: "y",
1309 handle: "h3",
1310 connectWith: ".connectedSortable",
1311 stop: function( event, ui )
1312 {
1313 // IE doesn't register the blur when sorting
1314 // so trigger focusout handlers to remove .ui-state-focus
1315 ui.item.children( "h3" ).triggerHandler( "focusout" );
1316
1317 // Refresh accordion to handle new order
1318 $( this ).accordion( "refresh" );
1319 },
1320 update: function( event, ui )
1321 {
1322 // Update hidden fields
1323 var fields_order = $(this).sortable('toArray');
1324
1325 fields_order = jQuery.grep(fields_order, function(value) {
1326 return value != 'radius-placeholder';
1327 });
1328
1329 $('#active_fields_order').val( fields_order.join("|") );
1330 }
1331 });
1332
1333 $( "#sortable2" )
1334 .accordion({
1335 collapsible: true,
1336 active: false,
1337 header: "> div > h3",
1338 heightStyle: "content"
1339 })
1340 .sortable({
1341 axis: "y",
1342 handle: "h3",
1343 connectWith: ".connectedSortable",
1344 stop: function( event, ui )
1345 {
1346 // IE doesn't register the blur when sorting
1347 // so trigger focusout handlers to remove .ui-state-focus
1348 ui.item.children( "h3" ).triggerHandler( "focusout" );
1349
1350 // Refresh accordion to handle new order
1351 $( this ).accordion( "refresh" );
1352 },
1353 update: function( event, ui )
1354 {
1355 // Update hidden fields
1356 var fields_order = $(this).sortable('toArray');
1357
1358 fields_order = jQuery.grep(fields_order, function(value) {
1359 return value != 'radius-placeholder';
1360 });
1361
1362 $('#inactive_fields_order').val( fields_order.join("|") );
1363 }
1364 });
1365
1366 // Handle add/remove options
1367 $('body').on('click', '.add-search-form-field-option', function(e)
1368 {
1369 e.preventDefault();
1370
1371 var this_id = $(this).attr('id').replace("add_search_form_field_option_", "");
1372
1373 var clone = $('#sortable_options_' + this_id).children('span').eq(0).clone();
1374 clone.find('input').val('');
1375
1376 clone.appendTo( $('#sortable_options_' + this_id) );
1377
1378 add_remove_option_links();
1379 });
1380
1381 $('body').on('click', '.remove-search-form-field-option', function(e)
1382 {
1383 e.preventDefault();
1384
1385 $(this).parent().remove();
1386
1387 add_remove_option_links();
1388 });
1389
1390 add_remove_option_links();
1391 });
1392
1393 function add_remove_option_links()
1394 {
1395 jQuery('.connectedSortable .group a.remove-search-form-field-option').remove();
1396
1397 jQuery('.connectedSortable .group').each(function()
1398 {
1399 if ( jQuery(this).find('.add-search-form-field-option').length > 0 )
1400 {
1401 console.log(jQuery(this).find('.form-field-options span').length);
1402 if ( jQuery(this).find('.form-field-options span').length > 1 )
1403 {
1404 jQuery(this).find('.form-field-options span').append(' <a href="" class="remove-search-form-field-option">X</a>');
1405 }
1406 }
1407 });
1408 }
1409 </script>
1410 <?php
1411 }
1412
1413 /**
1414 * Get flag settings
1415 *
1416 * @return array Array of settings
1417 */
1418 public function get_flags_settings() {
1419
1420 $current_settings = get_option( 'propertyhive_template_assistant', array() );
1421
1422 $settings = array(
1423
1424 array( 'title' => __( 'Flags', 'propertyhive' ), 'type' => 'title', 'desc' => '', 'id' => 'template_assistant_flags_settings' )
1425
1426 );
1427
1428 $settings[] = array(
1429 'title' => __( 'Show Flags On Search Results', 'propertyhive' ),
1430 'id' => 'flags_active',
1431 'type' => 'checkbox',
1432 'default' => ( ( isset($current_settings['flags_active']) && $current_settings['flags_active'] == '1' ) ? 'yes' : ''),
1433 'desc' => 'If checked flags will be shown in search results over the property thumbnail containing the property availability or marketing flag if one selected'
1434 );
1435
1436 $settings[] = array(
1437 'title' => __( 'Show Flags On Property Details', 'propertyhive' ),
1438 'id' => 'flags_active_single',
1439 'type' => 'checkbox',
1440 'default' => ( ( isset($current_settings['flags_active_single']) && $current_settings['flags_active_single'] == '1' ) ? 'yes' : ''),
1441 'desc' => 'If checked flags will be shown over the main image slideshow on the full property details page'
1442 );
1443
1444 $settings[] = array(
1445 'title' => __( 'Position Over Thumbnail', 'propertyhive' ),
1446 'id' => 'flag_position',
1447 'type' => 'select',
1448 'default' => ( isset($current_settings['flag_position']) ? $current_settings['flag_position'] : ''),
1449 'options' => array(
1450 'top:0; left:0;' => 'Top Left',
1451 'top:0; right:0;' => 'Top Right',
1452 'bottom:0; left:0;' => 'Bottom Left',
1453 'bottom:0; right:0;' => 'Bottom Right',
1454 'top:0; left:0; right:0;' => 'Across Top',
1455 'bottom:0; left:0; right:0;' => 'Across Bottom',
1456 )
1457 );
1458
1459 $settings[] = array(
1460 'title' => __( 'Background Colour', 'propertyhive' ),
1461 'id' => 'flag_bg_color',
1462 'type' => 'color',
1463 'default' => ( isset($current_settings['flag_bg_color']) ? $current_settings['flag_bg_color'] : '#000'),
1464 );
1465
1466 $settings[] = array(
1467 'title' => __( 'Text Colour', 'propertyhive' ),
1468 'id' => 'flag_text_color',
1469 'type' => 'color',
1470 'default' => ( isset($current_settings['flag_text_color']) ? $current_settings['flag_text_color'] : '#FFF'),
1471 );
1472
1473 $settings[] = array( 'type' => 'sectionend', 'id' => 'template_assistant_flags_settings');
1474
1475 return $settings;
1476 }
1477
1478 /**
1479 * Output the settings.
1480 */
1481 public function output() {
1482 global $current_section, $hide_save_button;
1483
1484 if ( $current_section )
1485 {
1486 switch ($current_section)
1487 {
1488 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Shared admin settings-view state; this global is intentionally used to control the common settings template and is not an arbitrary application global.
1489 case "search-forms": { $hide_save_button = true; $settings = $this->get_search_forms_settings(); break; }
1490 case "addsearchform": { $settings = $this->get_search_form_settings(); break; }
1491 case "editsearchform": { $settings = $this->get_search_form_settings(); break; }
1492 case "flags": { $settings = $this->get_flags_settings(); break; }
1493 default: { die("Unknown setting section"); }
1494 }
1495 }
1496 else
1497 {
1498 $settings = $this->get_settings();
1499 }
1500
1501 PH_Admin_Settings::output_fields( $settings );
1502 }
1503
1504 /**
1505 * Save settings.
1506 */
1507 public function save()
1508 {
1509 if ( ! current_user_can( 'manage_options' ) || ! isset( $_REQUEST['_wpnonce'] ) || ! is_string( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ), 'propertyhive-settings' ) ) {
1510 return;
1511 }
1512
1513 global $current_section;
1514
1515 $current_settings = get_option( 'propertyhive_template_assistant', array() );
1516
1517 if ( $current_section != '' )
1518 {
1519 switch ($current_section)
1520 {
1521 case "flags":
1522 {
1523 $flag_input = array();
1524 foreach ( array( 'flags_active', 'flags_active_single', 'flag_position', 'flag_bg_color', 'flag_text_color' ) as $flag_key ) {
1525 if ( isset( $_POST[$flag_key] ) && ! is_string( $_POST[$flag_key] ) ) {
1526 return;
1527 }
1528 $flag_input[$flag_key] = isset( $_POST[$flag_key] ) ? sanitize_text_field( wp_unslash( $_POST[$flag_key] ) ) : '';
1529 }
1530 foreach ( array( 'flag_position', 'flag_bg_color', 'flag_text_color' ) as $flag_key ) {
1531 if ( ! isset( $_POST[$flag_key] ) ) {
1532 return;
1533 }
1534 }
1535 $propertyhive_template_assistant = array(
1536 'flags_active' => $flag_input['flags_active'],
1537 'flags_active_single' => $flag_input['flags_active_single'],
1538 'flag_position' => $flag_input['flag_position'],
1539 'flag_bg_color' => $flag_input['flag_bg_color'],
1540 'flag_text_color' => $flag_input['flag_text_color'],
1541 );
1542
1543 $propertyhive_template_assistant = array_merge($current_settings, $propertyhive_template_assistant);
1544
1545 update_option( 'propertyhive_template_assistant', $propertyhive_template_assistant );
1546 break;
1547 }
1548 case "addsearchform":
1549 case "editsearchform":
1550 {
1551 $current_id = ( isset( $_REQUEST['id'] ) && is_string( $_REQUEST['id'] ) ) ? sanitize_title( wp_unslash( $_REQUEST['id'] ) ) : '';
1552
1553 $existing_search_forms = ( (isset($current_settings['search_forms'])) ? $current_settings['search_forms'] : array() );
1554
1555 if ( $current_section == 'editsearchform' && $current_id != 'default' && !isset($existing_search_forms[$current_id]) )
1556 {
1557 die("Trying to edit a non-existant search form. Please go back and try again");
1558 }
1559
1560 if ( isset($existing_search_forms[$current_id]) )
1561 {
1562 unset($existing_search_forms[$current_id]);
1563 }
1564
1565 $submitted_fields = array();
1566 foreach ( array( 'show_label', 'label', 'type', 'before', 'after', 'placeholder', 'min', 'max', 'step', 'blank_option', 'parent_terms_only', 'dynamic_population', 'hide_empty', 'multiselect' ) as $input_key ) {
1567 if ( isset( $_POST[$input_key] ) && ! is_array( $_POST[$input_key] ) ) {
1568 return;
1569 }
1570 $submitted_fields[$input_key] = array();
1571 if ( isset( $_POST[$input_key] ) ) {
1572 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Iteration preserves the raw element type for validation; accepted strings are unslashed and sanitized inside this loop before use.
1573 foreach ( $_POST[$input_key] as $field_id => $value ) {
1574 if ( ! is_string( $value ) ) {
1575 return;
1576 }
1577 $value = wp_unslash( $value );
1578 $submitted_fields[$input_key][$field_id] = in_array( $input_key, array( 'label', 'before', 'after' ), true ) ? wp_kses_post( $value ) : sanitize_text_field( $value );
1579 }
1580 }
1581 }
1582 foreach ( array( 'form_id', 'active_fields_order', 'inactive_fields_order' ) as $input_key ) {
1583 if ( isset( $_POST[$input_key] ) && ! is_string( $_POST[$input_key] ) ) {
1584 return;
1585 }
1586 }
1587
1588 $current_id = ( ( isset($_POST['form_id']) && $_POST['form_id'] != '' ) ? str_replace("-", "_", sanitize_title( wp_unslash( $_POST['form_id'] ) )) : $current_id );
1589 if ($current_section == 'addsearchform' && trim($current_id) == '' )
1590 {
1591 $current_id = 'custom';
1592 }
1593
1594 $active_fields = array();
1595 $inactive_fields = array();
1596
1597 if ( isset($_POST['active_fields_order']) && $_POST['active_fields_order'] != '' )
1598 {
1599 $field_ids = explode("|", sanitize_text_field( wp_unslash( $_POST['active_fields_order'] ) ));
1600 if ( !empty($field_ids) )
1601 {
1602 foreach ( $field_ids as $field_id )
1603 {
1604 $active_fields[$field_id] = array(
1605 'show_label' => ( ( isset($submitted_fields['show_label'][$field_id]) && $submitted_fields['show_label'][$field_id] == '1' ) ? true : false ),
1606 'label' => ( isset($submitted_fields['label'][$field_id]) ? $submitted_fields['label'][$field_id] : '' ),
1607 );
1608
1609 if ( isset($submitted_fields['type'][$field_id]) && $submitted_fields['type'][$field_id] != '' )
1610 {
1611 $active_fields[$field_id]['type'] = $submitted_fields['type'][$field_id];
1612 }
1613 if ( isset($submitted_fields['before'][$field_id]) && $submitted_fields['before'][$field_id] != '' )
1614 {
1615 $active_fields[$field_id]['before'] = $submitted_fields['before'][$field_id];
1616 }
1617 if ( isset($submitted_fields['after'][$field_id]) && $submitted_fields['after'][$field_id] != '' )
1618 {
1619 $active_fields[$field_id]['after'] = $submitted_fields['after'][$field_id];
1620 }
1621 if ( isset($submitted_fields['placeholder'][$field_id]) && $submitted_fields['placeholder'][$field_id] != '' )
1622 {
1623 $active_fields[$field_id]['placeholder'] = $submitted_fields['placeholder'][$field_id];
1624 }
1625 if ( isset($submitted_fields['min'][$field_id]) && $submitted_fields['min'][$field_id] != '' )
1626 {
1627 $active_fields[$field_id]['min'] = $submitted_fields['min'][$field_id];
1628 }
1629 if ( isset($submitted_fields['max'][$field_id]) && $submitted_fields['max'][$field_id] != '' )
1630 {
1631 $active_fields[$field_id]['max'] = $submitted_fields['max'][$field_id];
1632 }
1633 if ( isset($submitted_fields['step'][$field_id]) && $submitted_fields['step'][$field_id] != '' )
1634 {
1635 $active_fields[$field_id]['step'] = $submitted_fields['step'][$field_id];
1636 }
1637 if ( isset($submitted_fields['blank_option'][$field_id]) && $submitted_fields['blank_option'][$field_id] != '' )
1638 {
1639 $active_fields[$field_id]['blank_option'] = $submitted_fields['blank_option'][$field_id];
1640 }
1641 if ( isset($submitted_fields['parent_terms_only'][$field_id]) && $submitted_fields['parent_terms_only'][$field_id] != '' )
1642 {
1643 $active_fields[$field_id]['parent_terms_only'] = true;
1644 }
1645 if ( isset($submitted_fields['dynamic_population'][$field_id]) && $submitted_fields['dynamic_population'][$field_id] != '' )
1646 {
1647 $active_fields[$field_id]['dynamic_population'] = true;
1648 }
1649 if ( isset($submitted_fields['hide_empty'][$field_id]) && $submitted_fields['hide_empty'][$field_id] != '' )
1650 {
1651 $active_fields[$field_id]['hide_empty'] = true;
1652 }
1653 if ( isset($submitted_fields['multiselect'][$field_id]) && $submitted_fields['multiselect'][$field_id] != '' )
1654 {
1655 $active_fields[$field_id]['multiselect'] = true;
1656 }
1657
1658 if ( isset($_POST['option_keys'][$field_id]) && is_array($_POST['option_keys'][$field_id]) && !empty($_POST['option_keys'][$field_id]) )
1659 {
1660 $options = array();
1661 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Iteration preserves the raw element type for validation; accepted strings are unslashed and sanitized inside this loop before use.
1662 foreach ( $_POST['option_keys'][$field_id] as $i => $key )
1663 {
1664 if ( ! is_string( $key ) || ! isset( $_POST['options_values'][$field_id][$i] ) || ! is_string( $_POST['options_values'][$field_id][$i] ) ) {
1665 return;
1666 }
1667 $options[sanitize_text_field( wp_unslash( $key ) )] = sanitize_text_field( wp_unslash( $_POST['options_values'][$field_id][$i] ) );
1668 }
1669 $active_fields[$field_id]['options'] = $options;
1670 }
1671 }
1672 }
1673 }
1674
1675 if ( isset($_POST['inactive_fields_order']) && $_POST['inactive_fields_order'] != '' )
1676 {
1677 $field_ids = explode("|", sanitize_text_field( wp_unslash( $_POST['inactive_fields_order'] ) ));
1678 if ( !empty($field_ids) )
1679 {
1680 foreach ( $field_ids as $field_id )
1681 {
1682 $inactive_fields[$field_id] = array(
1683 'show_label' => ( ( isset($submitted_fields['show_label'][$field_id]) && $submitted_fields['show_label'][$field_id] == '1' ) ? true : false ),
1684 'label' => ( isset($submitted_fields['label'][$field_id]) ? $submitted_fields['label'][$field_id] : '' ),
1685 );
1686
1687 if ( isset($submitted_fields['type'][$field_id]) && $submitted_fields['type'][$field_id] != '' )
1688 {
1689 $inactive_fields[$field_id]['type'] = $submitted_fields['type'][$field_id];
1690 }
1691 if ( isset($submitted_fields['before'][$field_id]) && $submitted_fields['before'][$field_id] != '' )
1692 {
1693 $inactive_fields[$field_id]['before'] = $submitted_fields['before'][$field_id];
1694 }
1695 if ( isset($submitted_fields['after'][$field_id]) && $submitted_fields['after'][$field_id] != '' )
1696 {
1697 $inactive_fields[$field_id]['after'] = $submitted_fields['after'][$field_id];
1698 }
1699 if ( isset($submitted_fields['placeholder'][$field_id]) && $submitted_fields['placeholder'][$field_id] != '' )
1700 {
1701 $inactive_fields[$field_id]['placeholder'] = $submitted_fields['placeholder'][$field_id];
1702 }
1703 if ( isset($submitted_fields['blank_option'][$field_id]) && $submitted_fields['blank_option'][$field_id] != '' )
1704 {
1705 $inactive_fields[$field_id]['blank_option'] = $submitted_fields['blank_option'][$field_id];
1706 }
1707 if ( isset($submitted_fields['parent_terms_only'][$field_id]) && $submitted_fields['parent_terms_only'][$field_id] != '' )
1708 {
1709 $inactive_fields[$field_id]['parent_terms_only'] = true;
1710 }
1711 if ( isset($submitted_fields['dynamic_population'][$field_id]) && $submitted_fields['dynamic_population'][$field_id] != '' )
1712 {
1713 $inactive_fields[$field_id]['dynamic_population'] = true;
1714 }
1715 if ( isset($submitted_fields['hide_empty'][$field_id]) && $submitted_fields['hide_empty'][$field_id] != '' )
1716 {
1717 $inactive_fields[$field_id]['hide_empty'] = true;
1718 }
1719 if ( isset($submitted_fields['multiselect'][$field_id]) && $submitted_fields['multiselect'][$field_id] != '' )
1720 {
1721 $inactive_fields[$field_id]['multiselect'] = true;
1722 }
1723
1724 if ( isset($_POST['option_keys'][$field_id]) && is_array($_POST['option_keys'][$field_id]) && !empty($_POST['option_keys'][$field_id]) )
1725 {
1726 $options = array();
1727 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Iteration preserves the raw element type for validation; accepted strings are unslashed and sanitized inside this loop before use.
1728 foreach ( $_POST['option_keys'][$field_id] as $i => $key )
1729 {
1730 if ( ! is_string( $key ) || ! isset( $_POST['options_values'][$field_id][$i] ) || ! is_string( $_POST['options_values'][$field_id][$i] ) ) {
1731 return;
1732 }
1733 $options[sanitize_text_field( wp_unslash( $key ) )] = sanitize_text_field( wp_unslash( $_POST['options_values'][$field_id][$i] ) );
1734 }
1735 $inactive_fields[$field_id]['options'] = $options;
1736 }
1737 }
1738 }
1739 }
1740
1741 $existing_search_forms[$current_id] = array(
1742 'active_fields' => $active_fields,
1743 'inactive_fields' => $inactive_fields,
1744 );
1745
1746 $current_settings['search_forms'] = $existing_search_forms;
1747
1748 update_option( 'propertyhive_template_assistant', $current_settings );
1749
1750 break;
1751 }
1752 default: { die("Unknown setting section"); }
1753 }
1754 }
1755 else
1756 {
1757 $frontend_input = array();
1758 foreach ( array( 'search_result_default_order', 'search_result_columns', 'search_result_layout', 'search_result_image_size', 'search_result_fields_custom_field', 'search_result_css' ) as $input_key ) {
1759 if ( isset( $_POST[$input_key] ) && ! is_string( $_POST[$input_key] ) ) {
1760 return;
1761 }
1762 $frontend_input[$input_key] = isset( $_POST[$input_key] ) ? sanitize_text_field( wp_unslash( $_POST[$input_key] ) ) : '';
1763 }
1764 foreach ( array( 'search_result_default_order', 'search_result_columns', 'search_result_layout', 'search_result_css' ) as $input_key ) {
1765 if ( ! isset( $_POST[$input_key] ) ) {
1766 return;
1767 }
1768 }
1769 if ( isset( $_POST['search_result_fields'] ) && ! is_array( $_POST['search_result_fields'] ) ) {
1770 return;
1771 }
1772 $search_results_fields = array();
1773 if ( isset($_POST['search_result_fields']) && is_array($_POST['search_result_fields']) )
1774 {
1775 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Iteration preserves the raw element type for validation; accepted strings are unslashed and sanitized inside this loop before use.
1776 foreach ( $_POST['search_result_fields'] as $search_result_field ) {
1777 if ( ! is_string( $search_result_field ) ) {
1778 return;
1779 }
1780 $search_results_fields[] = sanitize_text_field( wp_unslash( $search_result_field ) );
1781 }
1782
1783 $new_search_results_fields = array();
1784 foreach ( $search_results_fields as $search_results_field )
1785 {
1786 if ( $search_results_field == 'custom_field' )
1787 {
1788 if ( isset($_POST['search_result_fields_custom_field']) && $_POST['search_result_fields_custom_field'] != '' )
1789 {
1790 $new_search_results_fields[] = $frontend_input['search_result_fields_custom_field'];
1791 }
1792 }
1793 else
1794 {
1795 $new_search_results_fields[] = $search_results_field;
1796 }
1797 }
1798
1799 $search_results_fields = $new_search_results_fields;
1800 }
1801
1802 $propertyhive_template_assistant = array(
1803 'search_result_default_order' => $frontend_input['search_result_default_order'],
1804 'search_result_columns' => (int)$frontend_input['search_result_columns'],
1805 'search_result_layout' => (int)$frontend_input['search_result_layout'],
1806 'search_result_fields' => $search_results_fields,
1807 'search_result_image_size' => ( isset($_POST['search_result_image_size']) ? $frontend_input['search_result_image_size'] : 'medium' ),
1808 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Administrator-authored CSS is intentionally preserved; the type is validated above and its stylesheet output protects the closing style boundary.
1809 'search_result_css' => isset( $_POST['search_result_css'] ) ? wp_unslash($_POST['search_result_css']) : '',
1810 'search_result_css_all_pages' => isset($_POST['search_result_css_all_pages']) ? 'yes' : '',
1811 );
1812
1813 $propertyhive_template_assistant = array_merge($current_settings, $propertyhive_template_assistant);
1814
1815 update_option( 'propertyhive_template_assistant', $propertyhive_template_assistant );
1816 }
1817 }
1818 }
1819
1820 endif;
1821
1822 return new PH_Settings_Frontend();