PluginProbe
Property Hive / 2.2.4
Property Hive v2.2.4
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 / class-ph-rest-api.php

class-ph-rest-api.php in Property Hive 2.2.4, at includes/class-ph-rest-api.php

1,216 lines 37.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 /**
8 * Serve properties using the REST API
9 *
10 * @class PH_Rest_Api
11 * @version 1.0.0
12 * @package PropertyHive/Classes/
13 * @category Class
14 * @author PropertyHive
15 */
16 class PH_Rest_Api {
17
18 /** @var PH_Rest_Api The single instance of the class */
19 protected static $_instance = null;
20
21 /**
22 * Main PH_Rest_Api Instance.
23 *
24 * Ensures only one instance of PH_Rest_Api is loaded or can be loaded.
25 *
26 * @since 1.0.0
27 * @static
28 * @return PH_Licenses Main instance
29 */
30 public static function instance() {
31 if ( is_null( self::$_instance ) ) {
32 self::$_instance = new self();
33 }
34 return self::$_instance;
35 }
36
37 /**
38 * Cloning is forbidden.
39 *
40 * @since 1.0.0
41 */
42 public function __clone() {
43 _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'propertyhive' ), '1.0.0' );
44 }
45
46 /**
47 * Unserializing instances of this class is forbidden.
48 *
49 * @since 1.0.0
50 */
51 public function __wakeup() {
52 _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'propertyhive' ), '1.0.0' );
53 }
54
55 /**
56 * Constructor for the licenses class
57 *
58 */
59 public function __construct() {
60 // Property
61 add_filter( 'rest_property_query', array( $this, 'modify_rest_property_query' ), 10, 2 );
62 add_filter( 'rest_prepare_property', array( $this, 'rest_prepare_property' ), 10, 3 );
63 add_action( 'rest_api_init', array( $this, 'register_rest_api_property_fields' ), 99 );
64 add_filter( 'rest_property_collection_params', array( $this, 'modify_rest_order_by' ), 10, 1 );
65 add_action( "rest_after_insert_property", array( $this, 'ensure_key_property_fields_set' ), 10, 3 );
66
67 // Enquiry - Create
68 add_action( 'rest_api_init', array( $this, 'register_enquiry_rest_route' ), 11 );
69 add_action( "rest_after_insert_enquiry", array( $this, 'ensure_key_enquiry_fields_set' ), 10, 3 );
70
71 // Enquiry - Read
72 add_filter( 'pre_get_posts', array( $this, 'restrict_enquiry_rest_listing' ));
73 add_filter( 'rest_pre_dispatch', array( $this, 'block_enquiry_rest_listing' ), 10, 3);
74 add_action( 'rest_api_init', array( $this, 'register_rest_api_enquiry_fields' ), 99 );
75
76 // Office
77 add_action( 'rest_api_init', array( $this, 'register_rest_api_office_fields' ), 99 );
78 }
79
80 // Restrict listing of enquiries via REST API
81 public function restrict_enquiry_rest_listing(WP_Query $query)
82 {
83 if ( !is_admin() && defined('REST_REQUEST') && REST_REQUEST )
84 {
85 $post_type = $query->get('post_type');
86
87 // Check if it's the 'enquiry' CPT
88 if ( $post_type === 'enquiry' )
89 {
90 if ( !current_user_can('manage_propertyhive') )
91 {
92 // Force an empty result
93 $query->set('post__in', [0]);
94 }
95 }
96 }
97 }
98
99 public function block_enquiry_rest_listing($response, $server, $request)
100 {
101 if ( $request->get_route() === '/wp/v2/enquiry' )
102 {
103 $current_user = wp_get_current_user();
104
105 if ( !current_user_can('manage_propertyhive') )
106 {
107 return new WP_Error(
108 'rest_forbidden',
109 __('You are not allowed to list enquiries.', 'propertyhive'),
110 ['status' => 403]
111 );
112 }
113
114 if ( get_option( 'propertyhive_module_disabled_enquiries', '' ) == 'yes' )
115 {
116 return new WP_Error(
117 'rest_forbidden',
118 __('The enquiries module is currently disabled.', 'propertyhive'),
119 ['status' => 403]
120 );
121 }
122
123 if ( get_option( 'propertyhive_store_property_enquiries', 'yes' ) != 'yes' )
124 {
125 return new WP_Error(
126 'rest_forbidden',
127 __('Storing of property enquiries has been disabled in the GDPR settings.', 'propertyhive'),
128 ['status' => 403]
129 );
130 }
131
132 }
133 return $response;
134 }
135
136 public function register_rest_api_enquiry_fields()
137 {
138 $field_array = array(
139 'office',
140 'negotiator',
141 'status',
142 'source',
143 'properties',
144 'details',
145 );
146
147 $field_array = apply_filters( 'propertyhive_rest_api_enquiry_fields', $field_array );
148
149 foreach ( $field_array as $field )
150 {
151 register_rest_field( 'enquiry',
152 $field,
153 array(
154 'get_callback' => function( $object, $field_name, $request )
155 {
156 $enquiry = new PH_Enquiry($object['id']);
157
158 $return = '';
159
160 switch ($field_name)
161 {
162 case "office":
163 {
164 $return = array(
165 'name' => get_the_title($enquiry->_office_id),
166 );
167 break;
168 }
169 case "negotiator":
170 {
171 $user = get_userdata( $enquiry->_negotiator_id );
172
173 $return = array(
174 'name' => ( $user !== false ) ? $user->display_name : '',
175 );
176 break;
177 }
178 case "properties":
179 {
180 $return = array();
181
182 $property_ids = $enquiry->get_properties();
183
184 if ( !empty($property_ids) )
185 {
186 foreach ( $property_ids as $property_id )
187 {
188 $property = new PH_Property((int)$property_id);
189
190 $return[] = array(
191 'id' => (int)$property_id,
192 'address' => $property->get_formatted_full_address()
193 );
194 }
195 }
196 break;
197 }
198 case "details":
199 {
200 $ignore_keys = array(
201 '_status',
202 '_source',
203 '_negotiator_id',
204 '_office_id',
205 '_action',
206 '_contact_id',
207 '_property_id',
208 'property_id',
209 );
210
211 $enquiry_meta = get_metadata( 'post', $object['id'] );
212
213 $return = array();
214
215 foreach ($enquiry_meta as $key => $value)
216 {
217 if ( !in_array( $key, $ignore_keys ) && substr( $key, 0, 1 ) != '_' && strpos($key, 'captcha') === FALSE )
218 {
219 $return[trim($key, "_")] = $value;
220 }
221 }
222 break;
223 }
224 default:
225 {
226 $return = $enquiry->{$field_name};
227 }
228 }
229
230 $return = apply_filters( 'propertyhive_rest_api_enquiry_field_callback', $return, $field_name, $enquiry );
231 return $return;
232 },
233 'schema' => null,
234 )
235 );
236 }
237 }
238
239 public function register_enquiry_rest_route()
240 {
241 register_rest_route('wp/v2', '/enquiry', array(
242 array(
243 'methods' => WP_REST_Server::CREATABLE,
244 'callback' => array( $this, 'handle_enquiry_post' ),
245 'permission_callback' => array( $this, 'enquiry_permission_check' )
246 ),
247 ));
248 }
249
250 public function enquiry_permission_check()
251 {
252 // Check if the user is authenticated
253 if (is_user_logged_in() || apply_filters('rest_authentication_errors', null) === null) {
254 // Check if the user has the capability to create enquiries (e.g., 'edit_posts')
255 if (current_user_can('edit_posts')) {
256 return true;
257 } else {
258 return new WP_Error('rest_forbidden', 'You do not have permissions to create enquiries.', array('status' => 403));
259 }
260 } else {
261 return new WP_Error('rest_forbidden', 'You are not authenticated.', array('status' => 403));
262 }
263 }
264
265 public function handle_enquiry_post(WP_REST_Request $request)
266 {
267 // Handle the creation of the enquiry post
268 $params = $request->get_params();
269
270 // validate office ID
271 if ( isset($params['office_id']) && !empty($params['office_id']) )
272 {
273 if ( get_post_type((int)$params['office_id']) != 'office' )
274 {
275 return new WP_Error('rest_enquiry_error', __( 'Invalid office ID passed', 'propertyhive' ) . ' ('. (int)$params['office_id'] . ')', array('status' => 400));
276 }
277 }
278
279 // validate negotiator ID
280 if ( isset($params['negotiator_id']) && !empty($params['negotiator_id']) )
281 {
282 if ( get_userdata((int)$params['negotiator_id']) === false )
283 {
284 return new WP_Error('rest_enquiry_error', __( 'Invalid negotiator ID passed', 'propertyhive' ) . ' ('. (int)$params['negotiator_id'] . ')', array('status' => 400));
285 }
286 }
287
288 // validate source
289 $valid_sources = array(
290 'office' => __( 'Office', 'propertyhive' ),
291 'website' => __( 'Website', 'propertyhive' )
292 );
293
294 $valid_sources = apply_filters( 'propertyhive_enquiry_sources', $valid_sources );
295
296 if ( isset($params['source']) && !empty($params['source']) )
297 {
298 if ( !array_key_exists($params['source'], $valid_sources) )
299 {
300 return new WP_Error('rest_enquiry_error', __( 'Invalid source passed. Should be one of', 'propertyhive' ) . ': ' . implode(", ", array_keys($valid_sources)), array('status' => 400));
301 }
302 }
303
304 if ( isset($params['property_id']) && !empty($params['property_id']) )
305 {
306 if ( !is_array($params['property_id']) )
307 {
308 $property_ids = array($params['property_id']);
309 }
310 else
311 {
312 $property_ids = $params['property_id'];
313 }
314
315 foreach ( $property_ids as $property_id )
316 {
317 if ( get_post_type((int)$property_id) != 'property' )
318 {
319 return new WP_Error('rest_enquiry_error', __( 'Invalid property ID passed', 'propertyhive' ) . ' ('. (int)$property_id . ')', array('status' => 400));
320 }
321 }
322 }
323
324 $title = ( isset($params['title']) && !empty($params['title']) ? $params['title'] : '' );
325 if (empty($title))
326 {
327 $title = 'Enquiry';
328 if ( isset($params['name']) && !empty($params['name']) )
329 {
330 $title .= ' from ' . $params['name'];
331 }
332 if ( isset($params['property_id']) && !empty($params['property_id']) )
333 {
334 if ( is_array($params['property_id']) )
335 {
336 $title .= ' about ' . count($params['property_id']) . ' properties';
337 }
338 else
339 {
340 $title .= ' about ' . get_the_title($params['property_id']);
341 }
342 }
343 }
344 $data = array(
345 'post_type' => 'enquiry',
346 'post_status' => 'publish',
347 'post_title' => sanitize_text_field($title),
348 'post_content' => '',
349 'comment_status' => 'closed',
350 'ping_status' => 'closed',
351 );
352
353 $post_id = wp_insert_post($data, true);
354
355 if ( is_wp_error($post_id) )
356 {
357 return new WP_Error('rest_enquiry_error', $post_id->get_error_message(), array('status' => 500));
358 }
359
360 // Status
361 if ( isset($params['status']) && !empty($params['status']) && in_array($params['status'], array('open', 'closed')) )
362 {
363 update_post_meta( $post_id, '_status', sanitize_text_field($params['status']) );
364 }
365 else
366 {
367 update_post_meta( $post_id, '_status', 'open' );
368 }
369
370 if ( isset($params['office_id']) && !empty($params['office_id']) && is_numeric($params['office_id']) )
371 {
372 // Should be a valid office ID as this has already been validated by this point
373 update_post_meta( $post_id, '_office_id', (int)$params['office_id'] );
374 }
375 else
376 {
377 $primary_office_id = '';
378 $args = array(
379 'post_type' => 'office',
380 'nopaging' => true
381 );
382 $office_query = new WP_Query($args);
383
384 if ($office_query->have_posts())
385 {
386 while ($office_query->have_posts())
387 {
388 $office_query->the_post();
389
390 if (get_post_meta(get_the_ID(), 'primary', TRUE) == '1')
391 {
392 $primary_office_id = get_the_ID();
393 }
394 }
395 }
396 $office_query->reset_postdata();
397
398 update_post_meta( $post_id, '_office_id', $primary_office_id );
399 }
400
401 if ( isset($params['negotiator_id']) && !empty($params['negotiator_id']) && is_numeric($params['negotiator_id']) )
402 {
403 // Should be a valid neg ID as this has already been validated by this point
404 update_post_meta( $post_id, '_negotiator_id', (int)$params['negotiator_id'] );
405 }
406
407 // Source
408 if ( isset($params['source']) && !empty($params['source']) && array_key_exists($params['source'], $valid_sources) )
409 {
410 update_post_meta( $post_id, '_source', sanitize_text_field($params['source']) );
411 }
412 else
413 {
414 update_post_meta( $post_id, '_source', 'website' );
415 }
416
417 if ( isset($params['name']) && !empty($params['name']) )
418 {
419 update_post_meta( $post_id, 'name', sanitize_text_field($params['name']) );
420 }
421
422 if ( isset($params['email_address']) && !empty($params['email_address']) )
423 {
424 update_post_meta( $post_id, 'email_address', sanitize_email($params['email_address']) );
425 }
426
427 if ( isset($params['telephone_number']) && !empty($params['telephone_number']) )
428 {
429 update_post_meta( $post_id, 'telephone_number', sanitize_text_field($params['telephone_number']) );
430 }
431
432 if ( isset($params['message']) && !empty($params['message']) )
433 {
434 update_post_meta( $post_id, 'message', sanitize_textarea_field($params['message']) );
435 }
436
437 if ( isset($params['property_id']) && !empty($params['property_id']) && ( is_numeric($params['property_id']) || is_array($params['property_id']) ) )
438 {
439 // Should be a valid property ID as this has already been validated by this point
440 $property_ids = $params['property_id'];
441 if ( !is_array($property_ids) ) { $property_ids = array($property_ids); }
442
443 foreach ( $property_ids as $property_id )
444 {
445 add_post_meta( $post_id, 'property_id', (int)$property_id );
446 }
447 }
448
449 return new WP_REST_Response(array('ID' => $post_id), 201);
450 }
451
452 public function ensure_key_property_fields_set( $post, $request, $creating )
453 {
454 // Country / price actual
455 $country = get_post_meta( $post->ID, '_address_country', true );
456 if ( $country == '' )
457 {
458 $default_country = get_option( 'propertyhive_default_country', 'GB' );
459 update_post_meta( $post->ID, '_address_country', $default_country );
460 }
461
462 $ph_countries = new PH_Countries();
463 $ph_countries->update_property_price_actual( $post->ID );
464
465 // Department
466 $department = get_post_meta( $post->ID, '_department', true );
467 if ( $department == '' )
468 {
469 $primary_department = get_option( 'propertyhive_primary_department', 'residential-sales' );
470 update_post_meta( $post->ID, '_department', $primary_department );
471 }
472
473 // On Market
474 $on_market = get_post_meta( $post->ID, '_on_market', true );
475 if ( $on_market != 'yes' )
476 {
477 update_post_meta( $post->ID, '_on_market', '' );
478 }
479
480 // Featured
481 $featured = get_post_meta( $post->ID, '_featured', true );
482 if ( $featured != 'yes' )
483 {
484 update_post_meta( $post->ID, '_featured', '' );
485 }
486
487 // Office
488 $office_id = get_post_meta( $post->ID, '_office_id', true );
489 if ( $office_id == '' )
490 {
491 $primary_office_id = '';
492 $args = array(
493 'post_type' => 'office',
494 'nopaging' => true
495 );
496 $office_query = new WP_Query($args);
497
498 if ($office_query->have_posts())
499 {
500 while ($office_query->have_posts())
501 {
502 $office_query->the_post();
503
504 if (get_post_meta(get_the_ID(), 'primary', TRUE) == '1')
505 {
506 $primary_office_id = get_the_ID();
507 }
508 }
509 }
510 $office_query->reset_postdata();
511
512 update_post_meta( $post->ID, '_office_id', $primary_office_id );
513 }
514 }
515
516 public function modify_rest_order_by($params)
517 {
518 $fields = ["price-asc", "price-desc"];
519
520 foreach ( $fields as $key => $value )
521 {
522 $params['orderby']['enum'][] = $value;
523 }
524
525 return $params;
526 }
527
528 public function modify_rest_property_query($args, $request)
529 {
530 /*if ( !isset( $args['meta_query'] ) )
531 {
532 $args['meta_query'] = array();
533 }*/
534
535 $PH_Query = new PH_Query();
536
537 // Meta query
538 $args['meta_query'] = $PH_Query->get_meta_query();
539
540 // Tax query
541 $args['tax_query'] = $PH_Query->get_tax_query();
542
543 // Date query
544 $args['date_query'] = $PH_Query->get_date_query();
545
546 $ordering = $PH_Query->get_search_results_ordering_args();
547 $args['orderby'] = $ordering['orderby'] . ' post_title';
548 $args['order'] = $ordering['order'];
549 if ( isset( $ordering['meta_key'] ) )
550 $args['meta_key'] = $ordering['meta_key'];
551
552 $args = apply_filters( 'propertyhive_rest_api_query_args', $args );
553
554 return $args;
555 }
556
557 public function register_rest_api_property_fields()
558 {
559 $field_array = array(
560 'department',
561 'reference_number',
562 'address_street',
563 'address_two',
564 'address_three',
565 'address_four',
566 'address_postcode',
567 'address_country',
568 'latitude',
569 'longitude',
570 'price_actual',
571 'price',
572 'price_from',
573 'price_to',
574 'price_units',
575 'rent_from',
576 'rent_to',
577 'rent_units',
578 'price_formatted',
579 'rent_frequency',
580 'currency',
581 'price_qualifier',
582 'sale_by',
583 'tenure',
584 'council_tax_band',
585 'deposit',
586 'furnished',
587 'available_date',
588 'bedrooms',
589 'bathrooms',
590 'reception_rooms',
591 'property_type',
592 'parking',
593 'outside_space',
594 'for_sale',
595 'to_rent',
596 'floor_area_from',
597 'floor_area_to',
598 'floor_area_units',
599 'site_area_from',
600 'site_area_to',
601 'site_area_units',
602 'on_market',
603 'featured',
604 'location',
605 'availability',
606 'marketing_flag',
607 'features',
608 'description',
609 'office',
610 'negotiator',
611 'images',
612 'floorplans',
613 'brochures',
614 'epcs',
615 'virtual_tours',
616 'views_total',
617 'views_last_7_days',
618 'views_last_14_days',
619 'views_last_30_days',
620 );
621
622 $field_array = apply_filters( 'propertyhive_rest_api_property_fields', $field_array );
623
624 foreach ( $field_array as $field )
625 {
626 register_rest_field( 'property',
627 $field,
628 array(
629 'get_callback' => function( $object, $field_name, $request )
630 {
631 $property = new PH_Property($object[ 'id' ]);
632
633 $return = '';
634
635 switch ($field_name)
636 {
637 case "price":
638 {
639 if ( $property->_poa != 'yes' )
640 {
641 $department = $property->_department;
642 if ( ph_get_custom_department_based_on( $department ) !== false )
643 {
644 $department = ph_get_custom_department_based_on( $department );
645 }
646 if ( $department == 'residential-lettings' ) { $return = $property->_rent; }else{ $return = $property->_price; }
647 }
648 break;
649 }
650 case "price_from":
651 case "price_to":
652 {
653 if ( $property->_price_poa != 'yes' )
654 {
655 $return = $property->{'_' . $field_name};
656 }
657 break;
658 }
659 case "rent_from":
660 case "rent_to":
661 {
662 if ( $property->_rent_poa != 'yes' )
663 {
664 $return = $property->{'_' . $field_name};
665 }
666 break;
667 }
668 case "price_formatted": { $return = $property->get_formatted_price(); break; }
669 case "features": { $return = $property->get_features(); break; }
670 case "description": { $return = $property->get_formatted_description(); break; }
671 case "office":
672 {
673 $return = array(
674 'name' => $property->office_name,
675 'address' => $property->office_address,
676 'telephone_number' => $property->office_telephone_number,
677 'email_address' => $property->office_email_address,
678 );
679 break;
680 }
681 case "negotiator":
682 {
683 $return = array(
684 'name' => $property->negotiator_name,
685 'telephone_number' => $property->negotiator_telephone_number,
686 'email_address' => $property->negotiator_email_address,
687 );
688 break;
689 }
690 case "images":
691 {
692 $images_array = array();
693 if ( get_option('propertyhive_images_stored_as', '') == 'urls' )
694 {
695 $image_urls = $property->_photo_urls;
696 if ( !is_array($image_urls) ) { $image_urls = array(); }
697
698 foreach ( $image_urls as $image_url )
699 {
700 if ( isset($image_url['url']) )
701 {
702 $images_array[] = array(
703 'url' => $image_url['url'],
704 'large' => $image_url['url'],
705 'medium' => $image_url['url'],
706 'thumbnail' => $image_url['url'],
707 );
708 }
709 }
710 }
711 else
712 {
713 $image_ids = $property->get_gallery_attachment_ids();
714 foreach ( $image_ids as $image_id )
715 {
716 $image_url = wp_get_attachment_url($image_id);
717 if ($image_url !== false)
718 {
719 $large_image = wp_get_attachment_image_src( $image_id, 'large' );
720 $medium_image = wp_get_attachment_image_src( $image_id, 'medium' );
721 $thumbnail_image = wp_get_attachment_image_src( $image_id, 'thumbnail' );
722
723 $images_array[] = array(
724 'url' => $image_url,
725 'large' => ( $large_image !== FALSE ? $large_image[0] : $image_url ),
726 'medium' => ( $medium_image !== FALSE ? $medium_image[0] : $image_url ),
727 'thumbnail' => ( $thumbnail_image !== FALSE ? $thumbnail_image[0] : $image_url ),
728 );
729 }
730 }
731 }
732 $return = $images_array;
733 break;
734 }
735 case "floorplans":
736 {
737 $floorplans_array = array();
738 if ( get_option('propertyhive_floorplans_stored_as', '') == 'urls' )
739 {
740 $floorplan_urls = $property->_floorplan_urls;
741 if ( !is_array($floorplan_urls) ) { $floorplan_urls = array(); }
742
743 foreach ( $floorplan_urls as $floorplan_url )
744 {
745 if ( isset($floorplan_url['url']) )
746 {
747 $floorplans_array[] = array(
748 'url' => $floorplan_url['url'],
749 'large' => $floorplan_url['url'],
750 'medium' => $floorplan_url['url'],
751 'thumbnail' => $floorplan_url['url'],
752 );
753 }
754 }
755 }
756 else
757 {
758 $floorplan_ids = $property->get_floorplan_attachment_ids();
759 foreach ( $floorplan_ids as $floorplan_id )
760 {
761 $floorplan_url = wp_get_attachment_url($floorplan_id);
762 if ($floorplan_url !== false)
763 {
764 $large_image = wp_get_attachment_image_src( $floorplan_id, 'large' );
765 $medium_image = wp_get_attachment_image_src( $floorplan_id, 'medium' );
766 $thumbnail_image = wp_get_attachment_image_src( $floorplan_id, 'thumbnail' );
767
768 $floorplans_array[] = array(
769 'url' => $floorplan_url,
770 'large' => ( $large_image !== FALSE ? $large_image[0] : $floorplan_url ),
771 'medium' => ( $medium_image !== FALSE ? $medium_image[0] : $floorplan_url ),
772 'thumbnail' => ( $thumbnail_image !== FALSE ? $thumbnail_image[0] : $floorplan_url ),
773 );
774 }
775 }
776 }
777 $return = $floorplans_array;
778 break;
779 }
780 case "brochures":
781 {
782 $brochures_array = array();
783 if ( get_option('propertyhive_brochures_stored_as', '') == 'urls' )
784 {
785 $brochure_urls = $property->_brochure_urls;
786 if ( !is_array($brochure_urls) ) { $brochure_urls = array(); }
787
788 foreach ( $brochure_urls as $brochure_url )
789 {
790 if ( isset($brochure_url['url']) )
791 {
792 $brochures_array[] = array(
793 'url' => $brochure_url['url'],
794 );
795 }
796 }
797 }
798 else
799 {
800 $brochure_ids = $property->get_brochure_attachment_ids();
801 foreach ( $brochure_ids as $brochure_id )
802 {
803 $brochure_url = wp_get_attachment_url($brochure_id);
804 if ($brochure_url !== false)
805 {
806 $brochures_array[] = array(
807 'url' => $brochure_url,
808 );
809 }
810 }
811 }
812 $return = $brochures_array;
813 break;
814 }
815 case "epcs":
816 {
817 $epcs_array = array();
818 if ( get_option('propertyhive_epcs_stored_as', '') == 'urls' )
819 {
820 $epc_urls = $property->_epc_urls;
821 if ( !is_array($epc_urls) ) { $epc_urls = array(); }
822
823 foreach ( $epc_urls as $epc_url )
824 {
825 if ( isset($epc_url['url']) )
826 {
827 $epcs_array[] = array(
828 'url' => $epc_url['url'],
829 );
830 }
831 }
832 }
833 else
834 {
835 $epc_ids = $property->get_epc_attachment_ids();
836 foreach ( $epc_ids as $epc_id )
837 {
838 $epc_url = wp_get_attachment_url($epc_id);
839 if ($epc_url !== false)
840 {
841 $epcs_array[] = array(
842 'url' => $epc_url,
843 );
844 }
845 }
846 }
847 $return = $epcs_array;
848 break;
849 }
850 case "virtual_tours":
851 {
852 $return = $property->get_virtual_tours();
853 break;
854 }
855 case "views_last_7_days":
856 case "views_last_14_days":
857 case "views_last_30_days":
858 case "views_total":
859 {
860 $view_statistics = $property->_view_statistics;
861 if ( !is_array($view_statistics) )
862 {
863 $view_statistics = array();
864 }
865
866 $views = 0;
867
868 $date_from = '2001-01-01';
869 switch ($field_name)
870 {
871 case "views_last_7_days": { $date_from = date("Y-m-d", strtotime('7 days ago')); break; }
872 case "views_last_14_days": { $date_from = date("Y-m-d", strtotime('14 days ago')); break; }
873 case "views_last_30_days": { $date_from = date("Y-m-d", strtotime('30 days ago')); break; }
874 }
875 $date_from = strtotime($date_from);
876
877 $date_to = date("Y-m-d");
878 $date_to = strtotime($date_to);
879
880 for ($i = $date_from; $i <= $date_to; $i += 86400)
881 {
882 if ( isset($view_statistics[date("Y-m-d", $i)]) )
883 {
884 $views += $view_statistics[date("Y-m-d", $i)];
885 }
886 }
887
888 $return = $views;
889 break;
890 }
891 default:
892 {
893 $return = $property->{$field_name};
894 }
895 }
896
897 $return = apply_filters( 'propertyhive_rest_api_property_field_callback', $return, $field_name, $property );
898 return $return;
899 },
900 'update_callback' => function ( $value, $object, $field_name )
901 {
902 if ( taxonomy_exists($field_name) )
903 {
904 wp_set_post_terms( $object->ID, $value, $field_name );
905 }
906 else
907 {
908 switch ( $field_name )
909 {
910 case "price":
911 {
912 $property = new PH_Property($object->ID);
913
914 $price = '';
915 if ( $value != '' )
916 {
917 $price = preg_replace("/[^0-9.]/", '', $value);
918 }
919
920 if ( isset($property->_department) && $property->_department == 'residential-lettings' )
921 {
922 update_post_meta( $object->ID, '_rent', $price );
923 }
924 else
925 {
926 update_post_meta( $object->ID, '_price', $price );
927 }
928
929 if ( $price != '' )
930 {
931 // Store price in common currency (GBP) used for ordering
932 $ph_countries = new PH_Countries();
933 $ph_countries->update_property_price_actual( $object->ID );
934 }
935
936 break;
937 }
938 case "features":
939 {
940 if ( is_array($value) && !empty($value) )
941 {
942 update_post_meta( $object->ID, '_features', count($value) );
943
944 $i = 0;
945 foreach ( $value as $feature )
946 {
947 update_post_meta( $object->ID, '_feature_' . $i, $feature );
948
949 ++$i;
950 }
951 }
952 break;
953 }
954 case "images":
955 case "floorplans":
956 case "brochures":
957 case "epcs":
958 {
959 if ( !function_exists('media_handle_upload') ) {
960 require_once(ABSPATH . "wp-admin" . '/includes/image.php');
961 require_once(ABSPATH . "wp-admin" . '/includes/file.php');
962 require_once(ABSPATH . "wp-admin" . '/includes/media.php');
963 }
964
965 $hive_field_name = trim($field_name, 's');
966 if ( $hive_field_name == 'image' ) { $hive_field_name = 'photo'; }
967
968 if ( is_array($value) && !empty($value) )
969 {
970 if ( get_option('propertyhive_' . $field_name . '_stored_as', '') == 'urls' )
971 {
972 $media_items = array();
973 foreach ( $value as $media_item )
974 {
975 if (
976 isset($media_item['url']) &&
977 (
978 substr( strtolower($media_item['url']), 0, 2 ) == '//' ||
979 substr( strtolower($media_item['url']), 0, 4 ) == 'http'
980 )
981 )
982 {
983 $media_items[] = array(
984 'url' => $media_item['url'],
985 );
986 }
987 }
988 update_post_meta( $object->ID, '_' . $hive_field_name . '_urls', $media_items );
989 }
990 else
991 {
992 $media_ids = array();
993 $previous_media_ids = get_post_meta( $object->ID, '_' . $hive_field_name . 's', TRUE );
994 foreach ( $value as $media_item )
995 {
996 if (
997 isset($media_item['url']) &&
998 (
999 substr( strtolower($media_item['url']), 0, 2 ) == '//' ||
1000 substr( strtolower($media_item['url']), 0, 4 ) == 'http'
1001 )
1002 )
1003 {
1004 // This is a URL
1005 $url = $media_item['url'];
1006 $description = '';
1007
1008 $filename = basename( $url );
1009
1010 // Check, based on the URL, whether we have previously imported this media
1011 $imported_previously = false;
1012 $imported_previously_id = '';
1013 if ( is_array($previous_media_ids) && !empty($previous_media_ids) )
1014 {
1015 foreach ( $previous_media_ids as $previous_media_id )
1016 {
1017 if (
1018 get_post_meta( $previous_media_id, '_imported_url', TRUE ) == $url
1019 )
1020 {
1021 $imported_previously = true;
1022 $imported_previously_id = $previous_media_id;
1023 break;
1024 }
1025 }
1026 }
1027
1028 if ($imported_previously)
1029 {
1030 $media_ids[] = $imported_previously_id;
1031 }
1032 else
1033 {
1034 $tmp = download_url( $url );
1035 $file_array = array(
1036 'name' => basename( $url ),
1037 'tmp_name' => $tmp
1038 );
1039
1040 // Check for download errors
1041 if ( is_wp_error( $tmp ) )
1042 {
1043 // ERROR: $tmp->get_error_message();
1044 }
1045 else
1046 {
1047 $id = media_handle_sideload( $file_array, $object->ID, $description, array('post_title' => $filename) );
1048
1049 // Check for handle sideload errors.
1050 if ( is_wp_error( $id ) )
1051 {
1052 @unlink( $file_array['tmp_name'] );
1053
1054 // ERROR: $id->get_error_message();
1055 }
1056 else
1057 {
1058 $media_ids[] = $id;
1059
1060 update_post_meta( $id, '_imported_url', $url);
1061 }
1062 }
1063 }
1064 }
1065 }
1066 update_post_meta( $object->ID, '_' . $hive_field_name . 's', $media_ids );
1067
1068 // Loop through $previous_media_ids, check each one exists in $media_ids, and if it doesn't then delete
1069 if ( is_array($previous_media_ids) && !empty($previous_media_ids) )
1070 {
1071 foreach ( $previous_media_ids as $previous_media_id )
1072 {
1073 if ( !in_array($previous_media_id, $media_ids) )
1074 {
1075 if ( wp_delete_attachment( $previous_media_id, TRUE ) !== FALSE )
1076 {
1077
1078 }
1079 }
1080 }
1081 }
1082 }
1083 }
1084
1085 break;
1086 }
1087 case "virtual_tours":
1088 {
1089 if ( is_array($value) && !empty($value) )
1090 {
1091 update_post_meta( $object->ID, '_virtual_tours', count($value) );
1092
1093 $i = 0;
1094 foreach ( $value as $virtual_tour )
1095 {
1096 update_post_meta( $object->ID, '_virtual_tour_' . $i, ( isset($virtual_tour['url']) ? $virtual_tour['url'] : '' ) );
1097 update_post_meta( $object->ID, '_virtual_tour_label_' . $i, ( isset($virtual_tour['label']) ? $virtual_tour['label'] : '' ) );
1098
1099 ++$i;
1100 }
1101 }
1102 break;
1103 }
1104 default:
1105 {
1106 update_post_meta( $object->ID, '_' . $field_name, $value );
1107 }
1108 }
1109 }
1110
1111 do_action( 'propertyhive_rest_api_property_field_update_callback', $value, $object, $field_name );
1112 },
1113 'schema' => null,
1114 )
1115 );
1116 }
1117 }
1118
1119 public function rest_prepare_property($response, $post, $request)
1120 {
1121 // Hide/show fields dynamically per item before it's returned
1122
1123 $data = $response->get_data();
1124
1125 // Get the department
1126 $department = $data['department'] ?? get_post_meta($post->ID, '_department', true);
1127 if ( ph_get_custom_department_based_on( $department ) !== false )
1128 {
1129 $department = ph_get_custom_department_based_on( $department );
1130 }
1131
1132 // Define the "not applicable" fields per department
1133 $remove_for = [
1134 'residential-sales' => [
1135 // specify non-sales fields
1136 'available_date', 'deposit', 'furnished', 'rent_frequency',
1137 'commercial_tenure', 'commercial_property_type', 'for_sale', 'to_rent', 'price_from', 'price_to', 'price_units', 'rent_from', 'rent_to', 'rent_units', 'floor_area_from', 'floor_area_to', 'floor_area_units', 'site_area_from', 'site_area_to', 'site_area_units'
1138 ],
1139 'residential-lettings' => [
1140 // specify non-lettings fields
1141 'sale_by', 'tenure',
1142 'commercial_tenure', 'commercial_property_type', 'for_sale', 'to_rent', 'price_from', 'price_to', 'price_units', 'rent_from', 'rent_to', 'rent_units', 'floor_area_from', 'floor_area_to', 'floor_area_units', 'site_area_from', 'site_area_to', 'site_area_units',
1143 ],
1144 'commercial' => [
1145 // specify non-commercial fields
1146 'price', 'price_actual', 'bedrooms', 'bathrooms', 'reception_rooms', 'outside_space', 'parking',
1147 'available_date', 'deposit', 'furnished', 'rent_frequency',
1148 ],
1149 ];
1150
1151 if ( !empty($remove_for[$department]) )
1152 {
1153 foreach ( $remove_for[$department] as $k )
1154 {
1155 unset($data[$k]);
1156 }
1157 }
1158
1159 $response->set_data($data);
1160
1161 return $response;
1162 }
1163
1164 public function register_rest_api_office_fields()
1165 {
1166 $field_array = array(
1167 'primary',
1168 'office_address_1',
1169 'office_address_2',
1170 'office_address_3',
1171 'office_address_4',
1172 'office_address_postcode',
1173 'office_latitude',
1174 'office_longitude',
1175 );
1176
1177 $departments = ph_get_departments();
1178
1179 foreach ( $departments as $key => $value )
1180 {
1181 $field_array[] = 'office_telephone_number_' . str_replace("residential-", "", $key);
1182 $field_array[] = 'office_email_address_' . str_replace("residential-", "", $key);
1183 }
1184
1185 $field_array = apply_filters( 'propertyhive_rest_api_office_fields', $field_array );
1186
1187 foreach ( $field_array as $field )
1188 {
1189 register_rest_field( 'office',
1190 $field,
1191 array(
1192 'get_callback' => function( $object, $field_name, $request )
1193 {
1194 $return = '';
1195
1196 switch ($field_name)
1197 {
1198 default:
1199 {
1200 $return = get_post_meta( $object[ 'id' ], '_' . $field_name, TRUE );
1201 }
1202 }
1203
1204 $return = apply_filters( 'propertyhive_rest_api_office_field_callback', $return, $field_name, $object[ 'id' ] );
1205 return $return;
1206 },
1207 'update_callback' => null,
1208 'schema' => null,
1209 )
1210 );
1211 }
1212 }
1213
1214 }
1215
1216