PluginProbe
Property Hive / 2.2.5
Property Hive v2.2.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 / admin / class-ph-admin-merge-contacts.php

class-ph-admin-merge-contacts.php in Property Hive 2.2.5, at includes/admin/class-ph-admin-merge-contacts.php

1,041 lines 37.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * PropertyHive Admin Merge Duplicate Contacts Class.
4 *
5 * @author PropertyHive
6 * @category Admin
7 * @package PropertyHive/Admin
8 * @version 1.0.0
9 */
10
11 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
12
13 if ( ! class_exists( 'PH_Admin_Merge_Contacts' ) ) :
14
15 /**
16 * PH_Admin_Merge_Contacts
17 */
18 class PH_Admin_Merge_Contacts {
19
20 /**
21 * Handles the display of contacts to merge, to allow the user to choose a primary contact
22 *
23 * @access public
24 * @return void
25 */
26 public function output()
27 {
28 ?>
29 <div class="wrap propertyhive">
30
31 <h1><?php echo esc_html(__('Merge Contacts', 'propertyhive')); ?></h1>
32
33 <p>When you click 'Merge Contacts', all associated records will be moved onto the contact selected as the primary contact, and all other contacts will be deleted.</p>
34
35 <p><strong>Note:</strong> This action is irreversible.</p>
36
37 <?php
38
39 if ( isset( $_GET['merge_ids'] ) && $_GET['merge_ids'] != '' )
40 {
41 $ids_to_merge = explode( '|', ph_clean( $_GET['merge_ids']) );
42 }
43
44 if ( isset( $ids_to_merge ) && count( $ids_to_merge ) > 1 )
45 {
46 foreach ( $ids_to_merge as $i => $contact_id )
47 {
48 echo '<div style="border:1px solid #CCC; padding:25px; background:#FFF; position:relative">';
49 $contact = new PH_Contact( (int)$contact_id );
50
51 // Initialise array to hold information about each contact
52 $contact_parts = array( '<h3 style="margin:0">' . ( trim($contact->post_title) != '' ? $contact->post_title : '(' . __('Unnamed Contact', 'propertyhive' ) . ')' ) . '</h3>' ) ;
53
54 $date_posted = get_the_date( '', $contact->id );
55 $contact_parts[] = 'Added on ' . $date_posted;
56
57 // Add contact address to contact parts
58 if ( $contact->get_formatted_full_address() != '' )
59 {
60 $contact_parts[] = $contact->get_formatted_full_address();
61 }
62
63 // Add email address and number to contact parts, if set
64 $email_address = $contact->_email_address;
65 $telephone_number = $contact->_telephone_number;
66 if ( !empty( $email_address ) || !empty( $telephone_number ) )
67 {
68 $contact_details_array = array_filter(array(
69 $contact->_email_address,
70 $contact->_telephone_number
71 ));
72 $contact_parts[] = implode( ', ', $contact_details_array );
73 }
74
75 // Display all selected contact types. This may be redundant when all profiles are displayed
76 $contact_types = $contact->_contact_types;
77 if ( !empty( $contact_types ) )
78 {
79 $contact_types_lookup = array(
80 'owner' => __( 'Owner', 'propertyhive' ),
81 'potentialowner' => __( 'Potential Owner', 'propertyhive' ),
82 'applicant' => __( 'Applicant', 'propertyhive' ),
83 'hotapplicant' => __( 'Hot Applicant', 'propertyhive' ),
84 'thirdparty' => __( 'Third Party Contact', 'propertyhive' ),
85 );
86
87 $contact_types_array = array();
88
89 foreach( $contact_types as $contact_type )
90 {
91 if ( isset( $contact_types_lookup[$contact_type] ) )
92 {
93 $contact_types_array[] = $contact_types_lookup[$contact_type];
94 }
95 else
96 {
97 $contact_types_array[] = ucfirst($contact_type);
98 }
99 }
100
101 $contact_parts[] = implode( ', ', $contact_types_array );
102 }
103
104 $contact_parts = $this->get_property_owner_records( $contact, $contact_parts );
105
106 $contact_parts = $this->get_potential_owner_records( $contact, $contact_parts );
107
108 $contact_parts = $this->get_third_party_records( $contact, $contact_parts );
109
110 $contact_parts = $this->get_applicant_records( $contact, $contact_parts );
111
112 $contact_parts = $this->get_enquiry_records( $contact, $contact_parts );
113
114 $contact_parts = $this->get_viewing_records( $contact, $contact_parts );
115
116 $contact_parts = $this->get_offer_records( $contact, $contact_parts );
117
118 $contact_parts = $this->get_sale_records( $contact, $contact_parts );
119
120 $contact_parts = $this->get_tenancy_records( $contact, $contact_parts );
121
122 $contact_parts = $this->get_note_records( $contact, $contact_parts );
123
124 $contact_parts = apply_filters( 'propertyhive_merge_contact_parts', $contact_parts );
125
126 echo implode( '<br>', $contact_parts );
127 ?>
128 <label style="position:absolute; right:25px; top:25px;">
129 <?php echo esc_html(__( 'Use as Primary Contact', 'propertyhive' )); ?>
130 <input type="radio" name="primary_merge_contact" value="<?php echo esc_attr((int)$contact_id); ?>"<?php if ( $i == 0 ) { echo ' checked'; } ?>>
131 </label>
132 <?php
133
134 echo "</div><br>";
135 }
136 ?>
137 <p class="form-field">
138 <input type="button" value="<?php echo esc_attr(__( 'Merge Contacts', 'propertyhive' )); ?>" class="button-primary" id="merge_contacts_button">
139 <a href="<?php echo esc_url(wp_get_raw_referer()); ?>" class="button" id="cancel_merge_button"><?php echo esc_html(__( 'Cancel', 'propertyhive' )); ?></a>
140 </p>
141
142 <script>
143
144 jQuery( function(jQuery) {
145
146 jQuery('#merge_contacts_button').click(function(e)
147 {
148 var selected_primary = jQuery('input[name="primary_merge_contact"]:checked').val();
149 if ( typeof(selected_primary) == 'undefined' )
150 {
151 alert('A primary contact must be selected');
152 return false;
153 }
154
155 var confirmBox = confirm('All records will now be merged onto the primary contact. Do you want to continue?');
156
157 if (confirmBox)
158 {
159 jQuery('#merge_contacts_button').val('Merging Contacts...');
160 jQuery('#merge_contacts_button').attr('disabled', 'disabled');
161
162 var data = {
163 action: 'propertyhive_merge_contact_records',
164 contact_ids : '<?php echo esc_js(ph_clean($_GET['merge_ids'])); ?>',
165 primary_contact_id: selected_primary,
166 nonce: '<?php echo wp_create_nonce( 'propertyhive_merge_contact' ); ?>',
167 };
168
169 jQuery.post( '<?php echo esc_url(admin_url('admin-ajax.php')); ?>', data, function(response) {
170
171 if (response.error)
172 {
173 alert(response.error);
174
175 jQuery('#merge_contacts_button').val('Merge Contacts');
176 jQuery('#merge_contacts_button').attr('disabled', false);
177 }
178 if (response.success)
179 {
180 // Redirect to referrer, adding message in admin_notices
181 window.location.href = '<?php echo admin_url('edit.php?post_type=contact&propertyhive_contacts_merged=1'); ?>';
182 }
183 });
184 }
185 });
186 });
187
188 </script>
189 <?php
190 }
191 else
192 {
193 ?>
194 <p>Could not find multiple contacts to merge. Please <a href="<?php echo esc_url(wp_get_raw_referer()); ?>">return to the contact list</a> and try again.</p>
195 <?php
196 }
197
198 ?>
199 </div>
200 <?php
201 }
202
203 /**
204 * Adds details of any associated properties to the list of contact parts
205 *
206 * @access private
207 * @return array
208 */
209 private function get_property_owner_records( $contact, $contact_parts )
210 {
211 // get properties where this is the owner
212 $args = array(
213 'post_type' => 'property',
214 'nopaging' => true,
215 'meta_query' => array(
216 'relation' => 'OR',
217 array(
218 'key' => '_owner_contact_id',
219 'value' => $contact->id,
220 'compare' => '='
221 ),
222 array(
223 'key' => '_owner_contact_id',
224 'value' => ':"' . $contact->id . '"',
225 'compare' => 'LIKE'
226 ),
227 array(
228 'key' => '_owner_contact_id',
229 'value' => ':' . $contact->id . ';',
230 'compare' => 'LIKE'
231 )
232 )
233 );
234 $property_query = new WP_Query($args);
235
236 if ($property_query->have_posts())
237 {
238 while ($property_query->have_posts())
239 {
240 $property_query->the_post();
241
242 $property = new PH_Property( get_the_ID() );
243
244 $property_department = ucwords( str_replace( '-', ' ', $property->_department) );
245
246 $contact_parts[] = $property_department . ' Owner: ' . $property->get_formatted_full_address();
247 }
248 }
249 wp_reset_postdata();
250 return $contact_parts;
251 }
252
253 /**
254 * Adds details of any potential owner records to the list of contact parts
255 *
256 * @access private
257 * @return array
258 */
259 private function get_potential_owner_records( $contact, $contact_parts )
260 {
261 // get appraisals where this is the owner and where not instructed
262 $args = array(
263 'post_type' => 'appraisal',
264 'nopaging' => true,
265 'meta_query' => array(
266 array(
267 'key' => '_property_owner_contact_id',
268 'value' => $contact->id,
269 'compare' => '='
270 ),
271 )
272 );
273
274 $appraisal_query = new WP_Query($args);
275
276 if ($appraisal_query->have_posts())
277 {
278 while ($appraisal_query->have_posts())
279 {
280 $appraisal_query->the_post();
281
282 $appraisal = new PH_Appraisal( get_the_ID() );
283
284 $property_department = ucwords( str_replace( '-', ' ', $appraisal->_department) );
285
286 $contact_parts[] = $property_department . ' Appraisal Owner: ' . $appraisal->get_formatted_full_address();
287 }
288 }
289 wp_reset_postdata();
290 return $contact_parts;
291 }
292
293 /**
294 * Adds details of any third party contact records to the list of contact parts
295 *
296 * @access private
297 * @return array
298 */
299 private function get_third_party_records( $contact, $contact_parts )
300 {
301 $third_party_categories = get_post_meta( $contact->id, '_third_party_categories', TRUE );
302 if ( is_array($third_party_categories) && !empty($third_party_categories) )
303 {
304 $third_party_category_names = array();
305
306 $ph_third_party_contacts = new PH_Third_Party_Contacts();
307
308 foreach ( $third_party_categories as $third_party_category )
309 {
310 if ( $third_party_category != '' && $third_party_category != 0 )
311 {
312 $category_name = $ph_third_party_contacts->get_category( $third_party_category );
313 if ( $category_name !== false )
314 {
315 $third_party_category_names[] = $category_name;
316 }
317 }
318 else
319 {
320 $third_party_category_names[] = 'General';
321 }
322 }
323
324 $contact_parts[] = 'Third Party Contact: ' . implode( ', ', $third_party_category_names);
325 }
326 return $contact_parts;
327 }
328
329 /**
330 * Adds details of any applicant records to the list of contact parts
331 *
332 * @access private
333 * @return array
334 */
335 private function get_applicant_records( $contact, $contact_parts )
336 {
337 $num_applicant_profiles = get_post_meta( $contact->id, '_applicant_profiles', TRUE );
338 if ( !empty( $num_applicant_profiles ) )
339 {
340 for ( $i = 0; $i < $num_applicant_profiles; ++$i )
341 {
342 $applicant_profile = get_post_meta( $contact->id, '_applicant_profile_' . $i, TRUE );
343
344 $applicant_department = isset( $applicant_profile['department'] ) ? $applicant_profile['department'] : 'Empty';
345
346 $applicant_profile_parts = array();
347
348 if ( $applicant_department == 'residential-sales' || ph_get_custom_department_based_on($applicant_department) == 'residential-sales' )
349 {
350 if ( isset( $applicant_profile['max_price'] ) && !empty( $applicant_profile['max_price'] ) )
351 {
352 $applicant_profile_parts[] = '£' . ph_display_price_field( $applicant_profile['max_price'] );
353 }
354
355 if ( isset( $applicant_profile['min_beds'] ) && !empty( $applicant_profile['min_beds'] ) )
356 {
357 $applicant_profile_parts[] = $applicant_profile['min_beds'] . ' bedrooms';
358 }
359 }
360
361 if ( $applicant_department == 'residential-lettings' || ph_get_custom_department_based_on($applicant_department) == 'residential-lettings' )
362 {
363 if ( isset( $applicant_profile['max_rent'] ) && !empty( $applicant_profile['max_rent'] ) )
364 {
365 $maximum_rent = '£' . ph_display_price_field( $applicant_profile['max_rent'] );
366 if ( isset( $applicant_profile['rent_frequency'] ) && !empty( $applicant_profile['rent_frequency'] ) )
367 {
368 $maximum_rent .= ' ' . $applicant_profile['rent_frequency'];
369 }
370 else
371 {
372 $maximum_rent .= 'pcm';
373 }
374 $applicant_profile_parts[] = $maximum_rent;
375 }
376
377 if ( isset( $applicant_profile['min_beds'] ) && !empty( $applicant_profile['min_beds'] ) )
378 {
379 $applicant_profile_parts[] = $applicant_profile['min_beds'] . ' bedrooms';
380 }
381 }
382
383 if ( $applicant_department == 'commercial' || ph_get_custom_department_based_on($applicant_department) == 'commercial' )
384 {
385 if ( isset( $applicant_profile['available_as'] ) && !empty( $applicant_profile['available_as'] ) )
386 {
387 $available_as = implode( '/', $applicant_profile['available_as'] );
388 $applicant_profile_parts[] = 'Available as ' . $available_as;
389 }
390 }
391 $applicant_profile_parts = array_filter( $applicant_profile_parts );
392
393 $applicant_profile_text = ucwords( str_replace( '-', ' ', $applicant_department ) ) . ' Applicant';
394 if ( count($applicant_profile_parts) > 0 )
395 {
396 $applicant_profile_text .= ': ' . implode( ', ', $applicant_profile_parts );
397 }
398
399 $contact_parts[] = $applicant_profile_text;
400 }
401 }
402 return $contact_parts;
403 }
404
405 /**
406 * Adds count of any enquiry records to the list of contact parts
407 *
408 * @access private
409 * @return array
410 */
411 private function get_enquiry_records( $contact, $contact_parts )
412 {
413 $meta_query = array(
414 'relation' => 'OR',
415 array(
416 'key' => '_contact_id',
417 'value' => $contact->id,
418 ),
419 );
420
421 // Not including email address lookup in enquiry count as they won't be moved or removed by the merge
422 $contact_email_address = $contact->_email_address;
423 if ( !empty($contact_email_address) )
424 {
425 $meta_query[] = array(
426 'key' => 'email',
427 'value' => $contact_email_address,
428 );
429
430 $meta_query[] = array(
431 'key' => 'email_address',
432 'value' => $contact_email_address,
433 );
434 }
435
436 $args = array(
437 'post_type' => 'enquiry',
438 'nopaging' => true,
439 'fields' => 'ids',
440 'meta_query' => $meta_query,
441 );
442 $enquiries_query = new WP_Query( $args );
443 $enquiries_count = $enquiries_query->found_posts;
444 wp_reset_postdata();
445
446 if ( $enquiries_count > 0 )
447 {
448 $contact_parts[] = $enquiries_count . ' enquir' . ( $enquiries_count != 1 ? 'ies' : 'y' );
449 }
450 return $contact_parts;
451 }
452
453 /**
454 * Adds count of any viewing records to the list of contact parts
455 *
456 * @access private
457 * @return array
458 */
459 private function get_viewing_records( $contact, $contact_parts )
460 {
461 $args = array(
462 'post_type' => 'viewing',
463 'posts_per_page' => 1,
464 'fields' => 'ids',
465 'meta_query' => array(
466 array(
467 'key' => '_applicant_contact_id',
468 'value' => $contact->id,
469 )
470 )
471 );
472 $viewings_query = new WP_Query( $args );
473 $viewings_count = $viewings_query->found_posts;
474 wp_reset_postdata();
475
476 if ( $viewings_count > 0 )
477 {
478 $contact_parts[] = $viewings_count . ' viewing' . ( $viewings_count != 1 ? 's' : '' );
479 }
480 return $contact_parts;
481 }
482
483 /**
484 * Adds count of any offer records to the list of contact parts
485 *
486 * @access private
487 * @return array
488 */
489 private function get_offer_records( $contact, $contact_parts )
490 {
491 $args = array(
492 'post_type' => 'offer',
493 'posts_per_page' => 1,
494 'fields' => 'ids',
495 'meta_query' => array(
496 array(
497 'key' => '_applicant_contact_id',
498 'value' => $contact->id,
499 )
500 )
501 );
502 $offers_query = new WP_Query( $args );
503 $offers_count = $offers_query->found_posts;
504 wp_reset_postdata();
505
506 if ( $offers_count > 0 )
507 {
508 $contact_parts[] = $offers_count . ' offer' . ( $offers_count != 1 ? 's' : '' );
509 }
510 return $contact_parts;
511 }
512
513 /**
514 * Adds count of any sale records to the list of contact parts
515 *
516 * @access private
517 * @return array
518 */
519 private function get_sale_records( $contact, $contact_parts )
520 {
521 $args = array(
522 'post_type' => 'sale',
523 'posts_per_page' => 1,
524 'fields' => 'ids',
525 'meta_query' => array(
526 array(
527 'key' => '_applicant_contact_id',
528 'value' => $contact->id,
529 )
530 )
531 );
532 $sales_query = new WP_Query( $args );
533 $sales_count = $sales_query->found_posts;
534 wp_reset_postdata();
535
536 if ( $sales_count > 0 )
537 {
538 $contact_parts[] = $sales_count . ' sale' . ( $sales_count != 1 ? 's' : '' );
539 }
540 return $contact_parts;
541 }
542
543 /**
544 * Adds count of any tenancy records to the list of contact parts
545 *
546 * @access private
547 * @return array
548 */
549 private function get_tenancy_records( $contact, $contact_parts )
550 {
551 $args = array(
552 'post_type' => 'tenancy',
553 'posts_per_page' => 1,
554 'fields' => 'ids',
555 'meta_query' => array(
556 array(
557 'key' => '_applicant_contact_id',
558 'value' => $contact->id
559 )
560 )
561 );
562 $tenancies_query = new WP_Query( $args );
563 $tenancies_count = $tenancies_query->found_posts;
564 wp_reset_postdata();
565
566 if ( $tenancies_count > 0 )
567 {
568 $contact_parts[] = $tenancies_count . ' tenanc' . ( $tenancies_count != 1 ? 'ies' : 'y' );
569 }
570 return $contact_parts;
571 }
572
573 /**
574 * Adds count of any note records to the list of contact parts
575 *
576 * @access private
577 * @return array
578 */
579 private function get_note_records( $contact, $contact_parts )
580 {
581 global $post;
582
583 $post = get_post((int)$contact->id);
584
585 $args = array(
586 'post_id' => (int)$contact->id,
587 'type' => 'propertyhive_note',
588 'meta_query' => array(
589 array(
590 'key' => 'related_to',
591 'value' => '"' . (int)$contact->id . '"',
592 'compare' => 'LIKE',
593 ),
594 )
595 );
596 $notes = get_comments( $args );
597
598 $notes_count = count($notes);
599
600 if ( $notes_count > 0 )
601 {
602 $contact_parts[] = $notes_count . ' note' . ( $notes_count != 1 ? 's' : '' );
603 }
604
605 return $contact_parts;
606 }
607
608 public function do_merge( $primary_contact_id, $contacts_to_merge )
609 {
610 global $wpdb, $post;
611
612 // Merge contact_types into primary
613 $primary_contact_types = get_post_meta( $primary_contact_id, '_contact_types', true );
614 if ( $primary_contact_types == '' || !is_array($primary_contact_types) )
615 {
616 $primary_contact_types = array();
617 }
618
619 foreach ( $contacts_to_merge as $child_contact_id )
620 {
621 $child_contact_types = get_post_meta( $child_contact_id, '_contact_types', true );
622 if ( is_array($child_contact_types) )
623 {
624 $primary_contact_types = array_merge( $primary_contact_types, $child_contact_types );
625 }
626 }
627
628 update_post_meta( $primary_contact_id, '_contact_types', array_unique( $primary_contact_types ) );
629
630 // Merge third party categories into primary
631 $primary_third_party_categories = get_post_meta( $primary_contact_id, '_third_party_categories', true );
632 if ( $primary_third_party_categories == '' || !is_array($primary_third_party_categories) )
633 {
634 $primary_third_party_categories = array();
635 }
636
637 foreach ( $contacts_to_merge as $child_contact_id )
638 {
639 $child_third_party_categories = get_post_meta( $child_contact_id, '_third_party_categories', true );
640 if ( is_array($child_third_party_categories) )
641 {
642 $primary_third_party_categories = array_merge( $primary_third_party_categories, $child_third_party_categories );
643 }
644 }
645
646 if ( count($primary_third_party_categories) > 0 )
647 {
648 update_post_meta( $primary_contact_id, '_third_party_categories', array_unique( $primary_third_party_categories ) );
649 }
650
651 // Move applicant profiles to primary
652 $primary_applicant_profiles = get_post_meta( $primary_contact_id, '_applicant_profiles', true );
653 if ( empty($primary_applicant_profiles) )
654 {
655 $primary_applicant_profiles = 0;
656 }
657
658 $hot_applicant = '';
659 foreach ( $contacts_to_merge as $child_contact_id )
660 {
661 $child_applicant_profiles = get_post_meta( $child_contact_id, '_applicant_profiles', true );
662 if ( !empty($child_applicant_profiles) )
663 {
664 for ( $i = 0; $i < $child_applicant_profiles; ++$i )
665 {
666 $child_applicant_profile = get_post_meta( $child_contact_id, '_applicant_profile_' . $i, true );
667 if ( !empty($child_applicant_profile) )
668 {
669 update_post_meta( $primary_contact_id, '_applicant_profile_' . $primary_applicant_profiles, $child_applicant_profile );
670
671 $child_applicant_profile_match_history = get_post_meta( $child_contact_id, '_applicant_profile_' . $i . '_match_history', true );
672 if ( !empty($child_applicant_profile_match_history) )
673 {
674 update_post_meta( $primary_contact_id, '_applicant_profile_' . $primary_applicant_profiles . '_match_history', $child_applicant_profile_match_history );
675 }
676
677 if ( isset($child_applicant_profile['grading']) && ph_clean($child_applicant_profile['grading']) == 'hot' )
678 {
679 $hot_applicant = 'yes';
680 }
681
682 ++$primary_applicant_profiles;
683 }
684 }
685 }
686 }
687
688 if ( $hot_applicant == 'yes' )
689 {
690 update_post_meta( $primary_contact_id, '_hot_applicant', $hot_applicant );
691 }
692
693 if ( $primary_applicant_profiles > 0 )
694 {
695 update_post_meta( $primary_contact_id, '_applicant_profiles', $primary_applicant_profiles );
696 }
697
698 // Merge dismissed properties
699 $primary_dismissed_properties = get_post_meta( $primary_contact_id, '_dismissed_properties', true );
700 if ( empty($primary_dismissed_properties) )
701 {
702 $primary_dismissed_properties = array();
703 }
704 foreach ( $contacts_to_merge as $child_contact_id )
705 {
706 $child_dismissed_properties = get_post_meta( $child_contact_id, '_dismissed_properties', true );
707 if ( is_array($child_dismissed_properties) && !empty($child_dismissed_properties) )
708 {
709 $primary_dismissed_properties = array_merge($primary_dismissed_properties, $child_dismissed_properties);
710 }
711 }
712 if ( !empty($primary_dismissed_properties) )
713 {
714 $primary_dismissed_properties = array_unique($primary_dismissed_properties);
715 update_post_meta( $primary_contact_id, '_dismissed_properties', $primary_dismissed_properties );
716 }
717
718 // Move appraisal records to primary
719 $args = array(
720 'post_type' => 'appraisal',
721 'nopaging' => true,
722 'meta_query' => array(
723 array(
724 'key' => '_property_owner_contact_id',
725 'value' => $contacts_to_merge,
726 'compare' => 'IN'
727 ),
728 )
729 );
730
731 $appraisal_query = new WP_Query($args);
732
733 if ($appraisal_query->have_posts())
734 {
735 while ($appraisal_query->have_posts())
736 {
737 $appraisal_query->the_post();
738 foreach ( $contacts_to_merge as $child_contact_id )
739 {
740 update_post_meta( get_the_id(), '_property_owner_contact_id', $primary_contact_id, $child_contact_id );
741 }
742 }
743 }
744 wp_reset_postdata();
745
746 foreach ( $contacts_to_merge as $child_contact_id )
747 {
748 // Move property owner records to primary
749 $args = array(
750 'post_type' => 'property',
751 'nopaging' => true,
752 'meta_query' => array(
753 'relation' => 'OR',
754 array(
755 'key' => '_owner_contact_id',
756 'value' => $child_contact_id,
757 'compare' => '='
758 ),
759 array(
760 'key' => '_owner_contact_id',
761 'value' => ':"' . $child_contact_id . '"',
762 'compare' => 'LIKE'
763 ),
764 array(
765 'key' => '_owner_contact_id',
766 'value' => ':' . $child_contact_id . ';',
767 'compare' => 'LIKE'
768 )
769 )
770 );
771 $property_query = new WP_Query($args);
772
773 if ($property_query->have_posts())
774 {
775 while ($property_query->have_posts())
776 {
777 $property_query->the_post();
778
779 $property_owner_ids = get_post_meta( get_the_id(), '_owner_contact_id', true );
780
781 if ( !is_array( $property_owner_ids ) )
782 {
783 update_post_meta( get_the_id(), '_owner_contact_id', $primary_contact_id, $child_contact_id );
784 }
785 else
786 {
787 unset($property_owner_ids[array_search($child_contact_id, $property_owner_ids)]);
788 $property_owner_ids[] = $primary_contact_id;
789 update_post_meta( get_the_id(), '_owner_contact_id', $property_owner_ids );
790 }
791 }
792 }
793 wp_reset_postdata();
794 }
795
796 // Move enquiries to primary
797 $args = array(
798 'post_type' => 'enquiry',
799 'nopaging' => true,
800 'fields' => 'ids',
801 'meta_query' => array(
802 array(
803 'key' => '_contact_id',
804 'value' => $contacts_to_merge,
805 'compare' => 'IN'
806 ),
807 ),
808 );
809 $enquiries_query = new WP_Query( $args );
810
811 if ($enquiries_query->have_posts())
812 {
813 while ($enquiries_query->have_posts())
814 {
815 $enquiries_query->the_post();
816 foreach ( $contacts_to_merge as $child_contact_id )
817 {
818 update_post_meta( get_the_id(), '_contact_id', $primary_contact_id, $child_contact_id );
819 }
820 }
821 }
822 wp_reset_postdata();
823
824 // Move viewings to primary
825 $args = array(
826 'post_type' => 'viewing',
827 'nopaging' => true,
828 'fields' => 'ids',
829 'meta_query' => array(
830 array(
831 'key' => '_applicant_contact_id',
832 'value' => $contacts_to_merge,
833 'compare' => 'IN'
834 ),
835 ),
836 );
837 $viewings_query = new WP_Query( $args );
838
839 if ($viewings_query->have_posts())
840 {
841 while ($viewings_query->have_posts())
842 {
843 $viewings_query->the_post();
844 foreach ( $contacts_to_merge as $child_contact_id )
845 {
846 update_post_meta( get_the_id(), '_applicant_contact_id', $primary_contact_id, $child_contact_id );
847 }
848 }
849 }
850 wp_reset_postdata();
851
852 // Move offers to primary
853 $args = array(
854 'post_type' => 'offer',
855 'nopaging' => true,
856 'fields' => 'ids',
857 'meta_query' => array(
858 array(
859 'key' => '_applicant_contact_id',
860 'value' => $contacts_to_merge,
861 'compare' => 'IN'
862 ),
863 ),
864 );
865 $offers_query = new WP_Query( $args );
866
867 if ($offers_query->have_posts())
868 {
869 while ($offers_query->have_posts())
870 {
871 $offers_query->the_post();
872 foreach ( $contacts_to_merge as $child_contact_id )
873 {
874 update_post_meta( get_the_id(), '_applicant_contact_id', $primary_contact_id, $child_contact_id );
875 }
876 }
877 }
878 wp_reset_postdata();
879
880 // Move sales to primary
881 $args = array(
882 'post_type' => 'sale',
883 'nopaging' => true,
884 'fields' => 'ids',
885 'meta_query' => array(
886 array(
887 'key' => '_applicant_contact_id',
888 'value' => $contacts_to_merge,
889 'compare' => 'IN'
890 ),
891 ),
892 );
893 $sales_query = new WP_Query( $args );
894
895 if ($sales_query->have_posts())
896 {
897 while ($sales_query->have_posts())
898 {
899 $sales_query->the_post();
900 foreach ( $contacts_to_merge as $child_contact_id )
901 {
902 update_post_meta( get_the_id(), '_applicant_contact_id', $primary_contact_id, $child_contact_id );
903 }
904 }
905 }
906 wp_reset_postdata();
907
908 // Move tenancies to primary
909 $args = array(
910 'post_type' => 'tenancy',
911 'nopaging' => true,
912 'fields' => 'ids',
913 'meta_query' => array(
914 array(
915 'key' => '_applicant_contact_id',
916 'value' => $contacts_to_merge,
917 'compare' => 'IN'
918 ),
919 ),
920 );
921 $tenancies_query = new WP_Query( $args );
922
923 if ($tenancies_query->have_posts())
924 {
925 while ($tenancies_query->have_posts())
926 {
927 $tenancies_query->the_post();
928 foreach ( $contacts_to_merge as $child_contact_id )
929 {
930 update_post_meta( get_the_id(), '_applicant_contact_id', $primary_contact_id, $child_contact_id );
931 }
932 }
933 }
934 wp_reset_postdata();
935
936 // Copy notes to primary
937 foreach ( $contacts_to_merge as $child_contact_id )
938 {
939 $post = get_post((int)$child_contact_id);
940
941 $args = array(
942 'post_id' => (int)$child_contact_id,
943 'type' => 'propertyhive_note',
944 'meta_query' => array(
945 array(
946 'key' => 'related_to',
947 'value' => '"' . (int)$child_contact_id . '"',
948 'compare' => 'LIKE',
949 ),
950 )
951 );
952 $notes = get_comments( $args );
953
954 foreach ( $notes as $note )
955 {
956 // Want to ignore note if it's an existing 'contact_merged' note. This would be confusing
957 $comment_content = @unserialize($note->comment_content, ['allowed_classes' => false]);
958 if (
959 $comment_content !== false &&
960 isset($comment_content['note_type']) && $comment_content['note_type'] == 'action' &&
961 isset($comment_content['action']) && $comment_content['action'] == 'contact_merged'
962 )
963 {
964 continue;
965 }
966
967 // This note could've been assigned to this contact, or this contact could just be related to it
968 // Need to check both
969 if ( $note->comment_post_ID == $child_contact_id )
970 {
971 $data = array(
972 'comment_ID' => $note->comment_ID,
973 'comment_post_ID' => $primary_contact_id
974 );
975 $updated = wp_update_comment( $data );
976 }
977
978 $related_tos = get_comment_meta( $note->comment_ID, 'related_to', true );
979 if ( !empty($related_tos) )
980 {
981 $new_related_to = array();
982 foreach ( $related_tos as $related_to )
983 {
984 if ( $related_to == $child_contact_id )
985 {
986 $new_related_to[] = (string)$primary_contact_id; // convert to string to LIKE lookups work
987 }
988 else
989 {
990 $new_related_to[] = (string)$related_to; // convert to string to LIKE lookups work
991 }
992 }
993 $new_related_to = array_unique($new_related_to);
994 update_comment_meta( $note->comment_ID, 'related_to', $new_related_to );
995 }
996 }
997 }
998
999 // Write a note to all contacts highlighting what has happened
1000 $current_user = wp_get_current_user();
1001 foreach ( $contacts_to_merge as $child_contact_id )
1002 {
1003 $comment = array(
1004 'note_type' => 'action',
1005 'action' => 'contact_merged',
1006 'merged_into' => (int)$primary_contact_id,
1007 );
1008
1009 $data = array(
1010 'comment_post_ID' => (int)$child_contact_id,
1011 'comment_author' => $current_user->display_name,
1012 'comment_author_email' => 'propertyhive@noreply.com',
1013 'comment_author_url' => '',
1014 'comment_date' => date("Y-m-d H:i:s"),
1015 'comment_content' => serialize($comment),
1016 'comment_approved' => 1,
1017 'comment_type' => 'propertyhive_note',
1018 );
1019 $comment_id = wp_insert_comment( $data );
1020
1021 // Move contact being merged to the bin
1022 wp_trash_post( (int)$child_contact_id );
1023 }
1024
1025 // Update email log
1026 foreach ( $contacts_to_merge as $child_contact_id )
1027 {
1028 $wpdb->query("
1029 UPDATE " . $wpdb->prefix . "ph_email_log
1030 SET
1031 contact_id = '" . (int)$primary_contact_id . "'
1032 WHERE
1033 contact_id = '" . (int)$child_contact_id . "'
1034 ");
1035 }
1036
1037 do_action( 'propertyhive_contacts_merged', $primary_contact_id, $contacts_to_merge );
1038 }
1039 }
1040
1041 endif;