PluginProbe
Property Hive / trunk
Property Hive vtrunk
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 1.4.63 All 259 releases
propertyhive / includes / class-ph-rest-api.php

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

1,235 lines 38.4 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 "description":
955 {
956 $property = new PH_Property($object->ID);
957
958 if ( isset($property->_department) && $property->_department == 'commercial' )
959 {
960 update_post_meta( $object->ID, '_descriptions', '1' );
961 update_post_meta( $object->ID, '_description_name_0', '' );
962 update_post_meta( $object->ID, '_description_0', $value );
963 }
964 else
965 {
966 update_post_meta( $object->ID, '_rooms', '1' );
967 update_post_meta( $object->ID, '_room_name_0', '' );
968 update_post_meta( $object->ID, '_room_dimensions_0', '' );
969 update_post_meta( $object->ID, '_room_description_0', $value );
970 }
971 break;
972 }
973 case "images":
974 case "floorplans":
975 case "brochures":
976 case "epcs":
977 {
978 if ( !function_exists('media_handle_upload') ) {
979 require_once(ABSPATH . "wp-admin" . '/includes/image.php');
980 require_once(ABSPATH . "wp-admin" . '/includes/file.php');
981 require_once(ABSPATH . "wp-admin" . '/includes/media.php');
982 }
983
984 $hive_field_name = trim($field_name, 's');
985 if ( $hive_field_name == 'image' ) { $hive_field_name = 'photo'; }
986
987 if ( is_array($value) && !empty($value) )
988 {
989 if ( get_option('propertyhive_' . $field_name . '_stored_as', '') == 'urls' )
990 {
991 $media_items = array();
992 foreach ( $value as $media_item )
993 {
994 if (
995 isset($media_item['url']) &&
996 (
997 substr( strtolower($media_item['url']), 0, 2 ) == '//' ||
998 substr( strtolower($media_item['url']), 0, 4 ) == 'http'
999 )
1000 )
1001 {
1002 $media_items[] = array(
1003 'url' => $media_item['url'],
1004 );
1005 }
1006 }
1007 update_post_meta( $object->ID, '_' . $hive_field_name . '_urls', $media_items );
1008 }
1009 else
1010 {
1011 $media_ids = array();
1012 $previous_media_ids = get_post_meta( $object->ID, '_' . $hive_field_name . 's', TRUE );
1013 foreach ( $value as $media_item )
1014 {
1015 if (
1016 isset($media_item['url']) &&
1017 (
1018 substr( strtolower($media_item['url']), 0, 2 ) == '//' ||
1019 substr( strtolower($media_item['url']), 0, 4 ) == 'http'
1020 )
1021 )
1022 {
1023 // This is a URL
1024 $url = $media_item['url'];
1025 $description = '';
1026
1027 $filename = basename( $url );
1028
1029 // Check, based on the URL, whether we have previously imported this media
1030 $imported_previously = false;
1031 $imported_previously_id = '';
1032 if ( is_array($previous_media_ids) && !empty($previous_media_ids) )
1033 {
1034 foreach ( $previous_media_ids as $previous_media_id )
1035 {
1036 if (
1037 get_post_meta( $previous_media_id, '_imported_url', TRUE ) == $url
1038 )
1039 {
1040 $imported_previously = true;
1041 $imported_previously_id = $previous_media_id;
1042 break;
1043 }
1044 }
1045 }
1046
1047 if ($imported_previously)
1048 {
1049 $media_ids[] = $imported_previously_id;
1050 }
1051 else
1052 {
1053 $tmp = download_url( $url );
1054 $file_array = array(
1055 'name' => basename( $url ),
1056 'tmp_name' => $tmp
1057 );
1058
1059 // Check for download errors
1060 if ( is_wp_error( $tmp ) )
1061 {
1062 // ERROR: $tmp->get_error_message();
1063 }
1064 else
1065 {
1066 $id = media_handle_sideload( $file_array, $object->ID, $description, array('post_title' => $filename) );
1067
1068 // Check for handle sideload errors.
1069 if ( is_wp_error( $id ) )
1070 {
1071 @unlink( $file_array['tmp_name'] );
1072
1073 // ERROR: $id->get_error_message();
1074 }
1075 else
1076 {
1077 $media_ids[] = $id;
1078
1079 update_post_meta( $id, '_imported_url', $url);
1080 }
1081 }
1082 }
1083 }
1084 }
1085 update_post_meta( $object->ID, '_' . $hive_field_name . 's', $media_ids );
1086
1087 // Loop through $previous_media_ids, check each one exists in $media_ids, and if it doesn't then delete
1088 if ( is_array($previous_media_ids) && !empty($previous_media_ids) )
1089 {
1090 foreach ( $previous_media_ids as $previous_media_id )
1091 {
1092 if ( !in_array($previous_media_id, $media_ids) )
1093 {
1094 if ( wp_delete_attachment( $previous_media_id, TRUE ) !== FALSE )
1095 {
1096
1097 }
1098 }
1099 }
1100 }
1101 }
1102 }
1103
1104 break;
1105 }
1106 case "virtual_tours":
1107 {
1108 if ( is_array($value) && !empty($value) )
1109 {
1110 update_post_meta( $object->ID, '_virtual_tours', count($value) );
1111
1112 $i = 0;
1113 foreach ( $value as $virtual_tour )
1114 {
1115 update_post_meta( $object->ID, '_virtual_tour_' . $i, ( isset($virtual_tour['url']) ? $virtual_tour['url'] : '' ) );
1116 update_post_meta( $object->ID, '_virtual_tour_label_' . $i, ( isset($virtual_tour['label']) ? $virtual_tour['label'] : '' ) );
1117
1118 ++$i;
1119 }
1120 }
1121 break;
1122 }
1123 default:
1124 {
1125 update_post_meta( $object->ID, '_' . $field_name, $value );
1126 }
1127 }
1128 }
1129
1130 do_action( 'propertyhive_rest_api_property_field_update_callback', $value, $object, $field_name );
1131 },
1132 'schema' => null,
1133 )
1134 );
1135 }
1136 }
1137
1138 public function rest_prepare_property($response, $post, $request)
1139 {
1140 // Hide/show fields dynamically per item before it's returned
1141
1142 $data = $response->get_data();
1143
1144 // Get the department
1145 $department = $data['department'] ?? get_post_meta($post->ID, '_department', true);
1146 if ( ph_get_custom_department_based_on( $department ) !== false )
1147 {
1148 $department = ph_get_custom_department_based_on( $department );
1149 }
1150
1151 // Define the "not applicable" fields per department
1152 $remove_for = [
1153 'residential-sales' => [
1154 // specify non-sales fields
1155 'available_date', 'deposit', 'furnished', 'rent_frequency',
1156 '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'
1157 ],
1158 'residential-lettings' => [
1159 // specify non-lettings fields
1160 'sale_by', 'tenure',
1161 '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',
1162 ],
1163 'commercial' => [
1164 // specify non-commercial fields
1165 'price', 'price_actual', 'bedrooms', 'bathrooms', 'reception_rooms', 'outside_space', 'parking',
1166 'available_date', 'deposit', 'furnished', 'rent_frequency',
1167 ],
1168 ];
1169
1170 if ( !empty($remove_for[$department]) )
1171 {
1172 foreach ( $remove_for[$department] as $k )
1173 {
1174 unset($data[$k]);
1175 }
1176 }
1177
1178 $response->set_data($data);
1179
1180 return $response;
1181 }
1182
1183 public function register_rest_api_office_fields()
1184 {
1185 $field_array = array(
1186 'primary',
1187 'office_address_1',
1188 'office_address_2',
1189 'office_address_3',
1190 'office_address_4',
1191 'office_address_postcode',
1192 'office_latitude',
1193 'office_longitude',
1194 );
1195
1196 $departments = ph_get_departments();
1197
1198 foreach ( $departments as $key => $value )
1199 {
1200 $field_array[] = 'office_telephone_number_' . str_replace("residential-", "", $key);
1201 $field_array[] = 'office_email_address_' . str_replace("residential-", "", $key);
1202 }
1203
1204 $field_array = apply_filters( 'propertyhive_rest_api_office_fields', $field_array );
1205
1206 foreach ( $field_array as $field )
1207 {
1208 register_rest_field( 'office',
1209 $field,
1210 array(
1211 'get_callback' => function( $object, $field_name, $request )
1212 {
1213 $return = '';
1214
1215 switch ($field_name)
1216 {
1217 default:
1218 {
1219 $return = get_post_meta( $object[ 'id' ], '_' . $field_name, TRUE );
1220 }
1221 }
1222
1223 $return = apply_filters( 'propertyhive_rest_api_office_field_callback', $return, $field_name, $object[ 'id' ] );
1224 return $return;
1225 },
1226 'update_callback' => null,
1227 'schema' => null,
1228 )
1229 );
1230 }
1231 }
1232
1233 }
1234
1235