PluginProbe
Property Hive / 1.4.6
Property Hive v1.4.6
2.3.1 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 All 261 releases
propertyhive / includes / class-ph-ajax.php

class-ph-ajax.php in Property Hive 1.4.6, at includes/class-ph-ajax.php

3,773 lines 133.3 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' ) ) exit; // Exit if accessed directly
4
5 /**
6 * PropertyHive PH_AJAX
7 *
8 * AJAX Event Handler
9 *
10 * @class PH_AJAX
11 * @version 1.0.0
12 * @package PropertyHive/Classes
13 * @category Class
14 * @author PropertyHive
15 */
16 class PH_AJAX {
17
18 /**
19 * Hook into ajax events
20 */
21 public function __construct() {
22
23 // propertyhive_EVENT => nopriv
24 $ajax_events = array(
25 'add_note' => false,
26 'delete_note' => false,
27 'search_contacts' => false,
28 'search_properties' => false,
29 'search_negotiators' => false,
30 'load_existing_owner_contact' => false,
31 'load_existing_features' => false,
32 'make_property_enquiry' => true,
33 'create_contact_from_enquiry' => false,
34
35 // Dashboard components
36 'get_news' => false,
37 'get_viewings_awaiting_applicant_feedback' => false,
38
39 // Contact actions
40 'create_contact_login' => false,
41
42 // Viewing actions
43 'book_viewing_property' => false,
44 'book_viewing_contact' => false,
45 'get_viewing_details_meta_box' => false,
46 'get_viewing_actions' => false,
47 'viewing_carried_out' => false,
48 'viewing_cancelled' => false,
49 'viewing_interested_feedback' => false,
50 'viewing_not_interested_feedback' => false,
51 'viewing_feedback_not_required' => false,
52 'viewing_revert_feedback_pending' => false,
53 'viewing_revert_pending' => false,
54 'viewing_feedback_passed_on' => false,
55 'get_property_viewings_meta_box' => false,
56 'get_contact_viewings_meta_box' => false,
57
58 // Offer actions
59 'record_offer_property' => false,
60 'record_offer_contact' => false,
61 'get_offer_details_meta_box' => false,
62 'get_offer_actions' => false,
63 'get_property_offers_meta_box' => false,
64 'offer_accepted' => false,
65 'offer_declined' => false,
66 'offer_revert_pending' => false,
67 'get_contact_offers_meta_box' => false,
68
69 // Sale actions
70 'get_sale_details_meta_box' => false,
71 'get_sale_actions' => false,
72 'get_sale_details_meta_box' => false,
73 'sale_exchanged' => false,
74 'sale_completed' => false,
75 'sale_fallen_through' => false,
76 'offer_declined' => false,
77 'get_property_sales_meta_box' => false,
78 'get_contact_sales_meta_box' => false,
79
80 'validate_save_contact' => false,
81 'applicant_registration' => true,
82 'login' => true,
83 'save_account_details' => true,
84 'save_account_requirements' => true,
85 );
86
87 foreach ( $ajax_events as $ajax_event => $nopriv ) {
88 add_action( 'wp_ajax_propertyhive_' . $ajax_event, array( $this, $ajax_event ) );
89
90 if ( $nopriv ) {
91 add_action( 'wp_ajax_nopriv_propertyhive_' . $ajax_event, array( $this, $ajax_event ) );
92 }
93 }
94 }
95
96 /**
97 * Output headers for JSON requests
98 */
99 private function json_headers() {
100 header( 'Content-Type: application/json; charset=utf-8' );
101 }
102
103 public function create_contact_login()
104 {
105 check_ajax_referer( 'create-login', 'security' );
106
107 $this->json_headers();
108
109 if (empty($_POST['contact_id']))
110 {
111 $return = array('error' => 'No contact selected');
112 echo json_encode( $return );
113 die();
114 }
115
116 if (empty($_POST['password']))
117 {
118 $return = array('error' => 'No password entered');
119 echo json_encode( $return );
120 die();
121 }
122
123 $contact = new PH_Contact((int)$_POST['contact_id']);
124
125 // Create user
126 $userdata = array(
127 'display_name' => get_the_title($_POST['contact_id']),
128 'user_login' => sanitize_email($contact->email_address),
129 'user_email' => sanitize_email($contact->email_address),
130 'user_pass' => $_POST['password'],
131 'role' => 'property_hive_contact',
132 'show_admin_bar_front' => 'false',
133 );
134
135 $user_id = wp_insert_user( $userdata );
136
137 // On success
138 if ( ! is_wp_error( $user_id ) )
139 {
140 // Assign user ID to CPT
141 add_post_meta( $_POST['contact_id'], '_user_id', $user_id );
142
143 $return = array('success' => true);
144 }
145 else
146 {
147 $return = array('error' => 'Failed to create user login');
148 }
149
150 echo json_encode( $return );
151 die();
152 }
153
154 /**
155 * Login user
156 */
157 public function login()
158 {
159 $return = array(
160 'success' => false,
161 'errors' => array(),
162 );
163
164 if ( check_ajax_referer( 'ph_login', 'security', false ) === FALSE )
165 {
166 $return['errors'][] = 'Invalid nonce';
167
168 $this->json_headers();
169 echo json_encode( $return );
170
171 // Quit out
172 die();
173 }
174
175 $creds = array(
176 'user_login' => $_POST['email_address'],
177 'user_password' => $_POST['password'],
178 );
179
180 $user = wp_signon( apply_filters( 'propertyhive_login_credentials', $creds ), is_ssl() );
181
182 if ( is_wp_error( $user ) )
183 {
184 //$return['errors'][] = $user->get_error_message();
185 }
186 else
187 {
188 // Check has associated contact CPT and is published
189 $args = array(
190 'post_type' => 'contact',
191 'fields' => 'ids',
192 'posts_per_page' => 1,
193 'post_status' => array( 'publish' ),
194 'meta_query' => array(
195 array(
196 'key' => '_user_id',
197 'value' => $user->ID
198 )
199 )
200 );
201
202 $contact_query = new WP_Query( $args );
203
204 if ( $contact_query->have_posts() )
205 {
206 // Has associated published contact CPT
207 $return['success'] = true;
208 }
209
210 wp_reset_postdata();
211 }
212
213 $this->json_headers();
214 echo json_encode( $return );
215
216 // Quit out
217 die();
218 }
219
220 /**
221 * Register applicant
222 */
223 public function applicant_registration()
224 {
225 // Validate contact
226 global $post;
227
228 $return = array(
229 'success' => false,
230 'errors' => array(),
231 );
232
233 if ( check_ajax_referer( 'ph_register', 'security', false ) === FALSE )
234 {
235 $return['errors'][] = 'Invalid nonce';
236
237 $this->json_headers();
238 echo json_encode( $return );
239
240 // Quit out
241 die();
242 }
243
244 // Validate
245 $errors = array();
246
247 $form_controls = ph_get_user_details_form_fields();
248
249 $form_controls = apply_filters( 'propertyhive_user_details_form_fields', $form_controls );
250
251 $form_controls_2 = ph_get_applicant_requirements_form_fields();
252
253 $form_controls_2 = apply_filters( 'propertyhive_applicant_requirements_form_fields', $form_controls_2 );
254
255 $form_controls = array_merge( $form_controls, $form_controls_2 );
256
257 foreach ( $form_controls as $key => $control )
258 {
259 if ( isset( $control ) && isset( $control['required'] ) && $control['required'] === TRUE )
260 {
261 // This field is mandatory. Lets check we received it in the post
262 if ( ! isset( $_POST[$key] ) || ( isset( $_POST[$key] ) && empty( $_POST[$key] ) ) )
263 {
264 $errors[] = __( 'Missing required field', 'propertyhive' ) . ': ' . $key;
265 }
266 }
267 if ( isset( $control['type'] ) && $control['type'] == 'email' && isset( $_POST[$key] ) && ! empty( $_POST[$key] ) )
268 {
269 if ( ! is_email( $_POST[$key] ) )
270 {
271 $errors[] = __( 'Invalid email address provided', 'propertyhive' );
272 }
273 else
274 {
275 // Make sure this email address doesn't exist already
276 $args = array(
277 'post_type' => 'contact',
278 'posts_per_page' => 1,
279 'fields' => 'ids',
280 'post_status' => array( 'publish' ),
281 'meta_query' => array(
282 array(
283 'key' => '_email_address',
284 'value' => $_POST[$key]
285 )
286 )
287 );
288
289 $contacts_query = new WP_Query( $args );
290
291 if ( $contacts_query->have_posts() )
292 {
293 $errors[] = __( 'This email address is already registered', 'propertyhive' );
294 }
295 else
296 {
297 if ( email_exists( $_POST[$key] ) )
298 {
299 $errors[] = __( 'This email address is already registered to a user', 'propertyhive' );
300 }
301 }
302 wp_reset_postdata();
303 }
304 }
305 }
306
307 // Check password and password2 match
308 if ( isset( $_POST['password'] ) && isset( $_POST['password2'] ) && $_POST['password'] != $_POST['password2'] )
309 {
310 $errors[] = __( 'The passwords entered do not match', 'propertyhive' );
311 }
312
313 if ( !empty($errors) )
314 {
315 // Failed validation
316
317 $return['success'] = false;
318 $return['reason'] = 'validation';
319 $return['errors'] = $errors;
320 }
321 else
322 {
323 // create CPT
324 $contact_post = array(
325 'post_title' => $_POST['name'],
326 'post_content' => '',
327 'post_type' => 'contact',
328 'post_status' => 'publish',
329 'comment_status'=> 'closed',
330 'ping_status' => 'closed',
331 );
332
333 // Insert the post into the database
334 $contact_post_id = wp_insert_post( $contact_post );
335
336 // Add post meta (contact details, requirements etc)
337 add_post_meta( $contact_post_id, '_email_address', sanitize_email($_POST['email_address']) );
338 add_post_meta( $contact_post_id, '_telephone_number', ( ( isset($_POST['telephone_number']) ) ? $_POST['telephone_number'] : '' ) );
339
340 add_post_meta( $contact_post_id, '_contact_types', array('applicant') );
341
342 add_post_meta( $contact_post_id, '_applicant_profiles', 1 );
343
344 $applicant_profile = array();
345 $applicant_profile['department'] = $_POST['department'];
346
347 if ( $_POST['department'] == 'residential-sales' )
348 {
349 $price = preg_replace("/[^0-9]/", '', $_POST['maximum_price']);
350
351 $applicant_profile['max_price'] = $price;
352
353 // Not used yet but could be if introducing currencies in the future.
354 $applicant_profile['max_price_actual'] = $price;
355 }
356 elseif ( $_POST['department'] == 'residential-lettings' )
357 {
358 $price = preg_replace("/[^0-9]/", '', $_POST['maximum_rent']);
359
360 $applicant_profile['max_rent'] = $price;
361 $applicant_profile['rent_frequency'] = 'pcm';
362 $price_actual = $price; // Stored in pcm
363 $applicant_profile['max_price_actual'] = $price_actual;
364 }
365
366 if ( $_POST['department'] == 'residential-sales' || $_POST['department'] == 'residential-lettings' )
367 {
368 $beds = preg_replace("/[^0-9]/", '', $_POST['minimum_bedrooms']);
369 $applicant_profile['min_beds'] = $beds;
370
371 if ( isset($_POST['property_type']) && !empty($_POST['property_type']) )
372 {
373 $applicant_profile['property_types'] = array($_POST['property_type']);
374 }
375 }
376
377 if ( isset($_POST['location']) && !empty($_POST['location']) )
378 {
379 $applicant_profile['locations'] = array($_POST['location']);
380 }
381
382 $applicant_profile['notes'] = ( ( isset($_POST['additional_requirements']) ) ? $_POST['additional_requirements'] : '' );
383
384 $applicant_profile['send_matching_properties'] = 'yes';
385 //$applicant_profile['auto_match_disabled'] = ''; // don't know what to do about this yet. Should probably look at global setting and reflect that
386
387 update_post_meta( $contact_post_id, '_applicant_profile_0', $applicant_profile );
388
389 // Create user
390 $userdata = array(
391 'display_name' => $_POST['name'],
392 'user_login' => sanitize_email($_POST['email_address']),
393 'user_email' => sanitize_email($_POST['email_address']),
394 'user_pass' => $_POST['password'],
395 'role' => 'property_hive_contact',
396 'show_admin_bar_front' => 'false',
397 );
398
399 $user_id = wp_insert_user( $userdata );
400
401 //On success
402 if ( ! is_wp_error( $user_id ) )
403 {
404 // Assign user ID to CPT
405 add_post_meta( $contact_post_id, '_user_id', $user_id );
406
407 $return['success'] = true;
408
409 wp_set_auth_cookie( $user_id, true );
410
411 do_action( 'propertyhive_applicant_registered', $contact_post_id, $user_id );
412 }
413 else
414 {
415 $return['success'] = false;
416 $return['reason'] = 'validation';
417 $return['errors'] = array('Failed to create user. You might experience issues with logging in');
418 }
419 }
420
421 $this->json_headers();
422 echo json_encode( $return );
423
424 // Quit out
425 die();
426 }
427
428 /**
429 * Save account details
430 */
431 public function save_account_details()
432 {
433 global $wpdb, $current_user;
434
435 add_filter( 'send_email_change_email', '__return_false' );
436
437 $return = array(
438 'success' => false,
439 'errors' => array(),
440 );
441
442 // Got an issue with nonce being declined on second submission.
443 // Need to sort before putting this back in
444 /*if ( check_ajax_referer( 'ph_details', 'security', false ) === FALSE )
445 {
446 $return['errors'][] = 'Invalid nonce';
447
448 $this->json_headers();
449 echo json_encode( $return );
450
451 // Quit out
452 die();
453 }*/
454
455 // Validate
456 $errors = array();
457
458 $user_id = (int) get_current_user_id();
459 $current_user = get_user_by( 'id', $user_id );
460 if ( $user_id <= 0 )
461 {
462 $return['success'] = false;
463 $return['reason'] = 'notloggedin';
464 $return['errors'] = array('It doesn\'t appear that you\'re logged in');
465
466 $this->json_headers();
467 echo json_encode( $return );
468
469 // Quit out
470 die();
471 }
472
473 $form_controls = ph_get_user_details_form_fields();
474
475 $form_controls = apply_filters( 'propertyhive_user_details_form_fields', $form_controls );
476
477 foreach ( $form_controls as $key => $control )
478 {
479 if ( isset( $control ) && isset( $control['required'] ) && $control['required'] === TRUE )
480 {
481 // This field is mandatory. Lets check we received it in the post
482 if ( ! isset( $_POST[$key] ) || ( isset( $_POST[$key] ) && empty( $_POST[$key] ) ) && $control['type'] != 'password' )
483 {
484 $errors[] = __( 'Missing required field', 'propertyhive' ) . ': ' . $key;
485 }
486 }
487 if ( isset( $control['type'] ) && $control['type'] == 'email' && isset( $_POST[$key] ) && ! empty( $_POST[$key] ) )
488 {
489 if ( ! is_email( $_POST[$key] ) )
490 {
491 $errors[] = __( 'Invalid email address provided', 'propertyhive' );
492 }
493
494 // need to see if email address is being changed and, if so, check new email address doesn't exist already
495 }
496 }
497
498 // Check password and password2 match
499 if ( isset( $_POST['password'] ) && isset( $_POST['password2'] ) && !empty( $_POST['password'] ) && $_POST['password'] != $_POST['password2'] )
500 {
501 $errors[] = __( 'The passwords entered do not match', 'propertyhive' );
502 }
503
504 if ( !empty($errors) )
505 {
506 // Failed validation
507
508 $return['success'] = false;
509 $return['reason'] = 'validation';
510 $return['errors'] = $errors;
511 }
512 else
513 {
514 $contact = new PH_Contact( '', $user_id );
515
516 // create CPT
517 $contact_post = array(
518 'ID' => $contact->id,
519 'post_title' => $_POST['name'],
520 );
521
522 // Update the post in the database
523 $contact_post_id = wp_update_post( $contact_post );
524
525 update_post_meta( $contact_post_id, '_email_address', sanitize_email($_POST['email_address']) );
526 if (isset($_POST['telephone_number']))
527 {
528 update_post_meta( $contact_post_id, '_telephone_number', $_POST['telephone_number'] );
529 }
530
531 // Update user
532 $userdata = array(
533 'ID' => $user_id,
534 'display_name' => $_POST['name'],
535 'user_email' => sanitize_email($_POST['email_address']),
536 );
537
538 if ( isset($_POST['password']) && !empty($_POST['password']) )
539 {
540 $userdata['user_pass'] = $_POST['password'];
541 }
542
543 $user_id = wp_update_user( $userdata );
544
545 $user_roles = $current_user->roles;
546 $user_role = array_shift($user_roles);
547
548 if ( $user_role === 'property_hive_contact' )
549 {
550 // Have to update login via SQL as wp_update_user won't allow altering
551 // Only do it for property hive contacts though as admin or editor might be viewing this page
552 $wpdb->update($wpdb->users, array('user_login' => sanitize_email($_POST['email_address'])), array('ID' => $user_id));
553 }
554
555 //On success
556 if ( ! is_wp_error( $user_id ) )
557 {
558 $return['success'] = true;
559
560 wp_set_auth_cookie( $user_id, true );
561
562 do_action( 'propertyhive_account_details_updated', $contact_post_id, $user_id );
563 }
564 else
565 {
566 $return['success'] = false;
567 $return['reason'] = 'validation';
568 $return['errors'] = array('Failed to update user. Please try again');
569 }
570 }
571
572 $this->json_headers();
573 echo json_encode( $return );
574
575 // Quit out
576 die();
577 }
578
579 /**
580 * Save account requirements
581 */
582 public function save_account_requirements()
583 {
584 // Validate contact
585 global $post;
586
587 $return = array(
588 'success' => false,
589 'errors' => array(),
590 );
591
592 // Got an issue with nonce being declined on second submission.
593 // Need to sort before putting this back in
594 /*if ( check_ajax_referer( 'ph_requirements', 'security', false ) === FALSE )
595 {
596 $return['errors'][] = 'Invalid nonce';
597
598 $this->json_headers();
599 echo json_encode( $return );
600
601 // Quit out
602 die();
603 }*/
604
605 // Validate
606 $errors = array();
607
608 $user_id = (int) get_current_user_id();
609 $current_user = get_user_by( 'id', $user_id );
610 if ( $user_id <= 0 )
611 {
612 $return['success'] = false;
613 $return['reason'] = 'notloggedin';
614 $return['errors'] = array('It doesn\'t appear that you\'re logged in');
615
616 $this->json_headers();
617 echo json_encode( $return );
618
619 // Quit out
620 die();
621 }
622
623 $form_controls = ph_get_applicant_requirements_form_fields();
624
625 $form_controls = apply_filters( 'propertyhive_applicant_requirements_form_fields', $form_controls );
626
627 foreach ( $form_controls as $key => $control )
628 {
629 if ( isset( $control ) && isset( $control['required'] ) && $control['required'] === TRUE )
630 {
631 // This field is mandatory. Lets check we received it in the post
632 if ( ! isset( $_POST[$key] ) || ( isset( $_POST[$key] ) && empty( $_POST[$key] ) ) )
633 {
634 $errors[] = __( 'Missing required field', 'propertyhive' ) . ': ' . $key;
635 }
636 }
637 }
638
639 if ( !empty($errors) )
640 {
641 // Failed validation
642
643 $return['success'] = false;
644 $return['reason'] = 'validation';
645 $return['errors'] = $errors;
646 }
647 else
648 {
649 $contact = new PH_Contact( '', $user_id );
650
651 $contact_post_id = $contact->id;
652
653 $applicant_profile = array();
654 $applicant_profile['department'] = $_POST['department'];
655
656 if ( $_POST['department'] == 'residential-sales' )
657 {
658 $price = preg_replace("/[^0-9]/", '', $_POST['maximum_price']);
659
660 $applicant_profile['max_price'] = $price;
661
662 // Not used yet but could be if introducing currencies in the future.
663 $applicant_profile['max_price_actual'] = $price;
664 }
665 elseif ( $_POST['department'] == 'residential-lettings' )
666 {
667 $price = preg_replace("/[^0-9]/", '', $_POST['maximum_rent']);
668
669 $applicant_profile['max_rent'] = $price;
670 $applicant_profile['rent_frequency'] = 'pcm';
671 $price_actual = $price; // Stored in pcm
672 $applicant_profile['max_price_actual'] = $price_actual;
673 }
674
675 if ( $_POST['department'] == 'residential-sales' || $_POST['department'] == 'residential-lettings' )
676 {
677 $beds = preg_replace("/[^0-9]/", '', $_POST['minimum_bedrooms']);
678 $applicant_profile['min_beds'] = $beds;
679
680 if ( isset($_POST['property_type']) && !empty($_POST['property_type']) )
681 {
682 $applicant_profile['property_types'] = array($_POST['property_type']);
683 }
684 }
685
686 if ( isset($_POST['location']) && !empty($_POST['location']) )
687 {
688 $applicant_profile['locations'] = array($_POST['location']);
689 }
690
691 $applicant_profile['notes'] = ( ( isset($_POST['additional_requirements']) ) ? $_POST['additional_requirements'] : '' );
692
693 $applicant_profile['send_matching_properties'] = 'yes';
694 //$applicant_profile['auto_match_disabled'] = ''; // don't know what to do about this yet. Should probably look at global setting and reflect that
695
696 update_post_meta( $contact_post_id, '_applicant_profile_0', $applicant_profile );
697
698 $return['success'] = true;
699
700 do_action( 'propertyhive_account_requirements_updated', $contact_post_id, $user_id );
701 }
702
703 $this->json_headers();
704 echo json_encode( $return );
705
706 // Quit out
707 die();
708 }
709
710 /**
711 * Load existing features
712 */
713 public function load_existing_features() {
714
715 global $post, $wpdb;
716
717 $this->json_headers();
718
719 $return = array();
720
721 $property_query = new WP_Query(array(
722 'post_type' => 'property',
723 'post_status' => 'any',
724 'nopaging' => true
725 ));
726
727 if ($property_query->have_posts())
728 {
729 while ($property_query->have_posts())
730 {
731 $property_query->the_post();
732
733 $num_property_features = get_post_meta($post->ID, '_features', TRUE);
734 if ($num_property_features == '') { $num_property_features = 0; }
735
736 for ($i = 0; $i < $num_property_features; ++$i)
737 {
738 $feature = get_post_meta($post->ID, '_feature_' . $i, TRUE);
739 if (!in_array($feature, $return) && trim($feature) != '')
740 {
741 $return[] = $feature;
742 }
743 }
744 }
745 }
746
747 echo json_encode($return);
748
749 // Quit out
750 die();
751 }
752
753 /**
754 * Load existing owner on property record
755 */
756 public function load_existing_owner_contact() {
757
758 check_ajax_referer( 'load-existing-owner-contact', 'security' );
759
760 $contact_id = $_POST['contact_id'];
761
762 $contact = get_post($contact_id);
763
764 echo '<div id="existing-owner-details-' . $contact_id . '">';
765
766 if ( !is_null( $contact ) )
767 {
768 echo '<p class="form-field">';
769 echo '<label>' . __('Name', 'propertyhive') . '</label>';
770 echo '<a href="' . get_edit_post_link( $contact_id ) . '">' . get_the_title($contact_id) . '</a>';
771 echo '</p>';
772
773 $address = array();
774 $address_elements = array( '_address_name_number', '_address_street', '_address_two', '_address_three', '_address_four', '_address_postcode' );
775 foreach ( $address_elements as $address_element )
776 {
777 if ( get_post_meta($contact_id, $address_element, TRUE) != '' )
778 {
779 $address[] = get_post_meta($contact_id, $address_element, TRUE);
780 }
781 }
782
783 echo '<p class="form-field">';
784 echo '<label>' . __('Address', 'propertyhive') . '</label>';
785 echo ( ( !empty($address) ) ? implode(", ", $address) : '-' );
786 echo '</p>';
787
788 echo '<p class="form-field">';
789 echo '<label>' . __('Telephone Number', 'propertyhive') . '</label>';
790 echo ( ( get_post_meta($contact_id, '_telephone_number', TRUE) != '' ) ? get_post_meta($contact_id, '_telephone_number', TRUE) : '-' );
791 echo '</p>';
792
793 echo '<p class="form-field">';
794 echo '<label>' . __('Email Address', 'propertyhive') . '</label>';
795 echo ( ( get_post_meta($contact_id, '_email_address', TRUE) != '' ) ? get_post_meta($contact_id, '_email_address', TRUE) : '-' );
796 echo '</p>';
797 }
798 else
799 {
800 echo __( 'Invalid contact record', 'propertyhive' );
801 }
802
803 echo '<p class="form-field">';
804 echo '<label></label>';
805 echo '<a href="" class="button" id="remove-owner-contact-' . $contact_id . '">Remove Owner</a> ';
806 echo '<a href="" class="button add-additional-owner-contact">Add Additional Owner</a>';
807 echo '</p>';
808
809 echo '</div>';
810
811 // Quit out
812 die();
813
814 }
815
816 /**
817 * Search contacts via ajax
818 */
819 public function search_contacts() {
820
821 global $post;
822
823 check_ajax_referer( 'search-contacts', 'security' );
824
825 $return = array();
826
827 $keyword = trim( $_POST['keyword'] );
828
829 if ( !empty( $keyword ) && strlen( $keyword ) > 2 )
830 {
831 // Get all contacts that match the name
832 $args = array(
833 'post_type' => 'contact',
834 'nopaging' => true,
835 'post_status' => array( 'publish' ),
836 'fields' => 'ids'
837 );
838 if ( isset($_POST['contact_type']) && $_POST['contact_type'] != '' )
839 {
840 $args['meta_query'] = array(
841 array(
842 'key' => '_contact_types',
843 'value' => $_POST['contact_type'],
844 'compare' => 'LIKE',
845 )
846 );
847 }
848
849 add_filter( 'posts_where', array( $this, 'search_contacts_where' ), 10, 2 );
850
851 $contact_query = new WP_Query( $args );
852
853 remove_filter( 'posts_where', array( $this, 'search_contacts_where' ) );
854
855 if ( $contact_query->have_posts() )
856 {
857 while ( $contact_query->have_posts() )
858 {
859 $contact_query->the_post();
860
861 $return[] = array(
862 'ID' => get_the_ID(),
863 'post_title' => get_the_title(get_the_ID())
864 );
865 }
866 }
867
868 wp_reset_postdata();
869 }
870
871 $this->json_headers();
872 echo json_encode( $return );
873
874 // Quit out
875 die();
876 }
877
878 public function search_contacts_where( $where, &$wp_query )
879 {
880 global $wpdb;
881
882 $where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . esc_sql( like_escape( trim( $_POST['keyword'] ) ) ) . '%\'';
883
884 return $where;
885 }
886
887 /**
888 * Search propertie via ajax
889 */
890 public function search_properties() {
891
892 global $post;
893
894 check_ajax_referer( 'search-properties', 'security' );
895
896 $return = array();
897
898 $keyword = trim( $_POST['keyword'] );
899
900 if ( !empty( $keyword ) && strlen( $keyword ) > 2 )
901 {
902 // Get all contacts that match the name
903 $args = array(
904 'post_type' => 'property',
905 'nopaging' => true,
906 'post_status' => array( 'publish' ),
907 'fields' => 'ids'
908 );
909
910 $meta_query = array();
911 if ( isset($_POST['department']) && $_POST['department'] != '' )
912 {
913 $meta_query[] = array(
914 'key' => '_department',
915 'value' => $_POST['department'],
916 );
917 }
918 if ( !empty($meta_query) )
919 {
920 $args['meta_query'] = $meta_query;
921 }
922
923 add_filter( 'posts_join', array( $this, 'search_properties_join' ), 10, 2 );
924 add_filter( 'posts_where', array( $this, 'search_properties_where' ), 10, 2 );
925
926 $property_query = new WP_Query( $args );
927
928 remove_filter( 'posts_join', array( $this, 'search_properties_join' ) );
929 remove_filter( 'posts_where', array( $this, 'search_properties_where' ) );
930
931 if ( $property_query->have_posts() )
932 {
933 while ( $property_query->have_posts() )
934 {
935 $property_query->the_post();
936
937 $property = new PH_Property(get_the_ID());
938
939 $return[] = array(
940 'ID' => get_the_ID(),
941 'post_title' => $property->get_formatted_full_address(),
942 );
943 }
944 }
945
946 wp_reset_postdata();
947 }
948
949 $this->json_headers();
950 echo json_encode( $return );
951
952 // Quit out
953 die();
954 }
955
956 public function search_properties_join( $joins )
957 {
958 global $wpdb;
959
960 $joins .= " INNER JOIN {$wpdb->postmeta} AS mt1 ON {$wpdb->posts}.ID = mt1.post_id ";
961
962 return $joins;
963 }
964
965 public function search_properties_where( $where )
966 {
967 $where .= " AND (
968 (mt1.meta_key='_address_name_number' AND mt1.meta_value LIKE '" . esc_sql($_POST['keyword']). "%')
969 OR
970 (mt1.meta_key='_address_street' AND mt1.meta_value LIKE '" . esc_sql($_POST['keyword']). "%')
971 OR
972 (mt1.meta_key='_address_2' AND mt1.meta_value LIKE '" . esc_sql($_POST['keyword']). "%')
973 OR
974 (mt1.meta_key='_address_3' AND mt1.meta_value LIKE '" . esc_sql($_POST['keyword']). "%')
975 OR
976 (mt1.meta_key='_address_4' AND mt1.meta_value LIKE '" . esc_sql($_POST['keyword']). "%')
977 OR
978 (mt1.meta_key='_address_postcode' AND mt1.meta_value LIKE '" . esc_sql($_POST['keyword']). "%')
979 OR
980 (mt1.meta_key='_reference_number' AND mt1.meta_value = '" . esc_sql($_POST['keyword']). "')
981 ) ";
982
983 return $where;
984 }
985
986 /**
987 * Search users/negotiators via ajax
988 */
989 public function search_negotiators() {
990
991 global $post;
992
993 check_ajax_referer( 'search-negotiators', 'security' );
994
995 $return = array();
996
997 $keyword = trim( $_POST['keyword'] );
998
999 if ( !empty( $keyword ) && strlen( $keyword ) > 2 )
1000 {
1001 // Get all contacts that match the name
1002 $args = array(
1003 'number' => 9999,
1004 'search' => $keyword . '*',
1005 'orderby' => 'display_name'
1006 );
1007
1008 $user_query = new WP_User_Query( $args );
1009
1010 // Get the results
1011 $users = $user_query->get_results();
1012
1013 if ( !empty($users) )
1014 {
1015 foreach ($users as $user)
1016 {
1017 $user_data = get_userdata($user->ID);
1018
1019 $return[] = array(
1020 'ID' => $user->ID,
1021 'post_title' => $user_data->display_name
1022 );
1023 }
1024 }
1025 }
1026
1027 $this->json_headers();
1028 echo json_encode( $return );
1029
1030 // Quit out
1031 die();
1032 }
1033
1034 /**
1035 * Add note via ajax
1036 */
1037 public function add_note() {
1038
1039 check_ajax_referer( 'add-note', 'security' );
1040
1041 $post_id = (int) $_POST['post_id'];
1042
1043 if ( $post_id > 0 ) {
1044
1045 $current_user = wp_get_current_user();
1046
1047 $note = wp_kses_post( trim( stripslashes( $_POST['note'] ) ) );
1048
1049 // Add note/comment to property
1050 $comment = array(
1051 'note_type' => 'note',
1052 'note' => $note
1053 );
1054
1055 $data = array(
1056 'comment_post_ID' => $post_id,
1057 'comment_author' => $current_user->display_name,
1058 'comment_author_email' => 'propertyhive@noreply.com',
1059 'comment_author_url' => '',
1060 'comment_date' => date("Y-m-d H:i:s"),
1061 'comment_content' => serialize($comment),
1062 'comment_approved' => 1,
1063 'comment_type' => 'propertyhive_note',
1064 );
1065 $comment_id = wp_insert_comment( $data );
1066
1067 if ($comment_id !== FALSE)
1068 {
1069 $comment = get_comment($comment_id);
1070
1071 ?>
1072 <li rel="<?php echo absint( $comment_id ) ; ?>" class="note">
1073 <div class="note_content">
1074 <?php echo wpautop( wptexturize( wp_kses_post( $note ) ) ); ?>
1075 </div>
1076 <p class="meta">
1077 <abbr class="exact-date" title="<?php echo $comment->comment_date_gmt; ?> GMT"><?php printf( __( '%s ago', 'propertyhive' ), human_time_diff( strtotime( $comment->comment_date_gmt ), current_time( 'timestamp', 1 ) ) ); ?></abbr>
1078 <?php if ( $comment->comment_author !== __( 'Property Hive', 'propertyhive' ) ) printf( ' ' . __( 'by %s', 'propertyhive' ), $comment->comment_author ); ?>
1079 <a href="#" class="delete_note"><?php _e( 'Delete', 'propertyhive' ); ?></a>
1080 </p>
1081 </li>
1082 <?php
1083 }
1084 }
1085
1086 // Quit out
1087 die();
1088 }
1089
1090 /**
1091 * Delete order note via ajax
1092 */
1093 public function delete_note() {
1094
1095 check_ajax_referer( 'delete-note', 'security' );
1096
1097 $note_id = (int) $_POST['note_id'];
1098
1099 if ( $note_id > 0 ) {
1100 wp_delete_comment( $note_id );
1101 }
1102
1103 // Quit out
1104 die();
1105 }
1106
1107 /**
1108 * Delete order note via ajax
1109 */
1110 public function make_property_enquiry() {
1111
1112 global $post;
1113
1114 $return = array();
1115
1116
1117 // Validate
1118 $errors = array();
1119 //if ( ! array_key_exists( 'property_id', $form_controls ) )
1120 //{
1121 // $errors[] = __( 'Property ID is a required field and must be supplied when making an enquiry', 'propertyhive' );
1122 //}
1123 //else
1124 //{
1125 if ( ! isset( $_POST['property_id'] ) || ( isset( $_POST['property_id'] ) && empty( $_POST['property_id'] ) ) )
1126 {
1127 $errors[] = __( 'Property ID is a required field and must be supplied when making an enquiry', 'propertyhive' ) . ': ' . $key;
1128 }
1129 else
1130 {
1131 $post = get_post($_POST['property_id']);
1132
1133 $form_controls = ph_get_property_enquiry_form_fields();
1134
1135 $form_controls = apply_filters( 'propertyhive_property_enquiry_form_fields', $form_controls );
1136 }
1137 //}
1138
1139 foreach ( $form_controls as $key => $control )
1140 {
1141 if ( isset( $control ) && isset( $control['required'] ) && $control['required'] === TRUE )
1142 {
1143 // This field is mandatory. Lets check we received it in the post
1144 if ( ! isset( $_POST[$key] ) || ( isset( $_POST[$key] ) && empty( $_POST[$key] ) ) )
1145 {
1146 $errors[] = __( 'Missing required field', 'propertyhive' ) . ': ' . $key;
1147 }
1148 }
1149 if ( isset( $control['type'] ) && $control['type'] == 'email' && isset( $_POST[$key] ) && ! empty( $_POST[$key] ) && ! is_email( $_POST[$key] ) )
1150 {
1151 $errors[] = __( 'Invalid email address provided', 'propertyhive' ) . ': ' . $key;
1152 }
1153 }
1154
1155 if ( !empty($errors) )
1156 {
1157 // Failed validation
1158
1159 $return['success'] = false;
1160 $return['reason'] = 'validation';
1161 $return['errors'] = $errors;
1162 }
1163 else
1164 {
1165 // Passed validation
1166
1167 // Get recipient email address
1168 $to = '';
1169
1170 // Try and get office's email address first, else fallback to admin email
1171 $office_id = get_post_meta($_POST['property_id'], '_office_id', TRUE);
1172 if ( $office_id != '' )
1173 {
1174 if ( get_post_type( $office_id ) == 'office' )
1175 {
1176 $property_department = get_post_meta($_POST['property_id'], '_department', TRUE);
1177
1178 $fields_to_check = array();
1179 switch ( $property_department )
1180 {
1181 case "residential-sales":
1182 {
1183 $fields_to_check[] = '_office_email_address_sales';
1184 $fields_to_check[] = '_office_email_address_lettings';
1185 $fields_to_check[] = '_office_email_address_commercial';
1186 break;
1187 }
1188 case "residential-lettings":
1189 {
1190 $fields_to_check[] = '_office_email_address_lettings';
1191 $fields_to_check[] = '_office_email_address_sales';
1192 $fields_to_check[] = '_office_email_address_commercial';
1193 break;
1194 }
1195 case "commercial":
1196 {
1197 $fields_to_check[] = '_office_email_address_commercial';
1198 $fields_to_check[] = '_office_email_address_lettings';
1199 $fields_to_check[] = '_office_email_address_sales';
1200 break;
1201 }
1202 }
1203
1204 foreach ( $fields_to_check as $field_to_check )
1205 {
1206 $to = get_post_meta($office_id, $field_to_check, TRUE);
1207 if ( $to != '' )
1208 {
1209 break;
1210 }
1211 }
1212 }
1213 }
1214 if ( $to == '' )
1215 {
1216 $to = get_option( 'admin_email' );
1217 }
1218
1219 $subject = __( 'New Property Enquiry', 'propertyhive' ) . ': ' . get_the_title( $_POST['property_id'] );
1220 $message = __( "You have received a property enquiry via your website. Please find details of the enquiry below", 'propertyhive' ) . "\n\n";
1221
1222 $message = apply_filters( 'propertyhive_property_enquiry_pre_body', $message, $_POST['property_id'] );
1223
1224 $message .= __( 'Property', 'propertyhive' ) . ': ' . get_the_title( $_POST['property_id'] ) . " (" . get_permalink( $_POST['property_id'] ) . ")\n\n";
1225
1226 unset($form_controls['action']);
1227 unset($_POST['action']);
1228 unset($form_controls['property_id']); // Unset so the fields dosn't get shown in the enquiry details
1229
1230 foreach ($form_controls as $key => $control)
1231 {
1232 $label = ( isset($control['label']) ) ? $control['label'] : $key;
1233 $message .= $label . ": " . $_POST[$key] . "\n";
1234 }
1235
1236 $from_email_address = get_option('propertyhive_email_from_address', '');
1237 if ( $from_email_address == '' )
1238 {
1239 $from_email_address = get_option('admin_email');
1240 }
1241 if ( $from_email_address == '' )
1242 {
1243 // Should never get here
1244 $from_email_address = $_POST['email_address'];
1245 }
1246
1247 $headers = array();
1248 if ( isset($_POST['name']) && ! empty($_POST['name']) )
1249 {
1250 $headers[] = 'From: ' . sanitize_text_field( $_POST['name'] ) . ' <' . sanitize_email( $from_email_address ) . '>';
1251 }
1252 else
1253 {
1254 $headers[] = 'From: <' . sanitize_email( $from_email_address ) . '>';
1255 }
1256 if ( isset($_POST['email_address']) && sanitize_email( $_POST['email_address'] ) != '' )
1257 {
1258 $headers[] = 'Reply-To: ' . sanitize_email( $_POST['email_address'] );
1259 }
1260
1261 $to = apply_filters( 'propertyhive_property_enquiry_to', $to, $_POST['property_id'] );
1262 $subject = apply_filters( 'propertyhive_property_enquiry_subject', $subject, $_POST['property_id'] );
1263 $message = apply_filters( 'propertyhive_property_enquiry_body', $message, $_POST['property_id'] );
1264 $headers = apply_filters( 'propertyhive_property_enquiry_headers', $headers, $_POST['property_id'] );
1265
1266 $sent = wp_mail( $to, $subject, $message, $headers );
1267
1268 if ( ! $sent )
1269 {
1270 $return['success'] = false;
1271 $return['reason'] = 'nosend';
1272 $return['errors'] = $errors;
1273 }
1274 else
1275 {
1276 $return['success'] = true;
1277
1278 // Now insert into enquiries section of WordPress
1279 $title = __( 'Property Enquiry', 'propertyhive' ) . ': ' . get_the_title( $_POST['property_id'] );
1280 if ( isset($_POST['name']) && ! empty($_POST['name']) )
1281 {
1282 $title .= __( ' from ', 'propertyhive' ) . sanitize_text_field($_POST['name']);
1283 }
1284
1285 $enquiry_post = array(
1286 'post_title' => $title,
1287 'post_content' => '',
1288 'post_type' => 'enquiry',
1289 'post_status' => 'publish',
1290 'comment_status' => 'closed',
1291 'ping_status' => 'closed',
1292 );
1293
1294 // Insert the post into the database
1295 $enquiry_post_id = wp_insert_post( $enquiry_post );
1296
1297 add_post_meta( $enquiry_post_id, '_status', 'open' );
1298 add_post_meta( $enquiry_post_id, '_source', 'website' );
1299 add_post_meta( $enquiry_post_id, '_negotiator_id', '' );
1300 add_post_meta( $enquiry_post_id, '_office_id', $office_id );
1301
1302 foreach ($_POST as $key => $value)
1303 {
1304 add_post_meta( $enquiry_post_id, $key, $value );
1305 }
1306
1307 // Send auto-responder
1308 if ( get_option( 'propertyhive_enquiry_auto_responder', '' ) == 'yes' )
1309 {
1310 // Auto-responder enabled
1311 PH()->email->send_enquiry_auto_responder( $_POST );
1312 }
1313 }
1314 }
1315
1316 $this->json_headers();
1317 echo json_encode( $return );
1318
1319 // Quit out
1320 die();
1321 }
1322
1323 /**
1324 * Create contact from enquiry
1325 */
1326 public function create_contact_from_enquiry()
1327 {
1328 global $post;
1329
1330 $enquiry_post_id = ( (isset($_POST['post_id'])) ? $_POST['post_id'] : '' );
1331 $nonce = ( (isset($_POST['security'])) ? $_POST['security'] : '' );
1332
1333 if ( ! wp_verify_nonce( $nonce, 'create-content-from-enquiry-nonce-' . $enquiry_post_id ) )
1334 {
1335 // This nonce is not valid.
1336 die( json_encode( array('error' => 'Invalid nonce. Please refresh and try again') ) );
1337 }
1338
1339 $enquiry_meta = get_metadata( 'post', $enquiry_post_id );
1340
1341 $name = false;
1342 $email = false;
1343 $telephone = false;
1344
1345 foreach ($enquiry_meta as $key => $value)
1346 {
1347 if ( strpos($key, 'name') !== false )
1348 {
1349 $name = $value[0];
1350 }
1351 elseif ( strpos($key, 'email') !== false )
1352 {
1353 $email = $value[0];
1354 }
1355 elseif ( strpos($key, 'telephone') !== false )
1356 {
1357 $telephone = $value[0];
1358 }
1359 }
1360
1361 if ( $name === false || $email === false )
1362 {
1363 // This nonce is not valid.
1364 die( json_encode( array('error' => 'Name or email address not found') ) );
1365 }
1366
1367 // We've not imported this property before
1368 $postdata = array(
1369 'post_excerpt' => '',
1370 'post_content' => '',
1371 'post_title' => utf8_encode(wp_strip_all_tags( $name )),
1372 'post_status' => 'publish',
1373 'post_type' => 'contact',
1374 'ping_status' => 'closed',
1375 'comment_status' => 'closed',
1376 );
1377
1378 $contact_post_id = wp_insert_post( $postdata, true );
1379
1380 if ( is_wp_error( $contact_post_id ) )
1381 {
1382 die( json_encode( array('error' => 'Error creating contact') ) );
1383 }
1384 elseif ( $contact_post_id == 0 )
1385 {
1386 die( json_encode( array('error' => 'Error creating contact') ) );
1387 }
1388
1389 if ( $telephone !== FALSE ) { update_post_meta( $contact_post_id, '_telephone_number', $telephone ); }
1390 if ( $email !== FALSE ) { update_post_meta( $contact_post_id, '_email_address', $email ); }
1391
1392 die( json_encode( array('success' => get_edit_post_link($contact_post_id, '')) ) );
1393 }
1394
1395 public function validate_save_contact()
1396 {
1397 global $post;
1398
1399 check_ajax_referer( 'contact-save-validation', 'security' );
1400
1401 $this->json_headers();
1402
1403 parse_str($_POST['form_data']);
1404 var_dump();
1405 $return = array('errors' => array());
1406
1407 if ( isset($_email_address) && $_email_address != '' )
1408 {
1409 $email_addresses = explode( ",", $_email_address );
1410
1411 foreach ( $email_addresses as $email_address )
1412 {
1413 $email_address = trim( $email_address );
1414
1415 if ( !is_email($email_address) )
1416 {
1417 $return['errors'][] = __( 'Email address is invalid', 'propertyhive' ) . ' - ' . $email_address;
1418 }
1419
1420 // Check it doesn't exist already
1421 $args = array(
1422 'post_type' => 'contact',
1423 'post_status' => 'any',
1424 'posts_per_page' => 1,
1425 'fields' => 'ids',
1426 'meta_query' => array(
1427 'relation' => 'OR',
1428 array(
1429 'key' => '_email_address',
1430 'value' => $email_address,
1431 'compare' => '='
1432 ),
1433 array(
1434 'key' => '_email_address',
1435 'value' => ',' . $email_address,
1436 'compare' => 'LIKE'
1437 )
1438 ,
1439 array(
1440 'key' => '_email_address',
1441 'value' => $email_address . ',',
1442 'compare' => 'LIKE'
1443 )
1444 )
1445 );
1446 if ( isset($post_ID) && $post_ID != '' )
1447 {
1448 $args['post__not_in'] = array( $post_ID );
1449 }
1450
1451 $contact_query = new WP_Query( $args );
1452
1453 if ( $contact_query->have_posts() )
1454 {
1455 while ( $contact_query->have_posts() )
1456 {
1457 $contact_query->the_post();
1458
1459 $return['errors'][] = __( 'A contact, ' . get_the_title() . ', already exists with email address', 'propertyhive' ) . ' ' . $email_address;
1460 }
1461 }
1462 }
1463 }
1464
1465 echo json_encode($return);
1466
1467 die();
1468 }
1469
1470 // Dashboard related functions
1471 public function get_news()
1472 {
1473 $this->json_headers();
1474
1475 include_once( ABSPATH . WPINC . '/feed.php' );
1476
1477 $return = array();
1478
1479 // Get a SimplePie feed object from the specified feed source.
1480 $rss = fetch_feed( 'https://wp-property-hive.com/category/property-hive-news/feed/' );
1481
1482 $maxitems = 0;
1483
1484 if ( ! is_wp_error( $rss ) ) : // Checks that the object is created correctly
1485
1486 // Figure out how many total items there are, but limit it to 5.
1487 $maxitems = $rss->get_item_quantity( 5 );
1488
1489 // Build an array of all the items, starting with element 0 (first element).
1490 $rss_items = $rss->get_items( 0, $maxitems );
1491
1492 foreach ( $rss_items as $item )
1493 {
1494 $return[] = array(
1495 'title' => esc_html( $item->get_title() ),
1496 'permalink' => esc_url( $item->get_permalink() ),
1497 'date' => $item->get_date('F d, Y')
1498 );
1499 }
1500
1501 endif;
1502
1503 echo json_encode($return);
1504
1505 die();
1506 }
1507
1508 public function get_viewings_awaiting_applicant_feedback()
1509 {
1510 global $post;
1511
1512 $this->json_headers();
1513
1514 $return = array();
1515
1516 $args = array(
1517 'post_type' => 'viewing',
1518 'fields' => 'ids',
1519 'post_status' => 'publish',
1520 'meta_query' => array(
1521 array(
1522 'key' => '_status',
1523 'value' => 'carried_out'
1524 ),
1525 array(
1526 'key' => '_feedback_status',
1527 'value' => ''
1528 )
1529 )
1530 );
1531
1532 $viewings_query = new WP_Query( $args );
1533
1534 if ( $viewings_query->have_posts() )
1535 {
1536 while ( $viewings_query->have_posts() )
1537 {
1538 $viewings_query->the_post();
1539
1540 $property_id = get_post_meta( get_the_ID(), '_property_id', TRUE );
1541 $property = new PH_Property((int)$property_id);
1542
1543 $applicant_contact_id = get_post_meta( get_the_ID(), '_applicant_contact_id', TRUE );
1544
1545 $return[] = array(
1546 'ID' => get_the_ID(),
1547 'edit_link' => get_edit_post_link( get_the_ID() ),
1548 'start_date_time' => get_post_meta( get_the_ID(), '_start_date_time', TRUE ),
1549 'start_date_time_formatted_Hi_jSFY' => date("H:i jS F Y", strtotime(get_post_meta( get_the_ID(), '_start_date_time', TRUE ))),
1550 'property_id' => $property_id,
1551 'property_address' => $property->get_formatted_full_address(),
1552 'applicant_contact_id' => $applicant_contact_id,
1553 'applicant_name' => get_the_title( $applicant_contact_id ),
1554 );
1555 }
1556 }
1557
1558 wp_reset_postdata();
1559
1560 echo json_encode($return);
1561
1562 die();
1563 }
1564
1565 // Viewing related functions
1566 public function book_viewing_property()
1567 {
1568 check_ajax_referer( 'book-viewing', 'security' );
1569
1570 $this->json_headers();
1571
1572 // TO DO: Should do validation on server side also
1573 if (empty($_POST['property_id']))
1574 {
1575 $return = array('error' => 'No property selected');
1576 echo json_encode( $return );
1577 die();
1578 }
1579
1580 $property = new PH_Property((int)$_POST['property_id']);
1581
1582 $applicant_contact_ids = array();
1583
1584 // Create applicant record if required
1585 if (empty($_POST['applicant_ids']) && !empty($_POST['applicant_name']))
1586 {
1587 // Need to create contact/applicant
1588 $contact_post = array(
1589 'post_title' => wp_strip_all_tags($_POST['applicant_name']),
1590 'post_content' => '',
1591 'post_type' => 'contact',
1592 'post_status' => 'publish',
1593 'comment_status' => 'closed',
1594 'ping_status' => 'closed',
1595 );
1596
1597 // Insert the post into the database
1598 $contact_post_id = wp_insert_post( $contact_post );
1599
1600 if ( is_wp_error($contact_post_id) || $contact_post_id == 0 )
1601 {
1602 $return = array('error' => 'Failed to create contact post. Please try again');
1603 echo json_encode( $return );
1604 die();
1605 }
1606
1607 update_post_meta( $contact_post_id, '_contact_types', array('applicant') );
1608
1609 update_post_meta( $contact_post_id, '_applicant_profiles', 1 );
1610 update_post_meta( $contact_post_id, '_applicant_profile_0', array( 'department' => $property->department, 'send_matching_properties' => '' ) );
1611
1612 $applicant_contact_ids[] = $contact_post_id;
1613 }
1614
1615 if (!empty($_POST['applicant_ids']) && empty($_POST['applicant_name']))
1616 {
1617 // This is an existing contact
1618 if ( !is_array($_POST['applicant_ids']) )
1619 {
1620 $_POST['applicant_ids'] = array($_POST['applicant_ids']);
1621 }
1622
1623 foreach ( $_POST['applicant_ids'] as $applicant_id )
1624 {
1625 $applicant_contact_ids[] = $applicant_id;
1626 }
1627 }
1628
1629 $applicant_contact_ids = array_unique($applicant_contact_ids);
1630
1631 if ( empty($applicant_contact_ids) )
1632 {
1633 $return = array('error' => 'No applicant selected, or unable to create applicant record');
1634 echo json_encode( $return );
1635 die();
1636 }
1637
1638 // Make sure each of the contacts has an applicant profile of the correct department
1639 /*foreach ( $applicant_contact_ids as $applicant_contact_id )
1640 {
1641 $has_correct_profile = false;
1642
1643 // Get all existing profiles
1644 $existing_contact_types = get_post_meta( $applicant_contact_id, '_contact_types', TRUE );
1645 if ( $existing_contact_types == '' || !is_array($existing_contact_types) )
1646 {
1647 $existing_contact_types = array();
1648 }
1649 if ( in_array( 'applicant', $existing_contact_types ) )
1650 {
1651 $num_applicant_profiles = get_post_meta( $applicant_contact_id, '_applicant_profiles', TRUE );
1652 if ( $num_applicant_profiles == '' )
1653 {
1654 $num_applicant_profiles = 0;
1655 }
1656
1657 if ( $num_applicant_profiles > 0 )
1658 {
1659 for ( $i = 0; $i < $num_applicant_profiles; ++$i )
1660 {
1661 $applicant_profile = get_post_meta( $applicant_contact_id, '_applicant_profile_' . $i, TRUE );
1662 if ( $applicant_profile['department'] == $property->department )
1663 {
1664 $has_correct_profile = true;
1665 }
1666 }
1667 }
1668 }
1669
1670 if ( !$has_correct_profile )
1671 {
1672 if ( in_array( 'applicant', $existing_contact_types ) )
1673 {
1674 // Already an applicant. Just need to add profile
1675 }
1676 else
1677 {
1678 $existing_contact_types[] = 'applicant';
1679 update_post_meta( $applicant_contact_id, '_contact_types', $existing_contact_types );
1680 }
1681
1682 $num_applicant_profiles = get_post_meta( $applicant_contact_id, '_applicant_profiles', TRUE );
1683 if ( $num_applicant_profiles == '' )
1684 {
1685 $num_applicant_profiles = 0;
1686 }
1687
1688 update_post_meta( $applicant_contact_id, '_applicant_profiles', $num_applicant_profiles + 1 );
1689 update_post_meta( $applicant_contact_id, '_applicant_profile_' . $num_applicant_profiles, array( 'department' => $property->department ) );
1690 }
1691 }*/
1692
1693 // Loop through contacts and create one viewing each
1694 // At the moment it's a 1-to-1 relationship, but might support multiple in the future
1695 foreach ( $applicant_contact_ids as $applicant_contact_id )
1696 {
1697 // Insert viewing record
1698 $viewing_post = array(
1699 'post_title' => '',
1700 'post_content' => '',
1701 'post_type' => 'viewing',
1702 'post_status' => 'publish',
1703 'comment_status' => 'closed',
1704 'ping_status' => 'closed',
1705 );
1706
1707 // Insert the post into the database
1708 $viewing_post_id = wp_insert_post( $viewing_post );
1709
1710 if ( is_wp_error($viewing_post_id) || $viewing_post_id == 0 )
1711 {
1712 $return = array('error' => 'Failed to create viewing post. Please try again');
1713 echo json_encode( $return );
1714 die();
1715 }
1716
1717 add_post_meta( $viewing_post_id, '_start_date_time', $_POST['start_date'] . ' ' . $_POST['start_time'] );
1718 add_post_meta( $viewing_post_id, '_duration', 30 * 60 ); // Stored in seconds. Default to 30 mins
1719 add_post_meta( $viewing_post_id, '_property_id', $_POST['property_id'] );
1720 add_post_meta( $viewing_post_id, '_applicant_contact_id', $applicant_contact_id );
1721 add_post_meta( $viewing_post_id, '_status', 'pending' );
1722 add_post_meta( $viewing_post_id, '_feedback_status', '' );
1723 add_post_meta( $viewing_post_id, '_feedback', '' );
1724 add_post_meta( $viewing_post_id, '_feedback_passed_on', '' );
1725
1726 if ( !empty($_POST['negotiator_ids']) )
1727 {
1728 foreach ( $_POST['negotiator_ids'] as $negotiator_id )
1729 {
1730 add_post_meta( $viewing_post_id, '_negotiator_id', $negotiator_id );
1731 }
1732 }
1733 }
1734
1735 $applicant_contacts = array();
1736 foreach ( $applicant_contact_ids as $applicant_contact_id )
1737 {
1738 $applicant_contacts[] = array(
1739 'ID' => $applicant_contact_id,
1740 'post_title' => get_the_title($applicant_contact_id),
1741 'edit_link' => get_edit_post_link( $applicant_contact_id, '' ),
1742 );
1743 }
1744
1745 $return = array('success' => array(
1746 'viewing' => array(
1747 'ID' => $viewing_post_id,
1748 'edit_link' => get_edit_post_link( $viewing_post_id, '' ),
1749 ),
1750 'applicant_contacts' => $applicant_contacts,
1751 ));
1752
1753 echo json_encode( $return );
1754
1755 die();
1756 }
1757
1758 public function book_viewing_contact()
1759 {
1760 check_ajax_referer( 'book-viewing', 'security' );
1761
1762 $this->json_headers();
1763
1764 // TO DO: Should do validation on server side also
1765 if (empty($_POST['contact_id']))
1766 {
1767 $return = array('error' => 'No contact selected');
1768 echo json_encode( $return );
1769 die();
1770 }
1771
1772 if (empty($_POST['property_ids']))
1773 {
1774 $return = array('error' => 'No property selected');
1775 echo json_encode( $return );
1776 die();
1777 }
1778
1779 // Loop through contacts and create one viewing each
1780 // At the moment it's a 1-to-1 relationship, but might support multiple in the future
1781 foreach ( $_POST['property_ids'] as $property_id )
1782 {
1783 // Insert viewing record
1784 $viewing_post = array(
1785 'post_title' => '',
1786 'post_content' => '',
1787 'post_type' => 'viewing',
1788 'post_status' => 'publish',
1789 'comment_status' => 'closed',
1790 'ping_status' => 'closed',
1791 );
1792
1793 // Insert the post into the database
1794 $viewing_post_id = wp_insert_post( $viewing_post );
1795
1796 if ( is_wp_error($viewing_post_id) || $viewing_post_id == 0 )
1797 {
1798 $return = array('error' => 'Failed to create viewing post. Please try again');
1799 echo json_encode( $return );
1800 die();
1801 }
1802
1803 add_post_meta( $viewing_post_id, '_start_date_time', $_POST['start_date'] . ' ' . $_POST['start_time'] );
1804 add_post_meta( $viewing_post_id, '_duration', 30 * 60 ); // Stored in seconds. Default to 30 mins
1805 add_post_meta( $viewing_post_id, '_property_id', $property_id );
1806 add_post_meta( $viewing_post_id, '_applicant_contact_id', $_POST['contact_id'] );
1807 add_post_meta( $viewing_post_id, '_status', 'pending' );
1808 add_post_meta( $viewing_post_id, '_feedback_status', '' );
1809 add_post_meta( $viewing_post_id, '_feedback', '' );
1810 add_post_meta( $viewing_post_id, '_feedback_passed_on', '' );
1811
1812 if ( !empty($_POST['negotiator_ids']) )
1813 {
1814 foreach ( $_POST['negotiator_ids'] as $negotiator_id )
1815 {
1816 add_post_meta( $viewing_post_id, '_negotiator_id', $negotiator_id );
1817 }
1818 }
1819 }
1820
1821 $properties = array();
1822 foreach ( $_POST['property_ids'] as $property_id )
1823 {
1824 $properties[] = array(
1825 'ID' => $property_id,
1826 'post_title' => get_the_title($property_id),
1827 'edit_link' => get_edit_post_link( $property_id, '' ),
1828 );
1829 }
1830
1831 $return = array('success' => array(
1832 'viewing' => array(
1833 'ID' => $viewing_post_id,
1834 'edit_link' => get_edit_post_link( $viewing_post_id, '' ),
1835 ),
1836 'properties' => $properties,
1837 ));
1838
1839 echo json_encode( $return );
1840
1841 die();
1842 }
1843
1844 public function get_viewing_details_meta_box()
1845 {
1846 check_ajax_referer( 'viewing-details-meta-box', 'security' );
1847
1848 $viewing = new PH_Viewing((int)$_POST['viewing_id']);
1849
1850 echo '<div class="propertyhive_meta_box">';
1851
1852 echo '<div class="options_group">';
1853
1854 echo '<p class="form-field">
1855
1856 <label for="">' . __('Status', 'propertyhive') . '</label>
1857
1858 ' . ucwords(str_replace("_", " ", $viewing->status));
1859
1860 if ( $viewing->status == 'offer_made' )
1861 {
1862 if ( get_option('propertyhive_module_disabled_offers_sales', '') != 'yes' )
1863 {
1864 $offer_id = get_post_meta( $viewing->id, '_offer_id', TRUE );
1865 if ( $offer_id != '' && get_post_status($offer_id) != 'publish' )
1866 {
1867 $offer_id = '';
1868 }
1869
1870 if ( $offer_id != '' )
1871 {
1872 echo ' (<a href="' . get_edit_post_link($offer_id) . '">' . __('View Offer', 'propertyhive') . '</a>)';
1873 }
1874 }
1875 }
1876
1877 echo '</p>';
1878
1879 if ( $viewing->status == 'carried_out' )
1880 {
1881 echo '<p class="form-field">
1882
1883 <label for="">' . __('Applicant Feedback', 'propertyhive') . '</label>';
1884
1885 switch ( $viewing->feedback_status )
1886 {
1887 case "interested":
1888 {
1889 echo 'Interested';
1890 break;
1891 }
1892 case "not_interested":
1893 {
1894 echo 'Not Interested';
1895 break;
1896 }
1897 case "not_required":
1898 {
1899 echo 'Feedback Not Required';
1900 break;
1901 }
1902 default:
1903 {
1904 echo 'Awaiting Feedback';
1905 }
1906 }
1907
1908 echo '</p>';
1909
1910 if ( $viewing->feedback_status == 'interested' || $viewing->feedback_status == 'not_interested' )
1911 {
1912 $args = array(
1913 'id' => '_feedback',
1914 'label' => __( 'Feedback', 'propertyhive' ),
1915 'desc_tip' => false,
1916 'class' => '',
1917 'value' => $viewing->feedback,
1918 'custom_attributes' => array(
1919 'style' => 'width:95%; max-width:500px;'
1920 )
1921 );
1922 propertyhive_wp_textarea_input( $args );
1923 }
1924 }
1925
1926 if ( $viewing->status == 'carried_out' && ( $viewing->feedback_status == 'interested' || $viewing->feedback_status == 'not_interested' ) )
1927 {
1928 echo '<p class="form-field">
1929
1930 <label for="">' . __('Feedback Passed On', 'propertyhive') . '</label>';
1931
1932 echo ( ($viewing->feedback_passed_on == 'yes') ? 'Yes' : 'No' );
1933
1934 echo '</p>';
1935 }
1936
1937 do_action('propertyhive_viewing_details_fields');
1938
1939 echo '</div>';
1940
1941 echo '</div>';
1942
1943 die();
1944 }
1945
1946 public function get_viewing_actions()
1947 {
1948 check_ajax_referer( 'viewing-actions', 'security' );
1949
1950 $post_id = $_POST['viewing_id'];
1951
1952 $status = get_post_meta( $post_id, '_status', TRUE );
1953 $feedback_status = get_post_meta( $post_id, '_feedback_status', TRUE );
1954
1955 echo '<div class="propertyhive_meta_box propertyhive_meta_box_actions" id="propertyhive_viewing_actions_meta_box">
1956
1957 <div class="options_group" style="padding-top:8px;">';
1958
1959 $show_feedback_meta_boxes = false;
1960
1961 $actions = array();
1962
1963 if ( $status == 'pending' )
1964 {
1965 $actions[] = '<a
1966 href="#action_panel_viewing_carried_out"
1967 class="button button-success viewing-action"
1968 style="width:100%; margin-bottom:7px; text-align:center"
1969 >' . __('Viewing Carried Out', 'propertyhive') . '</a>';
1970 $actions[] = '<a
1971 href="#action_panel_viewing_cancelled"
1972 class="button viewing-action"
1973 style="width:100%; margin-bottom:7px; text-align:center"
1974 >' . __('Viewing Cancelled', 'propertyhive') . '</a>';
1975 }
1976
1977 if ( $status == 'carried_out' )
1978 {
1979 if ( $feedback_status == '' )
1980 {
1981 $actions[] = '<a
1982 href="#action_panel_viewing_interested"
1983 class="button button-success viewing-action"
1984 style="width:100%; margin-bottom:7px; text-align:center"
1985 >' . __('Applicant Interested', 'propertyhive') . '</a>';
1986
1987 $actions[] = '<a
1988 href="#action_panel_viewing_not_interested"
1989 class="button button-danger viewing-action"
1990 style="width:100%; margin-bottom:7px; text-align:center"
1991 >' . __('Applicant Not Interested', 'propertyhive') . '</a>';
1992
1993 $actions[] = '<a
1994 href="#action_panel_viewing_feedback_not_required"
1995 class="button viewing-action"
1996 style="width:100%; margin-bottom:7px; text-align:center"
1997 >' . __('Feedback Not Required', 'propertyhive') . '</a>';
1998
1999 $show_feedback_meta_boxes = true;
2000 }
2001
2002 if ( $feedback_status == 'interested' )
2003 {
2004 $actions[] = '<a
2005 href="' . trim(admin_url(), '/') . '/post-new.php?post_type=viewing&applicant_contact_id=' . get_post_meta( $post_id, '_applicant_contact_id', TRUE ) . '&property_id=' . get_post_meta( $post_id, '_property_id', TRUE ) . '&viewing_id=' . $post_id .'"
2006 class="button button-success"
2007 style="width:100%; margin-bottom:7px; text-align:center"
2008 >' . __('Book Second Viewing', 'propertyhive') . '</a>';
2009
2010 if ( get_option('propertyhive_module_disabled_offers_sales', '') != 'yes' )
2011 {
2012 $property_id = get_post_meta( $post_id, '_property_id', TRUE );
2013 if ( get_post_meta( $property_id, '_department', TRUE ) == 'residential-sales' )
2014 {
2015 // See if an offer has this viewing id associated with it
2016 $offer_id = get_post_meta( $post_id, '_offer_id', TRUE );
2017 if ( $offer_id != '' && get_post_status($offer_id) != 'publish' )
2018 {
2019 $offer_id = '';
2020 }
2021
2022 if ( $offer_id != '' )
2023 {
2024 $actions[] = '<a
2025 href="' . get_edit_post_link( $offer_id, '' ) . '"
2026 class="button"
2027 style="width:100%; margin-bottom:7px; text-align:center"
2028 >' . __('View Offer', 'propertyhive') . '</a>';
2029 }
2030 else
2031 {
2032 $actions[] = '<a
2033 href="' . wp_nonce_url( admin_url( 'post.php?post=' . $post_id . '&action=edit' ), '1', 'create_offer' ) . '"
2034 class="button button-success"
2035 style="width:100%; margin-bottom:7px; text-align:center"
2036 >' . __('Record Offer', 'propertyhive') . '</a>';
2037 }
2038 }
2039 }
2040 }
2041
2042 if ( get_post_meta( $post_id, '_feedback_passed_on', TRUE ) != 'yes' && ( $feedback_status == 'interested' || $feedback_status == 'not_interested' ) )
2043 {
2044 $actions[] = '<a
2045 href="#action_panel_viewing_revert_feedback_passed_on"
2046 class="button viewing-action"
2047 style="width:100%; margin-bottom:7px; text-align:center"
2048 >' . __('Feedback Passed On To Owner', 'propertyhive') . '</a>';
2049 }
2050
2051 if ( $feedback_status == 'interested' || $feedback_status == 'not_interested' || $feedback_status == 'not_required' )
2052 {
2053 $actions[] = '<a
2054 href="#action_panel_viewing_revert_feedback_pending"
2055 class="button viewing-action"
2056 style="width:100%; margin-bottom:7px; text-align:center"
2057 >' . __('Revert To Feedback Pending', 'propertyhive') . '</a>';
2058 }
2059 }
2060
2061 if ( $status == 'offer_made' )
2062 {
2063 if ( get_option('propertyhive_module_disabled_offers_sales', '') != 'yes' )
2064 {
2065 $offer_id = get_post_meta( $post_id, '_offer_id', TRUE );
2066 if ( $offer_id != '' && get_post_status($offer_id) != 'publish' )
2067 {
2068 $offer_id = '';
2069 }
2070
2071 if ( $offer_id != '' )
2072 {
2073 $actions[] = '<a
2074 href="' . get_edit_post_link( $offer_id, '' ) . '"
2075 class="button"
2076 style="width:100%; margin-bottom:7px; text-align:center"
2077 >' . __('View Offer', 'propertyhive') . '</a>';
2078 }
2079 }
2080 }
2081
2082 if ( ( $status == 'carried_out' && $feedback_status == '' ) || $status == 'cancelled' )
2083 {
2084 $actions[] = '<a
2085 href="#action_panel_viewing_revert_pending"
2086 class="button viewing-action"
2087 style="width:100%; margin-bottom:7px; text-align:center"
2088 >' . __('Revert To Pending', 'propertyhive') . '</a>';
2089 }
2090
2091 $actions = apply_filters( 'propertyhive_admin_viewing_actions', $actions, $post->ID );
2092
2093 if ( !empty($actions) )
2094 {
2095 echo implode("", $actions);
2096 }
2097 else
2098 {
2099 echo '<div style="text-align:center">' . __( 'No actions to display', 'propertyhive' ) . '</div>';
2100 }
2101
2102 echo '</div>
2103
2104 </div>';
2105
2106 if ( $show_feedback_meta_boxes )
2107 {
2108 echo '<div class="propertyhive_meta_box propertyhive_meta_box_actions" id="action_panel_viewing_interested" style="display:none;">
2109
2110 <div class="options_group" style="padding-top:8px;">
2111
2112 <div class="form-field">
2113
2114 <label for="_viewing_interested_feedback">' . __( 'Applicant Feedback', 'propertyhive' ) . '</label>
2115
2116 <textarea id="_interested_feedback" name="_interested_feedback" style="width:100%;">' . get_post_meta( $post_id, '_feedback', TRUE ) . '</textarea>
2117
2118 </div>
2119
2120 <a class="button action-cancel" href="#">' . __( 'Cancel', 'propertyhive' ) . '</a>
2121 <a class="button button-primary interested-feedback-action-submit" href="#">' . __( 'Save Feedback', 'propertyhive' ) . '</a>
2122
2123 </div>
2124
2125 </div>';
2126
2127 echo '<div class="propertyhive_meta_box propertyhive_meta_box_actions" id="action_panel_viewing_not_interested" style="display:none;">
2128
2129 <div class="options_group" style="padding-top:8px;">
2130
2131 <div class="form-field">
2132
2133 <label for="_viewing_not_interested_feedback">' . __( 'Applicant Feedback', 'propertyhive' ) . '</label>
2134
2135 <textarea id="_not_interested_feedback" name="_not_interested_feedback" style="width:100%;">' . get_post_meta( $post_id, '_feedback', TRUE ) . '</textarea>
2136
2137 </div>
2138
2139 <a class="button action-cancel" href="#">' . __( 'Cancel', 'propertyhive' ) . '</a>
2140 <a class="button button-primary not-interested-feedback-action-submit" href="#">' . __( 'Save Feedback', 'propertyhive' ) . '</a>
2141
2142 </div>
2143
2144 </div>';
2145 }
2146
2147 die();
2148 }
2149
2150 public function viewing_carried_out()
2151 {
2152 check_ajax_referer( 'viewing-actions', 'security' );
2153
2154 $post_id = $_POST['viewing_id'];
2155
2156 $status = get_post_meta( $post_id, '_status', TRUE );
2157
2158 if ( $status == 'pending' )
2159 {
2160 update_post_meta( $post_id, '_status', 'carried_out' );
2161
2162 $current_user = wp_get_current_user();
2163
2164 // Add note/comment to viewing
2165 $comment = array(
2166 'note_type' => 'action',
2167 'action' => 'viewing_carried_out',
2168 );
2169
2170 $data = array(
2171 'comment_post_ID' => $post_id,
2172 'comment_author' => $current_user->display_name,
2173 'comment_author_email' => 'propertyhive@noreply.com',
2174 'comment_author_url' => '',
2175 'comment_date' => date("Y-m-d H:i:s"),
2176 'comment_content' => serialize($comment),
2177 'comment_approved' => 1,
2178 'comment_type' => 'propertyhive_note',
2179 );
2180 $comment_id = wp_insert_comment( $data );
2181 }
2182
2183 die();
2184 }
2185
2186 public function viewing_cancelled()
2187 {
2188 check_ajax_referer( 'viewing-actions', 'security' );
2189
2190 $post_id = $_POST['viewing_id'];
2191
2192 $status = get_post_meta( $post_id, '_status', TRUE );
2193
2194 if ( $status == 'pending' )
2195 {
2196 update_post_meta( $post_id, '_status', 'cancelled' );
2197
2198 $current_user = wp_get_current_user();
2199
2200 // Add note/comment to viewing
2201 $comment = array(
2202 'note_type' => 'action',
2203 'action' => 'viewing_cancelled',
2204 );
2205
2206 $data = array(
2207 'comment_post_ID' => $post_id,
2208 'comment_author' => $current_user->display_name,
2209 'comment_author_email' => 'propertyhive@noreply.com',
2210 'comment_author_url' => '',
2211 'comment_date' => date("Y-m-d H:i:s"),
2212 'comment_content' => serialize($comment),
2213 'comment_approved' => 1,
2214 'comment_type' => 'propertyhive_note',
2215 );
2216 $comment_id = wp_insert_comment( $data );
2217 }
2218
2219 die();
2220 }
2221
2222 public function viewing_interested_feedback()
2223 {
2224 check_ajax_referer( 'viewing-actions', 'security' );
2225
2226 $post_id = $_POST['viewing_id'];
2227
2228 $status = get_post_meta( $post_id, '_status', TRUE );
2229
2230 if ( $status == 'carried_out' )
2231 {
2232 update_post_meta( $post_id, '_feedback_status', 'interested' );
2233 update_post_meta( $post_id, '_feedback', $_POST['feedback'] );
2234
2235 $current_user = wp_get_current_user();
2236
2237 // Add note/comment to viewing
2238 $comment = array(
2239 'note_type' => 'action',
2240 'action' => 'viewing_applicant_interested',
2241 );
2242
2243 $data = array(
2244 'comment_post_ID' => $post_id,
2245 'comment_author' => $current_user->display_name,
2246 'comment_author_email' => 'propertyhive@noreply.com',
2247 'comment_author_url' => '',
2248 'comment_date' => date("Y-m-d H:i:s"),
2249 'comment_content' => serialize($comment),
2250 'comment_approved' => 1,
2251 'comment_type' => 'propertyhive_note',
2252 );
2253 $comment_id = wp_insert_comment( $data );
2254 }
2255
2256 die();
2257 }
2258
2259 public function viewing_not_interested_feedback()
2260 {
2261 check_ajax_referer( 'viewing-actions', 'security' );
2262
2263 $post_id = $_POST['viewing_id'];
2264
2265 $status = get_post_meta( $post_id, '_status', TRUE );
2266
2267 if ( $status == 'carried_out' )
2268 {
2269 update_post_meta( $post_id, '_feedback_status', 'not_interested' );
2270 update_post_meta( $post_id, '_feedback', $_POST['feedback'] );
2271
2272 $current_user = wp_get_current_user();
2273
2274 // Add note/comment to viewing
2275 $comment = array(
2276 'note_type' => 'action',
2277 'action' => 'viewing_applicant_not_interested',
2278 );
2279
2280 $data = array(
2281 'comment_post_ID' => $post_id,
2282 'comment_author' => $current_user->display_name,
2283 'comment_author_email' => 'propertyhive@noreply.com',
2284 'comment_author_url' => '',
2285 'comment_date' => date("Y-m-d H:i:s"),
2286 'comment_content' => serialize($comment),
2287 'comment_approved' => 1,
2288 'comment_type' => 'propertyhive_note',
2289 );
2290 $comment_id = wp_insert_comment( $data );
2291 }
2292
2293 die();
2294 }
2295
2296 public function viewing_feedback_not_required()
2297 {
2298 check_ajax_referer( 'viewing-actions', 'security' );
2299
2300 $post_id = $_POST['viewing_id'];
2301
2302 $status = get_post_meta( $post_id, '_status', TRUE );
2303
2304 if ( $status == 'carried_out' )
2305 {
2306 update_post_meta( $post_id, '_feedback_status', 'not_required' );
2307
2308 $current_user = wp_get_current_user();
2309
2310 // Add note/comment to viewing
2311 $comment = array(
2312 'note_type' => 'action',
2313 'action' => 'viewing_feedback_not_required',
2314 );
2315
2316 $data = array(
2317 'comment_post_ID' => $post_id,
2318 'comment_author' => $current_user->display_name,
2319 'comment_author_email' => 'propertyhive@noreply.com',
2320 'comment_author_url' => '',
2321 'comment_date' => date("Y-m-d H:i:s"),
2322 'comment_content' => serialize($comment),
2323 'comment_approved' => 1,
2324 'comment_type' => 'propertyhive_note',
2325 );
2326 $comment_id = wp_insert_comment( $data );
2327 }
2328
2329 die();
2330 }
2331
2332 public function viewing_revert_feedback_pending()
2333 {
2334 check_ajax_referer( 'viewing-actions', 'security' );
2335
2336 $post_id = $_POST['viewing_id'];
2337
2338 $status = get_post_meta( $post_id, '_status', TRUE );
2339
2340 if ( $status == 'carried_out' )
2341 {
2342 update_post_meta( $post_id, '_feedback_status', '' );
2343 update_post_meta( $post_id, '_feedback_passed_on', '' );
2344
2345 $current_user = wp_get_current_user();
2346
2347 // Add note/comment to viewing
2348 $comment = array(
2349 'note_type' => 'action',
2350 'action' => 'viewing_revert_feedback_pending',
2351 );
2352
2353 $data = array(
2354 'comment_post_ID' => $post_id,
2355 'comment_author' => $current_user->display_name,
2356 'comment_author_email' => 'propertyhive@noreply.com',
2357 'comment_author_url' => '',
2358 'comment_date' => date("Y-m-d H:i:s"),
2359 'comment_content' => serialize($comment),
2360 'comment_approved' => 1,
2361 'comment_type' => 'propertyhive_note',
2362 );
2363 $comment_id = wp_insert_comment( $data );
2364 }
2365
2366 die();
2367 }
2368
2369 public function viewing_revert_pending()
2370 {
2371 check_ajax_referer( 'viewing-actions', 'security' );
2372
2373 $post_id = $_POST['viewing_id'];
2374
2375 $status = get_post_meta( $post_id, '_status', TRUE );
2376
2377 if ( $status == 'carried_out' || $status == 'cancelled' )
2378 {
2379 update_post_meta( $post_id, '_status', 'pending' );
2380 update_post_meta( $post_id, '_feedback_status', '' );
2381
2382 $current_user = wp_get_current_user();
2383
2384 // Add note/comment to viewing
2385 $comment = array(
2386 'note_type' => 'action',
2387 'action' => 'viewing_revert_pending',
2388 );
2389
2390 $data = array(
2391 'comment_post_ID' => $post_id,
2392 'comment_author' => $current_user->display_name,
2393 'comment_author_email' => 'propertyhive@noreply.com',
2394 'comment_author_url' => '',
2395 'comment_date' => date("Y-m-d H:i:s"),
2396 'comment_content' => serialize($comment),
2397 'comment_approved' => 1,
2398 'comment_type' => 'propertyhive_note',
2399 );
2400 $comment_id = wp_insert_comment( $data );
2401 }
2402
2403 die();
2404 }
2405
2406 public function viewing_feedback_passed_on()
2407 {
2408 check_ajax_referer( 'viewing-actions', 'security' );
2409
2410 $post_id = $_POST['viewing_id'];
2411
2412 $status = get_post_meta( $post_id, '_status', TRUE );
2413
2414 if ( $status == 'carried_out' )
2415 {
2416 update_post_meta( $post_id, '_feedback_passed_on', 'yes' );
2417
2418 $current_user = wp_get_current_user();
2419
2420 // Add note/comment to viewing
2421 $comment = array(
2422 'note_type' => 'action',
2423 'action' => 'viewing_feedback_passed_on',
2424 );
2425
2426 $data = array(
2427 'comment_post_ID' => $post_id,
2428 'comment_author' => $current_user->display_name,
2429 'comment_author_email' => 'propertyhive@noreply.com',
2430 'comment_author_url' => '',
2431 'comment_date' => date("Y-m-d H:i:s"),
2432 'comment_content' => serialize($comment),
2433 'comment_approved' => 1,
2434 'comment_type' => 'propertyhive_note',
2435 );
2436 $comment_id = wp_insert_comment( $data );
2437 }
2438
2439 die();
2440 }
2441
2442 public function get_property_viewings_meta_box()
2443 {
2444 check_ajax_referer( 'get_property_viewings_meta_box', 'security' );
2445
2446 global $post;
2447
2448 echo '<div class="propertyhive_meta_box">';
2449
2450 echo '<div class="options_group">';
2451
2452 $args = array(
2453 'post_type' => 'viewing',
2454 'nopaging' => true,
2455 'orderby' => 'meta_value',
2456 'order' => 'DESC',
2457 'meta_key' => '_start_date_time',
2458 'post_status' => 'publish',
2459 'meta_query' => array(
2460 array(
2461 'key' => '_property_id',
2462 'value' => $_POST['post_id']
2463 )
2464 )
2465 );
2466 $viewings_query = new WP_Query( $args );
2467
2468 if ( $viewings_query->have_posts() )
2469 {
2470 echo '<table style="width:100%">
2471 <thead>
2472 <tr>
2473 <th style="text-align:left;">' . __( 'Date', 'propertyhive' ) . ' / ' . __( 'Time', 'propertyhive' ) . '</th>
2474 <th style="text-align:left;">' . __( 'Applicant', 'propertyhive' ) . '</th>
2475 <th style="text-align:left;">' . __( 'Attending Negotiator(s)', 'propertyhive' ) . '</th>
2476 <th style="text-align:left;">' . __( 'Status', 'propertyhive' ) . '</th>
2477 </tr>
2478 </thead>
2479 <tbody>';
2480
2481 while ( $viewings_query->have_posts() )
2482 {
2483 $viewings_query->the_post();
2484
2485 echo '<tr>';
2486 echo '<td style="text-align:left;"><a href="' . get_edit_post_link( get_the_ID(), '' ) . '">' . date("H:i jS F Y", strtotime(get_post_meta(get_the_ID(), '_start_date_time', TRUE))) . '</a></td>';
2487 echo '<td style="text-align:left;"><a href="' . get_edit_post_link( get_post_meta(get_the_ID(), '_applicant_contact_id', TRUE), '' ) . '">' . get_the_title(get_post_meta(get_the_ID(), '_applicant_contact_id', TRUE)) . '</a></td>';
2488 echo '<td style="text-align:left;">';
2489
2490 $negotiator_ids = get_post_meta(get_the_ID(), '_negotiator_id');
2491
2492 if (!empty($negotiator_ids))
2493 {
2494 $i = 0;
2495 foreach ($negotiator_ids as $negotiator_id)
2496 {
2497 if ( $i > 0 ) { echo ', '; }
2498
2499 $userdata = get_userdata( $negotiator_id );
2500 if ( $userdata !== FALSE )
2501 {
2502 echo $userdata->display_name;
2503 }
2504 else
2505 {
2506 echo '<em>Unknown user</em>';
2507 }
2508 ++$i;
2509 }
2510 }
2511 else
2512 {
2513 echo 'Unattended';
2514 }
2515
2516 echo '</td>';
2517 echo '<td style="text-align:left;">';
2518
2519 $status = get_post_meta(get_the_ID(), '_status', TRUE);
2520 echo ucwords(str_replace("_", " ", $status));
2521 if ( $status == 'carried_out' )
2522 {
2523 echo '<br>';
2524 $feedback_status = get_post_meta(get_the_ID(), '_feedback_status', TRUE);
2525 switch ( $feedback_status )
2526 {
2527 case "interested": { echo 'Applicant Interested'; break; }
2528 case "not_interested": { echo 'Applicant Not Interested'; break; }
2529 case "not_required": { echo 'Feedback Not Required'; break; }
2530 default: { echo 'Awaiting Feedback'; }
2531 }
2532
2533 if ( $feedback_status == 'interested' || $feedback_status == 'not_interested' )
2534 {
2535 $feedback_passed_on = get_post_meta(get_the_ID(), '_feedback_passed_on', TRUE);
2536 echo '<br>' . ( ($feedback_passed_on == 'yes') ? 'Feedback Passed On' : 'Feedback Not Passed On' );
2537 }
2538 }
2539 echo '</td>';
2540 echo '</tr>';
2541 }
2542
2543 echo '
2544 </tbody>
2545 </table>
2546 <br>';
2547 }
2548 else
2549 {
2550 echo '<p>' . __( 'No viewings exist for this property', 'propertyhive') . '</p>';
2551 }
2552 wp_reset_postdata();
2553
2554 do_action('propertyhive_property_viewings_fields');
2555
2556 echo '</div>';
2557
2558 echo '</div>';
2559
2560 die();
2561 }
2562
2563 public function get_contact_viewings_meta_box()
2564 {
2565 check_ajax_referer( 'get_contact_viewings_meta_box', 'security' );
2566
2567 global $post;
2568
2569 echo '<div class="propertyhive_meta_box">';
2570
2571 echo '<div class="options_group">';
2572
2573 $args = array(
2574 'post_type' => 'viewing',
2575 'nopaging' => true,
2576 'orderby' => 'meta_value',
2577 'order' => 'DESC',
2578 'post_status' => 'publish',
2579 'meta_key' => '_start_date_time',
2580 'meta_query' => array(
2581 array(
2582 'key' => '_applicant_contact_id',
2583 'value' => $_POST['post_id']
2584 )
2585 )
2586 );
2587 $viewings_query = new WP_Query( $args );
2588
2589 if ( $viewings_query->have_posts() )
2590 {
2591 echo '<table style="width:100%">
2592 <thead>
2593 <tr>
2594 <th style="text-align:left;">' . __( 'Date', 'propertyhive' ) . ' / ' . __( 'Time', 'propertyhive' ) . '</th>
2595 <th style="text-align:left;">' . __( 'Property', 'propertyhive' ) . '</th>
2596 <th style="text-align:left;">' . __( 'Attending Negotiator(s)', 'propertyhive' ) . '</th>
2597 <th style="text-align:left;">' . __( 'Status', 'propertyhive' ) . '</th>
2598 </tr>
2599 </thead>
2600 <tbody>';
2601
2602 while ( $viewings_query->have_posts() )
2603 {
2604 $viewings_query->the_post();
2605
2606 $property = new PH_Property((int)get_post_meta(get_the_ID(), '_property_id', TRUE));
2607
2608 echo '<tr>';
2609 echo '<td style="text-align:left;"><a href="' . get_edit_post_link( get_the_ID(), '') . '">' . date("H:i jS F Y", strtotime(get_post_meta(get_the_ID(), '_start_date_time', TRUE))) . '</a></td>';
2610 echo '<td style="text-align:left;"><a href="' . get_edit_post_link( get_post_meta(get_the_ID(), '_property_id', TRUE), '' ) . '">' . $property->get_formatted_full_address() . '</a></td>';
2611 echo '<td style="text-align:left;">';
2612
2613 $negotiator_ids = get_post_meta(get_the_ID(), '_negotiator_id');
2614
2615 if (!empty($negotiator_ids))
2616 {
2617 $i = 0;
2618 foreach ($negotiator_ids as $negotiator_id)
2619 {
2620 if ( $i > 0 ) { echo ', '; }
2621
2622 $userdata = get_userdata( $negotiator_id );
2623 if ( $userdata !== FALSE )
2624 {
2625 echo $userdata->display_name;
2626 }
2627 else
2628 {
2629 echo '<em>Unknown user</em>';
2630 }
2631 ++$i;
2632 }
2633 }
2634 else
2635 {
2636 echo 'Unattended';
2637 }
2638
2639 echo '</td>';
2640 echo '<td style="text-align:left;">';
2641
2642 $status = get_post_meta(get_the_ID(), '_status', TRUE);
2643 echo ucwords(str_replace("_", " ", $status));
2644 if ( $status == 'carried_out' )
2645 {
2646 echo '<br>';
2647 $feedback_status = get_post_meta(get_the_ID(), '_feedback_status', TRUE);
2648 switch ( get_post_meta(get_the_ID(), '_feedback_status', TRUE) )
2649 {
2650 case "interested": { echo 'Applicant Interested'; break; }
2651 case "not_interested": { echo 'Applicant Not Interested'; break; }
2652 case "not_required": { echo 'Feedback Not Required'; break; }
2653 default: { echo 'Awaiting Feedback'; }
2654 }
2655
2656 if ( $feedback_status == 'interested' || $feedback_status == 'not_interested' )
2657 {
2658 $feedback_passed_on = get_post_meta(get_the_ID(), '_feedback_passed_on', TRUE);
2659 echo '<br>' . ( ($feedback_passed_on == 'yes') ? 'Feedback Passed On' : 'Feedback Not Passed On' );
2660 }
2661 }
2662 echo '</td>';
2663 echo '</tr>';
2664 }
2665
2666 echo '
2667 </tbody>
2668 </table>
2669 <br>';
2670 }
2671 else
2672 {
2673 echo '<p>' . __( 'No viewings exist for this contact', 'propertyhive') . '</p>';
2674 }
2675 wp_reset_postdata();
2676
2677 do_action('propertyhive_contact_viewings_fields');
2678
2679 echo '</div>';
2680
2681 echo '</div>';
2682
2683 die();
2684 }
2685
2686 // Offer related functions
2687 public function record_offer_property()
2688 {
2689 check_ajax_referer( 'record-offer', 'security' );
2690
2691 $this->json_headers();
2692
2693 // TO DO: Should do validation on server side also
2694 if (empty($_POST['property_id']))
2695 {
2696 $return = array('error' => 'No property selected');
2697 echo json_encode( $return );
2698 die();
2699 }
2700
2701 $property = new PH_Property((int)$_POST['property_id']);
2702
2703 $applicant_contact_ids = array();
2704
2705 // Create applicant record if required
2706 if (empty($_POST['applicant_ids']) && !empty($_POST['applicant_name']))
2707 {
2708 // Need to create contact/applicant
2709 $contact_post = array(
2710 'post_title' => wp_strip_all_tags($_POST['applicant_name']),
2711 'post_content' => '',
2712 'post_type' => 'contact',
2713 'post_status' => 'publish',
2714 'comment_status' => 'closed',
2715 'ping_status' => 'closed',
2716 );
2717
2718 // Insert the post into the database
2719 $contact_post_id = wp_insert_post( $contact_post );
2720
2721 if ( is_wp_error($contact_post_id) || $contact_post_id == 0 )
2722 {
2723 $return = array('error' => 'Failed to create contact post. Please try again');
2724 echo json_encode( $return );
2725 die();
2726 }
2727
2728 update_post_meta( $contact_post_id, '_contact_types', array('applicant') );
2729
2730 update_post_meta( $contact_post_id, '_applicant_profiles', 1 );
2731 update_post_meta( $contact_post_id, '_applicant_profile_0', array( 'department' => $property->department, 'send_matching_properties' => '' ) );
2732
2733 $applicant_contact_ids[] = $contact_post_id;
2734 }
2735
2736 if (!empty($_POST['applicant_ids']) && empty($_POST['applicant_name']))
2737 {
2738 // This is an existing contact
2739 if ( !is_array($_POST['applicant_ids']) )
2740 {
2741 $_POST['applicant_ids'] = array($_POST['applicant_ids']);
2742 }
2743
2744 foreach ( $_POST['applicant_ids'] as $applicant_id )
2745 {
2746 $applicant_contact_ids[] = $applicant_id;
2747 }
2748 }
2749
2750 $applicant_contact_ids = array_unique($applicant_contact_ids);
2751
2752 if ( empty($applicant_contact_ids) )
2753 {
2754 $return = array('error' => 'No applicant selected, or unable to create applicant record');
2755 echo json_encode( $return );
2756 die();
2757 }
2758
2759 // Loop through contacts and create one offer each
2760 // At the moment it's a 1-to-1 relationship, but might support multiple in the future
2761 foreach ( $applicant_contact_ids as $applicant_contact_id )
2762 {
2763 // Insert offer record
2764 $offer_post = array(
2765 'post_title' => '',
2766 'post_content' => '',
2767 'post_type' => 'offer',
2768 'post_status' => 'publish',
2769 'comment_status' => 'closed',
2770 'ping_status' => 'closed',
2771 );
2772
2773 // Insert the post into the database
2774 $offer_post_id = wp_insert_post( $offer_post );
2775
2776 if ( is_wp_error($offer_post_id) || $offer_post_id == 0 )
2777 {
2778 $return = array('error' => 'Failed to create offer post. Please try again');
2779 echo json_encode( $return );
2780 die();
2781 }
2782
2783 $amount = preg_replace("/[^0-9]/", '', $_POST['amount']);
2784
2785 add_post_meta( $offer_post_id, '_offer_date_time', $_POST['offer_date'] . ' ' . $_POST['offer_time'] );
2786 add_post_meta( $offer_post_id, '_property_id', $_POST['property_id'] );
2787 add_post_meta( $offer_post_id, '_applicant_contact_id', $applicant_contact_id );
2788 add_post_meta( $offer_post_id, '_amount', $amount );
2789 add_post_meta( $offer_post_id, '_status', 'pending' );
2790 }
2791
2792 $applicant_contacts = array();
2793 foreach ( $applicant_contact_ids as $applicant_contact_id )
2794 {
2795 $applicant_contacts[] = array(
2796 'ID' => $applicant_contact_id,
2797 'post_title' => get_the_title($applicant_contact_id),
2798 'edit_link' => get_edit_post_link( $applicant_contact_id, '' ),
2799 );
2800 }
2801
2802 $return = array('success' => array(
2803 'offer' => array(
2804 'ID' => $offer_post_id,
2805 'edit_link' => get_edit_post_link( $offer_post_id, '' ),
2806 ),
2807 'applicant_contacts' => $applicant_contacts,
2808 ));
2809
2810 echo json_encode( $return );
2811
2812 die();
2813 }
2814
2815 public function record_offer_contact()
2816 {
2817 check_ajax_referer( 'record-offer', 'security' );
2818
2819 $this->json_headers();
2820
2821 // TO DO: Should do validation on server side also
2822 if (empty($_POST['contact_id']))
2823 {
2824 $return = array('error' => 'No contact selected');
2825 echo json_encode( $return );
2826 die();
2827 }
2828
2829 if (empty($_POST['property_ids']))
2830 {
2831 $return = array('error' => 'No property selected');
2832 echo json_encode( $return );
2833 die();
2834 }
2835
2836 // Loop through contacts and create one offer each
2837 // At the moment it's a 1-to-1 relationship, but might support multiple in the future
2838 foreach ( $_POST['property_ids'] as $property_id )
2839 {
2840 // Insert offer record
2841 $offer_post = array(
2842 'post_title' => '',
2843 'post_content' => '',
2844 'post_type' => 'offer',
2845 'post_status' => 'publish',
2846 'comment_status' => 'closed',
2847 'ping_status' => 'closed',
2848 );
2849
2850 // Insert the post into the database
2851 $offer_post_id = wp_insert_post( $offer_post );
2852
2853 if ( is_wp_error($offer_post_id) || $offer_post_id == 0 )
2854 {
2855 $return = array('error' => 'Failed to create offer post. Please try again');
2856 echo json_encode( $return );
2857 die();
2858 }
2859
2860 $amount = preg_replace("/[^0-9]/", '', $_POST['amount']);
2861
2862 add_post_meta( $offer_post_id, '_offer_date_time', $_POST['offer_date'] . ' ' . $_POST['offer_time'] );
2863 add_post_meta( $offer_post_id, '_property_id', $property_id );
2864 add_post_meta( $offer_post_id, '_applicant_contact_id', $_POST['contact_id'] );
2865 add_post_meta( $offer_post_id, '_amount', $amount );
2866 add_post_meta( $offer_post_id, '_status', 'pending' );
2867 }
2868
2869 $properties = array();
2870 foreach ( $_POST['property_ids'] as $property_id )
2871 {
2872 $properties[] = array(
2873 'ID' => $property_id,
2874 'post_title' => get_the_title($property_id),
2875 'edit_link' => get_edit_post_link( $property_id, '' ),
2876 );
2877 }
2878
2879 $return = array('success' => array(
2880 'offer' => array(
2881 'ID' => $offer_post_id,
2882 'edit_link' => get_edit_post_link( $offer_post_id, '' ),
2883 ),
2884 'properties' => $properties,
2885 ));
2886
2887 echo json_encode( $return );
2888
2889 die();
2890 }
2891
2892 public function get_offer_details_meta_box()
2893 {
2894 check_ajax_referer( 'offer-details-meta-box', 'security' );
2895
2896 $offer = new PH_Offer((int)$_POST['offer_id']);
2897
2898 echo '<div class="propertyhive_meta_box">';
2899
2900 echo '<div class="options_group">';
2901
2902 if ( $offer->status != '' )
2903 {
2904 echo '<p class="form-field">
2905
2906 <label for="">' . __('Status', 'propertyhive') . '</label>
2907
2908 ' . ucwords(str_replace("_", " ", $offer->status)) . '
2909
2910 </p>';
2911 }
2912
2913 $offer_date_time = $offer->offer_date_time;
2914 if ( empty($offer_date_time) )
2915 {
2916 $offer_date_time = date("Y-m-d H:i:s");
2917 }
2918
2919 echo '<p class="form-field offer_date_time_field">
2920
2921 <label for="_offer_date">' . __('Offer Date / Time', 'propertyhive') . '</label>
2922
2923 <input type="text" id="_offer_date" name="_offer_date" class="date-picker short" placeholder="yyyy-mm-dd" style="width:120px;" value="' . date("Y-m-d", strtotime($offer_date_time)) . '">
2924 <select id="_offer_time_hours" name="_offer_time_hours" class="select short" style="width:55px">';
2925
2926 if ( empty($offer_date_time) )
2927 {
2928 $value = date("H");
2929 }
2930 else
2931 {
2932 $value = date( "H", strtotime( $offer_date_time ) );
2933 }
2934 for ( $i = 0; $i < 23; ++$i )
2935 {
2936 $j = str_pad($i, 2, '0', STR_PAD_LEFT);
2937 echo '<option value="' . $j . '"';
2938 if ($i == $value) { echo ' selected'; }
2939 echo '>' . $j . '</option>';
2940 }
2941
2942 echo '</select>
2943 :
2944 <select id="_offer_time_minutes" name="_offer_time_minutes" class="select short" style="width:55px">';
2945
2946 if ( empty($offer_date_time) )
2947 {
2948 $value = '';
2949 }
2950 else
2951 {
2952 $value = date( "i", strtotime( $offer_date_time ) );
2953 }
2954 for ( $i = 0; $i < 60; $i+=5 )
2955 {
2956 $j = str_pad($i, 2, '0', STR_PAD_LEFT);
2957 echo '<option value="' . $j . '"';
2958 if ($i == $value) { echo ' selected'; }
2959 echo '>' . $j . '</option>';
2960 }
2961
2962 echo '</select>
2963
2964 </p>';
2965
2966 $args = array(
2967 'id' => '_amount',
2968 'label' => __( 'Offer Amount', 'propertyhive' ) . ' (&pound;)',
2969 'desc_tip' => false,
2970 'class' => 'short',
2971 'value' => ( is_numeric($offer->amount) ? number_format($offer->amount) : '' ),
2972 'custom_attributes' => array(
2973 //'style' => 'width:95%; max-width:500px;'
2974 )
2975 );
2976 propertyhive_wp_text_input( $args );
2977
2978 do_action('propertyhive_offer_details_fields');
2979
2980 echo '</div>';
2981
2982 echo '</div>';
2983
2984 die();
2985 }
2986
2987 public function get_offer_actions()
2988 {
2989 check_ajax_referer( 'offer-actions', 'security' );
2990
2991 $post_id = $_POST['offer_id'];
2992
2993 $status = get_post_meta( $post_id, '_status', TRUE );
2994
2995 echo '<div class="propertyhive_meta_box propertyhive_meta_box_actions" id="propertyhive_offer_actions_meta_box">
2996
2997 <div class="options_group" style="padding-top:8px;">';
2998
2999 $actions = array();
3000
3001 if ( $status == 'pending' )
3002 {
3003 $actions[] = '<a
3004 href="#action_panel_offer_accepted"
3005 class="button button-success offer-action"
3006 style="width:100%; margin-bottom:7px; text-align:center"
3007 >' . __('Accept Offer', 'propertyhive') . '</a>';
3008 $actions[] = '<a
3009 href="#action_panel_offer_declined"
3010 class="button button-danger offer-action"
3011 style="width:100%; margin-bottom:7px; text-align:center"
3012 >' . __('Decline Offer', 'propertyhive') . '</a>';
3013 }
3014
3015 if ( $status == 'accepted' )
3016 {
3017 // See if a sale has this offer id associated with it
3018 $sale_id = get_post_meta( $post_id, '_sale_id', TRUE );
3019 if ( $sale_id != '' && get_post_status($sale_id) != 'publish' )
3020 {
3021 $sale_id = '';
3022 }
3023
3024 if ( $sale_id != '' )
3025 {
3026 $actions[] = '<a
3027 href="' . get_edit_post_link( $sale_id, '' ) . '"
3028 class="button"
3029 style="width:100%; margin-bottom:7px; text-align:center"
3030 >' . __('View Sale', 'propertyhive') . '</a>';
3031 }
3032 else
3033 {
3034 $actions[] = '<a
3035 href="' . wp_nonce_url( admin_url( 'post.php?post=' . $post_id . '&action=edit' ), '1', 'create_sale' ) . '"
3036 class="button button-success"
3037 style="width:100%; margin-bottom:7px; text-align:center"
3038 >' . __('Create Sale', 'propertyhive') . '</a>';
3039 }
3040 }
3041
3042 if ( $status == 'declined' )
3043 {
3044
3045 }
3046
3047 if ( $status == 'accepted' || $status == 'declined' )
3048 {
3049 $actions[] = '<a
3050 href="#action_panel_offer_revert_pending"
3051 class="button offer-action"
3052 style="width:100%; margin-bottom:7px; text-align:center"
3053 >' . __('Revert To Pending', 'propertyhive') . '</a>';
3054 }
3055
3056 $actions = apply_filters( 'propertyhive_admin_offer_actions', $actions, $post->ID );
3057
3058 if ( !empty($actions) )
3059 {
3060 echo implode("", $actions);
3061 }
3062 else
3063 {
3064 echo '<div style="text-align:center">' . __( 'No actions to display', 'propertyhive' ) . '</div>';
3065 }
3066
3067 echo '</div>
3068
3069 </div>';
3070
3071 die();
3072 }
3073
3074 public function offer_accepted()
3075 {
3076 check_ajax_referer( 'offer-actions', 'security' );
3077
3078 $post_id = $_POST['offer_id'];
3079
3080 $status = get_post_meta( $post_id, '_status', TRUE );
3081
3082 if ( $status == 'pending' )
3083 {
3084 update_post_meta( $post_id, '_status', 'accepted' );
3085
3086 $current_user = wp_get_current_user();
3087
3088 // Add note/comment to offer
3089 $comment = array(
3090 'note_type' => 'action',
3091 'action' => 'offer_accepted',
3092 );
3093
3094 $data = array(
3095 'comment_post_ID' => $post_id,
3096 'comment_author' => $current_user->display_name,
3097 'comment_author_email' => 'propertyhive@noreply.com',
3098 'comment_author_url' => '',
3099 'comment_date' => date("Y-m-d H:i:s"),
3100 'comment_content' => serialize($comment),
3101 'comment_approved' => 1,
3102 'comment_type' => 'propertyhive_note',
3103 );
3104 $comment_id = wp_insert_comment( $data );
3105 }
3106
3107 die();
3108 }
3109
3110 public function offer_declined()
3111 {
3112 check_ajax_referer( 'offer-actions', 'security' );
3113
3114 $post_id = $_POST['offer_id'];
3115
3116 $status = get_post_meta( $post_id, '_status', TRUE );
3117
3118 if ( $status == 'pending' )
3119 {
3120 update_post_meta( $post_id, '_status', 'declined' );
3121
3122 $current_user = wp_get_current_user();
3123
3124 // Add note/comment to offer
3125 $comment = array(
3126 'note_type' => 'action',
3127 'action' => 'offer_declined',
3128 );
3129
3130 $data = array(
3131 'comment_post_ID' => $post_id,
3132 'comment_author' => $current_user->display_name,
3133 'comment_author_email' => 'propertyhive@noreply.com',
3134 'comment_author_url' => '',
3135 'comment_date' => date("Y-m-d H:i:s"),
3136 'comment_content' => serialize($comment),
3137 'comment_approved' => 1,
3138 'comment_type' => 'propertyhive_note',
3139 );
3140 $comment_id = wp_insert_comment( $data );
3141 }
3142
3143 die();
3144 }
3145
3146 public function offer_revert_pending()
3147 {
3148 check_ajax_referer( 'offer-actions', 'security' );
3149
3150 $post_id = $_POST['offer_id'];
3151
3152 $status = get_post_meta( $post_id, '_status', TRUE );
3153
3154 if ( $status == 'accepted' || $status == 'declined' )
3155 {
3156 update_post_meta( $post_id, '_status', 'pending' );
3157
3158 $current_user = wp_get_current_user();
3159
3160 // Add note/comment to offer
3161 $comment = array(
3162 'note_type' => 'action',
3163 'action' => 'offer_revert_pending',
3164 );
3165
3166 $data = array(
3167 'comment_post_ID' => $post_id,
3168 'comment_author' => $current_user->display_name,
3169 'comment_author_email' => 'propertyhive@noreply.com',
3170 'comment_author_url' => '',
3171 'comment_date' => date("Y-m-d H:i:s"),
3172 'comment_content' => serialize($comment),
3173 'comment_approved' => 1,
3174 'comment_type' => 'propertyhive_note',
3175 );
3176 $comment_id = wp_insert_comment( $data );
3177 }
3178
3179 die();
3180 }
3181
3182 public function get_property_offers_meta_box()
3183 {
3184 check_ajax_referer( 'get_property_offers_meta_box', 'security' );
3185
3186 global $post;
3187
3188 echo '<div class="propertyhive_meta_box">';
3189
3190 echo '<div class="options_group">';
3191
3192 $args = array(
3193 'post_type' => 'offer',
3194 'nopaging' => true,
3195 'orderby' => 'meta_value',
3196 'order' => 'DESC',
3197 'meta_key' => '_offer_date_time',
3198 'post_status' => 'publish',
3199 'meta_query' => array(
3200 array(
3201 'key' => '_property_id',
3202 'value' => $_POST['post_id']
3203 )
3204 )
3205 );
3206 $offers_query = new WP_Query( $args );
3207
3208 if ( $offers_query->have_posts() )
3209 {
3210 echo '<table style="width:100%">
3211 <thead>
3212 <tr>
3213 <th style="text-align:left;">' . __( 'Offer Date', 'propertyhive' ) . '</th>
3214 <th style="text-align:left;">' . __( 'Applicant', 'propertyhive' ) . '</th>
3215 <th style="text-align:left;">' . __( 'Offer Amount', 'propertyhive' ) . '</th>
3216 <th style="text-align:left;">' . __( 'Status', 'propertyhive' ) . '</th>
3217 </tr>
3218 </thead>
3219 <tbody>';
3220
3221 while ( $offers_query->have_posts() )
3222 {
3223 $offers_query->the_post();
3224
3225 $offer = new PH_Offer(get_the_ID());
3226
3227 echo '<tr>';
3228 echo '<td style="text-align:left;"><a href="' . get_edit_post_link( get_the_ID(), '' ) . '">' . date("jS F Y", strtotime(get_post_meta(get_the_ID(), '_offer_date_time', TRUE))) . '</a></td>';
3229 echo '<td style="text-align:left;"><a href="' . get_edit_post_link( get_post_meta(get_the_ID(), '_applicant_contact_id', TRUE), '' ) . '">' . get_the_title(get_post_meta(get_the_ID(), '_applicant_contact_id', TRUE)) . '</a></td>';
3230 echo '<td style="text-align:left;">' . $offer->get_formatted_amount() . '</td>';
3231 echo '<td style="text-align:left;">';
3232 $status = get_post_meta(get_the_ID(), '_status', TRUE);
3233 echo ucwords(str_replace("_", " ", $status));
3234 echo '</td>';
3235 echo '</tr>';
3236 }
3237
3238 echo '
3239 </tbody>
3240 </table>
3241 <br>';
3242 }
3243 else
3244 {
3245 echo '<p>' . __( 'No offers exist for this property', 'propertyhive') . '</p>';
3246 }
3247 wp_reset_postdata();
3248
3249 do_action('propertyhive_property_offers_fields');
3250
3251 echo '</div>';
3252
3253 echo '</div>';
3254
3255 die();
3256 }
3257
3258 public function get_contact_offers_meta_box()
3259 {
3260 check_ajax_referer( 'get_contact_offers_meta_box', 'security' );
3261
3262 global $post;
3263
3264 echo '<div class="propertyhive_meta_box">';
3265
3266 echo '<div class="options_group">';
3267
3268 $args = array(
3269 'post_type' => 'offer',
3270 'nopaging' => true,
3271 'orderby' => 'meta_value',
3272 'order' => 'DESC',
3273 'post_status' => 'publish',
3274 'meta_key' => '_offer_date_time',
3275 'meta_query' => array(
3276 array(
3277 'key' => '_applicant_contact_id',
3278 'value' => $_POST['post_id']
3279 )
3280 )
3281 );
3282 $offers_query = new WP_Query( $args );
3283
3284 if ( $offers_query->have_posts() )
3285 {
3286 echo '<table style="width:100%">
3287 <thead>
3288 <tr>
3289 <th style="text-align:left;">' . __( 'Offer Date', 'propertyhive' ) . '</th>
3290 <th style="text-align:left;">' . __( 'Property', 'propertyhive' ) . '</th>
3291 <th style="text-align:left;">' . __( 'Property Owner', 'propertyhive' ) . '</th>
3292 <th style="text-align:left;">' . __( 'Offer Amount', 'propertyhive' ) . '</th>
3293 <th style="text-align:left;">' . __( 'Status', 'propertyhive' ) . '</th>
3294 </tr>
3295 </thead>
3296 <tbody>';
3297
3298 while ( $offers_query->have_posts() )
3299 {
3300 $offers_query->the_post();
3301
3302 $property = new PH_Property((int)get_post_meta(get_the_ID(), '_property_id', TRUE));
3303 $offer = new PH_Offer(get_the_ID());
3304
3305 echo '<tr>';
3306 echo '<td style="text-align:left;"><a href="' . get_edit_post_link( get_the_ID(), '') . '">' . date("jS F Y", strtotime(get_post_meta(get_the_ID(), '_offer_date_time', TRUE))) . '</a></td>';
3307 echo '<td style="text-align:left;"><a href="' . get_edit_post_link( get_post_meta(get_the_ID(), '_property_id', TRUE), '' ) . '">' . $property->get_formatted_full_address() . '</a></td>';
3308 echo '<td style="text-align:left;">';
3309
3310 $owner_contact_ids = $property->_owner_contact_id;
3311 if (
3312 ( !is_array($owner_contact_ids) && $owner_contact_ids != '' && $owner_contact_ids != 0 )
3313 ||
3314 ( is_array($owner_contact_ids) && !empty($owner_contact_ids) )
3315 )
3316 {
3317 if ( !is_array($owner_contact_ids) )
3318 {
3319 $owner_contact_ids = array($owner_contact_ids);
3320 }
3321
3322 foreach ( $owner_contact_ids as $owner_contact_id )
3323 {
3324 echo get_the_title($owner_contact_id) . '<br>';
3325 echo '<div style="color:#BBB">';
3326 echo 'T: ' . get_post_meta($owner_contact_id, '_telephone_number', TRUE) . '<br>';
3327 echo 'E: ' . get_post_meta($owner_contact_id, '_email_address', TRUE);
3328 echo '</div>';
3329 }
3330 }
3331
3332 echo '</td>';
3333 echo '<td style="text-align:left;">' . $offer->get_formatted_amount() . '</td>';
3334 echo '<td style="text-align:left;">';
3335 $status = get_post_meta(get_the_ID(), '_status', TRUE);
3336 echo ucwords(str_replace("_", " ", $status));
3337 echo '</td>';
3338 echo '</tr>';
3339 }
3340
3341 echo '
3342 </tbody>
3343 </table>
3344 <br>';
3345 }
3346 else
3347 {
3348 echo '<p>' . __( 'No offers exist for this contact', 'propertyhive') . '</p>';
3349 }
3350 wp_reset_postdata();
3351
3352 do_action('propertyhive_contact_offers_fields');
3353
3354 echo '</div>';
3355
3356 echo '</div>';
3357
3358 die();
3359 }
3360
3361 // Sale related functions
3362 public function get_sale_details_meta_box()
3363 {
3364 check_ajax_referer( 'sale-details-meta-box', 'security' );
3365
3366 $sale = new PH_Offer((int)$_POST['sale_id']);
3367
3368 echo '<div class="propertyhive_meta_box">';
3369
3370 echo '<div class="options_group">';
3371
3372 if ( $sale->status != '' )
3373 {
3374 echo '<p class="form-field">
3375
3376 <label for="">' . __('Status', 'propertyhive') . '</label>
3377
3378 ' . ucwords(str_replace("_", " ", $sale->status)) . '
3379
3380 </p>';
3381 }
3382
3383 $sale_date_time = $sale->sale_date_time;
3384 if ( empty($sale_date_time) )
3385 {
3386 $sale_date_time = date("Y-m-d H:i:s");
3387 }
3388
3389 echo '<p class="form-field sale_date_field">
3390
3391 <label for="_sale_date">' . __('Sale Date', 'propertyhive') . '</label>
3392
3393 <input type="text" id="_sale_date" name="_sale_date" class="date-picker short" placeholder="yyyy-mm-dd" style="width:120px;" value="' . date("Y-m-d", strtotime($sale_date_time)) . '">
3394
3395 </p>';
3396
3397 $args = array(
3398 'id' => '_amount',
3399 'label' => __( 'Sale Amount', 'propertyhive' ) . ' (&pound;)',
3400 'desc_tip' => false,
3401 'class' => 'short',
3402 'value' => ( is_numeric($sale->amount) ? number_format($sale->amount) : '' ),
3403 'custom_attributes' => array(
3404 //'style' => 'width:95%; max-width:500px;'
3405 )
3406 );
3407 propertyhive_wp_text_input( $args );
3408
3409 do_action('propertyhive_sale_details_fields');
3410
3411 echo '</div>';
3412
3413 echo '</div>';
3414
3415 die();
3416 }
3417
3418 public function get_sale_actions()
3419 {
3420 check_ajax_referer( 'sale-actions', 'security' );
3421
3422 $post_id = $_POST['sale_id'];
3423
3424 $status = get_post_meta( $post_id, '_status', TRUE );
3425
3426 echo '<div class="propertyhive_meta_box propertyhive_meta_box_actions" id="propertyhive_sale_actions_meta_box">
3427
3428 <div class="options_group" style="padding-top:8px;">';
3429
3430 $actions = array();
3431
3432 if ( $status == 'current' )
3433 {
3434 $actions[] = '<a
3435 href="#action_panel_sale_exchanged"
3436 class="button button-success sale-action"
3437 style="width:100%; margin-bottom:7px; text-align:center"
3438 >' . __('Sale Exchanged', 'propertyhive') . '</a>';
3439
3440 }
3441
3442 if ( $status == 'exchanged' )
3443 {
3444 $actions[] = '<a
3445 href="#action_panel_sale_completed"
3446 class="button button-success sale-action"
3447 style="width:100%; margin-bottom:7px; text-align:center"
3448 >' . __('Sale Completed', 'propertyhive') . '</a>';
3449 }
3450
3451 if ( $status == 'completed' )
3452 {
3453
3454 }
3455
3456 if ( $status == 'current' || $status == 'exchanged' )
3457 {
3458 $actions[] = '<a
3459 href="#action_panel_sale_fallen_through"
3460 class="button sale-action"
3461 style="width:100%; margin-bottom:7px; text-align:center"
3462 >' . __('Sale Fallen Through', 'propertyhive') . '</a>';
3463 }
3464
3465 $actions = apply_filters( 'propertyhive_admin_sale_actions', $actions, $post->ID );
3466
3467 if ( !empty($actions) )
3468 {
3469 echo implode("", $actions);
3470 }
3471 else
3472 {
3473 echo '<div style="text-align:center">' . __( 'No actions to display', 'propertyhive' ) . '</div>';
3474 }
3475
3476 echo '</div>
3477
3478 </div>';
3479
3480 die();
3481 }
3482
3483 public function sale_exchanged()
3484 {
3485 check_ajax_referer( 'sale-actions', 'security' );
3486
3487 $post_id = $_POST['sale_id'];
3488
3489 $status = get_post_meta( $post_id, '_status', TRUE );
3490
3491 if ( $status == 'current' )
3492 {
3493 update_post_meta( $post_id, '_status', 'exchanged' );
3494
3495 $current_user = wp_get_current_user();
3496
3497 // Add note/comment to sale
3498 $comment = array(
3499 'note_type' => 'action',
3500 'action' => 'sale_exchanged',
3501 );
3502
3503 $data = array(
3504 'comment_post_ID' => $post_id,
3505 'comment_author' => $current_user->display_name,
3506 'comment_author_email' => 'propertyhive@noreply.com',
3507 'comment_author_url' => '',
3508 'comment_date' => date("Y-m-d H:i:s"),
3509 'comment_content' => serialize($comment),
3510 'comment_approved' => 1,
3511 'comment_type' => 'propertyhive_note',
3512 );
3513 $comment_id = wp_insert_comment( $data );
3514 }
3515
3516 die();
3517 }
3518
3519 public function sale_completed()
3520 {
3521 check_ajax_referer( 'sale-actions', 'security' );
3522
3523 $post_id = $_POST['sale_id'];
3524
3525 $status = get_post_meta( $post_id, '_status', TRUE );
3526
3527 if ( $status == 'exchanged' )
3528 {
3529 update_post_meta( $post_id, '_status', 'completed' );
3530
3531 $current_user = wp_get_current_user();
3532
3533 // Add note/comment to sale
3534 $comment = array(
3535 'note_type' => 'action',
3536 'action' => 'sale_completed',
3537 );
3538
3539 $data = array(
3540 'comment_post_ID' => $post_id,
3541 'comment_author' => $current_user->display_name,
3542 'comment_author_email' => 'propertyhive@noreply.com',
3543 'comment_author_url' => '',
3544 'comment_date' => date("Y-m-d H:i:s"),
3545 'comment_content' => serialize($comment),
3546 'comment_approved' => 1,
3547 'comment_type' => 'propertyhive_note',
3548 );
3549 $comment_id = wp_insert_comment( $data );
3550 }
3551
3552 die();
3553 }
3554
3555 public function sale_fallen_through()
3556 {
3557 check_ajax_referer( 'sale-actions', 'security' );
3558
3559 $post_id = $_POST['sale_id'];
3560
3561 $status = get_post_meta( $post_id, '_status', TRUE );
3562
3563 if ( $status == 'current' || $status == 'exchanged' )
3564 {
3565 update_post_meta( $post_id, '_status', 'fallen_through' );
3566
3567 $current_user = wp_get_current_user();
3568
3569 // Add note/comment to sale
3570 $comment = array(
3571 'note_type' => 'action',
3572 'action' => 'sale_fallen_through',
3573 );
3574
3575 $data = array(
3576 'comment_post_ID' => $post_id,
3577 'comment_author' => $current_user->display_name,
3578 'comment_author_email' => 'propertyhive@noreply.com',
3579 'comment_author_url' => '',
3580 'comment_date' => date("Y-m-d H:i:s"),
3581 'comment_content' => serialize($comment),
3582 'comment_approved' => 1,
3583 'comment_type' => 'propertyhive_note',
3584 );
3585 $comment_id = wp_insert_comment( $data );
3586 }
3587
3588 die();
3589 }
3590
3591 public function get_property_sales_meta_box()
3592 {
3593 check_ajax_referer( 'get_property_sales_meta_box', 'security' );
3594
3595 global $post;
3596
3597 echo '<div class="propertyhive_meta_box">';
3598
3599 echo '<div class="options_group">';
3600
3601 $args = array(
3602 'post_type' => 'sale',
3603 'nopaging' => true,
3604 'orderby' => 'meta_value',
3605 'order' => 'DESC',
3606 'meta_key' => '_sale_date_time',
3607 'post_status' => 'publish',
3608 'meta_query' => array(
3609 array(
3610 'key' => '_property_id',
3611 'value' => $_POST['post_id']
3612 )
3613 )
3614 );
3615 $sales_query = new WP_Query( $args );
3616
3617 if ( $sales_query->have_posts() )
3618 {
3619 echo '<table style="width:100%">
3620 <thead>
3621 <tr>
3622 <th style="text-align:left;">' . __( 'Sale Date', 'propertyhive' ) . '</th>
3623 <th style="text-align:left;">' . __( 'Applicant', 'propertyhive' ) . '</th>
3624 <th style="text-align:left;">' . __( 'Sale Amount', 'propertyhive' ) . '</th>
3625 <th style="text-align:left;">' . __( 'Status', 'propertyhive' ) . '</th>
3626 </tr>
3627 </thead>
3628 <tbody>';
3629
3630 while ( $sales_query->have_posts() )
3631 {
3632 $sales_query->the_post();
3633
3634 $sale = new PH_Sale(get_the_ID());
3635
3636 echo '<tr>';
3637 echo '<td style="text-align:left;"><a href="' . get_edit_post_link( get_the_ID(), '' ) . '">' . date("jS F Y", strtotime(get_post_meta(get_the_ID(), '_sale_date_time', TRUE))) . '</a></td>';
3638 echo '<td style="text-align:left;"><a href="' . get_edit_post_link( get_post_meta(get_the_ID(), '_applicant_contact_id', TRUE), '' ) . '">' . get_the_title(get_post_meta(get_the_ID(), '_applicant_contact_id', TRUE)) . '</a></td>';
3639 echo '<td style="text-align:left;">' . $sale->get_formatted_amount() . '</td>';
3640 echo '<td style="text-align:left;">';
3641 $status = get_post_meta(get_the_ID(), '_status', TRUE);
3642 echo ucwords(str_replace("_", " ", $status));
3643 echo '</td>';
3644 echo '</tr>';
3645 }
3646
3647 echo '
3648 </tbody>
3649 </table>
3650 <br>';
3651 }
3652 else
3653 {
3654 echo '<p>' . __( 'No sales exist for this property', 'propertyhive') . '</p>';
3655 }
3656 wp_reset_postdata();
3657
3658 do_action('propertyhive_property_sales_fields');
3659
3660 echo '</div>';
3661
3662 echo '</div>';
3663
3664 die();
3665 }
3666
3667 public function get_contact_sales_meta_box()
3668 {
3669 check_ajax_referer( 'get_contact_sales_meta_box', 'security' );
3670
3671 global $post;
3672
3673 echo '<div class="propertyhive_meta_box">';
3674
3675 echo '<div class="options_group">';
3676
3677 $args = array(
3678 'post_type' => 'sale',
3679 'nopaging' => true,
3680 'orderby' => 'meta_value',
3681 'order' => 'DESC',
3682 'post_status' => 'publish',
3683 'meta_key' => '_sale_date_time',
3684 'meta_query' => array(
3685 array(
3686 'key' => '_applicant_contact_id',
3687 'value' => $_POST['post_id']
3688 )
3689 )
3690 );
3691 $sales_query = new WP_Query( $args );
3692
3693 if ( $sales_query->have_posts() )
3694 {
3695 echo '<table style="width:100%">
3696 <thead>
3697 <tr>
3698 <th style="text-align:left;">' . __( 'Offer Date', 'propertyhive' ) . '</th>
3699 <th style="text-align:left;">' . __( 'Property', 'propertyhive' ) . '</th>
3700 <th style="text-align:left;">' . __( 'Property Owner', 'propertyhive' ) . '</th>
3701 <th style="text-align:left;">' . __( 'Offer Amount', 'propertyhive' ) . '</th>
3702 <th style="text-align:left;">' . __( 'Status', 'propertyhive' ) . '</th>
3703 </tr>
3704 </thead>
3705 <tbody>';
3706
3707 while ( $sales_query->have_posts() )
3708 {
3709 $sales_query->the_post();
3710
3711 $sale = new PH_Sale(get_the_ID());
3712
3713 $property = new PH_Property((int)get_post_meta(get_the_ID(), '_property_id', TRUE));
3714
3715 echo '<tr>';
3716 echo '<td style="text-align:left;"><a href="' . get_edit_post_link( get_the_ID(), '') . '">' . date("jS F Y", strtotime(get_post_meta(get_the_ID(), '_sale_date_time', TRUE))) . '</a></td>';
3717 echo '<td style="text-align:left;"><a href="' . get_edit_post_link( get_post_meta(get_the_ID(), '_property_id', TRUE), '' ) . '">' . $property->get_formatted_full_address() . '</a></td>';
3718 echo '<td style="text-align:left;">';
3719
3720 $owner_contact_ids = $property->_owner_contact_id;
3721 if (
3722 ( !is_array($owner_contact_ids) && $owner_contact_ids != '' && $owner_contact_ids != 0 )
3723 ||
3724 ( is_array($owner_contact_ids) && !empty($owner_contact_ids) )
3725 )
3726 {
3727 if ( !is_array($owner_contact_ids) )
3728 {
3729 $owner_contact_ids = array($owner_contact_ids);
3730 }
3731
3732 foreach ( $owner_contact_ids as $owner_contact_id )
3733 {
3734 echo get_the_title($owner_contact_id) . '<br>';
3735 echo '<div style="color:#BBB">';
3736 echo 'T: ' . get_post_meta($owner_contact_id, '_telephone_number', TRUE) . '<br>';
3737 echo 'E: ' . get_post_meta($owner_contact_id, '_email_address', TRUE);
3738 echo '</div>';
3739 }
3740 }
3741
3742 echo '</td>';
3743 echo '<td style="text-align:left;">' . $sale->get_formatted_amount() . '</td>';
3744 echo '<td style="text-align:left;">';
3745 $status = get_post_meta(get_the_ID(), '_status', TRUE);
3746 echo ucwords(str_replace("_", " ", $status));
3747 echo '</td>';
3748 echo '</tr>';
3749 }
3750
3751 echo '
3752 </tbody>
3753 </table>
3754 <br>';
3755 }
3756 else
3757 {
3758 echo '<p>' . __( 'No sales exist for this contact', 'propertyhive') . '</p>';
3759 }
3760 wp_reset_postdata();
3761
3762 do_action('propertyhive_contact_sales_fields');
3763
3764 echo '</div>';
3765
3766 echo '</div>';
3767
3768 die();
3769 }
3770 }
3771
3772 new PH_AJAX();
3773