PluginProbe
Property Hive / trunk
Property Hive vtrunk
2.2.6 2.2.5 2.2.4 2.2.3 2.2.2 1.4.46 1.4.47 1.4.48 1.4.49 1.4.5 1.4.50 1.4.51 1.4.52 1.4.53 1.4.54 1.4.55 1.4.56 1.4.57 1.4.58 1.4.59 1.4.6 1.4.60 1.4.61 1.4.62 1.4.63 All 259 releases
propertyhive / includes / class-ph-emails.php

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

937 lines 31.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' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 /**
8 * Transactional Emails Controller
9 *
10 * Property Hive Emails Class which handles the sending on transactional emails and email templates. This class loads in available emails.
11 *
12 * @class PH_Emails
13 * @version 1.0.0
14 * @package PropertyHive/Classes/Emails
15 * @category Class
16 * @author PropertyHive
17 */
18 class PH_Emails {
19
20 /** @var PH_Emails The single instance of the class */
21 protected static $_instance = null;
22
23 /**
24 * Main PH_Emails Instance.
25 *
26 * Ensures only one instance of PH_Emails is loaded or can be loaded.
27 *
28 * @since 1.0.0
29 * @static
30 * @return PH_Emails Main instance
31 */
32 public static function instance() {
33 if ( is_null( self::$_instance ) ) {
34 self::$_instance = new self();
35 }
36 return self::$_instance;
37 }
38
39 /**
40 * Cloning is forbidden.
41 *
42 * @since 1.0.0
43 */
44 public function __clone() {
45 _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'propertyhive' ), '1.0.0' );
46 }
47
48 /**
49 * Unserializing instances of this class is forbidden.
50 *
51 * @since 1.0.0
52 */
53 public function __wakeup() {
54 _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'propertyhive' ), '1.0.0' );
55 }
56
57 /**
58 * Constructor for the email class hooks in all emails that can be sent.
59 *
60 */
61 public function __construct() {
62 $this->init();
63
64 // Email Header, Footer
65 add_action( 'propertyhive_email_header', array( $this, 'email_header' ), 10, 1 );
66 add_action( 'propertyhive_email_footer', array( $this, 'email_footer' ), 10, 1 );
67
68 add_action( 'propertyhive_process_email_log', array( $this, 'ph_process_email_log' ) );
69 add_action( 'propertyhive_auto_email_match', array( $this, 'ph_auto_email_match' ) );
70
71 // Send applicant registration email
72 add_action( 'propertyhive_applicant_registered', array( $this, 'send_applicant_registration_alert' ), 10, 2 );
73
74 add_action( 'admin_init', array( $this, 'run_custom_email_cron' ), 10, 1 );
75
76 add_action( 'init', array( $this, 'check_email_queue_is_scheduled'), 99 );
77 }
78
79 public function check_email_queue_is_scheduled()
80 {
81 $schedule = wp_get_schedule( 'propertyhive_process_email_log' );
82
83 if ( $schedule === FALSE )
84 {
85 // Hmm... cron job not found. Let's set it up
86 $timestamp = wp_next_scheduled( 'propertyhive_process_email_log' );
87 wp_unschedule_event($timestamp, 'propertyhive_process_email_log' );
88 wp_clear_scheduled_hook('propertyhive_process_email_log');
89
90 wp_schedule_event( time(), 'every_fifteen_minutes', 'propertyhive_process_email_log' );
91 }
92 }
93
94 public function run_custom_email_cron()
95 {
96 if (isset($_GET['custom_email_log_cron']) && in_array($_GET['custom_email_log_cron'], array('propertyhive_process_email_log', 'propertyhive_auto_email_match')) )
97 {
98 do_action($_GET['custom_email_log_cron']);
99 }
100 }
101
102 public function send_applicant_registration_alert( $contact_post_id, $user_id )
103 {
104 if (
105 get_option( 'propertyhive_new_registration_alert', '' ) == 'yes' &&
106 isset($_POST['office_id']) && // in the future we should have office stored against contact and use that
107 $_POST['office_id'] != '' &&
108 isset($_POST['department']) && // Should really take department from contacts requirements
109 $_POST['department'] != ''
110 )
111 {
112 $to = get_post_meta( (int)$_POST['office_id'], '_office_email_address_' . str_replace("residential-", "", ph_clean($_POST['department'])), TRUE );
113
114 if ( $to == '' )
115 {
116 $to = get_option( 'admin_email', '' );
117 }
118
119 $subject = sprintf(
120 /* translators: %s: person name */
121 __( 'A new applicant, %s, has registered through your website', 'propertyhive' ),
122 get_the_title($contact_post_id)
123 );
124
125 $message = __( "A new applicant has registered through your website. Please find details of the applicant below:", 'propertyhive' ) . "\n\n";
126
127 $message = apply_filters( 'propertyhive_applicant_registration_email_pre_body', $message, $contact_post_id );
128
129 $form_controls = ph_get_user_details_form_fields();
130
131 $form_controls = apply_filters( 'propertyhive_user_details_form_fields', $form_controls );
132
133 $form_controls_2 = ph_get_applicant_requirements_form_fields();
134
135 $form_controls_2 = apply_filters( 'propertyhive_applicant_requirements_form_fields', $form_controls_2, get_post_meta( $contact_post_id, '_applicant_profile_0', true ) );
136
137 $form_controls = array_merge( $form_controls, $form_controls_2 );
138
139 $form_controls = apply_filters( 'propertyhive_applicant_registration_form_fields', $form_controls );
140
141 unset($form_controls['office_id']);
142
143 foreach ($form_controls as $key => $control)
144 {
145 if ( isset($control['type']) && $control['type'] == 'password' )
146 {
147 continue;
148 }
149
150 $value = ph_clean($_POST[$key]);
151 $values = array();
152 if ( !empty($value) && taxonomy_exists($key) )
153 {
154 if ( !is_array($value) ) { $value = array($value); }
155
156 foreach ( $value as $value_term )
157 {
158 $term = get_term( ph_clean($value_term), $key );
159
160 if ( isset($term->name) )
161 {
162 $values[] = $term->name;
163 }
164 }
165
166 $value = implode(", ", $values);
167 }
168
169 if ( ph_clean($value) == '' )
170 {
171 continue;
172 }
173
174 $label = ( isset($control['label']) ) ? $control['label'] : $key;
175 $message .= $label . ": " . $value . "\n";
176 }
177
178 wp_mail($to, $subject, $message);
179 }
180 }
181
182 /**
183 * Process ph_email_log table. Handle failed, hung and pending emails
184 */
185 public function ph_process_email_log()
186 {
187 global $wpdb;
188
189 $lock_id = uniqid( "", true );
190
191 $wpdb->query("
192 UPDATE " . $wpdb->prefix . "ph_email_log
193 SET
194 status = 'fail2',
195 lock_id = ''
196 WHERE
197 status = 'fail1'
198 AND
199 lock_id <> ''
200 AND
201 locked_at <= '" . date("Y-m-d H:i:s", strtotime('24 hours ago')) . "'
202 ");
203
204 $wpdb->query("
205 UPDATE " . $wpdb->prefix . "ph_email_log
206 SET
207 status = 'fail1',
208 lock_id = ''
209 WHERE
210 status = ''
211 AND
212 lock_id <> ''
213 AND
214 locked_at <= '" . date("Y-m-d H:i:s", strtotime('24 hours ago')) . "'
215 ");
216
217 // Lock/reserve all emails in log that are status blank or 'fail1' and lock_id blank and send_at in the past
218 // Only grab 25 at a time to prevent hanging/being seen as spamming
219 $wpdb->query("
220 UPDATE " . $wpdb->prefix . "ph_email_log
221 SET
222 lock_id = '" . $lock_id . "',
223 locked_at = '" . date("Y-m-d H:i:s") . "'
224 WHERE
225 (status = '' OR status = 'fail1')
226 AND
227 lock_id = ''
228 AND
229 send_at <= '" . date("Y-m-d H:i:s") . "'
230 LIMIT " . apply_filters( 'propertyhive_email_process_limit', 25 ) . "
231 ");
232
233 // We now have up to 25 emails locked. Get this 25 and attempt to send
234 $emails_to_send = $wpdb->get_results("
235 SELECT *
236 FROM " . $wpdb->prefix . "ph_email_log
237 WHERE
238 lock_id = '" . $lock_id . "'
239 ");
240
241 foreach ( $emails_to_send as $email_to_send )
242 {
243 $email_id = $email_to_send->email_id;
244
245 $headers = array();
246 $headers[] = 'From: ' . html_entity_decode($email_to_send->from_name) . ' <' . $email_to_send->from_email_address . '>';
247 if ( $email_to_send->cc_email_address != '' )
248 {
249 $headers[] = 'Cc: ' . $email_to_send->cc_email_address;
250 }
251 if ( $email_to_send->bcc_email_address != '' )
252 {
253 $headers[] = 'Bcc: ' . $email_to_send->bcc_email_address;
254 }
255 $headers[] = 'Content-Type: text/html; charset=UTF-8';
256
257 $body = $email_to_send->body;
258
259 if ( extension_loaded('zlib') && @gzuncompress($body) !== false )
260 {
261 $body = gzuncompress($body);
262 }
263
264 $body = apply_filters( 'propertyhive_mail_content', $this->style_inline( $this->wrap_message( $body, $email_to_send->contact_id ) ) );
265
266 $sent = wp_mail(
267 $email_to_send->to_email_address,
268 $email_to_send->subject,
269 $body,
270 $headers/*,
271 string|array $attachments = array() */
272 );
273
274 $new_status = '';
275 if ( $sent )
276 {
277 // Sent successfully
278 $new_status = 'sent';
279 }
280 else
281 {
282 // Failed to send
283 if ($email_to_send->status == '')
284 {
285 $new_status = 'fail1';
286 }
287 else
288 {
289 $new_status = 'fail2';
290 }
291 }
292 $wpdb->query("
293 UPDATE " . $wpdb->prefix . "ph_email_log
294 SET
295 status = '" . $new_status . "',
296 lock_id = ''
297 WHERE
298 email_id = '" . $email_id . "'
299 ");
300 }
301
302 // Delete old logs
303 $keep_logs_days = (string)apply_filters( 'propertyhive_keep_email_logs_days', '3650' ); // 10 years
304
305 // Revert back to 3650 days if anything other than numbers has been passed
306 // This prevent SQL injection and errors
307 if ( !preg_match("/^\d+$/", $keep_logs_days) )
308 {
309 $keep_logs_days = '3650';
310 }
311
312 $wpdb->query( "DELETE FROM " . $wpdb->prefix . "ph_email_log WHERE send_at < DATE_SUB(NOW(), INTERVAL " . $keep_logs_days . " DAY)" );
313 }
314
315 /*
316 * Automatically send new properties to registered applicants
317 */
318 public function ph_auto_email_match()
319 {
320 global $post;
321
322 $dry_run = isset($_GET['dry_run']) ? true : false;
323
324 if ( $dry_run === true ) { echo 'Running auto-match in dry run mode. Logging will be output and no emails will be sent.' . "<br>\n"; }
325
326 // Auto emails enabled in settings
327 // Auto emails not disabled in applicant record
328 // Property added more recently that setting enabled in settings
329 // Property not already previously sent
330 // Valid email address
331 // 'Do not email' not selected
332
333 $auto_property_match_enabled = get_option( 'propertyhive_auto_property_match', '' );
334
335 if ( $dry_run === true ) { echo 'Auto-match setting enabled: ' . $auto_property_match_enabled . "<br>\n"; }
336
337 if ( $auto_property_match_enabled == '' )
338 {
339 return false;
340 }
341
342 $auto_property_match_enabled_date = get_option( 'propertyhive_auto_property_match_enabled_date', '' );
343
344 if ( $dry_run === true ) { echo 'Auto-match setting enabled date: ' . $auto_property_match_enabled_date . "<br>\n"; }
345
346 if ( $auto_property_match_enabled_date == '' )
347 {
348 return false;
349 }
350
351 // Get all of the offices and store them in an array to save having to query them for every email
352 $args = array(
353 'post_type' => 'office',
354 'nopaging' => true
355 );
356
357 $office_names = array();
358 $office_email_addresses = array();
359 $office_query = new WP_Query( $args );
360
361 if ( $office_query->have_posts() )
362 {
363 while ( $office_query->have_posts() )
364 {
365 $office_query->the_post();
366
367 $office_names[get_the_ID()] = get_the_title( get_the_ID() );
368
369 $office_email_addresses['residential-sales'][get_the_ID()] = get_post_meta( get_the_ID(), '_office_email_address_sales', TRUE );
370 $office_email_addresses['residential-lettings'][get_the_ID()] = get_post_meta( get_the_ID(), '_office_email_address_lettings', TRUE );
371 $office_email_addresses['commercial'][get_the_ID()] = get_post_meta( get_the_ID(), '_office_email_address_commercial', TRUE );
372 }
373 }
374
375 wp_reset_postdata();
376
377 // Get all of the negotiators and store them in an array to save having to query them for every email
378 $negotiator_names = array();
379 $negotiator_email_addresses = array();
380
381 $args = array(
382 'number' => 9999,
383 'role__not_in' => apply_filters( 'property_negotiator_exclude_roles', array('property_hive_contact', 'subscriber') ),
384 'fields' => array( 'ID', 'display_name', 'user_email' )
385 );
386
387 $args = apply_filters( 'propertyhive_negotiators_query', $args );
388
389 $user_query = new WP_User_Query( $args );
390
391 $negotiators = array();
392
393 if ( ! empty( $user_query->results ) )
394 {
395 foreach ( $user_query->results as $user )
396 {
397 $negotiator_names[$user->ID] = $user->display_name;
398
399 $negotiator_email_addresses[$user->ID] = $user->user_email;
400 }
401 }
402
403 include_once( dirname(__FILE__) . '/admin/class-ph-admin-matching-properties.php' );
404 $ph_admin_matching_properties = new PH_Admin_Matching_Properties();
405
406 $meta_query = array(
407 array(
408 'key' => '_contact_types',
409 'value' => 'applicant',
410 'compare' => 'LIKE'
411 )
412 );
413
414 if ( version_compare( get_bloginfo( 'version' ), '5.1', '>=' ) )
415 {
416 // If WP version contains compare_key, check contact has at least one applicant profile with Send Matching Properties checked
417 $meta_query[] = array(
418 'key' => '_applicant_profile_',
419 'compare_key' => 'LIKE',
420 'value' => 'send_matching_properties";s:3:"yes"',
421 'compare' => 'LIKE',
422 );
423 }
424
425 // Get all contacts that have a type of applicant
426 $args = array(
427 'post_type' => 'contact',
428 'nopaging' => true,
429 'meta_query' => $meta_query,
430 'fields' => 'ids'
431 );
432
433 if ( $dry_run === true ) { echo 'Running query to get contacts with args: ' . print_r($args, true) . "<br>\n"; }
434
435 $contact_query = new WP_Query( $args );
436
437 if ( $dry_run === true ) { echo 'Found ' . $contact_query->found_posts . ' contacts' . "<br>\n"; }
438
439 if ( $contact_query->have_posts() )
440 {
441 $default_subject = get_option( 'propertyhive_property_match_default_email_subject', '' );
442 $default_body = get_option( 'propertyhive_property_match_default_email_body', '' );
443
444 $allowed_tags = array(
445 'strong' => array(),
446 'span' => array(),
447 'em' => array(),
448 'h1' => array(),
449 'h2' => array(),
450 'h3' => array(),
451 'h4' => array(),
452 'h5' => array(),
453 'h6' => array(),
454 'i' => array(),
455 'u' => array(),
456 'b' => array(),
457 'a' => array(
458 'href' => array(),
459 'target' => array(),
460 ),
461 );
462 $allowed_tags = apply_filters( 'propertyhive_match_email_allowed_tags', $allowed_tags );
463
464 $default_body = wp_kses($default_body, $allowedposttags);
465
466 while ( $contact_query->have_posts() )
467 {
468 $contact_query->the_post();
469
470 $contact_id = get_the_ID();
471
472 if ( $dry_run === true ) { echo 'Doing contact: ' . get_the_title() . "<br>\n"; }
473
474 // invalid email address
475 if ( strpos( get_post_meta( $contact_id, '_email_address', TRUE ), '@' ) === FALSE )
476 {
477 if ( $dry_run === true ) { echo 'Invalid email address. Skipping' . "<br>\n"; }
478
479 continue;
480 }
481
482 // email in the list of forbidden contact methods
483 $forbidden_contact_methods = get_post_meta( $contact_id, '_forbidden_contact_methods', TRUE );
484 if ( is_array($forbidden_contact_methods) && in_array('email', $forbidden_contact_methods) )
485 {
486 if ( $dry_run === true ) { echo 'Email communication forbidden in contact preferences. Skipping' . "<br>\n"; }
487
488 continue;
489 }
490
491 $applicant_profiles = get_post_meta( $contact_id, '_applicant_profiles', TRUE );
492
493 if ( $applicant_profiles != '' && $applicant_profiles > 0 )
494 {
495 $dismissed_properties = get_post_meta( $contact_id, '_dismissed_properties', TRUE );
496 if ( $dismissed_properties == '' )
497 {
498 $dismissed_properties = array();
499 }
500
501 if ( $dry_run === true ) { if ( !empty($dismissed_properties) ) { echo 'Dismissed properties: ' . print_r($dismissed_properties, true) . "<br>\n"; } }
502
503 for ( $i = 0; $i < $applicant_profiles; ++$i )
504 {
505 $applicant_profile = get_post_meta( $contact_id, '_applicant_profile_' . $i, TRUE );
506
507 if ( $applicant_profile == '' || !is_array($applicant_profile) || !isset($applicant_profile['department']) )
508 {
509 if ( $dry_run === true ) { echo 'Applicant relationship empty or no department set' . "<br>\n"; }
510 continue;
511 }
512
513 if ( !isset($applicant_profile['send_matching_properties']) || ( isset($applicant_profile['send_matching_properties']) && $applicant_profile['send_matching_properties'] != 'yes' ) )
514 {
515 if ( $dry_run === true ) { echo 'Send matching properties disabled' . "<br>\n"; }
516 continue;
517 }
518
519 if ( isset($applicant_profile['auto_match_disabled']) && $applicant_profile['auto_match_disabled'] == 'yes' )
520 {
521 if ( $dry_run === true ) { echo 'Auto match disabled' . "<br>\n"; }
522 continue;
523 }
524
525 if ( $dry_run === true ) { echo 'Getting matching properties' . "<br>\n"; }
526
527 $matching_properties = $ph_admin_matching_properties->get_matching_properties( $contact_id, $i, $auto_property_match_enabled_date );
528
529 if ( $dry_run === true ) { echo 'Found ' . count($matching_properties) . ' matching properties' . "<br>\n"; }
530
531 if ( !empty($matching_properties) )
532 {
533 $already_sent_properties = get_post_meta( $contact_id, '_applicant_profile_' . $i . '_match_history', TRUE );
534
535 // Remove from this array if on market changed or price changed
536 if ( is_array($already_sent_properties) )
537 {
538 if ( $dry_run === true ) { echo 'Already sent properties before: ' . print_r($already_sent_properties, true) . "<br>\n"; }
539
540 foreach ( $already_sent_properties as $already_sent_property_id => $sends )
541 {
542 $highest_send = $sends[count($sends) - 1]['date'];
543
544 if ( $highest_send != '' )
545 {
546 if ( $dry_run === true ) { echo 'Property: ' . $already_sent_property_id . ' last sent: ' . $highest_send . "<br>\n"; }
547
548 $on_market_change_date = get_post_meta( $already_sent_property_id, '_on_market_change_date', TRUE );
549
550 if ( $dry_run === true ) { echo 'Property: ' . $already_sent_property_id . ' last on market change: ' . $on_market_change_date . "<br>\n"; }
551
552 $price_change_date = get_post_meta( $already_sent_property_id, '_price_change_date', TRUE );
553
554 if ( $dry_run === true ) { echo 'Property: ' . $already_sent_property_id . ' last price change: ' . $price_change_date . "<br>\n"; }
555
556 if ( $on_market_change_date > $highest_send )
557 {
558 if ( $dry_run === true ) { echo 'Property: ' . $already_sent_property_id . ' has changed on market since last sent' . "<br>\n"; }
559
560 // This property has changed since it was last sent. Remove from already sent list so it gets sent again
561 unset($already_sent_properties[$already_sent_property_id]);
562 }
563 elseif ( $price_change_date > $highest_send )
564 {
565 if ( $dry_run === true ) { echo 'Property: ' . $already_sent_property_id . ' has changed price since last sent' . "<br>\n"; }
566
567 // This property has changed since it was last sent. Remove from already sent list so it gets sent again
568 unset($already_sent_properties[$already_sent_property_id]);
569 }
570 }
571 }
572
573 if ( $dry_run === true ) { echo 'Already sent properties after: ' . print_r($already_sent_properties, true) . "<br>\n"; }
574 }
575
576 if ( $dry_run === true ) { echo 'Matching properties before removing already sent: ' . print_r($matching_properties, true) . "<br>\n"; }
577
578 // Check properties haven't already been sent and not marked as 'not interested'
579 $new_matching_properties = array();
580 foreach ($matching_properties as $matching_property)
581 {
582 if ( !isset($already_sent_properties[$matching_property->id]) && !in_array($matching_property->id, $dismissed_properties) )
583 {
584 $new_matching_properties[] = $matching_property->id;
585 }
586 }
587
588 if ( $dry_run === true ) { echo 'Matching properties after removing already sent: ' . print_r($new_matching_properties, true) . "<br>\n"; }
589
590 $max_results = apply_filters( 'propertyhive_auto_match_maximum_results', FALSE);
591 if ( $max_results !== FALSE )
592 {
593 $new_matching_properties = array_slice($new_matching_properties, 0, (int)$max_results);
594 }
595
596 if ( $dry_run === true ) { echo 'Found ' . count($new_matching_properties) . ' matching properties after removing already sent and dismissed' . "<br>\n"; }
597
598 if ( !empty($new_matching_properties) )
599 {
600 $subject = str_replace("[property_count]", count($new_matching_properties) . ' propert' . ( ( count($new_matching_properties) != 1 ) ? 'ies' : 'y' ), $default_subject);
601
602 $contact = new PH_Contact($contact_id);
603 $body = str_replace("[contact_name]", $contact->post_title, $default_body);
604 $body = str_replace("[contact_dear]", $contact->dear(), $body);
605 $body = str_replace("[property_count]", count($new_matching_properties) . ' propert' . ( ( count($new_matching_properties) != 1 ) ? 'ies' : 'y' ), $body);
606
607 $office_counts = array();
608 $negotiator_counts = array();
609
610 if ( strpos($body, '[properties]') !== FALSE )
611 {
612 ob_start();
613
614 if ( !empty($new_matching_properties) )
615 {
616 foreach ( $new_matching_properties as $email_property_id )
617 {
618 $property = new PH_Property((int)$email_property_id);
619
620 if ( $property->office_id != '' && $property->office_id != 0 )
621 {
622 if ( !isset($office_counts[$property->office_id]) ) { $office_counts[$property->office_id] = 0; }
623 ++$office_counts[$property->office_id];
624 }
625
626 if ( $property->negotiator_id != '' && $property->negotiator_id != 0 )
627 {
628 if ( !isset($negotiator_counts[$property->negotiator_id]) ) { $negotiator_counts[$property->negotiator_id] = 0; }
629 ++$negotiator_counts[$property->negotiator_id];
630 }
631
632 ph_get_template( 'emails/applicant-match-property.php', array( 'property' => $property ) );
633 }
634 }
635 $body = str_replace("[properties]", ob_get_clean(), $body);
636 }
637
638 // Get email address of office with most properties
639 $highest_office_name = '';
640 $highest_office_email_address = '';
641 if ( !empty($office_counts) )
642 {
643 arsort($office_counts);
644 reset($office_counts);
645 $highest_office_id = key($office_counts);
646 $highest_office_name = ( isset($office_names[$highest_office_id]) ? $office_names[$highest_office_id] : '' );
647 $highest_office_email_address = ( isset($office_email_addresses[$applicant_profile['department']][$highest_office_id]) ? $office_email_addresses[$applicant_profile['department']][$highest_office_id] : '' );
648 }
649 if ( $highest_office_email_address == '' )
650 {
651 // fallback to admin email address
652 $highest_office_email_address = get_option('admin_email');
653 }
654
655 $body = str_replace("[office_name]", $highest_office_name, $body);
656 $body = str_replace("[office_email_address]", $highest_office_email_address, $body);
657
658 $highest_negotiator_name = '';
659 $highest_negotiator_email_address = '';
660 if ( !empty($negotiator_counts) )
661 {
662 arsort($negotiator_counts);
663 reset($negotiator_counts);
664 $highest_negotiator_id = key($negotiator_counts);
665 $highest_negotiator_name = ( isset($negotiator_names[$highest_negotiator_id]) ? $negotiator_names[$highest_negotiator_id] : '' );
666 $highest_negotiator_email_address = ( isset($negotiator_email_addresses[$highest_negotiator_id]) ? $negotiator_email_addresses[$highest_negotiator_id] : '' );
667 }
668
669 $body = str_replace("[negotiator_name]", $highest_negotiator_name, $body);
670 $body = str_replace("[negotiator_email_address]", $highest_negotiator_email_address, $body);
671
672 $highest_office_email_address = apply_filters( 'propertyhive_auto_match_from_email_address', $highest_office_email_address );
673
674 if ( !$dry_run )
675 {
676 $ph_admin_matching_properties->send_emails(
677 $contact_id,
678 $i,
679 $new_matching_properties,
680 get_bloginfo('name'),
681 $highest_office_email_address,
682 $subject,
683 $body
684 );
685 }
686 else
687 {
688 echo 'Would\'ve sent email. Not sending due to being ran in dry run mode' . "<br>\n";
689 }
690 }
691 }
692 }
693 }
694 else
695 {
696 if ( $dry_run === true ) { echo 'No applicant profiles found. Skipping' . "<br>\n"; }
697 }
698 }
699 }
700
701 if ( $dry_run === true ) { echo 'Finished auto-match process' . "<br>\n"; die(); }
702
703 wp_reset_postdata();
704 }
705
706 /**
707 * Init email classes.
708 */
709 public function init() {
710
711 }
712
713 /**
714 * Apply inline styles to dynamic content.
715 *
716 * @param string|null $content
717 * @return string
718 */
719 public function style_inline( $content ) {
720 // make sure we only inline CSS for html emails
721 if ( class_exists( 'DOMDocument' ) ) {
722 ob_start();
723 ph_get_template( 'emails/email-styles.php' );
724 $css = apply_filters( 'propertyhive_email_styles', ob_get_clean() );
725
726 // include css inliner
727 if ( ! class_exists( 'Emogrifier' ) && class_exists( 'DOMDocument' ) ) {
728 include_once( dirname( __FILE__ ) . '/libraries/class-emogrifier.php' );
729 }
730
731 // apply CSS styles inline for picky email clients
732 try {
733 $emogrifier = new Emogrifier( $content, $css );
734 $content = $emogrifier->emogrify();
735 } catch ( Exception $e ) {
736 die(esc_html("Error converting CSS styles to be inline. Error as follows: " . $e->getMessage()));
737 }
738 }
739 return $content;
740 }
741
742 /**
743 * Get the email header.
744 */
745 public function email_header( $contact_id = '' ) {
746 ph_get_template( 'emails/email-header.php' );
747 }
748
749 /**
750 * Get the email footer.
751 */
752 public function email_footer( $contact_id = '' ) {
753 $unsubscribe_link = '';
754 if ($contact_id != '')
755 {
756 $unsubscribe_link = site_url() .'?ph_unsubscribe=' . base64_encode($contact_id . '|' . md5( get_post_meta( $contact_id, '_email_address', TRUE ) ) );
757 }
758
759 ph_get_template( 'emails/email-footer.php', array( 'unsubscribe_link' => $unsubscribe_link ) );
760 }
761
762 /**
763 * Wraps a message in the Property Hive mail template.
764 *
765 * @param mixed $email_heading
766 * @param string $message
767 * @return string
768 */
769 public function wrap_message( $message, $contact_id = '', $plain_text = false ) {
770 // Buffer
771 ob_start();
772
773 do_action( 'propertyhive_email_header', $contact_id );
774
775 echo wpautop( wptexturize( $message ) );
776
777 do_action( 'propertyhive_email_footer', $contact_id );
778
779 // Get contents
780 $message = ob_get_clean();
781
782 return $message;
783 }
784
785 public function send_enquiry_auto_responder( $data = array() )
786 {
787 if ( isset($data['property_id']) && !empty(ph_clean($data['property_id'])) )
788 {
789 $property_ids = ph_clean(explode("|", $data['property_id']));
790 if ( !is_array($property_ids) ) { $property_ids = array($property_ids); }
791
792 $to = sanitize_email( $_POST['email_address'] );
793 $subject = get_option( 'propertyhive_enquiry_auto_responder_email_subject', '' );
794 $body = get_option( 'propertyhive_enquiry_auto_responder_email_body', '' );
795
796 if ( $to != '' && $subject != '' && $body != '' )
797 {
798 $headers = array();
799 $headers[] = 'From: ' . html_entity_decode(get_bloginfo('name')) . ' <' . get_option( 'propertyhive_email_from_address', get_option( 'admin_email' ) ) . '>';
800 $headers[] = 'Content-Type: text/html; charset=UTF-8';
801
802 $body = str_replace( "[name]", ( isset($_POST['name']) ? ph_clean($_POST['name']) : '' ), $body );
803
804 $property_address_hyperlinked = array();
805 foreach ( $property_ids as $property_id )
806 {
807 $property_address_hyperlinked[] = '<a href="' . get_permalink($property_id) . '">' . get_the_title($property_id) . '</a>';
808 }
809 $body = str_replace( "[property_address_hyperlinked]", implode(' and ', array_filter(array_merge(array(join(', ', array_slice($property_address_hyperlinked, 0, -1))), array_slice($property_address_hyperlinked, -1)), 'strlen')), $body );
810
811 if ( strpos( $body, '[similar_properties]' ) !== FALSE )
812 {
813 $similar_html = '';
814
815 foreach ( $property_ids as $property_id )
816 {
817 $department = get_post_meta( $property_id, '_department', TRUE );
818
819 // Get three similar properties
820 $args = array(
821 'post_type' => 'property',
822 'post_status' => 'publish',
823 'posts_per_page' => 3,
824 'orderby' => 'rand',
825 'post__not_in' => array($property_id),
826 );
827
828 $meta_query = array();
829
830 $meta_query[] = array(
831 'key' => '_department',
832 'value' => $department,
833 );
834
835 $meta_query[] = array(
836 'key' => '_on_market',
837 'value' => 'yes',
838 );
839
840 if ( $department != 'commercial' && ph_get_custom_department_based_on( $department ) != 'commercial' )
841 {
842 $bedrooms = get_post_meta( $property_id, '_bedrooms', TRUE );
843
844 $meta_query[] = array(
845 'key' => '_bedrooms',
846 'value' => $bedrooms,
847 'type' => 'NUMERIC'
848 );
849
850
851 $price = get_post_meta( $property_id, '_price_actual', true );
852 $lower_price = $price - ($price / 10);
853 $higher_price = $price + ($price / 10);
854
855 $meta_query[] = array(
856 'key' => '_price_actual',
857 'value' => $lower_price,
858 'compare' => '>=',
859 'type' => 'NUMERIC'
860 );
861
862 $meta_query[] = array(
863 'key' => '_price_actual',
864 'value' => $higher_price,
865 'compare' => '<=',
866 'type' => 'NUMERIC'
867 );
868 }
869 else
870 {
871 $for_sale = get_post_meta( $property_id, '_for_sale', true );
872 $to_rent = get_post_meta( $property_id, '_to_rent', true );
873
874 if ( $for_sale == 'yes' )
875 {
876 $meta_query[] = array(
877 'key' => '_for_sale',
878 'value' => 'yes',
879 );
880 }
881 elseif ( $to_rent == 'yes' )
882 {
883 $meta_query[] = array(
884 'key' => '_to_rent',
885 'value' => 'yes',
886 );
887 }
888 }
889
890 $args['meta_query'] = $meta_query;
891
892 $property_match_statuses = get_option( 'propertyhive_property_match_statuses', '' );
893 if ( $property_match_statuses != '' && is_array($property_match_statuses) && !empty($property_match_statuses) )
894 {
895 $args['tax_query'] = array(
896 array(
897 'taxonomy' => 'availability',
898 'field' => 'term_id',
899 'terms' => $property_match_statuses,
900 'operator' => 'IN',
901 )
902 );
903 }
904
905 $properties_query = new WP_Query( apply_filters( 'propertyhive_auto_responder_similar_properties_query', $args, $property_id ) );
906
907 if ( $properties_query->have_posts() )
908 {
909 while ( $properties_query->have_posts() )
910 {
911 $properties_query->the_post();
912
913 $property = new PH_Property( get_the_ID() );
914
915 ob_start();
916
917 ph_get_template( 'emails/enquiry-autoresponder-similar-property.php', array( 'property' => $property ) );
918
919 $similar_html .= ob_get_clean();
920 }
921 }
922 }
923 if ( !empty($similar_html) )
924 {
925 $similar_html = '<br><hr><br><h3>Similar Properties You Might Like:</h3>' . $similar_html;
926 }
927 $body = str_replace( "[similar_properties]", $similar_html, $body );
928 }
929
930 $body = apply_filters( 'propertyhive_enquiry_auto_responder_body', $body, $property_ids[0] );
931 $body = apply_filters( 'propertyhive_mail_content', $this->style_inline( $this->wrap_message( $body ) ) );
932
933 wp_mail( $to, $subject, $body, $headers );
934 }
935 }
936 }
937 }