PluginProbe
Property Hive / 1.4.5
Property Hive v1.4.5
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.5, at includes/class-ph-ajax.php

3,770 lines 133.2 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 $headers[] = 'Reply-To: ' . sanitize_email( $_POST['email_address'] );
1257
1258 $to = apply_filters( 'propertyhive_property_enquiry_to', $to, $_POST['property_id'] );
1259 $subject = apply_filters( 'propertyhive_property_enquiry_subject', $subject, $_POST['property_id'] );
1260 $message = apply_filters( 'propertyhive_property_enquiry_body', $message, $_POST['property_id'] );
1261 $headers = apply_filters( 'propertyhive_property_enquiry_headers', $headers, $_POST['property_id'] );
1262
1263 $sent = wp_mail( $to, $subject, $message, $headers );
1264
1265 if ( ! $sent )
1266 {
1267 $return['success'] = false;
1268 $return['reason'] = 'nosend';
1269 $return['errors'] = $errors;
1270 }
1271 else
1272 {
1273 $return['success'] = true;
1274
1275 // Now insert into enquiries section of WordPress
1276 $title = __( 'Property Enquiry', 'propertyhive' ) . ': ' . get_the_title( $_POST['property_id'] );
1277 if ( isset($_POST['name']) && ! empty($_POST['name']) )
1278 {
1279 $title .= __( ' from ', 'propertyhive' ) . sanitize_text_field($_POST['name']);
1280 }
1281
1282 $enquiry_post = array(
1283 'post_title' => $title,
1284 'post_content' => '',
1285 'post_type' => 'enquiry',
1286 'post_status' => 'publish',
1287 'comment_status' => 'closed',
1288 'ping_status' => 'closed',
1289 );
1290
1291 // Insert the post into the database
1292 $enquiry_post_id = wp_insert_post( $enquiry_post );
1293
1294 add_post_meta( $enquiry_post_id, '_status', 'open' );
1295 add_post_meta( $enquiry_post_id, '_source', 'website' );
1296 add_post_meta( $enquiry_post_id, '_negotiator_id', '' );
1297 add_post_meta( $enquiry_post_id, '_office_id', $office_id );
1298
1299 foreach ($_POST as $key => $value)
1300 {
1301 add_post_meta( $enquiry_post_id, $key, $value );
1302 }
1303
1304 // Send auto-responder
1305 if ( get_option( 'propertyhive_enquiry_auto_responder', '' ) == 'yes' )
1306 {
1307 // Auto-responder enabled
1308 PH()->email->send_enquiry_auto_responder( $_POST );
1309 }
1310 }
1311 }
1312
1313 $this->json_headers();
1314 echo json_encode( $return );
1315
1316 // Quit out
1317 die();
1318 }
1319
1320 /**
1321 * Create contact from enquiry
1322 */
1323 public function create_contact_from_enquiry()
1324 {
1325 global $post;
1326
1327 $enquiry_post_id = ( (isset($_POST['post_id'])) ? $_POST['post_id'] : '' );
1328 $nonce = ( (isset($_POST['security'])) ? $_POST['security'] : '' );
1329
1330 if ( ! wp_verify_nonce( $nonce, 'create-content-from-enquiry-nonce-' . $enquiry_post_id ) )
1331 {
1332 // This nonce is not valid.
1333 die( json_encode( array('error' => 'Invalid nonce. Please refresh and try again') ) );
1334 }
1335
1336 $enquiry_meta = get_metadata( 'post', $enquiry_post_id );
1337
1338 $name = false;
1339 $email = false;
1340 $telephone = false;
1341
1342 foreach ($enquiry_meta as $key => $value)
1343 {
1344 if ( strpos($key, 'name') !== false )
1345 {
1346 $name = $value[0];
1347 }
1348 elseif ( strpos($key, 'email') !== false )
1349 {
1350 $email = $value[0];
1351 }
1352 elseif ( strpos($key, 'telephone') !== false )
1353 {
1354 $telephone = $value[0];
1355 }
1356 }
1357
1358 if ( $name === false || $email === false )
1359 {
1360 // This nonce is not valid.
1361 die( json_encode( array('error' => 'Name or email address not found') ) );
1362 }
1363
1364 // We've not imported this property before
1365 $postdata = array(
1366 'post_excerpt' => '',
1367 'post_content' => '',
1368 'post_title' => utf8_encode(wp_strip_all_tags( $name )),
1369 'post_status' => 'publish',
1370 'post_type' => 'contact',
1371 'ping_status' => 'closed',
1372 'comment_status' => 'closed',
1373 );
1374
1375 $contact_post_id = wp_insert_post( $postdata, true );
1376
1377 if ( is_wp_error( $contact_post_id ) )
1378 {
1379 die( json_encode( array('error' => 'Error creating contact') ) );
1380 }
1381 elseif ( $contact_post_id == 0 )
1382 {
1383 die( json_encode( array('error' => 'Error creating contact') ) );
1384 }
1385
1386 if ( $telephone !== FALSE ) { update_post_meta( $contact_post_id, '_telephone_number', $telephone ); }
1387 if ( $email !== FALSE ) { update_post_meta( $contact_post_id, '_email_address', $email ); }
1388
1389 die( json_encode( array('success' => get_edit_post_link($contact_post_id, '')) ) );
1390 }
1391
1392 public function validate_save_contact()
1393 {
1394 global $post;
1395
1396 check_ajax_referer( 'contact-save-validation', 'security' );
1397
1398 $this->json_headers();
1399
1400 parse_str($_POST['form_data']);
1401 var_dump();
1402 $return = array('errors' => array());
1403
1404 if ( isset($_email_address) && $_email_address != '' )
1405 {
1406 $email_addresses = explode( ",", $_email_address );
1407
1408 foreach ( $email_addresses as $email_address )
1409 {
1410 $email_address = trim( $email_address );
1411
1412 if ( !is_email($email_address) )
1413 {
1414 $return['errors'][] = __( 'Email address is invalid', 'propertyhive' ) . ' - ' . $email_address;
1415 }
1416
1417 // Check it doesn't exist already
1418 $args = array(
1419 'post_type' => 'contact',
1420 'post_status' => 'any',
1421 'posts_per_page' => 1,
1422 'fields' => 'ids',
1423 'meta_query' => array(
1424 'relation' => 'OR',
1425 array(
1426 'key' => '_email_address',
1427 'value' => $email_address,
1428 'compare' => '='
1429 ),
1430 array(
1431 'key' => '_email_address',
1432 'value' => ',' . $email_address,
1433 'compare' => 'LIKE'
1434 )
1435 ,
1436 array(
1437 'key' => '_email_address',
1438 'value' => $email_address . ',',
1439 'compare' => 'LIKE'
1440 )
1441 )
1442 );
1443 if ( isset($post_ID) && $post_ID != '' )
1444 {
1445 $args['post__not_in'] = array( $post_ID );
1446 }
1447
1448 $contact_query = new WP_Query( $args );
1449
1450 if ( $contact_query->have_posts() )
1451 {
1452 while ( $contact_query->have_posts() )
1453 {
1454 $contact_query->the_post();
1455
1456 $return['errors'][] = __( 'A contact, ' . get_the_title() . ', already exists with email address', 'propertyhive' ) . ' ' . $email_address;
1457 }
1458 }
1459 }
1460 }
1461
1462 echo json_encode($return);
1463
1464 die();
1465 }
1466
1467 // Dashboard related functions
1468 public function get_news()
1469 {
1470 $this->json_headers();
1471
1472 include_once( ABSPATH . WPINC . '/feed.php' );
1473
1474 $return = array();
1475
1476 // Get a SimplePie feed object from the specified feed source.
1477 $rss = fetch_feed( 'https://wp-property-hive.com/category/property-hive-news/feed/' );
1478
1479 $maxitems = 0;
1480
1481 if ( ! is_wp_error( $rss ) ) : // Checks that the object is created correctly
1482
1483 // Figure out how many total items there are, but limit it to 5.
1484 $maxitems = $rss->get_item_quantity( 5 );
1485
1486 // Build an array of all the items, starting with element 0 (first element).
1487 $rss_items = $rss->get_items( 0, $maxitems );
1488
1489 foreach ( $rss_items as $item )
1490 {
1491 $return[] = array(
1492 'title' => esc_html( $item->get_title() ),
1493 'permalink' => esc_url( $item->get_permalink() ),
1494 'date' => $item->get_date('F d, Y')
1495 );
1496 }
1497
1498 endif;
1499
1500 echo json_encode($return);
1501
1502 die();
1503 }
1504
1505 public function get_viewings_awaiting_applicant_feedback()
1506 {
1507 global $post;
1508
1509 $this->json_headers();
1510
1511 $return = array();
1512
1513 $args = array(
1514 'post_type' => 'viewing',
1515 'fields' => 'ids',
1516 'post_status' => 'publish',
1517 'meta_query' => array(
1518 array(
1519 'key' => '_status',
1520 'value' => 'carried_out'
1521 ),
1522 array(
1523 'key' => '_feedback_status',
1524 'value' => ''
1525 )
1526 )
1527 );
1528
1529 $viewings_query = new WP_Query( $args );
1530
1531 if ( $viewings_query->have_posts() )
1532 {
1533 while ( $viewings_query->have_posts() )
1534 {
1535 $viewings_query->the_post();
1536
1537 $property_id = get_post_meta( get_the_ID(), '_property_id', TRUE );
1538 $property = new PH_Property((int)$property_id);
1539
1540 $applicant_contact_id = get_post_meta( get_the_ID(), '_applicant_contact_id', TRUE );
1541
1542 $return[] = array(
1543 'ID' => get_the_ID(),
1544 'edit_link' => get_edit_post_link( get_the_ID() ),
1545 'start_date_time' => get_post_meta( get_the_ID(), '_start_date_time', TRUE ),
1546 'start_date_time_formatted_Hi_jSFY' => date("H:i jS F Y", strtotime(get_post_meta( get_the_ID(), '_start_date_time', TRUE ))),
1547 'property_id' => $property_id,
1548 'property_address' => $property->get_formatted_full_address(),
1549 'applicant_contact_id' => $applicant_contact_id,
1550 'applicant_name' => get_the_title( $applicant_contact_id ),
1551 );
1552 }
1553 }
1554
1555 wp_reset_postdata();
1556
1557 echo json_encode($return);
1558
1559 die();
1560 }
1561
1562 // Viewing related functions
1563 public function book_viewing_property()
1564 {
1565 check_ajax_referer( 'book-viewing', 'security' );
1566
1567 $this->json_headers();
1568
1569 // TO DO: Should do validation on server side also
1570 if (empty($_POST['property_id']))
1571 {
1572 $return = array('error' => 'No property selected');
1573 echo json_encode( $return );
1574 die();
1575 }
1576
1577 $property = new PH_Property((int)$_POST['property_id']);
1578
1579 $applicant_contact_ids = array();
1580
1581 // Create applicant record if required
1582 if (empty($_POST['applicant_ids']) && !empty($_POST['applicant_name']))
1583 {
1584 // Need to create contact/applicant
1585 $contact_post = array(
1586 'post_title' => wp_strip_all_tags($_POST['applicant_name']),
1587 'post_content' => '',
1588 'post_type' => 'contact',
1589 'post_status' => 'publish',
1590 'comment_status' => 'closed',
1591 'ping_status' => 'closed',
1592 );
1593
1594 // Insert the post into the database
1595 $contact_post_id = wp_insert_post( $contact_post );
1596
1597 if ( is_wp_error($contact_post_id) || $contact_post_id == 0 )
1598 {
1599 $return = array('error' => 'Failed to create contact post. Please try again');
1600 echo json_encode( $return );
1601 die();
1602 }
1603
1604 update_post_meta( $contact_post_id, '_contact_types', array('applicant') );
1605
1606 update_post_meta( $contact_post_id, '_applicant_profiles', 1 );
1607 update_post_meta( $contact_post_id, '_applicant_profile_0', array( 'department' => $property->department, 'send_matching_properties' => '' ) );
1608
1609 $applicant_contact_ids[] = $contact_post_id;
1610 }
1611
1612 if (!empty($_POST['applicant_ids']) && empty($_POST['applicant_name']))
1613 {
1614 // This is an existing contact
1615 if ( !is_array($_POST['applicant_ids']) )
1616 {
1617 $_POST['applicant_ids'] = array($_POST['applicant_ids']);
1618 }
1619
1620 foreach ( $_POST['applicant_ids'] as $applicant_id )
1621 {
1622 $applicant_contact_ids[] = $applicant_id;
1623 }
1624 }
1625
1626 $applicant_contact_ids = array_unique($applicant_contact_ids);
1627
1628 if ( empty($applicant_contact_ids) )
1629 {
1630 $return = array('error' => 'No applicant selected, or unable to create applicant record');
1631 echo json_encode( $return );
1632 die();
1633 }
1634
1635 // Make sure each of the contacts has an applicant profile of the correct department
1636 /*foreach ( $applicant_contact_ids as $applicant_contact_id )
1637 {
1638 $has_correct_profile = false;
1639
1640 // Get all existing profiles
1641 $existing_contact_types = get_post_meta( $applicant_contact_id, '_contact_types', TRUE );
1642 if ( $existing_contact_types == '' || !is_array($existing_contact_types) )
1643 {
1644 $existing_contact_types = array();
1645 }
1646 if ( in_array( 'applicant', $existing_contact_types ) )
1647 {
1648 $num_applicant_profiles = get_post_meta( $applicant_contact_id, '_applicant_profiles', TRUE );
1649 if ( $num_applicant_profiles == '' )
1650 {
1651 $num_applicant_profiles = 0;
1652 }
1653
1654 if ( $num_applicant_profiles > 0 )
1655 {
1656 for ( $i = 0; $i < $num_applicant_profiles; ++$i )
1657 {
1658 $applicant_profile = get_post_meta( $applicant_contact_id, '_applicant_profile_' . $i, TRUE );
1659 if ( $applicant_profile['department'] == $property->department )
1660 {
1661 $has_correct_profile = true;
1662 }
1663 }
1664 }
1665 }
1666
1667 if ( !$has_correct_profile )
1668 {
1669 if ( in_array( 'applicant', $existing_contact_types ) )
1670 {
1671 // Already an applicant. Just need to add profile
1672 }
1673 else
1674 {
1675 $existing_contact_types[] = 'applicant';
1676 update_post_meta( $applicant_contact_id, '_contact_types', $existing_contact_types );
1677 }
1678
1679 $num_applicant_profiles = get_post_meta( $applicant_contact_id, '_applicant_profiles', TRUE );
1680 if ( $num_applicant_profiles == '' )
1681 {
1682 $num_applicant_profiles = 0;
1683 }
1684
1685 update_post_meta( $applicant_contact_id, '_applicant_profiles', $num_applicant_profiles + 1 );
1686 update_post_meta( $applicant_contact_id, '_applicant_profile_' . $num_applicant_profiles, array( 'department' => $property->department ) );
1687 }
1688 }*/
1689
1690 // Loop through contacts and create one viewing each
1691 // At the moment it's a 1-to-1 relationship, but might support multiple in the future
1692 foreach ( $applicant_contact_ids as $applicant_contact_id )
1693 {
1694 // Insert viewing record
1695 $viewing_post = array(
1696 'post_title' => '',
1697 'post_content' => '',
1698 'post_type' => 'viewing',
1699 'post_status' => 'publish',
1700 'comment_status' => 'closed',
1701 'ping_status' => 'closed',
1702 );
1703
1704 // Insert the post into the database
1705 $viewing_post_id = wp_insert_post( $viewing_post );
1706
1707 if ( is_wp_error($viewing_post_id) || $viewing_post_id == 0 )
1708 {
1709 $return = array('error' => 'Failed to create viewing post. Please try again');
1710 echo json_encode( $return );
1711 die();
1712 }
1713
1714 add_post_meta( $viewing_post_id, '_start_date_time', $_POST['start_date'] . ' ' . $_POST['start_time'] );
1715 add_post_meta( $viewing_post_id, '_duration', 30 * 60 ); // Stored in seconds. Default to 30 mins
1716 add_post_meta( $viewing_post_id, '_property_id', $_POST['property_id'] );
1717 add_post_meta( $viewing_post_id, '_applicant_contact_id', $applicant_contact_id );
1718 add_post_meta( $viewing_post_id, '_status', 'pending' );
1719 add_post_meta( $viewing_post_id, '_feedback_status', '' );
1720 add_post_meta( $viewing_post_id, '_feedback', '' );
1721 add_post_meta( $viewing_post_id, '_feedback_passed_on', '' );
1722
1723 if ( !empty($_POST['negotiator_ids']) )
1724 {
1725 foreach ( $_POST['negotiator_ids'] as $negotiator_id )
1726 {
1727 add_post_meta( $viewing_post_id, '_negotiator_id', $negotiator_id );
1728 }
1729 }
1730 }
1731
1732 $applicant_contacts = array();
1733 foreach ( $applicant_contact_ids as $applicant_contact_id )
1734 {
1735 $applicant_contacts[] = array(
1736 'ID' => $applicant_contact_id,
1737 'post_title' => get_the_title($applicant_contact_id),
1738 'edit_link' => get_edit_post_link( $applicant_contact_id, '' ),
1739 );
1740 }
1741
1742 $return = array('success' => array(
1743 'viewing' => array(
1744 'ID' => $viewing_post_id,
1745 'edit_link' => get_edit_post_link( $viewing_post_id, '' ),
1746 ),
1747 'applicant_contacts' => $applicant_contacts,
1748 ));
1749
1750 echo json_encode( $return );
1751
1752 die();
1753 }
1754
1755 public function book_viewing_contact()
1756 {
1757 check_ajax_referer( 'book-viewing', 'security' );
1758
1759 $this->json_headers();
1760
1761 // TO DO: Should do validation on server side also
1762 if (empty($_POST['contact_id']))
1763 {
1764 $return = array('error' => 'No contact selected');
1765 echo json_encode( $return );
1766 die();
1767 }
1768
1769 if (empty($_POST['property_ids']))
1770 {
1771 $return = array('error' => 'No property selected');
1772 echo json_encode( $return );
1773 die();
1774 }
1775
1776 // Loop through contacts and create one viewing each
1777 // At the moment it's a 1-to-1 relationship, but might support multiple in the future
1778 foreach ( $_POST['property_ids'] as $property_id )
1779 {
1780 // Insert viewing record
1781 $viewing_post = array(
1782 'post_title' => '',
1783 'post_content' => '',
1784 'post_type' => 'viewing',
1785 'post_status' => 'publish',
1786 'comment_status' => 'closed',
1787 'ping_status' => 'closed',
1788 );
1789
1790 // Insert the post into the database
1791 $viewing_post_id = wp_insert_post( $viewing_post );
1792
1793 if ( is_wp_error($viewing_post_id) || $viewing_post_id == 0 )
1794 {
1795 $return = array('error' => 'Failed to create viewing post. Please try again');
1796 echo json_encode( $return );
1797 die();
1798 }
1799
1800 add_post_meta( $viewing_post_id, '_start_date_time', $_POST['start_date'] . ' ' . $_POST['start_time'] );
1801 add_post_meta( $viewing_post_id, '_duration', 30 * 60 ); // Stored in seconds. Default to 30 mins
1802 add_post_meta( $viewing_post_id, '_property_id', $property_id );
1803 add_post_meta( $viewing_post_id, '_applicant_contact_id', $_POST['contact_id'] );
1804 add_post_meta( $viewing_post_id, '_status', 'pending' );
1805 add_post_meta( $viewing_post_id, '_feedback_status', '' );
1806 add_post_meta( $viewing_post_id, '_feedback', '' );
1807 add_post_meta( $viewing_post_id, '_feedback_passed_on', '' );
1808
1809 if ( !empty($_POST['negotiator_ids']) )
1810 {
1811 foreach ( $_POST['negotiator_ids'] as $negotiator_id )
1812 {
1813 add_post_meta( $viewing_post_id, '_negotiator_id', $negotiator_id );
1814 }
1815 }
1816 }
1817
1818 $properties = array();
1819 foreach ( $_POST['property_ids'] as $property_id )
1820 {
1821 $properties[] = array(
1822 'ID' => $property_id,
1823 'post_title' => get_the_title($property_id),
1824 'edit_link' => get_edit_post_link( $property_id, '' ),
1825 );
1826 }
1827
1828 $return = array('success' => array(
1829 'viewing' => array(
1830 'ID' => $viewing_post_id,
1831 'edit_link' => get_edit_post_link( $viewing_post_id, '' ),
1832 ),
1833 'properties' => $properties,
1834 ));
1835
1836 echo json_encode( $return );
1837
1838 die();
1839 }
1840
1841 public function get_viewing_details_meta_box()
1842 {
1843 check_ajax_referer( 'viewing-details-meta-box', 'security' );
1844
1845 $viewing = new PH_Viewing((int)$_POST['viewing_id']);
1846
1847 echo '<div class="propertyhive_meta_box">';
1848
1849 echo '<div class="options_group">';
1850
1851 echo '<p class="form-field">
1852
1853 <label for="">' . __('Status', 'propertyhive') . '</label>
1854
1855 ' . ucwords(str_replace("_", " ", $viewing->status));
1856
1857 if ( $viewing->status == 'offer_made' )
1858 {
1859 if ( get_option('propertyhive_module_disabled_offers_sales', '') != 'yes' )
1860 {
1861 $offer_id = get_post_meta( $viewing->id, '_offer_id', TRUE );
1862 if ( $offer_id != '' && get_post_status($offer_id) != 'publish' )
1863 {
1864 $offer_id = '';
1865 }
1866
1867 if ( $offer_id != '' )
1868 {
1869 echo ' (<a href="' . get_edit_post_link($offer_id) . '">' . __('View Offer', 'propertyhive') . '</a>)';
1870 }
1871 }
1872 }
1873
1874 echo '</p>';
1875
1876 if ( $viewing->status == 'carried_out' )
1877 {
1878 echo '<p class="form-field">
1879
1880 <label for="">' . __('Applicant Feedback', 'propertyhive') . '</label>';
1881
1882 switch ( $viewing->feedback_status )
1883 {
1884 case "interested":
1885 {
1886 echo 'Interested';
1887 break;
1888 }
1889 case "not_interested":
1890 {
1891 echo 'Not Interested';
1892 break;
1893 }
1894 case "not_required":
1895 {
1896 echo 'Feedback Not Required';
1897 break;
1898 }
1899 default:
1900 {
1901 echo 'Awaiting Feedback';
1902 }
1903 }
1904
1905 echo '</p>';
1906
1907 if ( $viewing->feedback_status == 'interested' || $viewing->feedback_status == 'not_interested' )
1908 {
1909 $args = array(
1910 'id' => '_feedback',
1911 'label' => __( 'Feedback', 'propertyhive' ),
1912 'desc_tip' => false,
1913 'class' => '',
1914 'value' => $viewing->feedback,
1915 'custom_attributes' => array(
1916 'style' => 'width:95%; max-width:500px;'
1917 )
1918 );
1919 propertyhive_wp_textarea_input( $args );
1920 }
1921 }
1922
1923 if ( $viewing->status == 'carried_out' && ( $viewing->feedback_status == 'interested' || $viewing->feedback_status == 'not_interested' ) )
1924 {
1925 echo '<p class="form-field">
1926
1927 <label for="">' . __('Feedback Passed On', 'propertyhive') . '</label>';
1928
1929 echo ( ($viewing->feedback_passed_on == 'yes') ? 'Yes' : 'No' );
1930
1931 echo '</p>';
1932 }
1933
1934 do_action('propertyhive_viewing_details_fields');
1935
1936 echo '</div>';
1937
1938 echo '</div>';
1939
1940 die();
1941 }
1942
1943 public function get_viewing_actions()
1944 {
1945 check_ajax_referer( 'viewing-actions', 'security' );
1946
1947 $post_id = $_POST['viewing_id'];
1948
1949 $status = get_post_meta( $post_id, '_status', TRUE );
1950 $feedback_status = get_post_meta( $post_id, '_feedback_status', TRUE );
1951
1952 echo '<div class="propertyhive_meta_box propertyhive_meta_box_actions" id="propertyhive_viewing_actions_meta_box">
1953
1954 <div class="options_group" style="padding-top:8px;">';
1955
1956 $show_feedback_meta_boxes = false;
1957
1958 $actions = array();
1959
1960 if ( $status == 'pending' )
1961 {
1962 $actions[] = '<a
1963 href="#action_panel_viewing_carried_out"
1964 class="button button-success viewing-action"
1965 style="width:100%; margin-bottom:7px; text-align:center"
1966 >' . __('Viewing Carried Out', 'propertyhive') . '</a>';
1967 $actions[] = '<a
1968 href="#action_panel_viewing_cancelled"
1969 class="button viewing-action"
1970 style="width:100%; margin-bottom:7px; text-align:center"
1971 >' . __('Viewing Cancelled', 'propertyhive') . '</a>';
1972 }
1973
1974 if ( $status == 'carried_out' )
1975 {
1976 if ( $feedback_status == '' )
1977 {
1978 $actions[] = '<a
1979 href="#action_panel_viewing_interested"
1980 class="button button-success viewing-action"
1981 style="width:100%; margin-bottom:7px; text-align:center"
1982 >' . __('Applicant Interested', 'propertyhive') . '</a>';
1983
1984 $actions[] = '<a
1985 href="#action_panel_viewing_not_interested"
1986 class="button button-danger viewing-action"
1987 style="width:100%; margin-bottom:7px; text-align:center"
1988 >' . __('Applicant Not Interested', 'propertyhive') . '</a>';
1989
1990 $actions[] = '<a
1991 href="#action_panel_viewing_feedback_not_required"
1992 class="button viewing-action"
1993 style="width:100%; margin-bottom:7px; text-align:center"
1994 >' . __('Feedback Not Required', 'propertyhive') . '</a>';
1995
1996 $show_feedback_meta_boxes = true;
1997 }
1998
1999 if ( $feedback_status == 'interested' )
2000 {
2001 $actions[] = '<a
2002 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 .'"
2003 class="button button-success"
2004 style="width:100%; margin-bottom:7px; text-align:center"
2005 >' . __('Book Second Viewing', 'propertyhive') . '</a>';
2006
2007 if ( get_option('propertyhive_module_disabled_offers_sales', '') != 'yes' )
2008 {
2009 $property_id = get_post_meta( $post_id, '_property_id', TRUE );
2010 if ( get_post_meta( $property_id, '_department', TRUE ) == 'residential-sales' )
2011 {
2012 // See if an offer has this viewing id associated with it
2013 $offer_id = get_post_meta( $post_id, '_offer_id', TRUE );
2014 if ( $offer_id != '' && get_post_status($offer_id) != 'publish' )
2015 {
2016 $offer_id = '';
2017 }
2018
2019 if ( $offer_id != '' )
2020 {
2021 $actions[] = '<a
2022 href="' . get_edit_post_link( $offer_id, '' ) . '"
2023 class="button"
2024 style="width:100%; margin-bottom:7px; text-align:center"
2025 >' . __('View Offer', 'propertyhive') . '</a>';
2026 }
2027 else
2028 {
2029 $actions[] = '<a
2030 href="' . wp_nonce_url( admin_url( 'post.php?post=' . $post_id . '&action=edit' ), '1', 'create_offer' ) . '"
2031 class="button button-success"
2032 style="width:100%; margin-bottom:7px; text-align:center"
2033 >' . __('Record Offer', 'propertyhive') . '</a>';
2034 }
2035 }
2036 }
2037 }
2038
2039 if ( get_post_meta( $post_id, '_feedback_passed_on', TRUE ) != 'yes' && ( $feedback_status == 'interested' || $feedback_status == 'not_interested' ) )
2040 {
2041 $actions[] = '<a
2042 href="#action_panel_viewing_revert_feedback_passed_on"
2043 class="button viewing-action"
2044 style="width:100%; margin-bottom:7px; text-align:center"
2045 >' . __('Feedback Passed On To Owner', 'propertyhive') . '</a>';
2046 }
2047
2048 if ( $feedback_status == 'interested' || $feedback_status == 'not_interested' || $feedback_status == 'not_required' )
2049 {
2050 $actions[] = '<a
2051 href="#action_panel_viewing_revert_feedback_pending"
2052 class="button viewing-action"
2053 style="width:100%; margin-bottom:7px; text-align:center"
2054 >' . __('Revert To Feedback Pending', 'propertyhive') . '</a>';
2055 }
2056 }
2057
2058 if ( $status == 'offer_made' )
2059 {
2060 if ( get_option('propertyhive_module_disabled_offers_sales', '') != 'yes' )
2061 {
2062 $offer_id = get_post_meta( $post_id, '_offer_id', TRUE );
2063 if ( $offer_id != '' && get_post_status($offer_id) != 'publish' )
2064 {
2065 $offer_id = '';
2066 }
2067
2068 if ( $offer_id != '' )
2069 {
2070 $actions[] = '<a
2071 href="' . get_edit_post_link( $offer_id, '' ) . '"
2072 class="button"
2073 style="width:100%; margin-bottom:7px; text-align:center"
2074 >' . __('View Offer', 'propertyhive') . '</a>';
2075 }
2076 }
2077 }
2078
2079 if ( ( $status == 'carried_out' && $feedback_status == '' ) || $status == 'cancelled' )
2080 {
2081 $actions[] = '<a
2082 href="#action_panel_viewing_revert_pending"
2083 class="button viewing-action"
2084 style="width:100%; margin-bottom:7px; text-align:center"
2085 >' . __('Revert To Pending', 'propertyhive') . '</a>';
2086 }
2087
2088 $actions = apply_filters( 'propertyhive_admin_viewing_actions', $actions, $post->ID );
2089
2090 if ( !empty($actions) )
2091 {
2092 echo implode("", $actions);
2093 }
2094 else
2095 {
2096 echo '<div style="text-align:center">' . __( 'No actions to display', 'propertyhive' ) . '</div>';
2097 }
2098
2099 echo '</div>
2100
2101 </div>';
2102
2103 if ( $show_feedback_meta_boxes )
2104 {
2105 echo '<div class="propertyhive_meta_box propertyhive_meta_box_actions" id="action_panel_viewing_interested" style="display:none;">
2106
2107 <div class="options_group" style="padding-top:8px;">
2108
2109 <div class="form-field">
2110
2111 <label for="_viewing_interested_feedback">' . __( 'Applicant Feedback', 'propertyhive' ) . '</label>
2112
2113 <textarea id="_interested_feedback" name="_interested_feedback" style="width:100%;">' . get_post_meta( $post_id, '_feedback', TRUE ) . '</textarea>
2114
2115 </div>
2116
2117 <a class="button action-cancel" href="#">' . __( 'Cancel', 'propertyhive' ) . '</a>
2118 <a class="button button-primary interested-feedback-action-submit" href="#">' . __( 'Save Feedback', 'propertyhive' ) . '</a>
2119
2120 </div>
2121
2122 </div>';
2123
2124 echo '<div class="propertyhive_meta_box propertyhive_meta_box_actions" id="action_panel_viewing_not_interested" style="display:none;">
2125
2126 <div class="options_group" style="padding-top:8px;">
2127
2128 <div class="form-field">
2129
2130 <label for="_viewing_not_interested_feedback">' . __( 'Applicant Feedback', 'propertyhive' ) . '</label>
2131
2132 <textarea id="_not_interested_feedback" name="_not_interested_feedback" style="width:100%;">' . get_post_meta( $post_id, '_feedback', TRUE ) . '</textarea>
2133
2134 </div>
2135
2136 <a class="button action-cancel" href="#">' . __( 'Cancel', 'propertyhive' ) . '</a>
2137 <a class="button button-primary not-interested-feedback-action-submit" href="#">' . __( 'Save Feedback', 'propertyhive' ) . '</a>
2138
2139 </div>
2140
2141 </div>';
2142 }
2143
2144 die();
2145 }
2146
2147 public function viewing_carried_out()
2148 {
2149 check_ajax_referer( 'viewing-actions', 'security' );
2150
2151 $post_id = $_POST['viewing_id'];
2152
2153 $status = get_post_meta( $post_id, '_status', TRUE );
2154
2155 if ( $status == 'pending' )
2156 {
2157 update_post_meta( $post_id, '_status', 'carried_out' );
2158
2159 $current_user = wp_get_current_user();
2160
2161 // Add note/comment to viewing
2162 $comment = array(
2163 'note_type' => 'action',
2164 'action' => 'viewing_carried_out',
2165 );
2166
2167 $data = array(
2168 'comment_post_ID' => $post_id,
2169 'comment_author' => $current_user->display_name,
2170 'comment_author_email' => 'propertyhive@noreply.com',
2171 'comment_author_url' => '',
2172 'comment_date' => date("Y-m-d H:i:s"),
2173 'comment_content' => serialize($comment),
2174 'comment_approved' => 1,
2175 'comment_type' => 'propertyhive_note',
2176 );
2177 $comment_id = wp_insert_comment( $data );
2178 }
2179
2180 die();
2181 }
2182
2183 public function viewing_cancelled()
2184 {
2185 check_ajax_referer( 'viewing-actions', 'security' );
2186
2187 $post_id = $_POST['viewing_id'];
2188
2189 $status = get_post_meta( $post_id, '_status', TRUE );
2190
2191 if ( $status == 'pending' )
2192 {
2193 update_post_meta( $post_id, '_status', 'cancelled' );
2194
2195 $current_user = wp_get_current_user();
2196
2197 // Add note/comment to viewing
2198 $comment = array(
2199 'note_type' => 'action',
2200 'action' => 'viewing_cancelled',
2201 );
2202
2203 $data = array(
2204 'comment_post_ID' => $post_id,
2205 'comment_author' => $current_user->display_name,
2206 'comment_author_email' => 'propertyhive@noreply.com',
2207 'comment_author_url' => '',
2208 'comment_date' => date("Y-m-d H:i:s"),
2209 'comment_content' => serialize($comment),
2210 'comment_approved' => 1,
2211 'comment_type' => 'propertyhive_note',
2212 );
2213 $comment_id = wp_insert_comment( $data );
2214 }
2215
2216 die();
2217 }
2218
2219 public function viewing_interested_feedback()
2220 {
2221 check_ajax_referer( 'viewing-actions', 'security' );
2222
2223 $post_id = $_POST['viewing_id'];
2224
2225 $status = get_post_meta( $post_id, '_status', TRUE );
2226
2227 if ( $status == 'carried_out' )
2228 {
2229 update_post_meta( $post_id, '_feedback_status', 'interested' );
2230 update_post_meta( $post_id, '_feedback', $_POST['feedback'] );
2231
2232 $current_user = wp_get_current_user();
2233
2234 // Add note/comment to viewing
2235 $comment = array(
2236 'note_type' => 'action',
2237 'action' => 'viewing_applicant_interested',
2238 );
2239
2240 $data = array(
2241 'comment_post_ID' => $post_id,
2242 'comment_author' => $current_user->display_name,
2243 'comment_author_email' => 'propertyhive@noreply.com',
2244 'comment_author_url' => '',
2245 'comment_date' => date("Y-m-d H:i:s"),
2246 'comment_content' => serialize($comment),
2247 'comment_approved' => 1,
2248 'comment_type' => 'propertyhive_note',
2249 );
2250 $comment_id = wp_insert_comment( $data );
2251 }
2252
2253 die();
2254 }
2255
2256 public function viewing_not_interested_feedback()
2257 {
2258 check_ajax_referer( 'viewing-actions', 'security' );
2259
2260 $post_id = $_POST['viewing_id'];
2261
2262 $status = get_post_meta( $post_id, '_status', TRUE );
2263
2264 if ( $status == 'carried_out' )
2265 {
2266 update_post_meta( $post_id, '_feedback_status', 'not_interested' );
2267 update_post_meta( $post_id, '_feedback', $_POST['feedback'] );
2268
2269 $current_user = wp_get_current_user();
2270
2271 // Add note/comment to viewing
2272 $comment = array(
2273 'note_type' => 'action',
2274 'action' => 'viewing_applicant_not_interested',
2275 );
2276
2277 $data = array(
2278 'comment_post_ID' => $post_id,
2279 'comment_author' => $current_user->display_name,
2280 'comment_author_email' => 'propertyhive@noreply.com',
2281 'comment_author_url' => '',
2282 'comment_date' => date("Y-m-d H:i:s"),
2283 'comment_content' => serialize($comment),
2284 'comment_approved' => 1,
2285 'comment_type' => 'propertyhive_note',
2286 );
2287 $comment_id = wp_insert_comment( $data );
2288 }
2289
2290 die();
2291 }
2292
2293 public function viewing_feedback_not_required()
2294 {
2295 check_ajax_referer( 'viewing-actions', 'security' );
2296
2297 $post_id = $_POST['viewing_id'];
2298
2299 $status = get_post_meta( $post_id, '_status', TRUE );
2300
2301 if ( $status == 'carried_out' )
2302 {
2303 update_post_meta( $post_id, '_feedback_status', 'not_required' );
2304
2305 $current_user = wp_get_current_user();
2306
2307 // Add note/comment to viewing
2308 $comment = array(
2309 'note_type' => 'action',
2310 'action' => 'viewing_feedback_not_required',
2311 );
2312
2313 $data = array(
2314 'comment_post_ID' => $post_id,
2315 'comment_author' => $current_user->display_name,
2316 'comment_author_email' => 'propertyhive@noreply.com',
2317 'comment_author_url' => '',
2318 'comment_date' => date("Y-m-d H:i:s"),
2319 'comment_content' => serialize($comment),
2320 'comment_approved' => 1,
2321 'comment_type' => 'propertyhive_note',
2322 );
2323 $comment_id = wp_insert_comment( $data );
2324 }
2325
2326 die();
2327 }
2328
2329 public function viewing_revert_feedback_pending()
2330 {
2331 check_ajax_referer( 'viewing-actions', 'security' );
2332
2333 $post_id = $_POST['viewing_id'];
2334
2335 $status = get_post_meta( $post_id, '_status', TRUE );
2336
2337 if ( $status == 'carried_out' )
2338 {
2339 update_post_meta( $post_id, '_feedback_status', '' );
2340 update_post_meta( $post_id, '_feedback_passed_on', '' );
2341
2342 $current_user = wp_get_current_user();
2343
2344 // Add note/comment to viewing
2345 $comment = array(
2346 'note_type' => 'action',
2347 'action' => 'viewing_revert_feedback_pending',
2348 );
2349
2350 $data = array(
2351 'comment_post_ID' => $post_id,
2352 'comment_author' => $current_user->display_name,
2353 'comment_author_email' => 'propertyhive@noreply.com',
2354 'comment_author_url' => '',
2355 'comment_date' => date("Y-m-d H:i:s"),
2356 'comment_content' => serialize($comment),
2357 'comment_approved' => 1,
2358 'comment_type' => 'propertyhive_note',
2359 );
2360 $comment_id = wp_insert_comment( $data );
2361 }
2362
2363 die();
2364 }
2365
2366 public function viewing_revert_pending()
2367 {
2368 check_ajax_referer( 'viewing-actions', 'security' );
2369
2370 $post_id = $_POST['viewing_id'];
2371
2372 $status = get_post_meta( $post_id, '_status', TRUE );
2373
2374 if ( $status == 'carried_out' || $status == 'cancelled' )
2375 {
2376 update_post_meta( $post_id, '_status', 'pending' );
2377 update_post_meta( $post_id, '_feedback_status', '' );
2378
2379 $current_user = wp_get_current_user();
2380
2381 // Add note/comment to viewing
2382 $comment = array(
2383 'note_type' => 'action',
2384 'action' => 'viewing_revert_pending',
2385 );
2386
2387 $data = array(
2388 'comment_post_ID' => $post_id,
2389 'comment_author' => $current_user->display_name,
2390 'comment_author_email' => 'propertyhive@noreply.com',
2391 'comment_author_url' => '',
2392 'comment_date' => date("Y-m-d H:i:s"),
2393 'comment_content' => serialize($comment),
2394 'comment_approved' => 1,
2395 'comment_type' => 'propertyhive_note',
2396 );
2397 $comment_id = wp_insert_comment( $data );
2398 }
2399
2400 die();
2401 }
2402
2403 public function viewing_feedback_passed_on()
2404 {
2405 check_ajax_referer( 'viewing-actions', 'security' );
2406
2407 $post_id = $_POST['viewing_id'];
2408
2409 $status = get_post_meta( $post_id, '_status', TRUE );
2410
2411 if ( $status == 'carried_out' )
2412 {
2413 update_post_meta( $post_id, '_feedback_passed_on', 'yes' );
2414
2415 $current_user = wp_get_current_user();
2416
2417 // Add note/comment to viewing
2418 $comment = array(
2419 'note_type' => 'action',
2420 'action' => 'viewing_feedback_passed_on',
2421 );
2422
2423 $data = array(
2424 'comment_post_ID' => $post_id,
2425 'comment_author' => $current_user->display_name,
2426 'comment_author_email' => 'propertyhive@noreply.com',
2427 'comment_author_url' => '',
2428 'comment_date' => date("Y-m-d H:i:s"),
2429 'comment_content' => serialize($comment),
2430 'comment_approved' => 1,
2431 'comment_type' => 'propertyhive_note',
2432 );
2433 $comment_id = wp_insert_comment( $data );
2434 }
2435
2436 die();
2437 }
2438
2439 public function get_property_viewings_meta_box()
2440 {
2441 check_ajax_referer( 'get_property_viewings_meta_box', 'security' );
2442
2443 global $post;
2444
2445 echo '<div class="propertyhive_meta_box">';
2446
2447 echo '<div class="options_group">';
2448
2449 $args = array(
2450 'post_type' => 'viewing',
2451 'nopaging' => true,
2452 'orderby' => 'meta_value',
2453 'order' => 'DESC',
2454 'meta_key' => '_start_date_time',
2455 'post_status' => 'publish',
2456 'meta_query' => array(
2457 array(
2458 'key' => '_property_id',
2459 'value' => $_POST['post_id']
2460 )
2461 )
2462 );
2463 $viewings_query = new WP_Query( $args );
2464
2465 if ( $viewings_query->have_posts() )
2466 {
2467 echo '<table style="width:100%">
2468 <thead>
2469 <tr>
2470 <th style="text-align:left;">' . __( 'Date', 'propertyhive' ) . ' / ' . __( 'Time', 'propertyhive' ) . '</th>
2471 <th style="text-align:left;">' . __( 'Applicant', 'propertyhive' ) . '</th>
2472 <th style="text-align:left;">' . __( 'Attending Negotiator(s)', 'propertyhive' ) . '</th>
2473 <th style="text-align:left;">' . __( 'Status', 'propertyhive' ) . '</th>
2474 </tr>
2475 </thead>
2476 <tbody>';
2477
2478 while ( $viewings_query->have_posts() )
2479 {
2480 $viewings_query->the_post();
2481
2482 echo '<tr>';
2483 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>';
2484 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>';
2485 echo '<td style="text-align:left;">';
2486
2487 $negotiator_ids = get_post_meta(get_the_ID(), '_negotiator_id');
2488
2489 if (!empty($negotiator_ids))
2490 {
2491 $i = 0;
2492 foreach ($negotiator_ids as $negotiator_id)
2493 {
2494 if ( $i > 0 ) { echo ', '; }
2495
2496 $userdata = get_userdata( $negotiator_id );
2497 if ( $userdata !== FALSE )
2498 {
2499 echo $userdata->display_name;
2500 }
2501 else
2502 {
2503 echo '<em>Unknown user</em>';
2504 }
2505 ++$i;
2506 }
2507 }
2508 else
2509 {
2510 echo 'Unattended';
2511 }
2512
2513 echo '</td>';
2514 echo '<td style="text-align:left;">';
2515
2516 $status = get_post_meta(get_the_ID(), '_status', TRUE);
2517 echo ucwords(str_replace("_", " ", $status));
2518 if ( $status == 'carried_out' )
2519 {
2520 echo '<br>';
2521 $feedback_status = get_post_meta(get_the_ID(), '_feedback_status', TRUE);
2522 switch ( $feedback_status )
2523 {
2524 case "interested": { echo 'Applicant Interested'; break; }
2525 case "not_interested": { echo 'Applicant Not Interested'; break; }
2526 case "not_required": { echo 'Feedback Not Required'; break; }
2527 default: { echo 'Awaiting Feedback'; }
2528 }
2529
2530 if ( $feedback_status == 'interested' || $feedback_status == 'not_interested' )
2531 {
2532 $feedback_passed_on = get_post_meta(get_the_ID(), '_feedback_passed_on', TRUE);
2533 echo '<br>' . ( ($feedback_passed_on == 'yes') ? 'Feedback Passed On' : 'Feedback Not Passed On' );
2534 }
2535 }
2536 echo '</td>';
2537 echo '</tr>';
2538 }
2539
2540 echo '
2541 </tbody>
2542 </table>
2543 <br>';
2544 }
2545 else
2546 {
2547 echo '<p>' . __( 'No viewings exist for this property', 'propertyhive') . '</p>';
2548 }
2549 wp_reset_postdata();
2550
2551 do_action('propertyhive_property_viewings_fields');
2552
2553 echo '</div>';
2554
2555 echo '</div>';
2556
2557 die();
2558 }
2559
2560 public function get_contact_viewings_meta_box()
2561 {
2562 check_ajax_referer( 'get_contact_viewings_meta_box', 'security' );
2563
2564 global $post;
2565
2566 echo '<div class="propertyhive_meta_box">';
2567
2568 echo '<div class="options_group">';
2569
2570 $args = array(
2571 'post_type' => 'viewing',
2572 'nopaging' => true,
2573 'orderby' => 'meta_value',
2574 'order' => 'DESC',
2575 'post_status' => 'publish',
2576 'meta_key' => '_start_date_time',
2577 'meta_query' => array(
2578 array(
2579 'key' => '_applicant_contact_id',
2580 'value' => $_POST['post_id']
2581 )
2582 )
2583 );
2584 $viewings_query = new WP_Query( $args );
2585
2586 if ( $viewings_query->have_posts() )
2587 {
2588 echo '<table style="width:100%">
2589 <thead>
2590 <tr>
2591 <th style="text-align:left;">' . __( 'Date', 'propertyhive' ) . ' / ' . __( 'Time', 'propertyhive' ) . '</th>
2592 <th style="text-align:left;">' . __( 'Property', 'propertyhive' ) . '</th>
2593 <th style="text-align:left;">' . __( 'Attending Negotiator(s)', 'propertyhive' ) . '</th>
2594 <th style="text-align:left;">' . __( 'Status', 'propertyhive' ) . '</th>
2595 </tr>
2596 </thead>
2597 <tbody>';
2598
2599 while ( $viewings_query->have_posts() )
2600 {
2601 $viewings_query->the_post();
2602
2603 $property = new PH_Property((int)get_post_meta(get_the_ID(), '_property_id', TRUE));
2604
2605 echo '<tr>';
2606 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>';
2607 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>';
2608 echo '<td style="text-align:left;">';
2609
2610 $negotiator_ids = get_post_meta(get_the_ID(), '_negotiator_id');
2611
2612 if (!empty($negotiator_ids))
2613 {
2614 $i = 0;
2615 foreach ($negotiator_ids as $negotiator_id)
2616 {
2617 if ( $i > 0 ) { echo ', '; }
2618
2619 $userdata = get_userdata( $negotiator_id );
2620 if ( $userdata !== FALSE )
2621 {
2622 echo $userdata->display_name;
2623 }
2624 else
2625 {
2626 echo '<em>Unknown user</em>';
2627 }
2628 ++$i;
2629 }
2630 }
2631 else
2632 {
2633 echo 'Unattended';
2634 }
2635
2636 echo '</td>';
2637 echo '<td style="text-align:left;">';
2638
2639 $status = get_post_meta(get_the_ID(), '_status', TRUE);
2640 echo ucwords(str_replace("_", " ", $status));
2641 if ( $status == 'carried_out' )
2642 {
2643 echo '<br>';
2644 $feedback_status = get_post_meta(get_the_ID(), '_feedback_status', TRUE);
2645 switch ( get_post_meta(get_the_ID(), '_feedback_status', TRUE) )
2646 {
2647 case "interested": { echo 'Applicant Interested'; break; }
2648 case "not_interested": { echo 'Applicant Not Interested'; break; }
2649 case "not_required": { echo 'Feedback Not Required'; break; }
2650 default: { echo 'Awaiting Feedback'; }
2651 }
2652
2653 if ( $feedback_status == 'interested' || $feedback_status == 'not_interested' )
2654 {
2655 $feedback_passed_on = get_post_meta(get_the_ID(), '_feedback_passed_on', TRUE);
2656 echo '<br>' . ( ($feedback_passed_on == 'yes') ? 'Feedback Passed On' : 'Feedback Not Passed On' );
2657 }
2658 }
2659 echo '</td>';
2660 echo '</tr>';
2661 }
2662
2663 echo '
2664 </tbody>
2665 </table>
2666 <br>';
2667 }
2668 else
2669 {
2670 echo '<p>' . __( 'No viewings exist for this contact', 'propertyhive') . '</p>';
2671 }
2672 wp_reset_postdata();
2673
2674 do_action('propertyhive_contact_viewings_fields');
2675
2676 echo '</div>';
2677
2678 echo '</div>';
2679
2680 die();
2681 }
2682
2683 // Offer related functions
2684 public function record_offer_property()
2685 {
2686 check_ajax_referer( 'record-offer', 'security' );
2687
2688 $this->json_headers();
2689
2690 // TO DO: Should do validation on server side also
2691 if (empty($_POST['property_id']))
2692 {
2693 $return = array('error' => 'No property selected');
2694 echo json_encode( $return );
2695 die();
2696 }
2697
2698 $property = new PH_Property((int)$_POST['property_id']);
2699
2700 $applicant_contact_ids = array();
2701
2702 // Create applicant record if required
2703 if (empty($_POST['applicant_ids']) && !empty($_POST['applicant_name']))
2704 {
2705 // Need to create contact/applicant
2706 $contact_post = array(
2707 'post_title' => wp_strip_all_tags($_POST['applicant_name']),
2708 'post_content' => '',
2709 'post_type' => 'contact',
2710 'post_status' => 'publish',
2711 'comment_status' => 'closed',
2712 'ping_status' => 'closed',
2713 );
2714
2715 // Insert the post into the database
2716 $contact_post_id = wp_insert_post( $contact_post );
2717
2718 if ( is_wp_error($contact_post_id) || $contact_post_id == 0 )
2719 {
2720 $return = array('error' => 'Failed to create contact post. Please try again');
2721 echo json_encode( $return );
2722 die();
2723 }
2724
2725 update_post_meta( $contact_post_id, '_contact_types', array('applicant') );
2726
2727 update_post_meta( $contact_post_id, '_applicant_profiles', 1 );
2728 update_post_meta( $contact_post_id, '_applicant_profile_0', array( 'department' => $property->department, 'send_matching_properties' => '' ) );
2729
2730 $applicant_contact_ids[] = $contact_post_id;
2731 }
2732
2733 if (!empty($_POST['applicant_ids']) && empty($_POST['applicant_name']))
2734 {
2735 // This is an existing contact
2736 if ( !is_array($_POST['applicant_ids']) )
2737 {
2738 $_POST['applicant_ids'] = array($_POST['applicant_ids']);
2739 }
2740
2741 foreach ( $_POST['applicant_ids'] as $applicant_id )
2742 {
2743 $applicant_contact_ids[] = $applicant_id;
2744 }
2745 }
2746
2747 $applicant_contact_ids = array_unique($applicant_contact_ids);
2748
2749 if ( empty($applicant_contact_ids) )
2750 {
2751 $return = array('error' => 'No applicant selected, or unable to create applicant record');
2752 echo json_encode( $return );
2753 die();
2754 }
2755
2756 // Loop through contacts and create one offer each
2757 // At the moment it's a 1-to-1 relationship, but might support multiple in the future
2758 foreach ( $applicant_contact_ids as $applicant_contact_id )
2759 {
2760 // Insert offer record
2761 $offer_post = array(
2762 'post_title' => '',
2763 'post_content' => '',
2764 'post_type' => 'offer',
2765 'post_status' => 'publish',
2766 'comment_status' => 'closed',
2767 'ping_status' => 'closed',
2768 );
2769
2770 // Insert the post into the database
2771 $offer_post_id = wp_insert_post( $offer_post );
2772
2773 if ( is_wp_error($offer_post_id) || $offer_post_id == 0 )
2774 {
2775 $return = array('error' => 'Failed to create offer post. Please try again');
2776 echo json_encode( $return );
2777 die();
2778 }
2779
2780 $amount = preg_replace("/[^0-9]/", '', $_POST['amount']);
2781
2782 add_post_meta( $offer_post_id, '_offer_date_time', $_POST['offer_date'] . ' ' . $_POST['offer_time'] );
2783 add_post_meta( $offer_post_id, '_property_id', $_POST['property_id'] );
2784 add_post_meta( $offer_post_id, '_applicant_contact_id', $applicant_contact_id );
2785 add_post_meta( $offer_post_id, '_amount', $amount );
2786 add_post_meta( $offer_post_id, '_status', 'pending' );
2787 }
2788
2789 $applicant_contacts = array();
2790 foreach ( $applicant_contact_ids as $applicant_contact_id )
2791 {
2792 $applicant_contacts[] = array(
2793 'ID' => $applicant_contact_id,
2794 'post_title' => get_the_title($applicant_contact_id),
2795 'edit_link' => get_edit_post_link( $applicant_contact_id, '' ),
2796 );
2797 }
2798
2799 $return = array('success' => array(
2800 'offer' => array(
2801 'ID' => $offer_post_id,
2802 'edit_link' => get_edit_post_link( $offer_post_id, '' ),
2803 ),
2804 'applicant_contacts' => $applicant_contacts,
2805 ));
2806
2807 echo json_encode( $return );
2808
2809 die();
2810 }
2811
2812 public function record_offer_contact()
2813 {
2814 check_ajax_referer( 'record-offer', 'security' );
2815
2816 $this->json_headers();
2817
2818 // TO DO: Should do validation on server side also
2819 if (empty($_POST['contact_id']))
2820 {
2821 $return = array('error' => 'No contact selected');
2822 echo json_encode( $return );
2823 die();
2824 }
2825
2826 if (empty($_POST['property_ids']))
2827 {
2828 $return = array('error' => 'No property selected');
2829 echo json_encode( $return );
2830 die();
2831 }
2832
2833 // Loop through contacts and create one offer each
2834 // At the moment it's a 1-to-1 relationship, but might support multiple in the future
2835 foreach ( $_POST['property_ids'] as $property_id )
2836 {
2837 // Insert offer record
2838 $offer_post = array(
2839 'post_title' => '',
2840 'post_content' => '',
2841 'post_type' => 'offer',
2842 'post_status' => 'publish',
2843 'comment_status' => 'closed',
2844 'ping_status' => 'closed',
2845 );
2846
2847 // Insert the post into the database
2848 $offer_post_id = wp_insert_post( $offer_post );
2849
2850 if ( is_wp_error($offer_post_id) || $offer_post_id == 0 )
2851 {
2852 $return = array('error' => 'Failed to create offer post. Please try again');
2853 echo json_encode( $return );
2854 die();
2855 }
2856
2857 $amount = preg_replace("/[^0-9]/", '', $_POST['amount']);
2858
2859 add_post_meta( $offer_post_id, '_offer_date_time', $_POST['offer_date'] . ' ' . $_POST['offer_time'] );
2860 add_post_meta( $offer_post_id, '_property_id', $property_id );
2861 add_post_meta( $offer_post_id, '_applicant_contact_id', $_POST['contact_id'] );
2862 add_post_meta( $offer_post_id, '_amount', $amount );
2863 add_post_meta( $offer_post_id, '_status', 'pending' );
2864 }
2865
2866 $properties = array();
2867 foreach ( $_POST['property_ids'] as $property_id )
2868 {
2869 $properties[] = array(
2870 'ID' => $property_id,
2871 'post_title' => get_the_title($property_id),
2872 'edit_link' => get_edit_post_link( $property_id, '' ),
2873 );
2874 }
2875
2876 $return = array('success' => array(
2877 'offer' => array(
2878 'ID' => $offer_post_id,
2879 'edit_link' => get_edit_post_link( $offer_post_id, '' ),
2880 ),
2881 'properties' => $properties,
2882 ));
2883
2884 echo json_encode( $return );
2885
2886 die();
2887 }
2888
2889 public function get_offer_details_meta_box()
2890 {
2891 check_ajax_referer( 'offer-details-meta-box', 'security' );
2892
2893 $offer = new PH_Offer((int)$_POST['offer_id']);
2894
2895 echo '<div class="propertyhive_meta_box">';
2896
2897 echo '<div class="options_group">';
2898
2899 if ( $offer->status != '' )
2900 {
2901 echo '<p class="form-field">
2902
2903 <label for="">' . __('Status', 'propertyhive') . '</label>
2904
2905 ' . ucwords(str_replace("_", " ", $offer->status)) . '
2906
2907 </p>';
2908 }
2909
2910 $offer_date_time = $offer->offer_date_time;
2911 if ( empty($offer_date_time) )
2912 {
2913 $offer_date_time = date("Y-m-d H:i:s");
2914 }
2915
2916 echo '<p class="form-field offer_date_time_field">
2917
2918 <label for="_offer_date">' . __('Offer Date / Time', 'propertyhive') . '</label>
2919
2920 <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)) . '">
2921 <select id="_offer_time_hours" name="_offer_time_hours" class="select short" style="width:55px">';
2922
2923 if ( empty($offer_date_time) )
2924 {
2925 $value = date("H");
2926 }
2927 else
2928 {
2929 $value = date( "H", strtotime( $offer_date_time ) );
2930 }
2931 for ( $i = 0; $i < 23; ++$i )
2932 {
2933 $j = str_pad($i, 2, '0', STR_PAD_LEFT);
2934 echo '<option value="' . $j . '"';
2935 if ($i == $value) { echo ' selected'; }
2936 echo '>' . $j . '</option>';
2937 }
2938
2939 echo '</select>
2940 :
2941 <select id="_offer_time_minutes" name="_offer_time_minutes" class="select short" style="width:55px">';
2942
2943 if ( empty($offer_date_time) )
2944 {
2945 $value = '';
2946 }
2947 else
2948 {
2949 $value = date( "i", strtotime( $offer_date_time ) );
2950 }
2951 for ( $i = 0; $i < 60; $i+=5 )
2952 {
2953 $j = str_pad($i, 2, '0', STR_PAD_LEFT);
2954 echo '<option value="' . $j . '"';
2955 if ($i == $value) { echo ' selected'; }
2956 echo '>' . $j . '</option>';
2957 }
2958
2959 echo '</select>
2960
2961 </p>';
2962
2963 $args = array(
2964 'id' => '_amount',
2965 'label' => __( 'Offer Amount', 'propertyhive' ) . ' (&pound;)',
2966 'desc_tip' => false,
2967 'class' => 'short',
2968 'value' => ( is_numeric($offer->amount) ? number_format($offer->amount) : '' ),
2969 'custom_attributes' => array(
2970 //'style' => 'width:95%; max-width:500px;'
2971 )
2972 );
2973 propertyhive_wp_text_input( $args );
2974
2975 do_action('propertyhive_offer_details_fields');
2976
2977 echo '</div>';
2978
2979 echo '</div>';
2980
2981 die();
2982 }
2983
2984 public function get_offer_actions()
2985 {
2986 check_ajax_referer( 'offer-actions', 'security' );
2987
2988 $post_id = $_POST['offer_id'];
2989
2990 $status = get_post_meta( $post_id, '_status', TRUE );
2991
2992 echo '<div class="propertyhive_meta_box propertyhive_meta_box_actions" id="propertyhive_offer_actions_meta_box">
2993
2994 <div class="options_group" style="padding-top:8px;">';
2995
2996 $actions = array();
2997
2998 if ( $status == 'pending' )
2999 {
3000 $actions[] = '<a
3001 href="#action_panel_offer_accepted"
3002 class="button button-success offer-action"
3003 style="width:100%; margin-bottom:7px; text-align:center"
3004 >' . __('Accept Offer', 'propertyhive') . '</a>';
3005 $actions[] = '<a
3006 href="#action_panel_offer_declined"
3007 class="button button-danger offer-action"
3008 style="width:100%; margin-bottom:7px; text-align:center"
3009 >' . __('Decline Offer', 'propertyhive') . '</a>';
3010 }
3011
3012 if ( $status == 'accepted' )
3013 {
3014 // See if a sale has this offer id associated with it
3015 $sale_id = get_post_meta( $post_id, '_sale_id', TRUE );
3016 if ( $sale_id != '' && get_post_status($sale_id) != 'publish' )
3017 {
3018 $sale_id = '';
3019 }
3020
3021 if ( $sale_id != '' )
3022 {
3023 $actions[] = '<a
3024 href="' . get_edit_post_link( $sale_id, '' ) . '"
3025 class="button"
3026 style="width:100%; margin-bottom:7px; text-align:center"
3027 >' . __('View Sale', 'propertyhive') . '</a>';
3028 }
3029 else
3030 {
3031 $actions[] = '<a
3032 href="' . wp_nonce_url( admin_url( 'post.php?post=' . $post_id . '&action=edit' ), '1', 'create_sale' ) . '"
3033 class="button button-success"
3034 style="width:100%; margin-bottom:7px; text-align:center"
3035 >' . __('Create Sale', 'propertyhive') . '</a>';
3036 }
3037 }
3038
3039 if ( $status == 'declined' )
3040 {
3041
3042 }
3043
3044 if ( $status == 'accepted' || $status == 'declined' )
3045 {
3046 $actions[] = '<a
3047 href="#action_panel_offer_revert_pending"
3048 class="button offer-action"
3049 style="width:100%; margin-bottom:7px; text-align:center"
3050 >' . __('Revert To Pending', 'propertyhive') . '</a>';
3051 }
3052
3053 $actions = apply_filters( 'propertyhive_admin_offer_actions', $actions, $post->ID );
3054
3055 if ( !empty($actions) )
3056 {
3057 echo implode("", $actions);
3058 }
3059 else
3060 {
3061 echo '<div style="text-align:center">' . __( 'No actions to display', 'propertyhive' ) . '</div>';
3062 }
3063
3064 echo '</div>
3065
3066 </div>';
3067
3068 die();
3069 }
3070
3071 public function offer_accepted()
3072 {
3073 check_ajax_referer( 'offer-actions', 'security' );
3074
3075 $post_id = $_POST['offer_id'];
3076
3077 $status = get_post_meta( $post_id, '_status', TRUE );
3078
3079 if ( $status == 'pending' )
3080 {
3081 update_post_meta( $post_id, '_status', 'accepted' );
3082
3083 $current_user = wp_get_current_user();
3084
3085 // Add note/comment to offer
3086 $comment = array(
3087 'note_type' => 'action',
3088 'action' => 'offer_accepted',
3089 );
3090
3091 $data = array(
3092 'comment_post_ID' => $post_id,
3093 'comment_author' => $current_user->display_name,
3094 'comment_author_email' => 'propertyhive@noreply.com',
3095 'comment_author_url' => '',
3096 'comment_date' => date("Y-m-d H:i:s"),
3097 'comment_content' => serialize($comment),
3098 'comment_approved' => 1,
3099 'comment_type' => 'propertyhive_note',
3100 );
3101 $comment_id = wp_insert_comment( $data );
3102 }
3103
3104 die();
3105 }
3106
3107 public function offer_declined()
3108 {
3109 check_ajax_referer( 'offer-actions', 'security' );
3110
3111 $post_id = $_POST['offer_id'];
3112
3113 $status = get_post_meta( $post_id, '_status', TRUE );
3114
3115 if ( $status == 'pending' )
3116 {
3117 update_post_meta( $post_id, '_status', 'declined' );
3118
3119 $current_user = wp_get_current_user();
3120
3121 // Add note/comment to offer
3122 $comment = array(
3123 'note_type' => 'action',
3124 'action' => 'offer_declined',
3125 );
3126
3127 $data = array(
3128 'comment_post_ID' => $post_id,
3129 'comment_author' => $current_user->display_name,
3130 'comment_author_email' => 'propertyhive@noreply.com',
3131 'comment_author_url' => '',
3132 'comment_date' => date("Y-m-d H:i:s"),
3133 'comment_content' => serialize($comment),
3134 'comment_approved' => 1,
3135 'comment_type' => 'propertyhive_note',
3136 );
3137 $comment_id = wp_insert_comment( $data );
3138 }
3139
3140 die();
3141 }
3142
3143 public function offer_revert_pending()
3144 {
3145 check_ajax_referer( 'offer-actions', 'security' );
3146
3147 $post_id = $_POST['offer_id'];
3148
3149 $status = get_post_meta( $post_id, '_status', TRUE );
3150
3151 if ( $status == 'accepted' || $status == 'declined' )
3152 {
3153 update_post_meta( $post_id, '_status', 'pending' );
3154
3155 $current_user = wp_get_current_user();
3156
3157 // Add note/comment to offer
3158 $comment = array(
3159 'note_type' => 'action',
3160 'action' => 'offer_revert_pending',
3161 );
3162
3163 $data = array(
3164 'comment_post_ID' => $post_id,
3165 'comment_author' => $current_user->display_name,
3166 'comment_author_email' => 'propertyhive@noreply.com',
3167 'comment_author_url' => '',
3168 'comment_date' => date("Y-m-d H:i:s"),
3169 'comment_content' => serialize($comment),
3170 'comment_approved' => 1,
3171 'comment_type' => 'propertyhive_note',
3172 );
3173 $comment_id = wp_insert_comment( $data );
3174 }
3175
3176 die();
3177 }
3178
3179 public function get_property_offers_meta_box()
3180 {
3181 check_ajax_referer( 'get_property_offers_meta_box', 'security' );
3182
3183 global $post;
3184
3185 echo '<div class="propertyhive_meta_box">';
3186
3187 echo '<div class="options_group">';
3188
3189 $args = array(
3190 'post_type' => 'offer',
3191 'nopaging' => true,
3192 'orderby' => 'meta_value',
3193 'order' => 'DESC',
3194 'meta_key' => '_offer_date_time',
3195 'post_status' => 'publish',
3196 'meta_query' => array(
3197 array(
3198 'key' => '_property_id',
3199 'value' => $_POST['post_id']
3200 )
3201 )
3202 );
3203 $offers_query = new WP_Query( $args );
3204
3205 if ( $offers_query->have_posts() )
3206 {
3207 echo '<table style="width:100%">
3208 <thead>
3209 <tr>
3210 <th style="text-align:left;">' . __( 'Offer Date', 'propertyhive' ) . '</th>
3211 <th style="text-align:left;">' . __( 'Applicant', 'propertyhive' ) . '</th>
3212 <th style="text-align:left;">' . __( 'Offer Amount', 'propertyhive' ) . '</th>
3213 <th style="text-align:left;">' . __( 'Status', 'propertyhive' ) . '</th>
3214 </tr>
3215 </thead>
3216 <tbody>';
3217
3218 while ( $offers_query->have_posts() )
3219 {
3220 $offers_query->the_post();
3221
3222 $offer = new PH_Offer(get_the_ID());
3223
3224 echo '<tr>';
3225 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>';
3226 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>';
3227 echo '<td style="text-align:left;">' . $offer->get_formatted_amount() . '</td>';
3228 echo '<td style="text-align:left;">';
3229 $status = get_post_meta(get_the_ID(), '_status', TRUE);
3230 echo ucwords(str_replace("_", " ", $status));
3231 echo '</td>';
3232 echo '</tr>';
3233 }
3234
3235 echo '
3236 </tbody>
3237 </table>
3238 <br>';
3239 }
3240 else
3241 {
3242 echo '<p>' . __( 'No offers exist for this property', 'propertyhive') . '</p>';
3243 }
3244 wp_reset_postdata();
3245
3246 do_action('propertyhive_property_offers_fields');
3247
3248 echo '</div>';
3249
3250 echo '</div>';
3251
3252 die();
3253 }
3254
3255 public function get_contact_offers_meta_box()
3256 {
3257 check_ajax_referer( 'get_contact_offers_meta_box', 'security' );
3258
3259 global $post;
3260
3261 echo '<div class="propertyhive_meta_box">';
3262
3263 echo '<div class="options_group">';
3264
3265 $args = array(
3266 'post_type' => 'offer',
3267 'nopaging' => true,
3268 'orderby' => 'meta_value',
3269 'order' => 'DESC',
3270 'post_status' => 'publish',
3271 'meta_key' => '_offer_date_time',
3272 'meta_query' => array(
3273 array(
3274 'key' => '_applicant_contact_id',
3275 'value' => $_POST['post_id']
3276 )
3277 )
3278 );
3279 $offers_query = new WP_Query( $args );
3280
3281 if ( $offers_query->have_posts() )
3282 {
3283 echo '<table style="width:100%">
3284 <thead>
3285 <tr>
3286 <th style="text-align:left;">' . __( 'Offer Date', 'propertyhive' ) . '</th>
3287 <th style="text-align:left;">' . __( 'Property', 'propertyhive' ) . '</th>
3288 <th style="text-align:left;">' . __( 'Property Owner', 'propertyhive' ) . '</th>
3289 <th style="text-align:left;">' . __( 'Offer Amount', 'propertyhive' ) . '</th>
3290 <th style="text-align:left;">' . __( 'Status', 'propertyhive' ) . '</th>
3291 </tr>
3292 </thead>
3293 <tbody>';
3294
3295 while ( $offers_query->have_posts() )
3296 {
3297 $offers_query->the_post();
3298
3299 $property = new PH_Property((int)get_post_meta(get_the_ID(), '_property_id', TRUE));
3300 $offer = new PH_Offer(get_the_ID());
3301
3302 echo '<tr>';
3303 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>';
3304 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>';
3305 echo '<td style="text-align:left;">';
3306
3307 $owner_contact_ids = $property->_owner_contact_id;
3308 if (
3309 ( !is_array($owner_contact_ids) && $owner_contact_ids != '' && $owner_contact_ids != 0 )
3310 ||
3311 ( is_array($owner_contact_ids) && !empty($owner_contact_ids) )
3312 )
3313 {
3314 if ( !is_array($owner_contact_ids) )
3315 {
3316 $owner_contact_ids = array($owner_contact_ids);
3317 }
3318
3319 foreach ( $owner_contact_ids as $owner_contact_id )
3320 {
3321 echo get_the_title($owner_contact_id) . '<br>';
3322 echo '<div style="color:#BBB">';
3323 echo 'T: ' . get_post_meta($owner_contact_id, '_telephone_number', TRUE) . '<br>';
3324 echo 'E: ' . get_post_meta($owner_contact_id, '_email_address', TRUE);
3325 echo '</div>';
3326 }
3327 }
3328
3329 echo '</td>';
3330 echo '<td style="text-align:left;">' . $offer->get_formatted_amount() . '</td>';
3331 echo '<td style="text-align:left;">';
3332 $status = get_post_meta(get_the_ID(), '_status', TRUE);
3333 echo ucwords(str_replace("_", " ", $status));
3334 echo '</td>';
3335 echo '</tr>';
3336 }
3337
3338 echo '
3339 </tbody>
3340 </table>
3341 <br>';
3342 }
3343 else
3344 {
3345 echo '<p>' . __( 'No offers exist for this contact', 'propertyhive') . '</p>';
3346 }
3347 wp_reset_postdata();
3348
3349 do_action('propertyhive_contact_offers_fields');
3350
3351 echo '</div>';
3352
3353 echo '</div>';
3354
3355 die();
3356 }
3357
3358 // Sale related functions
3359 public function get_sale_details_meta_box()
3360 {
3361 check_ajax_referer( 'sale-details-meta-box', 'security' );
3362
3363 $sale = new PH_Offer((int)$_POST['sale_id']);
3364
3365 echo '<div class="propertyhive_meta_box">';
3366
3367 echo '<div class="options_group">';
3368
3369 if ( $sale->status != '' )
3370 {
3371 echo '<p class="form-field">
3372
3373 <label for="">' . __('Status', 'propertyhive') . '</label>
3374
3375 ' . ucwords(str_replace("_", " ", $sale->status)) . '
3376
3377 </p>';
3378 }
3379
3380 $sale_date_time = $sale->sale_date_time;
3381 if ( empty($sale_date_time) )
3382 {
3383 $sale_date_time = date("Y-m-d H:i:s");
3384 }
3385
3386 echo '<p class="form-field sale_date_field">
3387
3388 <label for="_sale_date">' . __('Sale Date', 'propertyhive') . '</label>
3389
3390 <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)) . '">
3391
3392 </p>';
3393
3394 $args = array(
3395 'id' => '_amount',
3396 'label' => __( 'Sale Amount', 'propertyhive' ) . ' (&pound;)',
3397 'desc_tip' => false,
3398 'class' => 'short',
3399 'value' => ( is_numeric($sale->amount) ? number_format($sale->amount) : '' ),
3400 'custom_attributes' => array(
3401 //'style' => 'width:95%; max-width:500px;'
3402 )
3403 );
3404 propertyhive_wp_text_input( $args );
3405
3406 do_action('propertyhive_sale_details_fields');
3407
3408 echo '</div>';
3409
3410 echo '</div>';
3411
3412 die();
3413 }
3414
3415 public function get_sale_actions()
3416 {
3417 check_ajax_referer( 'sale-actions', 'security' );
3418
3419 $post_id = $_POST['sale_id'];
3420
3421 $status = get_post_meta( $post_id, '_status', TRUE );
3422
3423 echo '<div class="propertyhive_meta_box propertyhive_meta_box_actions" id="propertyhive_sale_actions_meta_box">
3424
3425 <div class="options_group" style="padding-top:8px;">';
3426
3427 $actions = array();
3428
3429 if ( $status == 'current' )
3430 {
3431 $actions[] = '<a
3432 href="#action_panel_sale_exchanged"
3433 class="button button-success sale-action"
3434 style="width:100%; margin-bottom:7px; text-align:center"
3435 >' . __('Sale Exchanged', 'propertyhive') . '</a>';
3436
3437 }
3438
3439 if ( $status == 'exchanged' )
3440 {
3441 $actions[] = '<a
3442 href="#action_panel_sale_completed"
3443 class="button button-success sale-action"
3444 style="width:100%; margin-bottom:7px; text-align:center"
3445 >' . __('Sale Completed', 'propertyhive') . '</a>';
3446 }
3447
3448 if ( $status == 'completed' )
3449 {
3450
3451 }
3452
3453 if ( $status == 'current' || $status == 'exchanged' )
3454 {
3455 $actions[] = '<a
3456 href="#action_panel_sale_fallen_through"
3457 class="button sale-action"
3458 style="width:100%; margin-bottom:7px; text-align:center"
3459 >' . __('Sale Fallen Through', 'propertyhive') . '</a>';
3460 }
3461
3462 $actions = apply_filters( 'propertyhive_admin_sale_actions', $actions, $post->ID );
3463
3464 if ( !empty($actions) )
3465 {
3466 echo implode("", $actions);
3467 }
3468 else
3469 {
3470 echo '<div style="text-align:center">' . __( 'No actions to display', 'propertyhive' ) . '</div>';
3471 }
3472
3473 echo '</div>
3474
3475 </div>';
3476
3477 die();
3478 }
3479
3480 public function sale_exchanged()
3481 {
3482 check_ajax_referer( 'sale-actions', 'security' );
3483
3484 $post_id = $_POST['sale_id'];
3485
3486 $status = get_post_meta( $post_id, '_status', TRUE );
3487
3488 if ( $status == 'current' )
3489 {
3490 update_post_meta( $post_id, '_status', 'exchanged' );
3491
3492 $current_user = wp_get_current_user();
3493
3494 // Add note/comment to sale
3495 $comment = array(
3496 'note_type' => 'action',
3497 'action' => 'sale_exchanged',
3498 );
3499
3500 $data = array(
3501 'comment_post_ID' => $post_id,
3502 'comment_author' => $current_user->display_name,
3503 'comment_author_email' => 'propertyhive@noreply.com',
3504 'comment_author_url' => '',
3505 'comment_date' => date("Y-m-d H:i:s"),
3506 'comment_content' => serialize($comment),
3507 'comment_approved' => 1,
3508 'comment_type' => 'propertyhive_note',
3509 );
3510 $comment_id = wp_insert_comment( $data );
3511 }
3512
3513 die();
3514 }
3515
3516 public function sale_completed()
3517 {
3518 check_ajax_referer( 'sale-actions', 'security' );
3519
3520 $post_id = $_POST['sale_id'];
3521
3522 $status = get_post_meta( $post_id, '_status', TRUE );
3523
3524 if ( $status == 'exchanged' )
3525 {
3526 update_post_meta( $post_id, '_status', 'completed' );
3527
3528 $current_user = wp_get_current_user();
3529
3530 // Add note/comment to sale
3531 $comment = array(
3532 'note_type' => 'action',
3533 'action' => 'sale_completed',
3534 );
3535
3536 $data = array(
3537 'comment_post_ID' => $post_id,
3538 'comment_author' => $current_user->display_name,
3539 'comment_author_email' => 'propertyhive@noreply.com',
3540 'comment_author_url' => '',
3541 'comment_date' => date("Y-m-d H:i:s"),
3542 'comment_content' => serialize($comment),
3543 'comment_approved' => 1,
3544 'comment_type' => 'propertyhive_note',
3545 );
3546 $comment_id = wp_insert_comment( $data );
3547 }
3548
3549 die();
3550 }
3551
3552 public function sale_fallen_through()
3553 {
3554 check_ajax_referer( 'sale-actions', 'security' );
3555
3556 $post_id = $_POST['sale_id'];
3557
3558 $status = get_post_meta( $post_id, '_status', TRUE );
3559
3560 if ( $status == 'current' || $status == 'exchanged' )
3561 {
3562 update_post_meta( $post_id, '_status', 'fallen_through' );
3563
3564 $current_user = wp_get_current_user();
3565
3566 // Add note/comment to sale
3567 $comment = array(
3568 'note_type' => 'action',
3569 'action' => 'sale_fallen_through',
3570 );
3571
3572 $data = array(
3573 'comment_post_ID' => $post_id,
3574 'comment_author' => $current_user->display_name,
3575 'comment_author_email' => 'propertyhive@noreply.com',
3576 'comment_author_url' => '',
3577 'comment_date' => date("Y-m-d H:i:s"),
3578 'comment_content' => serialize($comment),
3579 'comment_approved' => 1,
3580 'comment_type' => 'propertyhive_note',
3581 );
3582 $comment_id = wp_insert_comment( $data );
3583 }
3584
3585 die();
3586 }
3587
3588 public function get_property_sales_meta_box()
3589 {
3590 check_ajax_referer( 'get_property_sales_meta_box', 'security' );
3591
3592 global $post;
3593
3594 echo '<div class="propertyhive_meta_box">';
3595
3596 echo '<div class="options_group">';
3597
3598 $args = array(
3599 'post_type' => 'sale',
3600 'nopaging' => true,
3601 'orderby' => 'meta_value',
3602 'order' => 'DESC',
3603 'meta_key' => '_sale_date_time',
3604 'post_status' => 'publish',
3605 'meta_query' => array(
3606 array(
3607 'key' => '_property_id',
3608 'value' => $_POST['post_id']
3609 )
3610 )
3611 );
3612 $sales_query = new WP_Query( $args );
3613
3614 if ( $sales_query->have_posts() )
3615 {
3616 echo '<table style="width:100%">
3617 <thead>
3618 <tr>
3619 <th style="text-align:left;">' . __( 'Sale Date', 'propertyhive' ) . '</th>
3620 <th style="text-align:left;">' . __( 'Applicant', 'propertyhive' ) . '</th>
3621 <th style="text-align:left;">' . __( 'Sale Amount', 'propertyhive' ) . '</th>
3622 <th style="text-align:left;">' . __( 'Status', 'propertyhive' ) . '</th>
3623 </tr>
3624 </thead>
3625 <tbody>';
3626
3627 while ( $sales_query->have_posts() )
3628 {
3629 $sales_query->the_post();
3630
3631 $sale = new PH_Sale(get_the_ID());
3632
3633 echo '<tr>';
3634 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>';
3635 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>';
3636 echo '<td style="text-align:left;">' . $sale->get_formatted_amount() . '</td>';
3637 echo '<td style="text-align:left;">';
3638 $status = get_post_meta(get_the_ID(), '_status', TRUE);
3639 echo ucwords(str_replace("_", " ", $status));
3640 echo '</td>';
3641 echo '</tr>';
3642 }
3643
3644 echo '
3645 </tbody>
3646 </table>
3647 <br>';
3648 }
3649 else
3650 {
3651 echo '<p>' . __( 'No sales exist for this property', 'propertyhive') . '</p>';
3652 }
3653 wp_reset_postdata();
3654
3655 do_action('propertyhive_property_sales_fields');
3656
3657 echo '</div>';
3658
3659 echo '</div>';
3660
3661 die();
3662 }
3663
3664 public function get_contact_sales_meta_box()
3665 {
3666 check_ajax_referer( 'get_contact_sales_meta_box', 'security' );
3667
3668 global $post;
3669
3670 echo '<div class="propertyhive_meta_box">';
3671
3672 echo '<div class="options_group">';
3673
3674 $args = array(
3675 'post_type' => 'sale',
3676 'nopaging' => true,
3677 'orderby' => 'meta_value',
3678 'order' => 'DESC',
3679 'post_status' => 'publish',
3680 'meta_key' => '_sale_date_time',
3681 'meta_query' => array(
3682 array(
3683 'key' => '_applicant_contact_id',
3684 'value' => $_POST['post_id']
3685 )
3686 )
3687 );
3688 $sales_query = new WP_Query( $args );
3689
3690 if ( $sales_query->have_posts() )
3691 {
3692 echo '<table style="width:100%">
3693 <thead>
3694 <tr>
3695 <th style="text-align:left;">' . __( 'Offer Date', 'propertyhive' ) . '</th>
3696 <th style="text-align:left;">' . __( 'Property', 'propertyhive' ) . '</th>
3697 <th style="text-align:left;">' . __( 'Property Owner', 'propertyhive' ) . '</th>
3698 <th style="text-align:left;">' . __( 'Offer Amount', 'propertyhive' ) . '</th>
3699 <th style="text-align:left;">' . __( 'Status', 'propertyhive' ) . '</th>
3700 </tr>
3701 </thead>
3702 <tbody>';
3703
3704 while ( $sales_query->have_posts() )
3705 {
3706 $sales_query->the_post();
3707
3708 $sale = new PH_Sale(get_the_ID());
3709
3710 $property = new PH_Property((int)get_post_meta(get_the_ID(), '_property_id', TRUE));
3711
3712 echo '<tr>';
3713 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>';
3714 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>';
3715 echo '<td style="text-align:left;">';
3716
3717 $owner_contact_ids = $property->_owner_contact_id;
3718 if (
3719 ( !is_array($owner_contact_ids) && $owner_contact_ids != '' && $owner_contact_ids != 0 )
3720 ||
3721 ( is_array($owner_contact_ids) && !empty($owner_contact_ids) )
3722 )
3723 {
3724 if ( !is_array($owner_contact_ids) )
3725 {
3726 $owner_contact_ids = array($owner_contact_ids);
3727 }
3728
3729 foreach ( $owner_contact_ids as $owner_contact_id )
3730 {
3731 echo get_the_title($owner_contact_id) . '<br>';
3732 echo '<div style="color:#BBB">';
3733 echo 'T: ' . get_post_meta($owner_contact_id, '_telephone_number', TRUE) . '<br>';
3734 echo 'E: ' . get_post_meta($owner_contact_id, '_email_address', TRUE);
3735 echo '</div>';
3736 }
3737 }
3738
3739 echo '</td>';
3740 echo '<td style="text-align:left;">' . $sale->get_formatted_amount() . '</td>';
3741 echo '<td style="text-align:left;">';
3742 $status = get_post_meta(get_the_ID(), '_status', TRUE);
3743 echo ucwords(str_replace("_", " ", $status));
3744 echo '</td>';
3745 echo '</tr>';
3746 }
3747
3748 echo '
3749 </tbody>
3750 </table>
3751 <br>';
3752 }
3753 else
3754 {
3755 echo '<p>' . __( 'No sales exist for this contact', 'propertyhive') . '</p>';
3756 }
3757 wp_reset_postdata();
3758
3759 do_action('propertyhive_contact_sales_fields');
3760
3761 echo '</div>';
3762
3763 echo '</div>';
3764
3765 die();
3766 }
3767 }
3768
3769 new PH_AJAX();
3770