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-comments.php

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

510 lines 16.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 /**
8 * Comments
9 *
10 * Handle comments.
11 *
12 * @class PH_Comments
13 * @version 1.0.0
14 * @package PropertyHive/Classes/Products
15 * @category Class
16 * @author PropertyHive
17 */
18 class PH_Comments {
19
20 /**
21 * Hook in methods.
22 */
23 public static function init() {
24 // Secure propertyhive notes
25 add_filter( 'comments_clauses', array( __CLASS__, 'exclude_note_comments' ), 10, 1 );
26
27 add_filter( 'comments_clauses', array( __CLASS__, 'related_to_or_post_id' ), 20, 1 );
28
29 // Count comments
30 add_filter( 'wp_count_comments', array( __CLASS__, 'wp_count_comments' ), 99, 2 );
31
32 // Delete comments count cache whenever there is a new comment or a comment status changes
33 add_action( 'wp_insert_comment', array( __CLASS__, 'delete_comments_count_cache' ) );
34 add_action( 'wp_set_comment_status', array( __CLASS__, 'delete_comments_count_cache' ) );
35
36 add_action( 'add_post_meta', array( __CLASS__, 'check_on_market_add' ), 10, 3 );
37 add_action( 'update_post_meta', array( __CLASS__, 'check_on_market_update' ), 10, 4 );
38
39 add_action( 'update_post_meta', array( __CLASS__, 'check_price_change' ), 10, 4 );
40
41 add_action( 'set_object_terms', array( __CLASS__, 'check_property_status_update' ), 10, 6 );
42 }
43
44 public static function check_property_status_update( $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids )
45 {
46 if ( $taxonomy == 'availability' )
47 {
48 if (
49 get_post_type($object_id) == 'property' &&
50 get_post_status($object_id) == 'publish' &&
51 $tt_ids != $old_tt_ids
52 )
53 {
54 if ( apply_filters( 'propertyhive_add_property_availability_change_note', true ) === true )
55 {
56 $all_availability_terms = get_terms( 'availability', array( 'hide_empty' => 0 ) );
57
58 $old_availability_id = '';
59 $old_availability_name = '';
60 if ( is_array($old_tt_ids) && !empty($old_tt_ids) )
61 {
62 $old_availability_id = (int)$old_tt_ids[0];
63
64 foreach( $all_availability_terms as $term )
65 {
66 $tt_id = (int)$term->term_taxonomy_id;
67 if( $tt_id == $old_availability_id )
68 {
69 $old_availability_name = $term->name;
70 }
71 }
72 }
73
74 $new_availability_id = '';
75 $new_availability_name = '';
76 if ( is_array($tt_ids) && !empty($tt_ids) )
77 {
78 $new_availability_id = (int)$tt_ids[0];
79
80 foreach( $all_availability_terms as $term )
81 {
82 $tt_id = (int)$term->term_taxonomy_id;
83 if( $tt_id == $new_availability_id )
84 {
85 $new_availability_name = $term->name;
86 }
87 }
88 }
89
90 $current_user = wp_get_current_user();
91
92 // Add note/comment to property
93 $comment = array(
94 'note_type' => 'action',
95 'action' => 'property_availability_change',
96 'original_value' => $old_availability_name,
97 'new_value' => $new_availability_name
98 );
99
100 $data = array(
101 'comment_post_ID' => (int)$object_id,
102 'comment_author' => $current_user->display_name,
103 'comment_author_email' => 'propertyhive@noreply.com',
104 'comment_author_url' => '',
105 'comment_date' => date("Y-m-d H:i:s"),
106 'comment_content' => serialize($comment),
107 'comment_approved' => 1,
108 'comment_type' => 'propertyhive_note',
109 );
110 $comment_id = wp_insert_comment( $data );
111 }
112
113 update_post_meta( $object_id, '_availability_change_date', date("Y-m-d H:i:s") );
114 }
115 }
116 }
117
118 public static function related_to_or_post_id( $clauses )
119 {
120 global $wpdb, $post;
121
122 if ( strpos($clauses['where'], 'related_to') !== FALSE )
123 {
124 $clauses['join'] = str_replace( 'INNER JOIN', 'LEFT JOIN', $clauses['join'] );
125
126 // Remove main post ID constraint as it's handled by OR below
127 $strpos_post_id = strpos($clauses['where'], 'comment_post_ID');
128 if ( $strpos_post_id !== FALSE )
129 {
130 $strpos_next_and = strpos($clauses['where'], 'AND', $strpos_post_id);
131 if ( $strpos_next_and !== FALSE )
132 {
133 $clauses['where'] = substr_replace($clauses['where'], ' 1=1 ', $strpos_post_id, $strpos_next_and - $strpos_post_id );
134 }
135 }
136
137 // we're searching for related_to so should check where main post is comment_post_ID
138 $clauses['where'] = str_replace(
139 $wpdb->prefix . 'commentmeta.meta_key',
140 '( ' . $wpdb->prefix . 'commentmeta.meta_key',
141 $clauses['where']
142 );
143 $clauses['where'] .= ' OR comment_post_ID = "' . $post->ID . '" ) ';
144 }
145
146 return $clauses;
147 }
148
149 public static function insert_note( $post_id, $comment )
150 {
151 $current_user = wp_get_current_user();
152
153 $post_type = get_post_type( $post_id );
154
155 $related_to = array( $post_id );
156
157 switch ( $post_type )
158 {
159 case "property": {
160 // get property owner
161 $owner_contact_ids = get_post_meta( $post_id, '_owner_contact_id', TRUE );
162 if ( !empty($owner_contact_ids) )
163 {
164 if ( !is_array($owner_contact_ids) )
165 {
166 $owner_contact_ids = array( $owner_contact_ids );
167 }
168 foreach ( $owner_contact_ids as $owner_contact_id )
169 {
170 $related_to[] = $owner_contact_id;
171 }
172 }
173 break;
174 }
175 case "contact": {
176 // check contact type, then add to property if owner
177 $contact_types = get_post_meta( $post_id, '_contact_types', TRUE );
178 if ( in_array('owner', $contact_types) )
179 {
180 // this contact is an owner
181 // get properties
182 $args = array(
183 'post_type' => 'property',
184 'nopaging' => true,
185 'fields' => 'ids',
186 'meta_query' => array(
187 'relation' => 'OR',
188 array(
189 'key' => '_owner_contact_id',
190 'value' => $post_id,
191 'compare' => '=',
192 ),
193 array(
194 'key' => '_owner_contact_id',
195 'value' => '"' . $post_id . '"',
196 'compare' => 'LIKE',
197 ),
198 )
199 );
200
201 $property_query = new WP_Query( $args );
202
203 if ( $property_query->have_posts() )
204 {
205 while ( $property_query->have_posts() )
206 {
207 $property_query->the_post();
208
209 $related_to[] = get_the_ID();
210 }
211 }
212 wp_reset_postdata();
213 }
214 break;
215 }
216 case "appraisal": {
217 // get potential owner
218 $property_owner_contact_id = get_post_meta( $post_id, '_property_owner_contact_id', TRUE );
219 if ( $property_owner_contact_id != '' )
220 {
221 $related_to[] = $property_owner_contact_id;
222 }
223 break;
224 }
225 case "viewing":
226 case "offer":
227 case "sale": {
228 // get property
229 $property_id = get_post_meta( $post_id, '_property_id', TRUE );
230 if ( $property_id != '' )
231 {
232 $related_to[] = $property_id;
233
234 // get property owner
235 $owner_contact_ids = get_post_meta( $property_id, '_owner_contact_id', TRUE );
236 if ( !empty($owner_contact_ids) )
237 {
238 if ( !is_array($owner_contact_ids) )
239 {
240 $owner_contact_ids = array( $owner_contact_ids );
241 }
242 foreach ( $owner_contact_ids as $owner_contact_id )
243 {
244 $related_to[] = $owner_contact_id;
245 }
246 }
247 }
248
249 // get applicant
250 $applicant_ids = get_post_meta( $post_id, '_applicant_contact_id' );
251 if ( !empty($applicant_ids) )
252 {
253 if ( !is_array($applicant_ids) )
254 {
255 $applicant_ids = array( $applicant_ids );
256 }
257 foreach ( $applicant_ids as $applicant_id )
258 {
259 $related_to[] = $applicant_id;
260 }
261 }
262 break;
263 }
264 }
265
266 if ( isset($comment['note_type']) && $comment['note_type'] == 'note' && isset($comment['note']) && !empty($comment['note']) )
267 {
268 // Regular expression pattern to match {{mention-ID|NAME}} or {{mention-ID}}
269 $pattern = '/\{\{mention-(\d+)(?:\|([^}]*))?\}\}/';
270
271 // Use preg_match_all to find all matches
272 if ( preg_match_all($pattern, $comment['note'], $matches, PREG_SET_ORDER) )
273 {
274 foreach ($matches as $match)
275 {
276 $related_to[] = (int)$match[1];
277 }
278 }
279 }
280
281 $related_to = apply_filters( 'property_insert_note_related_to', $related_to, $post_id );
282
283 $related_to = array_filter( $related_to );
284
285 // Ensure they all go in as strings to allow LIKE query to work when querying related_to
286 $new_related_to = array();
287 foreach ( $related_to as $related_to_value )
288 {
289 $new_related_to[] = (string)$related_to_value;
290 }
291
292 $data = array(
293 'comment_post_ID' => $post_id,
294 'comment_author' => $current_user->display_name,
295 'comment_author_email' => 'propertyhive@noreply.com',
296 'comment_author_url' => '',
297 'comment_date' => date("Y-m-d H:i:s"),
298 'comment_content' => serialize($comment),
299 'comment_approved' => 1,
300 'comment_type' => 'propertyhive_note',
301 'comment_meta' => array(
302 'related_to' => $new_related_to,
303 ),
304 );
305 $comment_id = wp_insert_comment( $data );
306
307 return $comment_id;
308 }
309
310 public static function check_price_change( $meta_id, $object_id, $meta_key, $meta_value )
311 {
312 if ( get_post_type($object_id) == 'property' && ( $meta_key == '_price' || $meta_key == '_rent' ) )
313 {
314 $original_value = get_post_meta( $object_id, $meta_key, TRUE );
315
316 if ( $original_value != $meta_value )
317 {
318 if ( apply_filters( 'propertyhive_add_property_price_change_note', true ) === true )
319 {
320 $current_user = wp_get_current_user();
321
322 // Add note/comment to property
323 $comment = array(
324 'note_type' => 'action',
325 'action' => 'property_price_change',
326 'original_value' => $original_value,
327 'new_value' => $meta_value
328 );
329
330 $data = array(
331 'comment_post_ID' => (int)$object_id,
332 'comment_author' => $current_user->display_name,
333 'comment_author_email' => 'propertyhive@noreply.com',
334 'comment_author_url' => '',
335 'comment_date' => date("Y-m-d H:i:s"),
336 'comment_content' => serialize($comment),
337 'comment_approved' => 1,
338 'comment_type' => 'propertyhive_note',
339 );
340 $comment_id = wp_insert_comment( $data );
341 }
342
343 update_post_meta( $object_id, '_price_change_date', date("Y-m-d H:i:s") );
344 }
345 }
346 }
347
348 public static function check_on_market_add( $object_id, $meta_key, $meta_value )
349 {
350 if ( get_post_type($object_id) == 'property' && $meta_key == '_on_market' )
351 {
352 if ( $meta_value == 'yes' )
353 {
354 if ( apply_filters( 'propertyhive_add_property_on_market_change_note', true ) === true )
355 {
356 $note_action = 'property_on_market';
357
358 $current_user = wp_get_current_user();
359
360 // Add note/comment to property
361 $comment = array(
362 'note_type' => 'action',
363 'action' => $note_action,
364 );
365
366 $data = array(
367 'comment_post_ID' => (int)$object_id,
368 'comment_author' => $current_user->display_name,
369 'comment_author_email' => 'propertyhive@noreply.com',
370 'comment_author_url' => '',
371 'comment_date' => date("Y-m-d H:i:s"),
372 'comment_content' => serialize($comment),
373 'comment_approved' => 1,
374 'comment_type' => 'propertyhive_note',
375 );
376 $comment_id = wp_insert_comment( $data );
377 }
378
379 update_post_meta( $object_id, '_on_market_change_date', date("Y-m-d H:i:s") );
380 }
381 }
382 }
383
384 public static function check_on_market_update( $meta_id, $object_id, $meta_key, $meta_value )
385 {
386 if ( get_post_type($object_id) == 'property' && $meta_key == '_on_market' )
387 {
388 $original_value = get_post_meta( $object_id, $meta_key, TRUE );
389
390 if ( $original_value != $meta_value )
391 {
392 if ( apply_filters( 'propertyhive_add_property_on_market_change_note', true ) === true )
393 {
394 $note_action = 'property_off_market';
395 if ($meta_value == 'yes')
396 {
397 $note_action = 'property_on_market';
398 }
399
400 $current_user = wp_get_current_user();
401
402 // Add note/comment to property
403 $comment = array(
404 'note_type' => 'action',
405 'action' => $note_action,
406 );
407
408 $data = array(
409 'comment_post_ID' => (int)$object_id,
410 'comment_author' => $current_user->display_name,
411 'comment_author_email' => 'propertyhive@noreply.com',
412 'comment_author_url' => '',
413 'comment_date' => date("Y-m-d H:i:s"),
414 'comment_content' => serialize($comment),
415 'comment_approved' => 1,
416 'comment_type' => 'propertyhive_note',
417 );
418 $comment_id = wp_insert_comment( $data );
419 }
420
421 update_post_meta( $object_id, '_on_market_change_date', date("Y-m-d H:i:s") );
422 }
423 }
424 }
425
426 /**
427 * Exclude propertyhive notes from queries and RSS.
428 *
429 * This code should exclude propertyhive_note comments from queries. Some queries (like the recent comments widget on the dashboard) are hardcoded.
430 * @param array $clauses
431 * @return array
432 */
433 public static function exclude_note_comments( $clauses ) {
434 //global $wpdb, $typenow;
435
436 if ( is_admin() && function_exists( 'get_current_screen' ) )
437 {
438 $screen = get_current_screen();
439
440 if (
441 ( isset($screen->id) && in_array( $screen->id, apply_filters( 'propertyhive_post_types_with_notes', array( 'property', 'contact', 'enquiry', 'appraisal', 'viewing', 'offer', 'sale', 'tenancy' ) ) ) )
442 ||
443 ( wp_doing_ajax() && isset($_POST['action']) && ($_POST['action'] == 'propertyhive_get_notes_grid' || $_POST['action'] == 'propertyhive_get_pinned_notes_grid' || $_POST['action'] == 'propertyhive_merge_contact_records') )
444 ||
445 ( wp_doing_ajax() && isset($_GET['action']) && strpos($_GET['action'], 'propertyhive_') !== FALSE && strpos($_GET['action'], '_lightbox') !== FALSE )
446 ||
447 ( isset($_GET['page']) && substr($_GET['page'], 0, 3) == 'ph-' )
448 )
449 {
450 return $clauses; // Don't hide when viewing Property Hive record
451 }
452 }
453
454 $clauses['where'] .= ' AND comment_type != "propertyhive_note"';
455
456 return $clauses;
457 }
458
459 /**
460 * Delete comments count cache whenever there is
461 * new comment or the status of a comment changes. Cache
462 * will be regenerated next time PH_Comments::wp_count_comments()
463 * is called.
464 *
465 * @return void
466 */
467 public static function delete_comments_count_cache() {
468 delete_transient( 'ph_count_comments' );
469 }
470 /**
471 * Remove propertyhive notes from wp_count_comments().
472 * @since 1.0.0
473 * @param object $stats
474 * @param int $post_id
475 * @return object
476 */
477 public static function wp_count_comments( $stats, $post_id ) {
478 global $wpdb;
479 if ( 0 === $post_id ) {
480 $stats = get_transient( 'ph_count_comments' );
481 if ( ! $stats ) {
482 $stats = array();
483 $count = $wpdb->get_results( "SELECT comment_approved, COUNT( * ) AS num_comments FROM {$wpdb->comments} WHERE comment_type != 'propertyhive_note' GROUP BY comment_approved", ARRAY_A );
484 $total = 0;
485 $approved = array( '0' => 'moderated', '1' => 'approved', 'spam' => 'spam', 'trash' => 'trash', 'post-trashed' => 'post-trashed' );
486 foreach ( (array) $count as $row ) {
487 // Don't count post-trashed toward totals
488 if ( 'post-trashed' != $row['comment_approved'] && 'trash' != $row['comment_approved'] ) {
489 $total += $row['num_comments'];
490 }
491 if ( isset( $approved[ $row['comment_approved'] ] ) ) {
492 $stats[ $approved[ $row['comment_approved'] ] ] = $row['num_comments'];
493 }
494 }
495 $stats['total_comments'] = $total;
496 $stats['all'] = $total;
497 foreach ( $approved as $key ) {
498 if ( empty( $stats[ $key ] ) ) {
499 $stats[ $key ] = 0;
500 }
501 }
502 $stats = (object) $stats;
503 set_transient( 'ph_count_comments', $stats );
504 }
505 }
506 return $stats;
507 }
508 }
509
510 PH_Comments::init();