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-general.php

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

1,214 lines 58.0 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 General 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_General' ) ) :
19
20 /**
21 * PH_Settings_General
22 */
23 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- Legacy public global class PH_Settings_General; preserving the existing PH_* class name is required for plugin and extension compatibility.
24 class PH_Settings_General extends PH_Settings_Page {
25
26 /**
27 * Constructor.
28 */
29 public function __construct() {
30 $this->id = 'general';
31 $this->label = __( 'General', 'propertyhive' );
32
33 add_filter( 'propertyhive_settings_tabs_array', array( $this, 'add_settings_page' ), 5 );
34 add_action( 'propertyhive_sections_' . $this->id, array( $this, 'output_sections' ) );
35 add_action( 'propertyhive_settings_' . $this->id, array( $this, 'output' ) );
36 add_action( 'propertyhive_settings_save_' . $this->id, array( $this, 'save' ) );
37 }
38
39 /**
40 * Get sections
41 *
42 * @return array
43 */
44 public function get_sections() {
45 $sections = array(
46 '' => __( 'General', 'propertyhive' ),
47 'modules' => __( 'Modules', 'propertyhive' ),
48 'map' => __( 'Map', 'propertyhive' ),
49 'media' => __( 'Media', 'propertyhive' ),
50 'international' => __( 'International', 'propertyhive' ),
51 'gdpr' => __( 'GDPR', 'propertyhive' ),
52 'captcha' => __( 'CAPTCHA', 'propertyhive' ),
53 'text-substitution' => __( 'Text Substitution', 'propertyhive' ),
54 'misc' => __( 'Miscellaneous', 'propertyhive' ),
55 );
56
57 return $sections;
58 }
59
60
61 /**
62 * Get general settings array
63 *
64 * @return array
65 */
66 public function get_settings() {
67
68 $default_departments = ph_get_departments(true);
69 $departments = ph_get_departments();
70 $custom_departments = ph_get_custom_departments(false);
71
72 $settings = array(
73
74 array( 'title' => __( 'General Options', 'propertyhive' ), 'type' => 'title', 'desc' => '', 'id' => 'general_options' ),
75
76 );
77
78 $active_departments_html = '<div id="active_departments">';
79
80 foreach ( $departments as $key => $value )
81 {
82 if ( isset($custom_departments[$key]) )
83 {
84
85 }
86 else
87 {
88 $active_departments_html .= '<fieldset>
89 <legend class="screen-reader-text"><span>' . esc_html(__( 'Active Departments', 'propertyhive' )) . '</span></legend>
90 <label for="propertyhive_active_departments_' . esc_attr(str_replace("residential-", "", $key)) . '">
91 <input name="propertyhive_active_departments_' . esc_attr(str_replace("residential-", "", $key)) . '" id="propertyhive_active_departments_' . esc_attr(str_replace("residential-", "", $key)) . '" type="checkbox" value="1" ' . checked( get_option('propertyhive_active_departments_' . str_replace("residential-", "", $key)) , 'yes', false ) . '> ' . esc_html($value) . '
92 </label>
93 </fieldset>';
94 }
95 }
96
97 if ( !empty($custom_departments) )
98 {
99 foreach ( $custom_departments as $key => $custom_department )
100 {
101 // key will be custom-0, for example
102 $active_departments_html .= '<fieldset id="propertyhive_active_department_fieldset_' . esc_attr($key) . '">
103 <legend class="screen-reader-text"><span>' . esc_html(__( 'Active Departments', 'propertyhive' )) . '</span></legend>
104 <label>
105 <input name="propertyhive_active_departments_' . esc_attr($key) . '" type="checkbox" value="1" ' . checked( get_option('propertyhive_active_departments_' . $key), 'yes', false ) . '>
106 <input type="text" name="propertyhive_active_departments_name_' . esc_attr($key) . '" value="' . $custom_department['name'] . '">
107 ' . __( 'based on', 'propertyhive' ) . '
108 <select name="propertyhive_active_departments_based_on_' . esc_attr($key) . '">
109 <option value=""></option>';
110 foreach ( $default_departments as $dept_key => $value )
111 {
112 $active_departments_html .= '<option value="' . esc_attr($dept_key) . '"' . selected( $custom_department['based_on'], $dept_key, false ) . '>' . esc_html($value) . '</option>';
113 }
114 $active_departments_html .= '
115 </select>
116 <a href="" class="delete-department" data-department="' . esc_attr($key) . '">Delete</a>
117 </label>
118 </fieldset>';
119 }
120 }
121
122 $active_departments_html .= '</div>
123 <a href="" id="add_department">+ ' . esc_html(__( 'Add Department', 'propertyhive' )) . '</a>
124 <input type="hidden" name="propertyhive_new_custom_departments" id="propertyhive_new_custom_departments" value="0">
125 <input type="hidden" name="propertyhive_custom_departments" id="propertyhive_custom_departments" value="' . esc_attr(implode(",", array_keys($custom_departments))) . '">
126 <input type="hidden" name="propertyhive_custom_departments_original" id="propertyhive_custom_departments_original" value="' . esc_attr(implode(",", array_keys($custom_departments))) . '">
127 ';
128
129 $active_departments_html .= '<div id="active_department_template" style="display:none">
130 <fieldset id="propertyhive_active_department_fieldset_template">
131 <legend class="screen-reader-text"><span>' . __( 'Active Departments', 'propertyhive' ) . '</span></legend>
132 <label>
133 <input name="propertyhive_active_departments_template" type="checkbox" value="1" checked>
134 <input type="text" name="propertyhive_active_departments_name_template" value="">
135 ' . __( 'based on', 'propertyhive' ) . '
136 <select name="propertyhive_active_departments_based_on_template">
137 <option value=""></option>';
138 foreach ( $default_departments as $key => $value )
139 {
140 $active_departments_html .= '<option value="' . esc_attr($key) . '">' . esc_html($value) . '</option>';
141 }
142 $active_departments_html .= '
143 </select>
144 <a href="" class="delete-department" data-department="template">Delete</a>
145 </label>
146 </fieldset>
147 </div>';
148
149 $settings[] = array(
150 'title' => __( 'Active Departments', 'propertyhive' ),
151 'id' => 'propertyhive_active_departments',
152 'type' => 'html',
153 'html' => $active_departments_html,
154 );
155
156 $settings[] = array(
157 'title' => __( 'Primary Department', 'propertyhive' ),
158 'id' => 'propertyhive_primary_department',
159 'type' => 'radio',
160 'default' => 'residential-sales',
161 'options' => $departments,
162 );
163
164 $settings[] = array(
165 'title' => __( 'Property Search Results Page', 'propertyhive' ),
166 'id' => 'propertyhive_search_results_page_id',
167 'type' => 'single_select_page',
168 'default' => '',
169 'css' => 'min-width:300px;',
170 'desc' => __( 'This sets the page of your property search results', 'propertyhive' ),
171 );
172
173 $settings[] = array(
174 'title' => __( 'Lettings Fees (Residential)', 'propertyhive' ),
175 'id' => 'propertyhive_lettings_fees',
176 'type' => 'textarea',
177 'css' => 'height:150px; width:100%; max-width:400px'
178 );
179
180 $settings[] = array(
181 'title' => __( 'Lettings Fees (Commercial)', 'propertyhive' ),
182 'id' => 'propertyhive_lettings_fees_commercial',
183 'type' => 'textarea',
184 'css' => 'height:150px; width:100%; max-width:400px'
185 );
186
187 $settings[] = array(
188 'title' => __( 'Display Link To Lettings Fees Next To Price', 'propertyhive' ),
189 'desc' => __( 'In Search Results', 'propertyhive' ),
190 'id' => 'propertyhive_lettings_fees_display_search_results',
191 'type' => 'checkbox',
192 'checkboxgroup' => 'start',
193 );
194
195 $settings[] = array(
196 'title' => __( 'Display Link To Lettings Fees Next To Price', 'propertyhive' ),
197 'desc' => __( 'On Property Details Page', 'propertyhive' ),
198 'id' => 'propertyhive_lettings_fees_display_single_property',
199 'type' => 'checkbox',
200 'checkboxgroup' => 'end',
201 );
202
203 $settings[] = array( 'type' => 'sectionend', 'id' => 'general_options');
204
205 return apply_filters( 'propertyhive_general_settings', $settings );
206 }
207
208 /**
209 * Get general modules settings array
210 *
211 * @return array
212 */
213 public function get_general_modules_setting() {
214
215 return apply_filters( 'propertyhive_general_modules_settings', array(
216
217 array( 'title' => __( 'Disabled Modules', 'propertyhive' ), 'type' => 'title', 'desc' => '', 'id' => 'modules_options' ),
218
219 array(
220 'type' => 'html',
221 'html' => __( 'Here you can choose which modules are enabled or disabled within Property Hive. Check the modules you <strong>DO NOT</strong> wish to use from the list below', 'propertyhive' ) . ':',
222 ),
223
224 array(
225 'title' => __( 'Disabled Modules', 'propertyhive' ),
226 'desc' => __( 'Contacts (Applicants, Owners/Landlords and Third Party Contacts)', 'propertyhive' ),
227 'id' => 'propertyhive_module_disabled_contacts',
228 'type' => 'checkbox',
229 'default' => '',
230 'checkboxgroup' => 'start'
231 ),
232
233 array(
234 'title' => __( 'Disabled Modules', 'propertyhive' ),
235 'desc' => __( 'Appraisals', 'propertyhive' ),
236 'id' => 'propertyhive_module_disabled_appraisals',
237 'type' => 'checkbox',
238 'default' => '',
239 'checkboxgroup' => 'middle'
240 ),
241
242 array(
243 'title' => __( 'Disabled Modules', 'propertyhive' ),
244 'desc' => __( 'Viewings', 'propertyhive' ),
245 'id' => 'propertyhive_module_disabled_viewings',
246 'type' => 'checkbox',
247 'default' => '',
248 'checkboxgroup' => 'middle'
249 ),
250
251 array(
252 'title' => __( 'Disabled Modules', 'propertyhive' ),
253 'desc' => __( 'Offers and Sales', 'propertyhive' ),
254 'id' => 'propertyhive_module_disabled_offers_sales',
255 'type' => 'checkbox',
256 'default' => '',
257 'checkboxgroup' => 'middle'
258 ),
259
260 array(
261 'title' => __( 'Disabled Modules', 'propertyhive' ),
262 'desc' => __( 'Tenancies', 'propertyhive' ),
263 'id' => 'propertyhive_module_disabled_tenancies',
264 'type' => 'checkbox',
265 'default' => '',
266 'checkboxgroup' => 'middle'
267 ),
268
269 array(
270 'title' => __( 'Disabled Modules', 'propertyhive' ),
271 'desc' => __( 'Enquiries', 'propertyhive' ),
272 'id' => 'propertyhive_module_disabled_enquiries',
273 'type' => 'checkbox',
274 'default' => '',
275 'checkboxgroup' => 'end'
276 ),
277
278 array( 'type' => 'sectionend', 'id' => 'modules_options'),
279
280 ) ); // End general module settings
281 }
282
283 /**
284 * Get international settings array
285 *
286 * @return array
287 */
288 public function get_general_international_setting() {
289
290 $settings = array(
291
292 array( 'title' => __( 'International Options', 'propertyhive' ), 'type' => 'title', 'desc' => '', 'id' => 'international_options' ),
293
294 array(
295 'title' => __( 'Countries Where You Operate', 'propertyhive' ),
296 'id' => 'propertyhive_countries',
297 'type' => 'multi_select_countries',
298 'css' => 'min-width:300px;',
299 'desc' => __( 'Hold ctrl/cmd whilst clicking to select multiple', 'propertyhive' )
300 ),
301
302 array(
303 'title' => __( 'Default Country', 'propertyhive' ),
304 'id' => 'propertyhive_default_country',
305 'type' => 'single_select_country',
306 'css' => 'min-width:300px;',
307 ),
308
309 array(
310 'title' => __( 'Price Thousand Separator', 'propertyhive' ),
311 'id' => 'propertyhive_price_thousand_separator',
312 'type' => 'text',
313 'default' => ',',
314 'css' => 'width:50px;',
315 'desc' => __( 'This only effects prices output on the frontend. Prices entered and displayed in the backend will use the comma character (,) as the thousand separator.', 'propertyhive' )
316 ),
317
318 array(
319 'title' => __( 'Price Decimal Separator', 'propertyhive' ),
320 'id' => 'propertyhive_price_decimal_separator',
321 'type' => 'text',
322 'default' => '.',
323 'css' => 'width:50px;',
324 'desc' => __( 'This only effects prices output on the frontend. Prices entered and displayed in the backend will use the period character (.) as the decimal separator.', 'propertyhive' )
325 )
326 );
327
328 $ph_countries = new PH_Countries();
329 $ph_countries = $ph_countries->countries;
330
331 $currencies = array();
332 $countries = array();
333 if ( !empty($ph_countries) )
334 {
335 foreach ( $ph_countries as $country_code => $country )
336 {
337 $currencies[$country['currency_code']] = $country['currency_code'];
338 $countries[$country_code] = $country;
339 }
340 }
341 $currencies = array_unique($currencies);
342 ksort($currencies);
343
344 $settings[] = array(
345 'title' => __( 'Currency Used In Search Forms', 'propertyhive' ),
346 'id' => 'propertyhive_search_form_currency',
347 'type' => 'select',
348 'options' => $currencies,
349 'default' => 'GBP',
350 'desc' => __( 'Please note that this doesn\'t change the currency symbol shown in price dropdowns within search forms. The easiest way to achieve that is to use our free <a href="https://wp-property-hive.com/addons/template-assistant/" target="_blank">Template Assistant add on</a>.', 'propertyhive' ),
351 );
352
353 $settings[] = array( 'type' => 'sectionend', 'id' => 'international_options');
354
355 $settings[] = array(
356 'type' => 'html',
357 'html' => '<script>
358
359 var countries = '. wp_json_encode( $countries, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT ) . ';
360
361 </script>'
362 );
363
364 return apply_filters( 'propertyhive_general_international_settings', $settings );
365 }
366
367 /**
368 * Get map settings array
369 *
370 * @return array
371 */
372 public function get_general_map_setting() {
373
374 $settings = array(
375
376 array( 'title' => __( 'Map Options', 'propertyhive' ), 'type' => 'title', 'desc' => '', 'id' => 'map_options' ),
377
378 array(
379 'title' => __( 'Maps Provider', 'propertyhive' ),
380 'id' => 'propertyhive_maps_provider',
381 'type' => 'radio',
382 'options' => array(
383 '' => 'Google Maps',
384 'mapbox' => 'Mapbox',
385 'osm' => 'OpenStreetMap',
386 ),
387 ),
388
389 array(
390 'title' => __( 'Google Maps API Key', 'propertyhive' ),
391 'id' => 'propertyhive_google_maps_api_key',
392 'type' => 'text',
393 'desc' => '<p>' . __( 'If you have a Google Maps API key you can enter it here. You can generate an API key <a href="https://developers.google.com/maps/documentation/javascript/get-api-key" target="_blank">here</a>.<br>This is used when displaying the map when adding/editing properties, and if using our <a href="https://wp-property-hive.com/addons/map-search/" target="_blank">Map Search</a> or <a href="https://wp-property-hive.com/addons/radial-search/" target="_blank">Radial Search</a> add ons.<br>When creating your API key we recommend that you enable the Geocoding library. More about this can be found <a href="https://docs.wp-property-hive.com/user-guide/maps-co-ordinates-and-geocoding/" target="_blank">here</a>.', 'propertyhive' ) . '</p>'
394 ),
395
396 array(
397 'title' => __( 'Mapbox API Key', 'propertyhive' ),
398 'id' => 'propertyhive_mapbox_api_key',
399 'type' => 'text',
400 'desc' => '<p>' . __( 'If you have a Mapbox API key you can enter it here. You can generate an API key <a href="https://account.mapbox.com/" target="_blank">here</a>.', 'propertyhive' ) . '</p>'
401 ),
402
403 array(
404 'title' => __( 'Geocoding Provider', 'propertyhive' ),
405 'id' => 'propertyhive_geocoding_provider',
406 'type' => 'radio',
407 'options' => array(
408 '' => 'Google Maps',
409 //'mapbox' => 'Mapbox',
410 'osm' => 'OpenStreetMap',
411 ),
412 ),
413
414 array(
415 'id' => 'propertyhive_osm_html',
416 'type' => 'html',
417 'html' => '<p>' . __( 'Note: OSM is an open source project maintained by volunteers and the geocoding results returned are reliant on the data sets available. If you find some addresses/search terms don\'t return results this is likely the issue, as opposed to it being an issue with Property Hive.', 'propertyhive' ) . '</p>'
418 ),
419 );
420
421 if ( apply_filters( 'propertyhive_use_google_maps_geocoding_api_key', false) === true )
422 {
423 $settings[] = array(
424 'title' => __( 'Google Maps Geocoding API Key', 'propertyhive' ),
425 'id' => 'propertyhive_google_maps_geocoding_api_key',
426 'type' => 'text',
427 'desc' => '<p>' . __( 'If you have referer restrictions applied to the main API key entered then server side geocoding requests will be blocked. To get around this you can setup a separate API key specifically for geocoding and enter it here, with IP restrictions applied instead if required.<br>More about this can be found <a href="https://docs.wp-property-hive.com/user-guide/maps-co-ordinates-and-geocoding/" target="_blank">here</a>.', 'propertyhive' ) . '</p>'
428 );
429
430 $settings[] = array(
431 'title' => __( 'Mapbox Geocoding API Key', 'propertyhive' ),
432 'id' => 'propertyhive_mapbox_geocoding_api_key',
433 'type' => 'text',
434 'desc' => '<p>' . __( 'If you have referer restrictions applied to the main API key entered then server side geocoding requests will be blocked. To get around this you can setup a separate API key specifically for geocoding and enter it here, with IP restrictions applied instead if required.<br>More about this can be found <a href="https://docs.wp-property-hive.com/user-guide/maps-co-ordinates-and-geocoding/" target="_blank">here</a>.', 'propertyhive' ) . '</p>'
435 );
436 }
437
438 $settings[] = array( 'type' => 'sectionend', 'id' => 'map_options');
439
440 return apply_filters( 'propertyhive_general_map_settings', $settings );
441 }
442
443 /**
444 * Get media settings array
445 *
446 * @return array
447 */
448 public function get_general_media_setting() {
449
450 $settings = array(
451
452 array( 'title' => __( 'Property Media Storage', 'propertyhive' ), 'type' => 'title', 'desc' => 'By default media attached to properties will be stored in the WordPress media library. If the property media is hosted elsewhere (for example if you import properties from a third party and they allow you to link direct to the files on their server) you can choose to store media as URL\'s. It also means that the images are not downloaded onto your server, thus saving diskspace.<br><br>Note: If you change this you\'ll need to re-add all of the property media for existing properties.<br>Note: Changing this will not delete all existing media or URLs entered.<br>Note: Choosing to store the media as URLs will mean you don\'t benefit from having access to different sized images (i.e. small, medium, large etc).', 'id' => 'media_storage_options' ),
453
454 array(
455 'title' => __( 'Images Stored As', 'propertyhive' ),
456 'id' => 'propertyhive_images_stored_as',
457 'type' => 'select',
458 'default' => 'files',
459 'options' => array(
460 'files' => __( 'Media Files', 'propertyhive' ),
461 'urls' => __( 'URLs', 'propertyhive' ),
462 ),
463 'desc' => ''
464 ),
465
466 array(
467 'title' => __( 'Floorplans Stored As', 'propertyhive' ),
468 'id' => 'propertyhive_floorplans_stored_as',
469 'type' => 'select',
470 'default' => 'files',
471 'options' => array(
472 'files' => __( 'Media Files', 'propertyhive' ),
473 'urls' => __( 'URLs', 'propertyhive' ),
474 ),
475 'desc' => ''
476 ),
477
478 array(
479 'title' => __( 'Brochures Stored As', 'propertyhive' ),
480 'id' => 'propertyhive_brochures_stored_as',
481 'type' => 'select',
482 'default' => 'files',
483 'options' => array(
484 'files' => __( 'Media Files', 'propertyhive' ),
485 'urls' => __( 'URLs', 'propertyhive' ),
486 ),
487 'desc' => ''
488 ),
489
490 array(
491 'title' => __( 'EPCs Stored As', 'propertyhive' ),
492 'id' => 'propertyhive_epcs_stored_as',
493 'type' => 'select',
494 'default' => 'files',
495 'options' => array(
496 'files' => __( 'Media Files', 'propertyhive' ),
497 'urls' => __( 'URLs', 'propertyhive' ),
498 ),
499 'desc' => ''
500 ),
501
502 array( 'type' => 'sectionend', 'id' => 'media_storage_options')
503
504 );
505
506 return apply_filters( 'propertyhive_general_media_settings', $settings );
507 }
508
509 /**
510 * Get GDPR settings array
511 *
512 * @return array
513 */
514 public function get_general_gdpr_setting() {
515
516 return apply_filters( 'propertyhive_general_gdpr_settings', array(
517
518 array( 'title' => __( 'GDPR Settings', 'propertyhive' ), 'type' => 'title', 'desc' => '', 'id' => 'gdpr_options' ),
519
520 array(
521 'title' => __( 'Store Property Enquiries', 'propertyhive' ),
522 'id' => 'propertyhive_store_property_enquiries',
523 'type' => 'checkbox',
524 'default' => 'yes',
525 'desc' => __( 'If using the default property enquiry form that comes with Property Hive, select this option if enquiries should be saved in the \'Enquiries\' section of Property Hive. Note that regardless of whether this is ticked or not, the enquiry will still be sent via email. This option simply determines whether we save it to the database or not.', 'propertyhive' )
526 ),
527
528 array(
529 'title' => __( 'Property Enquiry Form Disclaimer', 'propertyhive' ),
530 'id' => 'propertyhive_property_enquiry_form_disclaimer',
531 'type' => 'wysiwyg',
532 'desc' => __( 'Add disclaimer text, including a link to a privacy policy, that will appear on the property enquiry form.', 'propertyhive' )
533 ),
534
535 array(
536 'title' => __( 'Applicant Registration Form Disclaimer', 'propertyhive' ),
537 'id' => 'propertyhive_applicant_registration_form_disclaimer',
538 'type' => 'wysiwyg',
539 'desc' => __( 'Add disclaimer text, including a link to a privacy policy, that will appear on the applicant registration form.', 'propertyhive' )
540 ),
541
542 array( 'type' => 'sectionend', 'id' => 'gdpr_options'),
543
544 ) ); // End general GDPR settings
545 }
546
547 /**
548 * Get CAPTCHA settings array
549 *
550 * @return array
551 */
552 public function get_general_captcha_setting() {
553
554 return apply_filters( 'propertyhive_general_captcha_settings', array(
555
556 array( 'title' => __( 'CAPTCHA Settings', 'propertyhive' ), 'type' => 'title', 'id' => 'captcha_options', 'desc' => __( 'Prevent spam and bots on forms provided by Property Hive by signing up to a CAPTCHA service and entering the details below.<br><br>When enabled, a CAPTCHA will be added to the register, property enquiry and send to friend forms.', 'propertyhive' ) ),
557
558 array(
559 'title' => __( 'CAPTCHA service', 'propertyhive' ),
560 'id' => 'propertyhive_captcha_service',
561 'type' => 'radio',
562 'options' => array(
563 '' => __( 'None', 'propertyhive' ),
564 'recaptcha' => __( 'Google reCaptcha v2', 'propertyhive' ) . ' (<a href="https://www.google.com/recaptcha/admin/create" target="_blank">register</a>)',
565 'recaptcha-v3' => __( 'Google reCaptcha v3', 'propertyhive' ) . ' (<a href="https://www.google.com/recaptcha/admin/create" target="_blank">register</a>)',
566 'hCaptcha' => __( 'hCaptcha', 'propertyhive' ) . ' (<a href="https://www.hcaptcha.com/" target="_blank">register</a>)',
567 'turnstile' => __( 'Cloudflare Turnstile', 'propertyhive' ) . ' (<a href="https://www.cloudflare.com/en-gb/application-services/products/turnstile/" target="_blank">register</a>)', // phpcs:ignore PluginCheck.CodeAnalysis.Offloading.OffloadedContent -- Registration hyperlink for the optional CAPTCHA provider.
568 ),
569 ),
570
571 array(
572 'title' => __( 'Site Key', 'propertyhive' ),
573 'id' => 'propertyhive_captcha_site_key',
574 'type' => 'text',
575 ),
576
577 array(
578 'title' => __( 'Secret', 'propertyhive' ),
579 'id' => 'propertyhive_captcha_secret',
580 'type' => 'text',
581 ),
582
583 array(
584 'title' => __( 'Score Threshold', 'propertyhive' ),
585 'id' => 'propertyhive_captcha_score_threshold',
586 'type' => 'text',
587 'default' => 0.5,
588 'desc' => __( 'Set the minimum score required to pass reCAPTCHA v3 verification (between 0 and 1). Lower values allow more submissions through but increase spam risk.', 'propertyhive' ),
589 ),
590
591 array(
592 //'title' => __( 'CAPTCHA service', 'propertyhive' ),
593 'id' => 'propertyhive_captcha_html',
594 'type' => 'html',
595 'html' => '<script>
596 jQuery(document).ready(function()
597 {
598 jQuery(\'input[name=\\\'propertyhive_captcha_service\\\']\').change(function()
599 {
600 ph_captcha_service_update();
601 });
602
603 ph_captcha_service_update();
604 });
605
606 function ph_captcha_service_update()
607 {
608 jQuery(\'#row_propertyhive_captcha_site_key\').hide();
609 jQuery(\'#row_propertyhive_captcha_secret\').hide();
610 jQuery(\'#row_propertyhive_captcha_score_threshold\').hide();
611
612 var selected_captcha_service = jQuery(\'input[name=\\\'propertyhive_captcha_service\\\']:checked\').val();
613
614 if ( selected_captcha_service != \'\' )
615 {
616 jQuery(\'#row_propertyhive_captcha_site_key\').show();
617 jQuery(\'#row_propertyhive_captcha_secret\').show();
618
619 if ( selected_captcha_service == \'recaptcha-v3\' )
620 {
621 jQuery(\'#row_propertyhive_captcha_score_threshold\').show();
622 }
623 }
624 }
625 </script>',
626 ),
627
628 array( 'type' => 'sectionend', 'id' => 'captcha_options'),
629
630 ) ); // End general CAPTCHA settings
631 }
632
633 /**
634 * Get text substitution settings array
635 *
636 * @return array
637 */
638 public function get_general_text_substitution_setting() {
639
640 $current_settings = get_option( 'propertyhive_template_assistant', array() );
641
642 $settings = array(
643
644 array( 'title' => __( 'Text Substitution', 'propertyhive' ), 'type' => 'title', 'desc' => 'Replace specific words or phrases used throughout Property Hive with your own preferred wording.', 'id' => 'template_assistant_text_translation_settings' )
645
646 );
647
648 $existing_translations = array();
649 if ( isset($current_settings['text_translations']) && is_array($current_settings['text_translations']) && !empty($current_settings['text_translations']) )
650 {
651 foreach ( $current_settings['text_translations'] as $text_translation )
652 {
653 $existing_translations[] = '<tr>
654 <td><input type="text" name="search[]" class="regular-text" value="' . esc_attr($text_translation['search']) . '"></td>
655 <td><input type="text" name="replace[]" class="regular-text" value="' . esc_attr($text_translation['replace']) . '"></td>
656 <td><a href="" class="delete-text-substitution" title="Delete Text Substitution"><span class="dashicons dashicons-trash"></span></a></td>
657 </tr>';
658 }
659 }
660
661 $settings[] = array(
662 'type' => 'html',
663 'full_width' => true,
664 'html' => '
665
666 <table class="widefat striped" style="max-width:520px;" >
667 <thead>
668 <tr>
669 <th style="padding:8px 10px;" scope="col">Text To Replace</th>
670 <th style="padding:8px 10px;" scope="col">Replace With</th>
671 <th style="padding:8px 10px;" scope="col">&nbsp;</th>
672 </tr>
673 </thead>
674 <tbody>
675 ' . implode("", $existing_translations) . '
676 <tr>
677 <td><input type="text" name="search[]" class="regular-text" placeholder="e.g. Make Enquiry"></td>
678 <td><input type="text" name="replace[]" class="regular-text" placeholder="e.g. Request Viewing"></td>
679 <td>&nbsp;</td>
680 </tr>
681 </tbody>
682 </table>
683
684 <script>
685 jQuery(document).ready(function()
686 {
687 jQuery(\'a.delete-text-substitution\').on(\'click\', function(e)
688 {
689 e.preventDefault();
690
691 jQuery(this).closest(\'tr\').find(\'input\').val(\'\');
692
693 setTimeout(function() {
694 jQuery(\'.submit button[type="submit"]\').trigger(\'click\');
695 }, 0);
696 });
697 });
698 </script>'
699 );
700
701 $settings[] = array( 'type' => 'sectionend', 'id' => 'template_assistant_text_translation_settings');
702
703 return $settings;
704 }
705
706 /**
707 * Get misc settings array
708 *
709 * @return array
710 */
711 public function get_general_misc_setting() {
712
713 return apply_filters( 'propertyhive_general_misc_settings', array(
714
715 array( 'title' => __( 'Property Options', 'propertyhive' ), 'type' => 'title', 'desc' => '', 'id' => 'property_options' ),
716
717 array(
718 'title' => __( 'Search By Address Should', 'propertyhive' ),
719 'id' => 'propertyhive_address_keyword_compare',
720 'type' => 'radio',
721 'default' => '=',
722 'options' => array(
723 '=' => __( 'Match Keyword Exactly', 'propertyhive' ),
724 'LIKE' => __( 'Perform Loose Search', 'propertyhive' ),
725 'polygon' => __( 'Search Within Location Perimeter', 'propertyhive' ),
726 ),
727 'desc_tip' => __( 'Applicable if you allow users to search by entering a location. If \'Match Keyword Exactly\' is selected a search for \'Walton\' would not return properties in \'Walton On Thames\', but would prevent properties in \'Lincolnshire\' appearing when searching for \'Lincoln\'. \'Perform Loose Search\' would do the opposite. \'Search Within Location Perimeter\' will make an API request to Nominatim to get the perimeter of the entered location and will search within the returned polygon.', 'propertyhive' )
728 ),
729
730 array(
731 'title' => __( 'Commercial Display In Search Results', 'propertyhive' ),
732 'id' => 'propertyhive_commercial_display',
733 'type' => 'select',
734 'default' => '',
735 'css' => 'min-width:300px;',
736 'options' => array(
737 '' => __( 'Display top level properties and units', 'propertyhive' ),
738 'top_level_only' => __( 'Display top level properties only', 'propertyhive' ),
739 'top_level_only_but_units_when_filtered' => __( 'Display top level properties only but units as well if matching filters', 'propertyhive' ),
740 ),
741 ),
742
743 array(
744 'title' => __( 'When An Off Market Property URL Is Viewed', 'propertyhive' ),
745 'id' => 'propertyhive_off_market_behaviour',
746 'type' => 'select',
747 'default' => '',
748 'css' => 'min-width:300px;',
749 'options' => array(
750 '' => __( 'Still show the property details', 'propertyhive' ),
751 'redirect' => __( 'Do a 301 redirect to the search results page', 'propertyhive' ),
752 ),
753 'desc' => __( 'If 301 redirect is selected, this will only apply to non-logged in users', 'propertyhive' )
754 ),
755
756 array(
757 'title' => __( 'When Entering Features', 'propertyhive' ),
758 'id' => 'propertyhive_features_type',
759 'type' => 'radio',
760 'options' => array(
761 '' => __( 'Allow Features To Be Freetyped', 'propertyhive' ),
762 'checkbox' => __( 'Select From A Predefined List (Editable from \'Custom Fields\')', 'propertyhive' ),
763 ),
764 ),
765
766 array(
767 'title' => __( 'Enable Auto-Incremental Reference Numbers', 'propertyhive' ),
768 'id' => 'propertyhive_auto_incremental_reference_numbers',
769 'type' => 'checkbox',
770 'desc' => __( 'Will prefill the property reference with an auto-incremental number when adding a new property', 'propertyhive' )
771 ),
772
773 array(
774 'title' => __( 'Next Incremental Reference Number', 'propertyhive' ),
775 'id' => 'propertyhive_auto_incremental_next',
776 'type' => 'number',
777 'default' => 1,
778 ),
779
780 array( 'type' => 'sectionend', 'id' => 'property_options'),
781
782 array( 'title' => __( 'Applicant Options', 'propertyhive' ), 'type' => 'title', 'desc' => '', 'id' => 'applicant_registration_options' ),
783
784 array(
785 'title' => __( 'Allow Applicants To Login and Manage Account', 'propertyhive' ),
786 'id' => 'propertyhive_applicant_users',
787 'type' => 'checkbox',
788 'desc' => __( 'Applicable when you allow users to register on a form using the [applicant_registration_form] shortcode.<br><br>Selecting this will allow applicants to create a password when registering, then login to manage their details and requirements. They will be created as a WordPress user with \'Property Hive Contact\' role.<br><br>If unticked applicants will still be able to register and they\'ll go into Property Hive as an applicant, they just won\'t be able to login at a later date.', 'propertyhive' )
789 ),
790
791 array(
792 'title' => __( 'Send Email When Applicant Registers', 'propertyhive' ),
793 'id' => 'propertyhive_new_registration_alert',
794 'type' => 'checkbox',
795 'desc' => __( 'Choose whether an email should be sent alerting you to the fact someone has registered. The email will be sent to the chosen office. Offices can be managed click selecting the \'Offices\' tab above.', 'propertyhive' )
796 ),
797
798 array(
799 'title' => __( 'My Account Page', 'propertyhive' ),
800 'id' => 'propertyhive_my_account_page_id',
801 'type' => 'single_select_page',
802 'default' => '',
803 'css' => 'min-width:300px;',
804 'desc' => __( 'This page should contain the [propertyhive_my_account] shortcode', 'propertyhive' ),
805 ),
806
807 array(
808 'title' => __( 'Applicant Login Page', 'propertyhive' ),
809 'id' => 'propertyhive_applicant_login_page_id',
810 'type' => 'single_select_page',
811 'default' => '',
812 'css' => 'min-width:300px;',
813 'desc' => __( 'This page should contain the [propertyhive_login_form] shortcode', 'propertyhive' ),
814 ),
815
816 array(
817 'title' => __( 'Applicant Reset Password Page', 'propertyhive' ),
818 'id' => 'propertyhive_applicant_reset_password_page_id',
819 'type' => 'single_select_page',
820 'default' => '',
821 'css' => 'min-width:300px;',
822 'desc' => __( 'This page should contain the [propertyhive_reset_password_form] shortcode', 'propertyhive' ),
823 ),
824
825 array(
826 'title' => __( 'Applicant Registration Page', 'propertyhive' ),
827 'id' => 'propertyhive_applicant_registration_page_id',
828 'type' => 'single_select_page',
829 'default' => '',
830 'css' => 'min-width:300px;',
831 'desc' => __( 'This page should contain the [applicant_registration_form] shortcode', 'propertyhive' ),
832 ),
833
834 array(
835 'title' => __( 'Match Price Range % (Lower)', 'propertyhive' ),
836 'id' => 'propertyhive_applicant_match_price_range_percentage_lower',
837 'type' => 'number',
838 'default' => '20',
839 'desc' => '<p>' . __( 'When a maximum price is entered against an applicants requirements we create a \'Match Price Range\' which determines the price of properties that would get matched to the applicant.<br>We do this because you:<br>a) Wouldn\'t want to send them properties that were way below their specified maximum price and<br>b) Would probably want to send them properties which are slightly just over the price specified as, if the perfect property came along, a lot of people would actually be able to increase their maximum.<br>These settings determine the % above and below the maximum price entered that the \'Match Price Range\' will default to per applicant.<br>For example, if the maximum price entered was &pound;500,000, the lower setting was 20% and the higher setting was 5%, the applicant would actually match to properties that were priced &pound;400,000 - &pound;525,000.<br>This price range can be overwritten on a per-applicant basis, or disabled completely by leaving these settings empty.<br>Note that this currently only applies to applicants looking for sales properties and changing this value at a later date will only effect applicants that don\'t already have a match price range set.', 'propertyhive' ) . '</p>',
840 ),
841
842 array(
843 'title' => __( 'Match Price Range % (Higher)', 'propertyhive' ),
844 'id' => 'propertyhive_applicant_match_price_range_percentage_higher',
845 'type' => 'number',
846 'default' => '5',
847 ),
848
849 array(
850 'title' => __( 'When Selecting Applicant Locations', 'propertyhive' ),
851 'id' => 'propertyhive_applicant_locations_type',
852 'type' => 'radio',
853 'options' => array(
854 'text' => __( 'Allow Locations To Be Freetyped', 'propertyhive' ),
855 '' => __( 'Select From A Predefined List (Editable from \'Custom Fields\')', 'propertyhive' ),
856 ),
857 'desc' => '<i>' . __( 'When this setting is changed, locations selected using the other method will no longer be used for matching', 'propertyhive' ) . '</i>',
858 ),
859
860 array( 'type' => 'sectionend', 'id' => 'applicant_registration_options'),
861
862 array( 'title' => __( 'Improve Property Hive', 'propertyhive' ), 'type' => 'title', 'desc' => '', 'id' => 'stat_tracking_options' ),
863
864 array(
865 'title' => __( 'Usage Data Sharing', 'propertyhive' ),
866 'id' => 'propertyhive_data_sharing',
867 'type' => 'checkbox',
868 'value' => ( get_option('propertyhive_data_sharing', FALSE) === FALSE ? 'yes' : get_option('propertyhive_data_sharing', '') ),
869 'desc' => __( 'Help improve Property Hive by periodically sending us non-sensitive plugin data. Untick this option to opt-out. <a href="https://docs.wp-property-hive.com/user-guide/share-usage-data/" target="_blank">Learn more</a>', 'propertyhive' )
870 ),
871
872 array( 'type' => 'sectionend', 'id' => 'stat_tracking_options'),
873
874 ) ); // End general misc settings
875 }
876
877 /**
878 * Output the settings
879 */
880 public function output() {
881 global $current_section;
882
883 if ( $current_section )
884 {
885 switch ($current_section)
886 {
887 case "modules": { $settings = $this->get_general_modules_setting(); break; }
888 case "international": { $settings = $this->get_general_international_setting(); break; }
889 case "map": { $settings = $this->get_general_map_setting(); break; }
890 case "media": { $settings = $this->get_general_media_setting(); break; }
891 case "gdpr": { $settings = $this->get_general_gdpr_setting(); break; }
892 case "captcha": { $settings = $this->get_general_captcha_setting(); break; }
893 case "text-substitution": { $settings = $this->get_general_text_substitution_setting(); break; }
894 case "misc": { $settings = $this->get_general_misc_setting(); break; }
895 default: { die("Unknown setting section"); }
896 }
897 }
898 else
899 {
900 $settings = $this->get_settings();
901 }
902
903 PH_Admin_Settings::output_fields( $settings );
904 }
905
906 /**
907 * Output a colour picker input box.
908 *
909 * @access public
910 * @param mixed $name
911 * @param mixed $id
912 * @param mixed $value
913 * @param string $desc (default: '')
914 * @return void
915 */
916 function color_picker( $name, $id, $value, $desc = '' ) {
917 echo '<div class="color_box"><strong><img class="help_tip" data-tip="' . esc_attr( $desc ) . '" src="' . esc_url(PH()->plugin_url() . '/assets/images/help.png') . '" height="16" width="16" /> ' . esc_html( $name ) . '</strong>
918 <input name="' . esc_attr( $id ). '" id="' . esc_attr( $id ) . '" type="text" value="' . esc_attr( $value ) . '" class="colorpick" /> <div id="colorPickerDiv_' . esc_attr( $id ) . '" class="colorpickdiv"></div>
919 </div>';
920 }
921
922 /**
923 * Save settings
924 */
925 public function save() {
926 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' ) ) {
927 return;
928 }
929
930 global $current_section;
931
932 if ( $current_section != '' )
933 {
934 switch ($current_section)
935 {
936 case 'modules':
937 {
938 $settings = $this->get_general_modules_setting();
939
940 PH_Admin_Settings::save_fields( $settings );
941 break;
942 }
943 case 'international':
944 {
945 $international = array();
946 foreach ( array( 'propertyhive_default_country', 'propertyhive_price_thousand_separator', 'propertyhive_price_decimal_separator', 'propertyhive_search_form_currency' ) as $input_key ) {
947 if ( ! isset( $_POST[$input_key] ) || ! is_string( $_POST[$input_key] ) ) {
948 return;
949 }
950 $international[$input_key] = sanitize_text_field( wp_unslash( $_POST[$input_key] ) );
951 }
952 if ( isset( $_POST['propertyhive_countries'] ) && ! is_array( $_POST['propertyhive_countries'] ) ) {
953 return;
954 }
955 $countries = array();
956 if ( isset( $_POST['propertyhive_countries'] ) ) {
957 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Each country is validated as a string, unslashed and sanitized in the loop before use.
958 foreach ( $_POST['propertyhive_countries'] as $country ) {
959 if ( ! is_string( $country ) ) {
960 return;
961 }
962 $countries[] = sanitize_text_field( wp_unslash( $country ) );
963 }
964 }
965 if ( empty( $countries ) ) {
966 // Preserve the existing default-country fallback when no list is selected.
967 update_option( 'propertyhive_countries', array( $international['propertyhive_default_country'] ) );
968 } else {
969 if ( ! in_array( $international['propertyhive_default_country'], $countries, true ) ) {
970 $international['propertyhive_default_country'] = $countries[0];
971 // Keep the normalized selection available to existing save-hook consumers.
972 $_POST['propertyhive_default_country'] = wp_slash( $countries[0] );
973 }
974 update_option( 'propertyhive_default_country', $international['propertyhive_default_country'] );
975 update_option( 'propertyhive_countries', $countries );
976 }
977 update_option( 'propertyhive_price_thousand_separator', $international['propertyhive_price_thousand_separator'] );
978 update_option( 'propertyhive_price_decimal_separator', $international['propertyhive_price_decimal_separator'] );
979 update_option( 'propertyhive_search_form_currency', $international['propertyhive_search_form_currency'] );
980 do_action( 'propertyhive_update_currency_exchange_rates' );
981 break;
982 }
983 case 'map':
984 {
985 $settings = $this->get_general_map_setting();
986
987 PH_Admin_Settings::save_fields( $settings );
988 break;
989 }
990 case 'media':
991 {
992 $settings = $this->get_general_media_setting();
993
994 PH_Admin_Settings::save_fields( $settings );
995 break;
996 }
997 case 'gdpr':
998 {
999 $settings = $this->get_general_gdpr_setting();
1000
1001 PH_Admin_Settings::save_fields( $settings );
1002 break;
1003 }
1004 case 'captcha':
1005 {
1006 $settings = $this->get_general_captcha_setting();
1007
1008 PH_Admin_Settings::save_fields( $settings );
1009 break;
1010 }
1011 case 'text-substitution':
1012 {
1013 $current_settings = get_option( 'propertyhive_template_assistant', array() );
1014
1015 if ( ! is_array( $current_settings ) ) {
1016 $current_settings = array();
1017 }
1018 foreach ( array( 'search', 'replace' ) as $field ) {
1019 if ( isset( $_POST[ $field ] ) && ! is_array( $_POST[ $field ] ) ) {
1020 return;
1021 }
1022 }
1023 $text_translations = array();
1024 if ( isset($_POST['search']) && is_array($_POST['search']) && !empty($_POST['search']) && isset($_POST['replace']) && is_array($_POST['replace']) && !empty($_POST['replace']) )
1025 {
1026 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Search members and paired replacement strings are shape-checked, unslashed and sanitized below.
1027 foreach ( $_POST['search'] as $i => $search )
1028 {
1029 if ( ! is_string( $search ) || ! isset( $_POST['replace'][$i] ) || ! is_string( $_POST['replace'][$i] ) ) {
1030 return;
1031 }
1032 $search = sanitize_text_field( wp_unslash( $search ) );
1033 $replace = sanitize_text_field( wp_unslash( $_POST['replace'][$i] ) );
1034 if ( trim( $search ) !== '' && trim( $replace ) !== '' )
1035 {
1036 $text_translations[] = array(
1037 'search' => $search,
1038 'replace' => $replace,
1039 );
1040 }
1041 }
1042 }
1043
1044 $propertyhive_template_assistant = array(
1045 'text_translations' => $text_translations,
1046 );
1047
1048 $propertyhive_template_assistant = array_merge($current_settings, $propertyhive_template_assistant);
1049
1050 update_option( 'propertyhive_template_assistant', $propertyhive_template_assistant );
1051 break;
1052 }
1053 case 'misc':
1054 {
1055 $settings = $this->get_general_misc_setting();
1056
1057 PH_Admin_Settings::save_fields( $settings );
1058 break;
1059 }
1060 default: { die("Unknown setting section"); }
1061 }
1062 }
1063 else
1064 {
1065 // Validate the complete custom-department form before any options are changed.
1066 $department_lists = array();
1067 foreach ( array( 'propertyhive_custom_departments', 'propertyhive_custom_departments_original' ) as $field ) {
1068 if ( isset( $_POST[ $field ] ) && ! is_string( $_POST[ $field ] ) ) {
1069 return;
1070 }
1071 $raw_list = isset( $_POST[ $field ] ) ? sanitize_text_field( wp_unslash( $_POST[ $field ] ) ) : '';
1072 $department_lists[ $field ] = array_filter( explode( ',', $raw_list ) );
1073 }
1074 $department_details = array();
1075 foreach ( $department_lists['propertyhive_custom_departments'] as $department_id ) {
1076 foreach ( array( 'name', 'based_on' ) as $detail ) {
1077 $field = 'propertyhive_active_departments_' . $detail . '_' . $department_id;
1078 if ( ! isset( $_POST[ $field ] ) || ! is_string( $_POST[ $field ] ) ) {
1079 return;
1080 }
1081 $department_details[ $department_id ][ $detail ] = sanitize_text_field( wp_unslash( $_POST[ $field ] ) );
1082 }
1083 }
1084
1085 $settings = $this->get_settings();
1086
1087 PH_Admin_Settings::save_fields( $settings );
1088
1089 $departments = ph_get_departments();
1090
1091 foreach ( $departments as $key => $value )
1092 {
1093 if ( substr($key, 0, 6) == 'phnew-' )
1094 {
1095 // Ignore new departments as we'll deal with them separately
1096 continue;
1097 }
1098
1099 if (
1100 isset($_POST['propertyhive_active_departments_' . str_replace("residential-", "", $key)])
1101 )
1102 {
1103 $option_value = 'yes';
1104 }
1105 else
1106 {
1107 $option_value = 'no';
1108 }
1109
1110 update_option( 'propertyhive_active_departments_' . str_replace("residential-", "", $key), $option_value );
1111 }
1112
1113 $custom_departments = array();
1114 if ( ! empty( $department_lists['propertyhive_custom_departments'] ) )
1115 {
1116 $submitted_custom_departments = $department_lists['propertyhive_custom_departments'];
1117 $submitted_custom_departments = array_filter($submitted_custom_departments);
1118 if ( !empty($submitted_custom_departments) )
1119 {
1120 foreach ( $submitted_custom_departments as $submitted_custom_department )
1121 {
1122 if (
1123 isset($_POST['propertyhive_active_departments_' . $submitted_custom_department])
1124 )
1125 {
1126 $option_value = 'yes';
1127 }
1128 else
1129 {
1130 $option_value = 'no';
1131 }
1132
1133 $key = $submitted_custom_department;
1134 if ( substr($submitted_custom_department, 0, 6) == 'phnew-' )
1135 {
1136 $key = sanitize_title( $department_details[ $submitted_custom_department ]['name'] );
1137 }
1138
1139 $custom_departments[$key] = array(
1140 'name' => $department_details[ $submitted_custom_department ]['name'],
1141 'based_on' => $department_details[ $submitted_custom_department ]['based_on']
1142 );
1143
1144 update_option( 'propertyhive_active_departments_' . $key, $option_value );
1145 }
1146 }
1147 }
1148
1149 update_option( 'propertyhive_custom_departments', $custom_departments );
1150
1151 // TO DO: Cater for deleted departments
1152 if ( ! empty( $department_lists['propertyhive_custom_departments_original'] ) )
1153 {
1154 $original_custom_departments = $department_lists['propertyhive_custom_departments_original'];
1155 $original_custom_departments = array_filter($original_custom_departments);
1156 if ( !empty($original_custom_departments) )
1157 {
1158 $submitted_custom_departments = $department_lists['propertyhive_custom_departments'];
1159 $submitted_custom_departments = array_filter($submitted_custom_departments);
1160
1161 foreach ( $original_custom_departments as $original_custom_department )
1162 {
1163 if ( !in_array($original_custom_department, $submitted_custom_departments) )
1164 {
1165 // no longer present
1166 delete_option( 'propertyhive_active_departments_' . $original_custom_department );
1167 }
1168 }
1169 }
1170 }
1171
1172 // Update departments in any search forms
1173 $current_settings = get_option( 'propertyhive_template_assistant', array() );
1174
1175 if ( isset($current_settings['search_forms']) && !empty($current_settings['search_forms']) )
1176 {
1177 foreach ( $current_settings['search_forms'] as $id => $form )
1178 {
1179 if ( isset($form['active_fields']) && isset($form['active_fields']['department']) && isset($form['active_fields']['department']['options']) )
1180 {
1181 // We have a department field in this form. Check options match current department settings
1182
1183 $departments = ph_get_departments();
1184
1185 foreach ( $departments as $key => $value )
1186 {
1187 $department_active = get_option( 'propertyhive_active_departments_' . str_replace("residential-", "", $key) );
1188
1189 if ( $department_active != 'yes' && isset($form['active_fields']['department']['options'][$key]) )
1190 {
1191 unset($form['active_fields']['department']['options'][$key]);
1192 }
1193
1194 if ( $department_active == 'yes' && !isset($form['active_fields']['department']['options'][$key]) )
1195 {
1196 $form['active_fields']['department']['options'][$key] = $value;
1197 }
1198 }
1199
1200 $current_settings['search_forms'][$id]['active_fields'] = $form['active_fields'];
1201 }
1202 }
1203 }
1204
1205 update_option( 'propertyhive_template_assistant', $current_settings );
1206 }
1207 }
1208
1209 }
1210
1211 endif;
1212
1213 return new PH_Settings_General();
1214