PluginProbe
Property Hive / 2.3.0
Property Hive v2.3.0
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 / post-types / class-ph-admin-meta-boxes.php

class-ph-admin-meta-boxes.php in Property Hive 2.3.0, at includes/admin/post-types/class-ph-admin-meta-boxes.php

2,833 lines 122.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // phpcs:set WordPress.Security.ValidatedSanitizedInput customSanitizingFunctions[] ph_clean
3 // ph_clean() recursively sanitizes text; presence, shape and unslashing checks remain separate.
4
5 /**
6 * PropertyHive Meta Boxes
7 *
8 * Sets up the write panels used by products and orders (custom post types)
9 *
10 * @author BIOSTA::
11 * @category Admin
12 * @package PropertyHive/Admin/Meta Boxes
13 * @version 1.0.0
14 */
15
16 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
17
18 if ( ! class_exists( 'PH_Admin_Meta_Boxes' ) )
19 {
20
21 /**
22 * PH_Admin_Meta_Boxes
23 */
24 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- Legacy public global class PH_Admin_Meta_Boxes; preserving the existing PH_* class name is required for plugin and extension compatibility.
25 class PH_Admin_Meta_Boxes {
26
27 private static $meta_box_errors = array();
28
29 /**
30 * Constructor
31 */
32 public function __construct() {
33
34 add_action( 'add_meta_boxes', array( $this, 'remove_meta_boxes' ), 10 );
35 add_action( 'add_meta_boxes', array( $this, 'rename_meta_boxes' ), 20 );
36 add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 30 );
37 add_action( 'save_post', array( $this, 'save_meta_boxes' ), 1, 2 );
38
39 add_action( 'post_submitbox_start', array( $this, 'add_archive_link_to_post_submitbox' ) );
40
41 // Save Property Meta Boxes
42 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Address::save', 10, 2 );
43 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Owner::save', 12, 2 );
44 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Record_Details::save', 13, 2 );
45 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Coordinates::save', 70, 2 );
46
47 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Department::save', 15, 2 );
48 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Residential_Details::save', 20, 2 );
49 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Residential_Lettings_Details::save', 25, 2 );
50 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Residential_Sales_Details::save', 30, 2 );
51 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Commercial_Details::save', 30, 2 );
52 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Material_Information::save', 32, 2 );
53
54 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Marketing::save', 35, 2 );
55
56 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Rooms::save', 40, 2 );
57 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Features::save', 45, 2 );
58 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Description::save', 45, 2 );
59
60 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Photos::save', 50, 2 );
61 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Floorplans::save', 55, 2 );
62 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Brochures::save', 65, 2 );
63 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Epcs::save', 70, 2 );
64 add_action( 'propertyhive_process_property_meta', 'PH_Meta_Box_Property_Virtual_Tours::save', 75, 2 );
65
66 // Save Contact Meta Boxes
67 // These checks only select the save callback; save_meta_boxes() verifies the post nonce and capability before dispatching it.
68 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Read-only callback selection; the actual save is gated by save_meta_boxes().
69 if ( isset($_POST['_contact_type_new']) )
70 {
71 add_action( 'propertyhive_process_contact_meta', 'PH_Meta_Box_Contact_New_Relationship::save', 1, 2 );
72 }
73 add_action( 'propertyhive_process_contact_meta', 'PH_Meta_Box_Contact_Correspondence_Address::save', 10, 2 );
74 add_action( 'propertyhive_process_contact_meta', 'PH_Meta_Box_Contact_Contact_Details::save', 15, 2 );
75 add_action( 'propertyhive_process_contact_meta', 'PH_Meta_Box_Contact_Solicitor::save', 20, 2 );
76 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Read-only callback selection; the actual save is gated by save_meta_boxes().
77 if ( !isset($_POST['_contact_type_new']) )
78 {
79 add_action( 'propertyhive_process_contact_meta', 'PH_Meta_Box_Contact_Relationships::save', 25, 2 );
80 }
81
82 // Save Enquiry Meta Boxes
83 if ( get_option('propertyhive_module_disabled_enquiries', '') != 'yes' )
84 {
85 add_action( 'propertyhive_process_enquiry_meta', 'PH_Meta_Box_Enquiry_Record_Details::save', 10, 2 );
86 add_action( 'propertyhive_process_enquiry_meta', 'PH_Meta_Box_Enquiry_Details::save', 15, 2 );
87 }
88
89 // Save Appraisal Meta Boxes
90 add_action( 'propertyhive_process_appraisal_meta', 'PH_Meta_Box_Appraisal_Details::save', 10, 2 );
91 add_action( 'propertyhive_process_appraisal_meta', 'PH_Meta_Box_Appraisal_Event::save', 15, 2 );
92 add_action( 'propertyhive_process_appraisal_meta', 'PH_Meta_Box_Appraisal_Property_Owner::save', 20, 2 );
93 add_action( 'propertyhive_process_appraisal_meta', 'PH_Meta_Box_Appraisal_Property::save', 25, 2 );
94
95 // Save Viewing Meta Boxes
96 add_action( 'propertyhive_process_viewing_meta', 'PH_Meta_Box_Viewing_Details::save', 10, 2 );
97 add_action( 'propertyhive_process_viewing_meta', 'PH_Meta_Box_Viewing_Event::save', 15, 2 );
98 add_action( 'propertyhive_process_viewing_meta', 'PH_Meta_Box_Viewing_Applicant::save', 20, 2 );
99 add_action( 'propertyhive_process_viewing_meta', 'PH_Meta_Box_Viewing_Property::save', 25, 2 );
100
101 // Save Offer Meta Boxes
102 add_action( 'propertyhive_process_offer_meta', 'PH_Meta_Box_Offer_Details::save', 10, 2 );
103 add_action( 'propertyhive_process_offer_meta', 'PH_Meta_Box_Offer_Applicant::save', 15, 2 );
104 add_action( 'propertyhive_process_offer_meta', 'PH_Meta_Box_Offer_Applicant_Solicitor::save', 20, 2 );
105 add_action( 'propertyhive_process_offer_meta', 'PH_Meta_Box_Offer_Property::save', 25, 2 );
106 add_action( 'propertyhive_process_offer_meta', 'PH_Meta_Box_Offer_Property_Owner_Solicitor::save', 30, 2 );
107
108 // Save Sale Meta Boxes
109 add_action( 'propertyhive_process_sale_meta', 'PH_Meta_Box_Sale_Details::save', 10, 2 );
110 add_action( 'propertyhive_process_sale_meta', 'PH_Meta_Box_Sale_Applicant_Solicitor::save', 15, 2 );
111 add_action( 'propertyhive_process_sale_meta', 'PH_Meta_Box_Sale_Property_Owner_Solicitor::save', 20, 2 );
112
113 // Save Tenancy Meta Boxes
114 add_action( 'propertyhive_process_tenancy_meta', 'PH_Meta_Box_Tenancy_Details::save', 10, 2 );
115 add_action( 'propertyhive_process_tenancy_meta', 'PH_Meta_Box_Tenancy_Applicant::save', 15, 2 );
116 add_action( 'propertyhive_process_tenancy_meta', 'PH_Meta_Box_Tenancy_Property::save', 20, 2 );
117 add_action( 'propertyhive_process_tenancy_meta', 'PH_Meta_Box_Tenancy_Deposit_Scheme::save', 25, 2 );
118 add_action( 'propertyhive_process_tenancy_meta', 'PH_Meta_Box_Tenancy_Meter_Readings::save', 25, 2 );
119 add_action( 'propertyhive_process_tenancy_meta', 'PH_Meta_Box_Tenancy_Management::save', 30, 2 );
120
121 // Error handling (for showing errors from meta boxes on next page load)
122 add_action( 'admin_notices', array( $this, 'output_errors' ) );
123 add_action( 'shutdown', array( $this, 'save_errors' ) );
124
125 add_filter( 'redirect_post_location', array( $this, 'redirect_to_tab' ), 10, 2 );
126
127 $this->check_contact_create_relationship();
128 $this->check_contact_delete_relationship();
129 $this->check_remove_solicitor();
130 $this->check_create_offer();
131 $this->check_create_sale();
132 $this->check_create_tenancy();
133 }
134
135 function add_archive_link_to_post_submitbox()
136 {
137 global $post, $current_screen;
138
139 if ( isset($current_screen) && $current_screen->base === 'post' && $current_screen->action === 'add' )
140 return;
141
142 // Check if the post status is not 'archive'
143 $post_types = array('property', 'contact', 'appraisal', 'viewing', 'offer', 'sale', 'tenancy', 'key_date');
144 $post_types = apply_filters( 'propertyhive_post_types_with_archive', $post_types );
145
146 if ( in_array($post->post_type, $post_types) )
147 {
148 if ( $post->post_status != 'archive' )
149 {
150 echo '<div id="archive-action" style="float:left; line-height:2.30769231">';
151 $archive_url = wp_nonce_url(admin_url('post.php?post=' . $post->ID . '&action=archive_single'), 'archive-post_' . $post->ID);
152 echo '<a href="' . esc_url($archive_url) . '" id="archive-post" class="submitdelete deletion">' . esc_html( __('Archive', 'propertyhive') ) . '</a>&nbsp;&nbsp;|&nbsp;&nbsp;';
153 echo '</div>';
154 }
155 else
156 {
157 // This is an archived post
158 echo '<div id="archive-action" style="float:left; line-height:2.30769231">';
159 $archive_url = wp_nonce_url(admin_url('post.php?post=' . $post->ID . '&action=unarchive_single'), 'unarchive-post_' . $post->ID);
160 echo '<a href="' . esc_url($archive_url) . '" id="unarchive-post" class="submitdelete deletion">' . esc_html( __('Unarchive', 'propertyhive') ) . '</a>&nbsp;&nbsp;|&nbsp;&nbsp;';
161 echo '</div>';
162 }
163 }
164 }
165
166 public function redirect_to_tab( $url, $post_id )
167 {
168 // The selected tab is only a redirect fragment; save_meta_boxes() verifies the nonce before processing the form.
169 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Read-only redirect-fragment selection; state-changing form handling verifies the save nonce.
170 if ( isset( $_POST['propertyhive_selected_metabox_tab'] ) && is_string( $_POST['propertyhive_selected_metabox_tab'] ) )
171 {
172 $posted_tab = $_POST['propertyhive_selected_metabox_tab']; // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Read-only redirect-fragment value is unslashed and sanitized immediately below; state-changing form handling verifies the save nonce.
173 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Read-only redirect-fragment selection; state-changing form handling verifies the save nonce.
174 $selected_tab = sanitize_text_field(
175 str_ireplace(
176 array( '%7C', '|' ),
177 '__PROPERTYHIVE_TAB_SEPARATOR__',
178 wp_unslash( $posted_tab )
179 )
180 );
181 $selected_tabs = preg_split( '/__PROPERTYHIVE_TAB_SEPARATOR__/', $selected_tab );
182 $selected_tabs = array_filter( array_map( 'sanitize_key', $selected_tabs ) );
183 if ( ! empty( $selected_tabs ) ) {
184 // Keep the encoded separator used by the tab JavaScript while restricting each identifier to a safe HTML ID token.
185 $url .= '#' . implode( '%7C', $selected_tabs );
186 }
187 }
188
189 return $url;
190 }
191
192 /**
193 * Read one scalar administrative request value.
194 *
195 * Action handlers call authorize_record_action() before changing any record.
196 *
197 * @param string $key Request key.
198 * @return string|false
199 */
200 private function get_request_value( $key ) {
201 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This helper only reads a routing or nonce value; each mutating caller verifies its nonce and capability before changing data.
202 if ( ! isset( $_GET[ $key ] ) || ! is_scalar( $_GET[ $key ] ) ) {
203 return false;
204 }
205
206 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This helper only reads a routing or nonce value; each mutating caller verifies its nonce and capability before changing data.
207 return sanitize_text_field( wp_unslash( (string) $_GET[ $key ] ) );
208 }
209
210 /** Require CRM and record access before processing a direct administrative action. */
211 private function authorize_record_action( $action, $verify_nonce = true ) {
212 $post_id = absint( $this->get_request_value( 'post' ) );
213 if ( ! current_user_can( 'manage_propertyhive' ) || ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) {
214 wp_die( esc_html__( 'Insufficient permissions', 'propertyhive' ), '', array( 'response' => 403 ) );
215 }
216 if ( $verify_nonce ) {
217 check_admin_referer( 'propertyhive-' . $action . '-' . $post_id, $action );
218 }
219
220 return $post_id;
221 }
222
223 public function check_contact_create_relationship()
224 {
225 $post_request = $this->get_request_value( 'post' );
226
227 if ( false !== $this->get_request_value( 'add_applicant_relationship' ) && false !== $post_request )
228 {
229 $post_id = $this->authorize_record_action( 'add_applicant_relationship' );
230 // Need to add blank applicant
231 if ( get_post_type( $post_id ) != 'contact' )
232 return;
233
234 $num_applicant_profiles = get_post_meta( $post_id, '_applicant_profiles', TRUE );
235 if ( $num_applicant_profiles == '' )
236 {
237 $num_applicant_profiles = 0;
238 }
239
240 update_post_meta( $post_id, '_applicant_profile_' . $num_applicant_profiles, '' );
241 update_post_meta( $post_id, '_applicant_profiles', $num_applicant_profiles + 1 );
242
243 $existing_contact_types = get_post_meta( $post_id, '_contact_types', TRUE );
244 if ( $existing_contact_types == '' || !is_array($existing_contact_types) )
245 {
246 $existing_contact_types = array();
247 }
248 if ( !in_array( 'applicant', $existing_contact_types ) )
249 {
250 $existing_contact_types[] = 'applicant';
251 update_post_meta( $post_id, '_contact_types', $existing_contact_types );
252 }
253
254 // Do redirect
255 wp_safe_redirect( admin_url( 'post.php?post=' . $post_id . '&action=edit#propertyhive-contact-relationships' ) );
256 exit();
257 }
258
259 if ( false !== $this->get_request_value( 'add_third_party_relationship' ) && false !== $post_request )
260 {
261 $post_id = $this->authorize_record_action( 'add_third_party_relationship' );
262 // Need to add blank third party relationship
263 if ( get_post_type( $post_id ) != 'contact' )
264 return;
265
266 $existing_third_party_categories = get_post_meta( $post_id, '_third_party_categories', TRUE );
267 if ( !is_array($existing_third_party_categories) )
268 {
269 $existing_third_party_categories = array();
270 }
271 $existing_third_party_categories[] = 0;
272 update_post_meta( $post_id, '_third_party_categories', $existing_third_party_categories );
273
274 $existing_contact_types = get_post_meta( $post_id, '_contact_types', TRUE );
275 if ( $existing_contact_types == '' || !is_array($existing_contact_types) )
276 {
277 $existing_contact_types = array();
278 }
279 if ( !in_array( 'thirdparty', $existing_contact_types ) )
280 {
281 $existing_contact_types[] = 'thirdparty';
282 update_post_meta( $post_id, '_contact_types', $existing_contact_types );
283 }
284 }
285 }
286
287 public function check_contact_delete_relationship()
288 {
289 $post_request = $this->get_request_value( 'post' );
290 $delete_nonce = $this->get_request_value( 'delete_applicant_relationship' );
291
292 if ( false !== $delete_nonce && false !== $post_request )
293 {
294 $post_id = $this->authorize_record_action( 'delete_applicant_relationship', false );
295 // Need to add blank applicant
296 if ( get_post_type( $post_id ) != 'contact' )
297 return;
298
299 $num_applicant_profiles = get_post_meta( $post_id, '_applicant_profiles', TRUE );
300 if ( $num_applicant_profiles == '' )
301 {
302 $num_applicant_profiles = 0;
303 }
304
305 for ( $i = 0; $i < $num_applicant_profiles; ++$i )
306 {
307 if ( wp_verify_nonce( $delete_nonce, 'propertyhive-delete-applicant-' . $post_id . '-' . $i ) )
308 {
309 $deleting_applicant_profile = $i;
310
311 // We're deleting this one
312 delete_post_meta( $post_id, '_applicant_profile_' . $i );
313
314 // Now need to rename any that are higher than $deleting_applicant_profile
315 for ( $j = 0; $j < $num_applicant_profiles; ++$j )
316 {
317 if ( $j > $deleting_applicant_profile )
318 {
319 $this_applicant_profile = get_post_meta( $post_id, '_applicant_profile_' . $j, true );
320 update_post_meta( $post_id, '_applicant_profile_' . ($j - 1), $this_applicant_profile );
321 delete_post_meta( $post_id, '_applicant_profile_' . $j );
322 }
323 }
324
325 // remove from _contact_types if no more profiles left
326 if ( $num_applicant_profiles == 1 )
327 {
328 $existing_contact_types = get_post_meta( $post_id, '_contact_types', TRUE );
329 if ( $existing_contact_types == '' || !is_array($existing_contact_types) )
330 {
331 $existing_contact_types = array();
332 }
333 if( ( $key = array_search('applicant', $existing_contact_types) ) !== false )
334 {
335 unset($existing_contact_types[$key]);
336 }
337 update_post_meta( $post_id, '_contact_types', $existing_contact_types );
338 }
339
340 update_post_meta( $post_id, '_applicant_profiles', $num_applicant_profiles - 1 );
341
342 // update applicant departments
343 $hot_applicant = '';
344 $applicant_departments = array();
345
346 $num_applicant_profiles = get_post_meta( $post_id, '_applicant_profiles', TRUE );
347 if ( $num_applicant_profiles == '' )
348 {
349 $num_applicant_profiles = 0;
350 }
351
352 for ( $j = 0; $j < $num_applicant_profiles; ++$j )
353 {
354 $applicant_profile = get_post_meta( $post_id, '_applicant_profile_' . $j, true );
355
356 if ( isset($applicant_profile['department']) && !empty($applicant_profile['department']) )
357 {
358 $applicant_departments[] = $applicant_profile['department'];
359 }
360
361 if ( isset($applicant_profile['grading']) && ph_clean($applicant_profile['grading']) == 'yes' )
362 {
363 $hot_applicant = 'yes';
364 }
365 }
366
367 update_post_meta( $post_id, '_hot_applicant', $hot_applicant );
368
369 if ( !empty($applicant_departments) )
370 {
371 $applicant_departments = array_filter($applicant_departments);
372 $applicant_departments = array_unique($applicant_departments);
373 }
374 update_post_meta( $post_id, '_applicant_departments', $applicant_departments );
375
376 // Do redirect
377 wp_safe_redirect( admin_url( 'post.php?post=' . $post_id . '&action=edit#propertyhive-contact-relationships' ) );
378 exit();
379 }
380 }
381 }
382 }
383
384 public function check_remove_solicitor()
385 {
386 $post_request = $this->get_request_value( 'post' );
387
388 if ( false !== $this->get_request_value( 'remove_contact_solicitor' ) && false !== $post_request )
389 {
390 $post_id = $this->authorize_record_action( 'remove_contact_solicitor' );
391 if ( get_post_type( $post_id ) != 'contact' )
392 return;
393
394 update_post_meta( $post_id, '_contact_solicitor_contact_id', '' );
395 }
396
397 if ( false !== $this->get_request_value( 'remove_property_owner_solicitor' ) && false !== $post_request )
398 {
399 $post_id = $this->authorize_record_action( 'remove_property_owner_solicitor' );
400 if ( get_post_type( $post_id ) != 'offer' && get_post_type( $post_id ) != 'sale' )
401 return;
402
403 update_post_meta( $post_id, '_property_owner_solicitor_contact_id', '' );
404 }
405
406 if ( false !== $this->get_request_value( 'remove_applicant_solicitor' ) && false !== $post_request )
407 {
408 $post_id = $this->authorize_record_action( 'remove_applicant_solicitor' );
409 if ( get_post_type( $post_id ) != 'offer' && get_post_type( $post_id ) != 'sale' )
410 return;
411
412 update_post_meta( $post_id, '_applicant_solicitor_contact_id', '' );
413 }
414 }
415
416 public function check_create_offer()
417 {
418 $post_request = $this->get_request_value( 'post' );
419
420 if ( false !== $this->get_request_value( 'create_offer' ) && false !== $post_request )
421 {
422 $post_id = $this->authorize_record_action( 'create_offer' );
423 $existing_id = absint( get_post_meta( $post_id, '_offer_id', true ) );
424 if ( 'offer' === get_post_type( $existing_id ) && 'trash' !== get_post_status( $existing_id ) ) {
425 wp_die( esc_html__( 'This record has already been created.', 'propertyhive' ), '', array( 'response' => 409 ) );
426 }
427 if ( get_post_type( $post_id ) != 'viewing')
428 return;
429
430 $viewing = new PH_Viewing( $post_id );
431
432 $viewing_applicant_ids = $viewing->get_applicant_ids();
433
434 $offer_post = array(
435 'post_title' => '',
436 'post_content' => '',
437 'post_type' => 'offer',
438 'post_status' => 'publish',
439 'comment_status' => 'closed',
440 'ping_status' => 'closed',
441 );
442
443 // Insert the post into the database
444 $offer_post_id = wp_insert_post( $offer_post );
445
446 add_post_meta( $offer_post_id, '_status', 'pending' );
447 add_post_meta( $offer_post_id, '_amount', '' );
448
449 $applicant_solicitor_contact_id = '';
450 foreach( $viewing_applicant_ids as $viewing_applicant_id )
451 {
452 add_post_meta( $offer_post_id, '_applicant_contact_id', $viewing_applicant_id );
453
454 // If any applicant has a solicitor assigned, select them as the offer applicant solicitor
455 if ( empty($applicant_solicitor_contact_id) )
456 {
457 if ( !empty( get_post_meta( $viewing_applicant_id, '_contact_solicitor_contact_id', TRUE ) ) )
458 {
459 $applicant_solicitor_contact_id = get_post_meta( $viewing_applicant_id, '_contact_solicitor_contact_id', TRUE );
460 }
461 }
462 }
463
464 add_post_meta( $offer_post_id, '_applicant_solicitor_contact_id', $applicant_solicitor_contact_id );
465 add_post_meta( $offer_post_id, '_property_id', $viewing->property_id );
466
467 // If any owner has a solicitor assigned, select them as the offer owner solicitor
468 $property_owner_solicitor_contact_id = '';
469
470 $owner_contact_ids = get_post_meta($viewing->property_id, '_owner_contact_id', TRUE);
471 if ( !empty( $owner_contact_ids ) )
472 {
473 if ( !is_array($owner_contact_ids) )
474 {
475 $owner_contact_ids = array($owner_contact_ids);
476 }
477
478 foreach( $owner_contact_ids as $owner_contact_id )
479 {
480 if ( empty($property_owner_solicitor_contact_id) )
481 {
482 if ( !empty( get_post_meta( $owner_contact_id, '_contact_solicitor_contact_id', TRUE ) ) )
483 {
484 $property_owner_solicitor_contact_id = get_post_meta( $owner_contact_id, '_contact_solicitor_contact_id', TRUE );
485 }
486 }
487 }
488 }
489 add_post_meta( $offer_post_id, '_property_owner_solicitor_contact_id', $property_owner_solicitor_contact_id );
490
491 add_post_meta( $offer_post_id, '_offer_date_time', gmdate("Y-m-d H:i:s") );
492
493 update_post_meta( $post_id, '_offer_id', $offer_post_id );
494 update_post_meta( $post_id, '_status', 'offer_made' );
495
496 $current_user = wp_get_current_user();
497
498 // Add note/comment to viewing
499 $comment = array(
500 'note_type' => 'action',
501 'action' => 'viewing_offer_made',
502 );
503
504 $data = array(
505 'comment_post_ID' => $post_id,
506 'comment_author' => $current_user->display_name,
507 'comment_author_email' => 'propertyhive@noreply.com',
508 'comment_author_url' => '',
509 'comment_date' => gmdate("Y-m-d H:i:s"),
510 'comment_content' => serialize($comment),
511 'comment_approved' => 1,
512 'comment_type' => 'propertyhive_note',
513 );
514 $comment_id = wp_insert_comment( $data );
515
516 // Do redirect
517 wp_safe_redirect( admin_url( 'post.php?post=' . $offer_post_id . '&action=edit' ) );
518 exit();
519 }
520
521 }
522
523 public function check_create_sale()
524 {
525 $post_request = $this->get_request_value( 'post' );
526
527 if ( false !== $this->get_request_value( 'create_sale' ) && false !== $post_request )
528 {
529 $post_id = $this->authorize_record_action( 'create_sale' );
530 $existing_id = absint( get_post_meta( $post_id, '_sale_id', true ) );
531 if ( 'sale' === get_post_type( $existing_id ) && 'trash' !== get_post_status( $existing_id ) ) {
532 wp_die( esc_html__( 'This record has already been created.', 'propertyhive' ), '', array( 'response' => 409 ) );
533 }
534 if ( get_post_type( $post_id ) != 'offer')
535 return;
536
537 $offer = new PH_Offer( $post_id );
538
539 $offer_applicant_ids = $offer->get_applicant_ids();
540
541 $sale_post = array(
542 'post_title' => '',
543 'post_content' => '',
544 'post_type' => 'sale',
545 'post_status' => 'publish',
546 'comment_status' => 'closed',
547 'ping_status' => 'closed',
548 );
549
550 // Insert the post into the database
551 $sale_post_id = wp_insert_post( $sale_post );
552
553 add_post_meta( $sale_post_id, '_status', 'current' );
554 add_post_meta( $sale_post_id, '_amount', $offer->amount );
555
556 foreach( $offer_applicant_ids as $offer_applicant_id )
557 {
558 add_post_meta( $sale_post_id, '_applicant_contact_id', $offer_applicant_id );
559 }
560
561 add_post_meta( $sale_post_id, '_applicant_solicitor_contact_id', $offer->applicant_solicitor_contact_id );
562 add_post_meta( $sale_post_id, '_property_id', $offer->property_id );
563 add_post_meta( $sale_post_id, '_property_owner_solicitor_contact_id', $offer->property_owner_solicitor_contact_id );
564 add_post_meta( $sale_post_id, '_sale_date_time', gmdate("Y-m-d H:i:s") );
565
566 update_post_meta( $post_id, '_sale_id', $sale_post_id );
567
568 $current_user = wp_get_current_user();
569
570 // Add note/comment to offer
571 $comment = array(
572 'note_type' => 'action',
573 'action' => 'offer_sale_created',
574 );
575
576 $data = array(
577 'comment_post_ID' => $post_id,
578 'comment_author' => $current_user->display_name,
579 'comment_author_email' => 'propertyhive@noreply.com',
580 'comment_author_url' => '',
581 'comment_date' => gmdate("Y-m-d H:i:s"),
582 'comment_content' => serialize($comment),
583 'comment_approved' => 1,
584 'comment_type' => 'propertyhive_note',
585 );
586 $comment_id = wp_insert_comment( $data );
587
588 // Do redirect
589 wp_safe_redirect( admin_url( 'post.php?post=' . $sale_post_id . '&action=edit' ) );
590 exit();
591 }
592
593 }
594
595 public function check_create_tenancy() {
596 $post_request = $this->get_request_value( 'post' );
597
598 if ( false !== $this->get_request_value( 'create_tenancy' ) && false !== $post_request ) {
599 $post_id = $this->authorize_record_action( 'create_tenancy' );
600 $existing_id = absint( get_post_meta( $post_id, '_tenancy_id', true ) );
601 if ( 'tenancy' === get_post_type( $existing_id ) && 'trash' !== get_post_status( $existing_id ) ) {
602 wp_die( esc_html__( 'This record has already been created.', 'propertyhive' ), '', array( 'response' => 409 ) );
603 }
604 if ( get_post_type( $post_id ) != 'viewing' ) {
605 return;
606 }
607
608 $viewing = new PH_Viewing( $post_id );
609
610 $viewing_applicant_ids = $viewing->get_applicant_ids();
611
612 $tenancy_post = array(
613 'post_title' => '',
614 'post_content' => '',
615 'post_type' => 'tenancy',
616 'post_status' => 'publish',
617 'comment_status' => 'closed',
618 'ping_status' => 'closed',
619 );
620
621 // Insert the post into the database
622 $tenancy_post_id = wp_insert_post( $tenancy_post );
623
624 $property_id = $viewing->property_id;
625
626 foreach( $viewing_applicant_ids as $viewing_applicant_id )
627 {
628 add_post_meta( $tenancy_post_id, '_applicant_contact_id', $viewing_applicant_id );
629 }
630
631 add_post_meta( $tenancy_post_id, '_property_id', $viewing->property_id );
632
633 add_post_meta( $tenancy_post_id, '_rent', get_post_meta( $property_id, '_rent', true ) );
634 add_post_meta( $tenancy_post_id, '_rent_frequency', get_post_meta( $property_id, '_rent_frequency', true ) );
635 add_post_meta( $tenancy_post_id, '_price_actual', get_post_meta( $property_id, '_price_actual', true ) );
636 add_post_meta( $tenancy_post_id, '_currency', get_post_meta( $property_id, '_currency', true ) );
637
638 add_post_meta( $tenancy_post_id, '_deposit', get_post_meta( $property_id, '_deposit', true ) );
639
640 update_post_meta( $post_id, '_tenancy_id', $tenancy_post_id );
641 update_post_meta( $post_id, '_status', 'offer_made' );
642
643 $current_user = wp_get_current_user();
644
645 // Add note/comment to viewing
646 $comment = array(
647 'note_type' => 'action',
648 'action' => 'viewing_offer_made',
649 );
650
651 $data = array(
652 'comment_post_ID' => $post_id,
653 'comment_author' => $current_user->display_name,
654 'comment_author_email' => 'propertyhive@noreply.com',
655 'comment_author_url' => '',
656 'comment_date' => gmdate( "Y-m-d H:i:s" ),
657 'comment_content' => serialize( $comment ),
658 'comment_approved' => 1,
659 'comment_type' => 'propertyhive_note',
660 );
661 $comment_id = wp_insert_comment( $data );
662
663 // Do redirect
664 wp_safe_redirect( admin_url( 'post.php?post=' . $tenancy_post_id . '&action=edit' ) );
665 exit();
666 }
667
668 }
669
670 /**
671 * Add an error message
672 * @param string $text
673 */
674 public static function add_error( $text ) {
675 self::$meta_box_errors[] = $text;
676 }
677
678 /**
679 * Save errors to an option
680 */
681 public function save_errors() {
682 update_option( 'propertyhivemeta_box_errors', self::$meta_box_errors );
683 }
684
685 /**
686 * Show any stored error messages.
687 */
688 public function output_errors() {
689
690 $errors = @unserialize( get_option( 'propertyhive_meta_box_errors' ), ['allowed_classes' => false] );
691
692 if ( $errors !== false && !empty( $errors ) ) {
693
694 echo '<div id="propertyhive_errors" class="error fade">';
695 foreach ( $errors as $error ) {
696 echo '<p>' . esc_html( $error ) . '</p>';
697 }
698 echo '</div>';
699
700 // Clear
701 delete_option( 'propertyhive_meta_box_errors' );
702 }
703 }
704
705 /**
706 * Add PH Meta boxes
707 */
708 public function add_meta_boxes() {
709
710 global $tabs, $post, $pagenow;
711
712 // PROPERTY
713 if (!isset($tabs)) $tabs = array();
714
715 /* PROPERTY SUMMARY META BOXES */
716 $meta_boxes = array();
717
718 $pinned_notes_args = array();
719 $pinned_notes = array();
720 if ( $pagenow != 'post-new.php' && isset($post->post_type) && in_array(
721 $post->post_type,
722 apply_filters( 'propertyhive_post_types_with_tabs', array('property', 'contact', 'enquiry', 'appraisal', 'viewing', 'offer', 'sale', 'tenancy') )
723 ) )
724 {
725 $pinned_notes_args = array(
726 'post_id' => (int)$post->ID,
727 'type' => 'propertyhive_note',
728 'fields' => 'ids',
729 'search' => '"pinned";s:1:"1"',
730 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Pinned notes store related post IDs in serialized note metadata; this admin panel requires the exact relationship filter.
731 'meta_query' => array(
732 array(
733 'key' => 'related_to',
734 'value' => '"' . (int)$post->ID . '"',
735 'compare' => 'LIKE',
736 ),
737 )
738 );
739
740 $pinned_notes = get_comments( $pinned_notes_args );
741 }
742
743 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'property' )
744 {
745 if ( !empty($pinned_notes) )
746 {
747 $meta_boxes[1] = array(
748 'id' => 'propertyhive-property-pinned-notes',
749 'title' => __( 'Pinned Notes', 'propertyhive' ),
750 'callback' => 'PH_Meta_Box_Property_Pinned_Notes::output',
751 'screen' => 'property',
752 'context' => 'normal',
753 'priority' => 'high',
754 );
755 }
756 }
757 $meta_boxes[5] = array(
758 'id' => 'propertyhive-property-address',
759 'title' => __( 'Property Address', 'propertyhive' ),
760 'callback' => 'PH_Meta_Box_Property_Address::output',
761 'screen' => 'property',
762 'context' => 'normal',
763 'priority' => 'high'
764 );
765 if ( get_option('propertyhive_module_disabled_contacts', '') != 'yes' )
766 {
767 $meta_boxes[10] = array(
768 'id' => 'propertyhive-property-owner',
769 'title' => __( 'Property Owner / Landlord', 'propertyhive' ),
770 'callback' => 'PH_Meta_Box_Property_Owner::output',
771 'screen' => 'property',
772 'context' => 'normal',
773 'priority' => 'high'
774 );
775 }
776 $meta_boxes[15] = array(
777 'id' => 'propertyhive-property-record-details',
778 'title' => __( 'Record Details', 'propertyhive' ),
779 'callback' => 'PH_Meta_Box_Property_Record_Details::output',
780 'screen' => 'property',
781 'context' => 'normal',
782 'priority' => 'high'
783 );
784 $meta_boxes[20] = array(
785 'id' => 'propertyhive-property-coordinates',
786 'title' => __( 'Property Location', 'propertyhive' ),
787 'callback' => 'PH_Meta_Box_Property_Coordinates::output',
788 'screen' => 'property',
789 'context' => 'normal',
790 'priority' => 'high'
791 );
792
793 $meta_boxes = apply_filters( 'propertyhive_property_summary_meta_boxes', $meta_boxes );
794 ksort($meta_boxes);
795
796 $ids = array();
797 foreach ($meta_boxes as $meta_box)
798 {
799 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
800 $ids[] = $meta_box['id'];
801 }
802
803 $tabs['tab_summary'] = array(
804 'name' => __( 'Summary', 'propertyhive' ),
805 'metabox_ids' => $ids,
806 'post_type' => 'property'
807 );
808 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'property' )
809 {
810 $tabs['tab_summary']['ajax_actions'] = array( '^^ph_redraw_pinned_notes_grid(\'property\')' );
811 }
812
813 /* PROPERTY DETAILS META BOXES */
814 $meta_boxes = array();
815 $meta_boxes[5] = array(
816 'id' => 'propertyhive-property-department',
817 'title' => __( 'Property Department', 'propertyhive' ),
818 'callback' => 'PH_Meta_Box_Property_Department::output',
819 'screen' => 'property',
820 'context' => 'normal',
821 'priority' => 'high'
822 );
823 $meta_boxes[10] = array(
824 'id' => 'propertyhive-property-residential-sales-details',
825 'title' => __( 'Residential Sales Details', 'propertyhive' ),
826 'callback' => 'PH_Meta_Box_Property_Residential_Sales_Details::output',
827 'screen' => 'property',
828 'context' => 'normal',
829 'priority' => 'high'
830 );
831 $meta_boxes[15] = array(
832 'id' => 'propertyhive-property-residential-lettings-details',
833 'title' => __( 'Residential Lettings Details', 'propertyhive' ),
834 'callback' => 'PH_Meta_Box_Property_Residential_Lettings_Details::output',
835 'screen' => 'property',
836 'context' => 'normal',
837 'priority' => 'high'
838 );
839 $meta_boxes[20] = array(
840 'id' => 'propertyhive-property-residential-details',
841 'title' => __( 'Residential Details', 'propertyhive' ),
842 'callback' => 'PH_Meta_Box_Property_Residential_Details::output',
843 'screen' => 'property',
844 'context' => 'normal',
845 'priority' => 'high'
846 );
847 $meta_boxes[25] = array(
848 'id' => 'propertyhive-property-commercial-details',
849 'title' => __( 'Commercial Details', 'propertyhive' ),
850 'callback' => 'PH_Meta_Box_Property_Commercial_Details::output',
851 'screen' => 'property',
852 'context' => 'normal',
853 'priority' => 'high'
854 );
855 $meta_boxes[30] = array(
856 'id' => 'propertyhive-property-material-information',
857 'title' => __( 'Utilities & Additional Information', 'propertyhive' ),
858 'callback' => 'PH_Meta_Box_Property_Material_Information::output',
859 'screen' => 'property',
860 'context' => 'normal',
861 'priority' => 'high'
862 );
863
864 $meta_boxes = apply_filters( 'propertyhive_property_details_meta_boxes', $meta_boxes );
865 ksort($meta_boxes);
866
867 $ids = array();
868 foreach ($meta_boxes as $meta_box)
869 {
870 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
871 $ids[] = $meta_box['id'];
872 }
873
874 $tabs['tab_details'] = array(
875 'name' => __( 'Details', 'propertyhive' ),
876 'metabox_ids' => $ids,
877 'post_type' => 'property'
878 );
879
880 if (
881 (
882 get_post_meta( $post->ID, '_department', TRUE ) == 'commercial' ||
883 ph_get_custom_department_based_on(get_post_meta( $post->ID, '_department', TRUE )) == 'commercial'
884 ) &&
885 isset($post->post_parent) &&
886 $post->post_parent == 0
887 )
888 {
889 $meta_boxes = array();
890 $meta_boxes[5] = array(
891 'id' => 'propertyhive-property-commercial-units',
892 'title' => __( 'Commercial Units', 'propertyhive' ),
893 'callback' => 'PH_Meta_Box_Property_Commercial_Units::output',
894 'screen' => 'property',
895 'context' => 'normal',
896 'priority' => 'high'
897 );
898
899 $meta_boxes = apply_filters( 'propertyhive_property_commercial_units_meta_boxes', $meta_boxes );
900 ksort($meta_boxes);
901
902 $ids = array();
903 foreach ($meta_boxes as $meta_box)
904 {
905 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
906 $ids[] = $meta_box['id'];
907 }
908
909 $tabs['tab_units'] = array(
910 'name' => __( 'Units', 'propertyhive' ),
911 'metabox_ids' => $ids,
912 'post_type' => 'property'
913 );
914 }
915
916 /* PROPERTY MARKETING META BOXES */
917 $meta_boxes = array();
918 $meta_boxes[5] = array(
919 'id' => 'propertyhive-property-marketing',
920 'title' => __( 'Property Marketing', 'propertyhive' ),
921 'callback' => 'PH_Meta_Box_Property_Marketing::output',
922 'screen' => 'property',
923 'context' => 'normal',
924 'priority' => 'high'
925 );
926 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'property' )
927 {
928 $meta_boxes[10] = array(
929 'id' => 'propertyhive-property-marketing-statistics',
930 'title' => __( 'Property Marketing Statistics', 'propertyhive' ),
931 'callback' => 'PH_Meta_Box_Property_Marketing_Statistics::output',
932 'screen' => 'property',
933 'context' => 'normal',
934 'priority' => 'high'
935 );
936 }
937
938 $meta_boxes = apply_filters( 'propertyhive_property_marketing_meta_boxes', $meta_boxes );
939 ksort($meta_boxes);
940
941 $ids = array();
942 foreach ($meta_boxes as $meta_box)
943 {
944 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
945 $ids[] = $meta_box['id'];
946 }
947
948 $tabs['tab_marketing'] = array(
949 'name' => __( 'Marketing', 'propertyhive' ),
950 'metabox_ids' => $ids,
951 'post_type' => 'property',
952 );
953 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'property' )
954 {
955 $tabs['tab_marketing']['ajax_actions'] = array( 'get_property_marketing_statistics_meta_box^' . wp_create_nonce( 'get_property_marketing_statistics_meta_box' ) . '^reload_marketing_statistics()' );
956 }
957
958 /* PROPERTY DESCRIPTIONS META BOXES */
959 $meta_boxes = array();
960 $meta_boxes[5] = array(
961 'id' => 'propertyhive-property-features',
962 'title' => __( 'Property Features', 'propertyhive' ),
963 'callback' => 'PH_Meta_Box_Property_Features::output',
964 'screen' => 'property',
965 'context' => 'normal',
966 'priority' => 'high'
967 );
968 $meta_boxes[10] = array(
969 'id' => 'postexcerpt',
970 'title' => __( 'Property Summary Description', 'propertyhive' ),
971 'callback' => 'PH_Meta_Box_Property_Summary_Description::output',
972 'screen' => 'property',
973 'context' => 'normal',
974 'priority' => 'high'
975 );
976 $meta_boxes[15] = array(
977 'id' => 'propertyhive-property-rooms',
978 'title' => __( 'Property Descriptions', 'propertyhive' ),
979 'callback' => 'PH_Meta_Box_Property_Rooms::output',
980 'screen' => 'property',
981 'context' => 'normal',
982 'priority' => 'high'
983 );
984 $meta_boxes[20] = array(
985 'id' => 'propertyhive-property-description',
986 'title' => __( 'Property Description', 'propertyhive' ),
987 'callback' => 'PH_Meta_Box_Property_Description::output',
988 'screen' => 'property',
989 'context' => 'normal',
990 'priority' => 'high'
991 );
992
993 $meta_boxes = apply_filters( 'propertyhive_property_descriptions_meta_boxes', $meta_boxes );
994 ksort($meta_boxes);
995
996 $ids = array();
997 foreach ($meta_boxes as $meta_box)
998 {
999 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
1000 $ids[] = $meta_box['id'];
1001 }
1002
1003 $tabs['tab_descriptions'] = array(
1004 'name' => __( 'Descriptions', 'propertyhive' ),
1005 'metabox_ids' => $ids,
1006 'post_type' => 'property'
1007 );
1008
1009 /* PROPERTY MEDIA META BOXES */
1010 $meta_boxes = array();
1011 $meta_boxes[5] = array(
1012 'id' => 'propertyhive-property-photos',
1013 'title' => __( 'Property Photos', 'propertyhive' ),
1014 'callback' => 'PH_Meta_Box_Property_Photos::output',
1015 'screen' => 'property',
1016 'context' => 'normal',
1017 'priority' => 'high'
1018 );
1019 $meta_boxes[10] = array(
1020 'id' => 'propertyhive-property-floorplans',
1021 'title' => __( 'Property Floorplans', 'propertyhive' ),
1022 'callback' => 'PH_Meta_Box_Property_Floorplans::output',
1023 'screen' => 'property',
1024 'context' => 'normal',
1025 'priority' => 'high'
1026 );
1027 $meta_boxes[15] = array(
1028 'id' => 'propertyhive-property-brochures',
1029 'title' => __( 'Property Brochures', 'propertyhive' ),
1030 'callback' => 'PH_Meta_Box_Property_Brochures::output',
1031 'screen' => 'property',
1032 'context' => 'normal',
1033 'priority' => 'high'
1034 );
1035 $meta_boxes[20] = array(
1036 'id' => 'propertyhive-property-epcs',
1037 'title' => __( 'Property EPCs', 'propertyhive' ),
1038 'callback' => 'PH_Meta_Box_Property_Epcs::output',
1039 'screen' => 'property',
1040 'context' => 'normal',
1041 'priority' => 'high'
1042 );
1043 $meta_boxes[25] = array(
1044 'id' => 'propertyhive-property-virtual-tours',
1045 'title' => __( 'Property Virtual Tours', 'propertyhive' ),
1046 'callback' => 'PH_Meta_Box_Property_Virtual_Tours::output',
1047 'screen' => 'property',
1048 'context' => 'normal',
1049 'priority' => 'high'
1050 );
1051
1052 $meta_boxes = apply_filters( 'propertyhive_property_media_meta_boxes', $meta_boxes );
1053 ksort($meta_boxes);
1054
1055 $ids = array();
1056 foreach ($meta_boxes as $meta_box)
1057 {
1058 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
1059 $ids[] = $meta_box['id'];
1060 }
1061
1062 $tabs['tab_media'] = array(
1063 'name' => __( 'Media', 'propertyhive' ),
1064 'metabox_ids' => $ids,
1065 'post_type' => 'property'
1066 );
1067
1068 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'property' )
1069 {
1070 /* PROPERTY VIEWINGS META BOXES */
1071 if ( get_option('propertyhive_module_disabled_viewings', '') != 'yes' )
1072 {
1073 $meta_boxes = array();
1074 $meta_boxes[5] = array(
1075 'id' => 'propertyhive-property-viewings',
1076 'title' => __( 'Viewings', 'propertyhive' ),
1077 'callback' => 'PH_Meta_Box_Property_Viewings::output',
1078 'screen' => 'property',
1079 'context' => 'normal',
1080 'priority' => 'high'
1081 );
1082
1083 $meta_boxes = apply_filters( 'propertyhive_property_viewings_meta_boxes', $meta_boxes );
1084 ksort($meta_boxes);
1085
1086 $ids = array();
1087 foreach ($meta_boxes as $meta_box)
1088 {
1089 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
1090 $ids[] = $meta_box['id'];
1091 }
1092
1093 $tab_name_suffix = '';
1094 if ( apply_filters( 'propertyhive_show_tab_counts', true ) === true )
1095 {
1096 $args = array(
1097 'post_type' => 'viewing',
1098 'posts_per_page' => 1,
1099 'no_found_rows' => false,
1100 'fields' => 'ids',
1101 'post_status' => 'publish',
1102 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- One-ID query retains found_rows to count all viewings for the current property.
1103 'meta_query' => array(
1104 array(
1105 'key' => '_property_id',
1106 'value' => $post->ID
1107 ),
1108 ),
1109 );
1110 $viewings_query = new WP_Query( $args );
1111 $viewings_count = $viewings_query->found_posts;
1112 wp_reset_postdata();
1113
1114 $tab_name_suffix = ' (' . $viewings_count . ')';
1115 }
1116
1117 $tabs['tab_viewings'] = array(
1118 'name' => __( 'Viewings', 'propertyhive' ) . $tab_name_suffix,
1119 'metabox_ids' => $ids,
1120 'post_type' => 'property',
1121 'ajax_actions' => array( 'get_property_viewings_meta_box' ),
1122 );
1123 }
1124
1125 if ( get_option('propertyhive_module_disabled_offers_sales', '') != 'yes' )
1126 {
1127 if (
1128 (
1129 get_post_meta( $post->ID, '_department', TRUE ) == 'residential-sales' ||
1130 ph_get_custom_department_based_on(get_post_meta( $post->ID, '_department', TRUE )) == 'residential-sales'
1131 )
1132 ||
1133 (
1134 (
1135 get_post_meta( $post->ID, '_department', TRUE ) == 'commercial' ||
1136 ph_get_custom_department_based_on(get_post_meta( $post->ID, '_department', TRUE )) == 'commercial'
1137 )
1138 &&
1139 get_post_meta( $post->ID, '_for_sale', TRUE ) == 'yes'
1140 )
1141 )
1142 {
1143 /* PROPERTY OFFERS META BOXES */
1144 $meta_boxes = array();
1145 $meta_boxes[5] = array(
1146 'id' => 'propertyhive-property-offers',
1147 'title' => __( 'Offers', 'propertyhive' ),
1148 'callback' => 'PH_Meta_Box_Property_Offers::output',
1149 'screen' => 'property',
1150 'context' => 'normal',
1151 'priority' => 'high'
1152 );
1153
1154 $meta_boxes = apply_filters( 'propertyhive_property_offers_meta_boxes', $meta_boxes );
1155 ksort($meta_boxes);
1156
1157 $ids = array();
1158 foreach ($meta_boxes as $meta_box)
1159 {
1160 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
1161 $ids[] = $meta_box['id'];
1162 }
1163
1164 $tab_name_suffix = '';
1165 if ( apply_filters( 'propertyhive_show_tab_counts', true ) === true )
1166 {
1167 $args = array(
1168 'post_type' => 'offer',
1169 'nopaging' => true,
1170 'fields' => 'ids',
1171 'post_status' => 'publish',
1172 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Property offer tab counts query the legacy relationship meta key and use found_posts to preserve the displayed count.
1173 'meta_query' => array(
1174 array(
1175 'key' => '_property_id',
1176 'value' => $post->ID
1177 ),
1178 ),
1179 );
1180 $offers_query = new WP_Query( $args );
1181 $offers_count = $offers_query->found_posts;
1182 wp_reset_postdata();
1183
1184 $tab_name_suffix = ' (' . $offers_count . ')';
1185 }
1186
1187 $tabs['tab_offers'] = array(
1188 'name' => __( 'Offers', 'propertyhive' ) . $tab_name_suffix,
1189 'metabox_ids' => $ids,
1190 'post_type' => 'property',
1191 'ajax_actions' => array( 'get_property_offers_meta_box' ),
1192 );
1193
1194 /* PROPERTY SALES META BOXES */
1195 $meta_boxes = array();
1196 $meta_boxes[5] = array(
1197 'id' => 'propertyhive-property-sales',
1198 'title' => __( 'Sales', 'propertyhive' ),
1199 'callback' => 'PH_Meta_Box_Property_Sales::output',
1200 'screen' => 'property',
1201 'context' => 'normal',
1202 'priority' => 'high'
1203 );
1204
1205 $meta_boxes = apply_filters( 'propertyhive_property_sales_meta_boxes', $meta_boxes );
1206 ksort($meta_boxes);
1207
1208 $ids = array();
1209 foreach ($meta_boxes as $meta_box)
1210 {
1211 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
1212 $ids[] = $meta_box['id'];
1213 }
1214
1215 $tab_name_suffix = '';
1216 if ( apply_filters( 'propertyhive_show_tab_counts', true ) === true )
1217 {
1218 $args = array(
1219 'post_type' => 'sale',
1220 'nopaging' => true,
1221 'fields' => 'ids',
1222 'post_status' => 'publish',
1223 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Property sale tab counts query the legacy relationship meta key and use found_posts to preserve the displayed count.
1224 'meta_query' => array(
1225 array(
1226 'key' => '_property_id',
1227 'value' => $post->ID
1228 ),
1229 ),
1230 );
1231 $sales_query = new WP_Query( $args );
1232 $sales_count = $sales_query->found_posts;
1233 wp_reset_postdata();
1234
1235 $tab_name_suffix = ' (' . $sales_count . ')';
1236 }
1237
1238 $tabs['tab_sales'] = array(
1239 'name' => __( 'Sales', 'propertyhive' ) . $tab_name_suffix,
1240 'metabox_ids' => $ids,
1241 'post_type' => 'property',
1242 'ajax_actions' => array( 'get_property_sales_meta_box' ),
1243 );
1244 }
1245 }
1246 }
1247
1248 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'property' )
1249 {
1250 if ( get_option('propertyhive_module_disabled_enquiries', '') != 'yes' )
1251 {
1252 /* PROPERTY ENQUIRIES META BOXES */
1253 $meta_boxes = array();
1254 $meta_boxes[5] = array(
1255 'id' => 'propertyhive-property-enquiries',
1256 'title' => __( 'Enquiries', 'propertyhive' ),
1257 'callback' => 'PH_Meta_Box_Property_Enquiries::output',
1258 'screen' => 'property',
1259 'context' => 'normal',
1260 'priority' => 'high'
1261 );
1262
1263 $meta_boxes = apply_filters( 'propertyhive_property_enquiries_meta_boxes', $meta_boxes );
1264 ksort($meta_boxes);
1265
1266 $ids = array();
1267 foreach ($meta_boxes as $meta_box)
1268 {
1269 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
1270 $ids[] = $meta_box['id'];
1271 }
1272
1273 $tab_name_suffix = '';
1274 if ( apply_filters( 'propertyhive_show_tab_counts', true ) === true )
1275 {
1276 $args = array(
1277 'post_type' => 'enquiry',
1278 'nopaging' => true,
1279 'fields' => 'ids',
1280 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Property enquiry counts must include both legacy property relationship meta keys for existing records.
1281 'meta_query' => array(
1282 'relation' => 'OR',
1283 array(
1284 'key' => 'property_id',
1285 'value' => $post->ID
1286 ),
1287 array(
1288 'key' => '_property_id',
1289 'value' => $post->ID
1290 )
1291 ),
1292 );
1293 $enquiry_query = new WP_Query( $args );
1294 $enquiry_count = $enquiry_query->found_posts;
1295 wp_reset_postdata();
1296
1297 $tab_name_suffix = ' (' . $enquiry_count . ')';
1298 }
1299
1300 $tabs['tab_enquiries'] = array(
1301 'name' => __( 'Enquiries', 'propertyhive' ) . $tab_name_suffix,
1302 'metabox_ids' => $ids,
1303 'post_type' => 'property',
1304 'ajax_actions' => array( 'get_property_enquiries_meta_box' ),
1305 );
1306 }
1307 }
1308
1309 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'property' ) {
1310
1311 if (
1312 get_post_meta( $post->ID, '_department', TRUE ) == 'residential-lettings' ||
1313 ph_get_custom_department_based_on(get_post_meta( $post->ID, '_department', TRUE )) == 'residential-lettings'
1314 )
1315 {
1316 if ( get_option( 'propertyhive_module_disabled_tenancies', '' ) != 'yes' )
1317 {
1318 /* TENANCY MANAGEMENT META BOXES */
1319 $meta_boxes = array();
1320
1321 $meta_boxes[5] = array(
1322 'id' => 'propertyhive-property-tenancies',
1323 'title' => __( 'Tenancies', 'propertyhive' ),
1324 'callback' => 'PH_Meta_Box_Property_Tenancies::output',
1325 'screen' => 'property',
1326 'context' => 'normal',
1327 'priority' => 'high'
1328 );
1329
1330 $meta_boxes[10] = array(
1331 'id' => 'propertyhive-management-dates',
1332 'title' => __( 'Management Dates', 'propertyhive' ),
1333 'callback' => 'PH_Meta_Box_Management_Dates::output',
1334 'screen' => 'property',
1335 'context' => 'normal',
1336 'priority' => 'high'
1337 );
1338
1339 $meta_boxes = apply_filters( 'propertyhive_property_management_meta_boxes', $meta_boxes );
1340 ksort( $meta_boxes );
1341
1342 $ids = array();
1343 foreach ( $meta_boxes as $meta_box ) {
1344 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
1345 $ids[] = $meta_box['id'];
1346 }
1347
1348 $tabs['tab_property_management'] = array(
1349 'name' => __( 'Management', 'propertyhive' ),
1350 'metabox_ids' => $ids,
1351 'post_type' => 'property',
1352 'ajax_actions' => array( 'get_property_tenancies_grid^' . wp_create_nonce( 'get_property_tenancies_grid' ) ),
1353 );
1354 }
1355 }
1356 }
1357
1358 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'property' )
1359 {
1360 /* PROPERTY NOTES META BOXES */
1361 $meta_boxes = array();
1362 $meta_boxes[5] = array(
1363 'id' => 'propertyhive-property-history-notes',
1364 'title' => __( 'Property History &amp; Notes', 'propertyhive' ),
1365 'callback' => 'PH_Meta_Box_Property_Notes::output',
1366 'screen' => 'property',
1367 'context' => 'normal',
1368 'priority' => 'high'
1369 );
1370
1371 $meta_boxes = apply_filters( 'propertyhive_property_notes_meta_boxes', $meta_boxes );
1372 ksort($meta_boxes);
1373
1374 $ids = array();
1375 foreach ($meta_boxes as $meta_box)
1376 {
1377 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
1378 $ids[] = $meta_box['id'];
1379 }
1380
1381 $tabs['tab_property_notes'] = array(
1382 'name' => __( 'History &amp; Notes', 'propertyhive' ),
1383 'metabox_ids' => $ids,
1384 'post_type' => 'property',
1385 'ajax_actions' => array( '^^ph_redraw_notes_grid(\'property\')' ),
1386 );
1387
1388 add_meta_box( 'propertyhive-property-actions', __( 'Actions', 'propertyhive' ), 'PH_Meta_Box_Property_Actions::output', 'property', 'side' );
1389 }
1390
1391 // CONTACT
1392 if (!isset($tabs)) $tabs = array();
1393
1394 $meta_boxes = array();
1395
1396 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'contact' )
1397 {
1398 if ( !empty($pinned_notes) )
1399 {
1400 $meta_boxes[1] = array(
1401 'id' => 'propertyhive-contact-pinned-notes',
1402 'title' => __( 'Pinned Notes', 'propertyhive' ),
1403 'callback' => 'PH_Meta_Box_Contact_Pinned_Notes::output',
1404 'screen' => 'contact',
1405 'context' => 'normal',
1406 'priority' => 'high',
1407 );
1408 }
1409 }
1410 if ( $pagenow == 'post-new.php' && get_post_type($post->ID) == 'contact' )
1411 {
1412 $meta_boxes[2] = array(
1413 'id' => 'propertyhive-contact-new-relationship',
1414 'title' => __( 'Contact Type', 'propertyhive' ),
1415 'callback' => 'PH_Meta_Box_Contact_New_Relationship::output',
1416 'screen' => 'contact',
1417 'context' => 'normal',
1418 'priority' => 'high'
1419 );
1420 }
1421
1422 $meta_boxes[5] = array(
1423 'id' => 'propertyhive-contact-correspondence-address',
1424 'title' => __( 'Correspondence Address', 'propertyhive' ),
1425 'callback' => 'PH_Meta_Box_Contact_Correspondence_Address::output',
1426 'screen' => 'contact',
1427 'context' => 'normal',
1428 'priority' => 'high'
1429 );
1430 $meta_boxes[10] = array(
1431 'id' => 'propertyhive-contact-contact-details',
1432 'title' => __( 'Contact Details', 'propertyhive' ),
1433 'callback' => 'PH_Meta_Box_Contact_Contact_Details::output',
1434 'screen' => 'contact',
1435 'context' => 'normal',
1436 'priority' => 'high'
1437 );
1438 $meta_boxes[15] = array(
1439 'id' => 'propertyhive-contact-solicitor',
1440 'title' => __( 'Contact Solicitor Details', 'propertyhive' ),
1441 'callback' => 'PH_Meta_Box_Contact_Solicitor::output',
1442 'screen' => 'contact',
1443 'context' => 'normal',
1444 'priority' => 'high'
1445 );
1446
1447 $meta_boxes = apply_filters( 'propertyhive_contact_details_meta_boxes', $meta_boxes );
1448 ksort($meta_boxes);
1449
1450 $ids = array();
1451 foreach ($meta_boxes as $meta_box)
1452 {
1453 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
1454 $ids[] = $meta_box['id'];
1455 }
1456
1457 $tabs['tab_contact_details'] = array(
1458 'name' => __( 'Contact Details', 'propertyhive' ),
1459 'metabox_ids' => $ids,
1460 'post_type' => 'contact'
1461 );
1462 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'contact' )
1463 {
1464 $tabs['tab_contact_details']['ajax_actions'] = array( '^^ph_redraw_pinned_notes_grid(\'contact\')' );
1465 }
1466
1467 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'contact' )
1468 {
1469 add_meta_box( 'propertyhive-contact-relationships', __( 'Relationships', 'propertyhive' ), 'PH_Meta_Box_Contact_Relationships::output', 'contact', 'normal', 'high' );
1470 $tabs['tab_contact_relationships'] = array(
1471 'name' => __( 'Relationships', 'propertyhive' ),
1472 'metabox_ids' => array('propertyhive-contact-relationships'),
1473 'post_type' => 'contact'
1474 );
1475 }
1476
1477 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'contact' )
1478 {
1479 $contact_types = get_post_meta( $post->ID, '_contact_types', TRUE );
1480
1481 if ( get_option('propertyhive_module_disabled_viewings', '') != 'yes' )
1482 {
1483 $args = array(
1484 'post_type' => 'viewing',
1485 'posts_per_page' => 1,
1486 'fields' => 'ids',
1487 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Contact tabs use posts_per_page=1 and fields=ids to test whether related records exist while found_posts supplies the count. Single _applicant_contact_id equality and posts_per_page=1 at every site; found_rows is intentionally retained.
1488 'meta_query' => array(
1489 array(
1490 'key' => '_applicant_contact_id',
1491 'value' => $post->ID
1492 )
1493 )
1494 );
1495 $viewing_query = new WP_Query( $args );
1496 $viewing_count = $viewing_query->found_posts;
1497 wp_reset_postdata();
1498
1499 // If contact is an applicant, or is attached to a viewing, show the viewings tab and meta box
1500 if (
1501 ( is_array($contact_types) && in_array('applicant', $contact_types) )
1502 ||
1503 $viewing_count > 0
1504 )
1505 {
1506 /* CONTACT VIEWINGS META BOXES */
1507 add_meta_box( 'propertyhive-contact-viewings', __( 'Viewings', 'propertyhive' ), 'PH_Meta_Box_Contact_Viewings::output', 'contact', 'normal', 'high' );
1508
1509 $tab_name_suffix = '';
1510 if ( apply_filters( 'propertyhive_show_tab_counts', true ) === true )
1511 {
1512 $tab_name_suffix = ' (' . $viewing_count . ')';
1513 }
1514
1515 $tabs['tab_viewings'] = array(
1516 'name' => __( 'Viewings', 'propertyhive' ) . $tab_name_suffix,
1517 'metabox_ids' => array('propertyhive-contact-viewings'),
1518 'post_type' => 'contact',
1519 'ajax_actions' => array( 'get_contact_viewings_meta_box' ),
1520 );
1521 }
1522 }
1523
1524 if ( get_option('propertyhive_module_disabled_offers_sales', '') != 'yes' )
1525 {
1526 $args = array(
1527 'post_type' => 'offer',
1528 'posts_per_page' => 1,
1529 'fields' => 'ids',
1530 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Contact tabs use posts_per_page=1 and fields=ids to test whether related records exist while found_posts supplies the count. Single _applicant_contact_id equality and posts_per_page=1 at every site; found_rows is intentionally retained.
1531 'meta_query' => array(
1532 array(
1533 'key' => '_applicant_contact_id',
1534 'value' => $post->ID
1535 )
1536 )
1537 );
1538 $offer_query = new WP_Query( $args );
1539 $offer_count = $offer_query->found_posts;
1540 wp_reset_postdata();
1541
1542 $args = array(
1543 'post_type' => 'sale',
1544 'posts_per_page' => 1,
1545 'fields' => 'ids',
1546 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Contact tabs use posts_per_page=1 and fields=ids to test whether related records exist while found_posts supplies the count. Single _applicant_contact_id equality and posts_per_page=1 at every site; found_rows is intentionally retained.
1547 'meta_query' => array(
1548 array(
1549 'key' => '_applicant_contact_id',
1550 'value' => $post->ID
1551 )
1552 )
1553 );
1554 $sale_query = new WP_Query( $args );
1555 $sale_count = $sale_query->found_posts;
1556 wp_reset_postdata();
1557
1558 $has_sales_applicant_profile = false;
1559 if ( $offer_count == 0 || $sale_count == 0 )
1560 {
1561 if ( is_array($contact_types) && in_array('applicant', $contact_types) )
1562 {
1563 $num_applicant_profiles = get_post_meta( $post->ID, '_applicant_profiles', TRUE );
1564 if ( $num_applicant_profiles == '' )
1565 {
1566 $num_applicant_profiles = 0;
1567 }
1568
1569 if ( $num_applicant_profiles > 0 )
1570 {
1571 for ( $i = 0; $i < $num_applicant_profiles; ++$i )
1572 {
1573 $applicant_profile = get_post_meta( $post->ID, '_applicant_profile_' . $i, TRUE );
1574
1575 if (
1576 isset($applicant_profile['department']) &&
1577 (
1578 $applicant_profile['department'] == 'residential-sales' ||
1579 ph_get_custom_department_based_on($applicant_profile['department']) == 'residential-sales'
1580 )
1581 )
1582 {
1583 $has_sales_applicant_profile = true;
1584 }
1585 }
1586 }
1587 }
1588 }
1589
1590 if ( $has_sales_applicant_profile === true || $offer_count > 0 )
1591 {
1592 /* CONTACT OFFERS META BOXES */
1593 add_meta_box( 'propertyhive-contact-offers', __( 'Offers', 'propertyhive' ), 'PH_Meta_Box_Contact_Offers::output', 'contact', 'normal', 'high' );
1594
1595 $tab_name_suffix = '';
1596 if ( apply_filters( 'propertyhive_show_tab_counts', true ) === true )
1597 {
1598 $tab_name_suffix = ' (' . $offer_count . ')';
1599 }
1600
1601 $tabs['tab_offers'] = array(
1602 'name' => __( 'Offers', 'propertyhive' ) . $tab_name_suffix,
1603 'metabox_ids' => array('propertyhive-contact-offers'),
1604 'post_type' => 'contact',
1605 'ajax_actions' => array( 'get_contact_offers_meta_box' ),
1606 );
1607 }
1608
1609 if ( $has_sales_applicant_profile === true || $sale_count > 0 )
1610 {
1611 /* CONTACT SALES META BOXES */
1612 add_meta_box( 'propertyhive-contact-sales', __( 'Sales', 'propertyhive' ), 'PH_Meta_Box_Contact_Sales::output', 'contact', 'normal', 'high' );
1613
1614 $tab_name_suffix = '';
1615 if ( apply_filters( 'propertyhive_show_tab_counts', true ) === true )
1616 {
1617 $tab_name_suffix = ' (' . $sale_count . ')';
1618 }
1619
1620 $tabs['tab_sales'] = array(
1621 'name' => __( 'Sales', 'propertyhive' ) . $tab_name_suffix,
1622 'metabox_ids' => array('propertyhive-contact-sales'),
1623 'post_type' => 'contact',
1624 'ajax_actions' => array( 'get_contact_sales_meta_box' ),
1625 );
1626 }
1627 }
1628
1629 if ( get_option( 'propertyhive_module_disabled_tenancies', '' ) != 'yes' )
1630 {
1631 $args = array(
1632 'post_type' => 'tenancy',
1633 'posts_per_page' => 1,
1634 'fields' => 'ids',
1635 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Contact tabs use posts_per_page=1 and fields=ids to test whether related records exist while found_posts supplies the count. Single _applicant_contact_id equality and posts_per_page=1 at every site; found_rows is intentionally retained.
1636 'meta_query' => array(
1637 array(
1638 'key' => '_applicant_contact_id',
1639 'value' => $post->ID
1640 )
1641 )
1642 );
1643 $tenancy_query = new WP_Query( $args );
1644 $tenancy_count = $tenancy_query->found_posts;
1645 wp_reset_postdata();
1646
1647 $has_lettings_applicant_profile = false;
1648 if ( $tenancy_count == 0 )
1649 {
1650 if ( is_array($contact_types) && in_array('applicant', $contact_types) )
1651 {
1652 $num_applicant_profiles = get_post_meta( $post->ID, '_applicant_profiles', TRUE );
1653 if ( $num_applicant_profiles == '' )
1654 {
1655 $num_applicant_profiles = 0;
1656 }
1657
1658 if ( $num_applicant_profiles > 0 )
1659 {
1660 for ( $i = 0; $i < $num_applicant_profiles; ++$i )
1661 {
1662 $applicant_profile = get_post_meta( $post->ID, '_applicant_profile_' . $i, TRUE );
1663
1664 if (
1665 isset($applicant_profile['department']) &&
1666 (
1667 $applicant_profile['department'] == 'residential-lettings' ||
1668 ph_get_custom_department_based_on($applicant_profile['department']) == 'residential-lettings'
1669 )
1670 )
1671 {
1672 $has_lettings_applicant_profile = true;
1673 }
1674 }
1675 }
1676 }
1677 }
1678
1679 if ( $has_lettings_applicant_profile === true || $tenancy_count > 0 )
1680 {
1681 $meta_boxes = array();
1682
1683 $meta_boxes[5] = array(
1684 'id' => 'propertyhive-contact-tenancies',
1685 'title' => __( 'Tenancies', 'propertyhive' ),
1686 'callback' => 'PH_Meta_Box_Contact_Tenancies::output',
1687 'screen' => 'contact',
1688 'context' => 'normal',
1689 'priority' => 'high'
1690 );
1691
1692 $meta_boxes = apply_filters( 'propertyhive_contact_tenancies_meta_boxes', $meta_boxes );
1693 ksort( $meta_boxes );
1694
1695 $ids = array();
1696 foreach ( $meta_boxes as $meta_box ) {
1697 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
1698 $ids[] = $meta_box['id'];
1699 }
1700
1701 $tab_name_suffix = '';
1702 if ( apply_filters( 'propertyhive_show_tab_counts', true ) === true )
1703 {
1704 $tab_name_suffix = ' (' . $tenancy_count . ')';
1705 }
1706
1707 $tabs['tab_contact_tenancies'] = array(
1708 'name' => __( 'Tenancies', 'propertyhive' ) . $tab_name_suffix,
1709 'metabox_ids' => $ids,
1710 'post_type' => 'contact',
1711 'ajax_actions' => array( 'get_contact_tenancies_grid^' . wp_create_nonce( 'get_contact_tenancies_grid' ) ),
1712 );
1713 }
1714 }
1715
1716 if ( get_option('propertyhive_module_disabled_enquiries', '') != 'yes' )
1717 {
1718 $meta_query = array(
1719 'relation' => 'OR',
1720 array(
1721 'key' => '_contact_id',
1722 'value' => $post->ID,
1723 ),
1724 );
1725
1726 $contact_email_address = get_post_meta( $post->ID, '_email_address', TRUE );
1727 if ( !empty($contact_email_address) )
1728 {
1729 $meta_query[] = array(
1730 'key' => 'email',
1731 'value' => $contact_email_address,
1732 );
1733
1734 $meta_query[] = array(
1735 'key' => 'email_address',
1736 'value' => $contact_email_address,
1737 );
1738 }
1739
1740 $tab_name_suffix = '';
1741 if ( apply_filters( 'propertyhive_show_tab_counts', true ) === true )
1742 {
1743 $args = array(
1744 'post_type' => 'enquiry',
1745 'nopaging' => true,
1746 'fields' => 'ids',
1747 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Contact enquiry counts must include the legacy contact and email relationship keys for existing records.
1748 'meta_query' => $meta_query,
1749 );
1750 $enquiry_query = new WP_Query( $args );
1751 $enquiry_count = $enquiry_query->found_posts;
1752
1753 $tab_name_suffix = ' (' . $enquiry_count . ')';
1754 }
1755
1756 wp_reset_postdata();
1757
1758 /* CONTACT ENQUIRIES META BOXES */
1759 add_meta_box( 'propertyhive-contact-enquiries', __( 'Enquiries', 'propertyhive' ), 'PH_Meta_Box_Contact_Enquiries::output', 'contact', 'normal', 'high' );
1760 $tabs['tab_contact_enquiries'] = array(
1761 'name' => __( 'Enquiries', 'propertyhive' ) . $tab_name_suffix,
1762 'metabox_ids' => array('propertyhive-contact-enquiries'),
1763 'post_type' => 'contact',
1764 'ajax_actions' => array( 'get_contact_enquiries_meta_box' ),
1765 );
1766 }
1767
1768 $meta_boxes = array();
1769 $meta_boxes[5] = array(
1770 'id' => 'propertyhive-contact-history-notes',
1771 'title' => __( 'Contact History &amp; Notes', 'propertyhive' ),
1772 'callback' => 'PH_Meta_Box_Contact_Notes::output',
1773 'screen' => 'contact',
1774 'context' => 'normal',
1775 'priority' => 'high'
1776 );
1777
1778 $meta_boxes = apply_filters( 'propertyhive_contact_notes_meta_boxes', $meta_boxes );
1779 ksort($meta_boxes);
1780
1781 $ids = array();
1782 foreach ($meta_boxes as $meta_box)
1783 {
1784 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
1785 $ids[] = $meta_box['id'];
1786 }
1787
1788 $tabs['tab_contact_notes'] = array(
1789 'name' => __( 'History &amp; Notes', 'propertyhive' ),
1790 'metabox_ids' => $ids,
1791 'post_type' => 'contact',
1792 'ajax_actions' => array( '^^ph_redraw_notes_grid(\'contact\')' ),
1793 );
1794
1795 add_meta_box( 'propertyhive-contact-actions', __( 'Actions', 'propertyhive' ), 'PH_Meta_Box_Contact_Actions::output', 'contact', 'side' );
1796 }
1797
1798 // ENQUIRY
1799 if (!isset($tabs)) $tabs = array();
1800
1801 $meta_boxes = array();
1802
1803 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'enquiry' )
1804 {
1805 if ( !empty($pinned_notes) )
1806 {
1807 $meta_boxes[1] = array(
1808 'id' => 'propertyhive-enquiry-pinned-notes',
1809 'title' => __( 'Pinned Notes', 'propertyhive' ),
1810 'callback' => 'PH_Meta_Box_Enquiry_Pinned_Notes::output',
1811 'screen' => 'enquiry',
1812 'context' => 'normal',
1813 'priority' => 'high',
1814 );
1815 }
1816 }
1817 $meta_boxes[5] = array(
1818 'id' => 'propertyhive-enquiry-record-details',
1819 'title' => __( 'Record Details', 'propertyhive' ),
1820 'callback' => 'PH_Meta_Box_Enquiry_Record_details::output',
1821 'screen' => 'enquiry',
1822 'context' => 'normal',
1823 'priority' => 'high'
1824 );
1825 $meta_boxes[10] = array(
1826 'id' => 'propertyhive-enquiry-details',
1827 'title' => __( 'Enquiry Details', 'propertyhive' ),
1828 'callback' => 'PH_Meta_Box_Enquiry_Details::output',
1829 'screen' => 'enquiry',
1830 'context' => 'normal',
1831 'priority' => 'high'
1832 );
1833 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'enquiry' )
1834 {
1835 $meta_boxes[15] = array(
1836 'id' => 'propertyhive-enquiry-lead-tracking',
1837 'title' => __( 'Lead Tracking', 'propertyhive' ),
1838 'callback' => 'PH_Meta_Box_Enquiry_Lead_Tracking::output',
1839 'screen' => 'enquiry',
1840 'context' => 'normal',
1841 'priority' => 'high'
1842 );
1843 }
1844
1845 $meta_boxes = apply_filters( 'propertyhive_enquiry_details_meta_boxes', $meta_boxes );
1846 ksort($meta_boxes);
1847
1848 $ids = array();
1849 foreach ($meta_boxes as $meta_box)
1850 {
1851 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
1852 $ids[] = $meta_box['id'];
1853 }
1854
1855 $tabs['tab_enquiry_details'] = array(
1856 'name' => __( 'Details', 'propertyhive' ),
1857 'metabox_ids' => $ids,
1858 'post_type' => 'enquiry'
1859 );
1860 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'enquiry' )
1861 {
1862 $tabs['tab_enquiry_details']['ajax_actions'] = array( '^^ph_redraw_pinned_notes_grid(\'enquiry\')' );
1863 }
1864
1865 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'enquiry' )
1866 {
1867 $meta_boxes = array();
1868 $meta_boxes[5] = array(
1869 'id' => 'propertyhive-enquiry-history-notes',
1870 'title' => __( 'Enquiry History &amp; Notes', 'propertyhive' ),
1871 'callback' => 'PH_Meta_Box_Enquiry_Notes::output',
1872 'screen' => 'enquiry',
1873 'context' => 'normal',
1874 'priority' => 'high'
1875 );
1876
1877 $meta_boxes = apply_filters( 'propertyhive_enquiry_notes_meta_boxes', $meta_boxes );
1878 ksort($meta_boxes);
1879
1880 $ids = array();
1881 foreach ($meta_boxes as $meta_box)
1882 {
1883 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
1884 $ids[] = $meta_box['id'];
1885 }
1886
1887 $tabs['tab_enquiry_notes'] = array(
1888 'name' => __( 'History &amp; Notes', 'propertyhive' ),
1889 'metabox_ids' => $ids,
1890 'post_type' => 'enquiry',
1891 'ajax_actions' => array( '^^ph_redraw_notes_grid(\'enquiry\')' ),
1892 );
1893 }
1894
1895 // APPRAISAL
1896 if (!isset($tabs)) $tabs = array();
1897
1898 /* APPRAISAL SUMMARY META BOXES */
1899 $meta_boxes = array();
1900 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'appraisal' )
1901 {
1902 if ( !empty($pinned_notes) )
1903 {
1904 $meta_boxes[1] = array(
1905 'id' => 'propertyhive-appraisal-pinned-notes',
1906 'title' => __( 'Pinned Notes', 'propertyhive' ),
1907 'callback' => 'PH_Meta_Box_Appraisal_Pinned_Notes::output',
1908 'screen' => 'appraisal',
1909 'context' => 'normal',
1910 'priority' => 'high',
1911 );
1912 }
1913 }
1914 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'appraisal' )
1915 {
1916 $meta_boxes[5] = array(
1917 'id' => 'propertyhive-appraisal-details',
1918 'title' => __( 'Appraisal Details', 'propertyhive' ),
1919 'callback' => 'PH_Meta_Box_Appraisal_Details::output',
1920 'screen' => 'appraisal',
1921 'context' => 'normal',
1922 'priority' => 'high'
1923 );
1924 }
1925 $meta_boxes[10] = array(
1926 'id' => 'propertyhive-appraisal-event',
1927 'title' => __( 'Event Details', 'propertyhive' ),
1928 'callback' => 'PH_Meta_Box_Appraisal_Event::output',
1929 'screen' => 'appraisal',
1930 'context' => 'normal',
1931 'priority' => 'high'
1932 );
1933 $meta_boxes[15] = array(
1934 'id' => 'propertyhive-appraisal-property-owner',
1935 'title' => __( 'Property Owner Details', 'propertyhive' ),
1936 'callback' => 'PH_Meta_Box_Appraisal_Property_Owner::output',
1937 'screen' => 'appraisal',
1938 'context' => 'normal',
1939 'priority' => 'high'
1940 );
1941 $meta_boxes[20] = array(
1942 'id' => 'propertyhive-appraisal-property',
1943 'title' => __( 'Property Details', 'propertyhive' ),
1944 'callback' => 'PH_Meta_Box_Appraisal_Property::output',
1945 'screen' => 'appraisal',
1946 'context' => 'normal',
1947 'priority' => 'high'
1948 );
1949
1950 $meta_boxes = apply_filters( 'propertyhive_appraisal_summary_meta_boxes', $meta_boxes );
1951 ksort($meta_boxes);
1952
1953 $ids = array();
1954 foreach ($meta_boxes as $meta_box)
1955 {
1956 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
1957 $ids[] = $meta_box['id'];
1958 }
1959
1960 $tabs['tab_appraisal_summary'] = array(
1961 'name' => __( 'Summary', 'propertyhive' ),
1962 'metabox_ids' => $ids,
1963 'post_type' => 'appraisal'
1964 );
1965 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'appraisal' )
1966 {
1967 $tabs['tab_appraisal_summary']['ajax_actions'] = array( '^^ph_redraw_pinned_notes_grid(\'appraisal\')' );
1968 }
1969
1970 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'appraisal' )
1971 {
1972 $meta_boxes = array();
1973 $meta_boxes[5] = array(
1974 'id' => 'propertyhive-appraisal-history-notes',
1975 'title' => __( 'Appraisal History &amp; Notes', 'propertyhive' ),
1976 'callback' => 'PH_Meta_Box_Appraisal_Notes::output',
1977 'screen' => 'appraisal',
1978 'context' => 'normal',
1979 'priority' => 'high'
1980 );
1981
1982 $meta_boxes = apply_filters( 'propertyhive_appraisal_notes_meta_boxes', $meta_boxes );
1983 ksort($meta_boxes);
1984
1985 $ids = array();
1986 foreach ($meta_boxes as $meta_box)
1987 {
1988 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
1989 $ids[] = $meta_box['id'];
1990 }
1991
1992 $tabs['tab_appraisal_notes'] = array(
1993 'name' => __( 'History &amp; Notes', 'propertyhive' ),
1994 'metabox_ids' => $ids,
1995 'post_type' => 'appraisal',
1996 'ajax_actions' => array( '^^ph_redraw_notes_grid(\'appraisal\')' ),
1997 );
1998
1999 add_meta_box( 'propertyhive-appraisal-actions', __( 'Actions', 'propertyhive' ), 'PH_Meta_Box_Appraisal_Actions::output', 'appraisal', 'side' );
2000 }
2001
2002 // VIEWING
2003 if (!isset($tabs)) $tabs = array();
2004
2005 /* VIEWING SUMMARY META BOXES */
2006 $meta_boxes = array();
2007 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'viewing' )
2008 {
2009 if ( !empty($pinned_notes) )
2010 {
2011 $meta_boxes[1] = array(
2012 'id' => 'propertyhive-viewing-pinned-notes',
2013 'title' => __( 'Pinned Notes', 'propertyhive' ),
2014 'callback' => 'PH_Meta_Box_Viewing_Pinned_Notes::output',
2015 'screen' => 'viewing',
2016 'context' => 'normal',
2017 'priority' => 'high',
2018 );
2019 }
2020 }
2021 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'viewing' )
2022 {
2023 $meta_boxes[5] = array(
2024 'id' => 'propertyhive-viewing-details',
2025 'title' => __( 'Viewing Details', 'propertyhive' ),
2026 'callback' => 'PH_Meta_Box_Viewing_Details::output',
2027 'screen' => 'viewing',
2028 'context' => 'normal',
2029 'priority' => 'high'
2030 );
2031 }
2032 $meta_boxes[10] = array(
2033 'id' => 'propertyhive-viewing-event',
2034 'title' => __( 'Event Details', 'propertyhive' ),
2035 'callback' => 'PH_Meta_Box_Viewing_Event::output',
2036 'screen' => 'viewing',
2037 'context' => 'normal',
2038 'priority' => 'high'
2039 );
2040 $meta_boxes[15] = array(
2041 'id' => 'propertyhive-viewing-applicant',
2042 'title' => __( 'Applicant Details', 'propertyhive' ),
2043 'callback' => 'PH_Meta_Box_Viewing_Applicant::output',
2044 'screen' => 'viewing',
2045 'context' => 'normal',
2046 'priority' => 'high'
2047 );
2048 $meta_boxes[20] = array(
2049 'id' => 'propertyhive-viewing-property',
2050 'title' => __( 'Property Details', 'propertyhive' ),
2051 'callback' => 'PH_Meta_Box_Viewing_Property::output',
2052 'screen' => 'viewing',
2053 'context' => 'normal',
2054 'priority' => 'high'
2055 );
2056
2057 $meta_boxes = apply_filters( 'propertyhive_viewing_summary_meta_boxes', $meta_boxes );
2058 ksort($meta_boxes);
2059
2060 $ids = array();
2061 foreach ($meta_boxes as $meta_box)
2062 {
2063 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
2064 $ids[] = $meta_box['id'];
2065 }
2066
2067 $tabs['tab_viewing_summary'] = array(
2068 'name' => __( 'Summary', 'propertyhive' ),
2069 'metabox_ids' => $ids,
2070 'post_type' => 'viewing'
2071 );
2072 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'viewing' )
2073 {
2074 $tabs['tab_viewing_summary']['ajax_actions'] = array( '^^ph_redraw_pinned_notes_grid(\'viewing\')' );
2075 }
2076
2077 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'viewing' )
2078 {
2079 $meta_boxes = array();
2080 $meta_boxes[5] = array(
2081 'id' => 'propertyhive-viewing-history-notes',
2082 'title' => __( 'Viewing History &amp; Notes', 'propertyhive' ),
2083 'callback' => 'PH_Meta_Box_Viewing_Notes::output',
2084 'screen' => 'viewing',
2085 'context' => 'normal',
2086 'priority' => 'high'
2087 );
2088
2089 $meta_boxes = apply_filters( 'propertyhive_viewing_notes_meta_boxes', $meta_boxes );
2090 ksort($meta_boxes);
2091
2092 $ids = array();
2093 foreach ($meta_boxes as $meta_box)
2094 {
2095 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
2096 $ids[] = $meta_box['id'];
2097 }
2098
2099 $tabs['tab_viewing_notes'] = array(
2100 'name' => __( 'History &amp; Notes', 'propertyhive' ),
2101 'metabox_ids' => $ids,
2102 'post_type' => 'viewing',
2103 'ajax_actions' => array( '^^ph_redraw_notes_grid(\'viewing\')' ),
2104 );
2105
2106 add_meta_box( 'propertyhive-viewing-actions', __( 'Actions', 'propertyhive' ), 'PH_Meta_Box_Viewing_Actions::output', 'viewing', 'side' );
2107 }
2108
2109 // OFFER
2110 if (!isset($tabs)) $tabs = array();
2111
2112 /* OFFER SUMMARY META BOXES */
2113 $meta_boxes = array();
2114 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'offer' )
2115 {
2116 if ( !empty($pinned_notes) )
2117 {
2118 $meta_boxes[1] = array(
2119 'id' => 'propertyhive-offer-pinned-notes',
2120 'title' => __( 'Pinned Notes', 'propertyhive' ),
2121 'callback' => 'PH_Meta_Box_Offer_Pinned_Notes::output',
2122 'screen' => 'offer',
2123 'context' => 'normal',
2124 'priority' => 'high',
2125 );
2126 }
2127 }
2128 $meta_boxes[5] = array(
2129 'id' => 'propertyhive-offer-details',
2130 'title' => __( 'Offer Details', 'propertyhive' ),
2131 'callback' => 'PH_Meta_Box_Offer_Details::output',
2132 'screen' => 'offer',
2133 'context' => 'normal',
2134 'priority' => 'high'
2135 );
2136 $meta_boxes[10] = array(
2137 'id' => 'propertyhive-offer-property',
2138 'title' => __( 'Property Details', 'propertyhive' ),
2139 'callback' => 'PH_Meta_Box_Offer_Property::output',
2140 'screen' => 'offer',
2141 'context' => 'normal',
2142 'priority' => 'high'
2143 );
2144 $meta_boxes[15] = array(
2145 'id' => 'propertyhive-offer-property-owner-solicitor',
2146 'title' => __( 'Property Owner Solicitor Details', 'propertyhive' ),
2147 'callback' => 'PH_Meta_Box_Offer_Property_Owner_Solicitor::output',
2148 'screen' => 'offer',
2149 'context' => 'normal',
2150 'priority' => 'high'
2151 );
2152 $meta_boxes[20] = array(
2153 'id' => 'propertyhive-offer-applicant',
2154 'title' => __( 'Applicant Details', 'propertyhive' ),
2155 'callback' => 'PH_Meta_Box_Offer_Applicant::output',
2156 'screen' => 'offer',
2157 'context' => 'normal',
2158 'priority' => 'high'
2159 );
2160 $meta_boxes[25] = array(
2161 'id' => 'propertyhive-offer-applicant-solicitor',
2162 'title' => __( 'Applicant Solicitor Details', 'propertyhive' ),
2163 'callback' => 'PH_Meta_Box_Offer_Applicant_Solicitor::output',
2164 'screen' => 'offer',
2165 'context' => 'normal',
2166 'priority' => 'high'
2167 );
2168
2169
2170 $meta_boxes = apply_filters( 'propertyhive_offer_summary_meta_boxes', $meta_boxes );
2171 ksort($meta_boxes);
2172
2173 $ids = array();
2174 foreach ($meta_boxes as $meta_box)
2175 {
2176 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
2177 $ids[] = $meta_box['id'];
2178 }
2179
2180 $tabs['tab_offer_summary'] = array(
2181 'name' => __( 'Summary', 'propertyhive' ),
2182 'metabox_ids' => $ids,
2183 'post_type' => 'offer'
2184 );
2185 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'offer' )
2186 {
2187 $tabs['tab_offer_summary']['ajax_actions'] = array( '^^ph_redraw_pinned_notes_grid(\'offer\')' );
2188 }
2189
2190 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'offer' )
2191 {
2192 $meta_boxes = array();
2193 $meta_boxes[5] = array(
2194 'id' => 'propertyhive-offer-history-notes',
2195 'title' => __( 'Offer History &amp; Notes', 'propertyhive' ),
2196 'callback' => 'PH_Meta_Box_Offer_Notes::output',
2197 'screen' => 'offer',
2198 'context' => 'normal',
2199 'priority' => 'high'
2200 );
2201
2202 $meta_boxes = apply_filters( 'propertyhive_offer_notes_meta_boxes', $meta_boxes );
2203 ksort($meta_boxes);
2204
2205 $ids = array();
2206 foreach ($meta_boxes as $meta_box)
2207 {
2208 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
2209 $ids[] = $meta_box['id'];
2210 }
2211
2212 $tabs['tab_offer_notes'] = array(
2213 'name' => __( 'History &amp; Notes', 'propertyhive' ),
2214 'metabox_ids' => $ids,
2215 'post_type' => 'offer',
2216 'ajax_actions' => array( '^^ph_redraw_notes_grid(\'offer\')' ),
2217 );
2218
2219 add_meta_box( 'propertyhive-offer-actions', __( 'Actions', 'propertyhive' ), 'PH_Meta_Box_Offer_Actions::output', 'offer', 'side' );
2220 }
2221
2222 // SALE
2223 if (!isset($tabs)) $tabs = array();
2224
2225 /* SALE SUMMARY META BOXES */
2226 $meta_boxes = array();
2227 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'sale' )
2228 {
2229 if ( !empty($pinned_notes) )
2230 {
2231 $meta_boxes[1] = array(
2232 'id' => 'propertyhive-sale-pinned-notes',
2233 'title' => __( 'Pinned Notes', 'propertyhive' ),
2234 'callback' => 'PH_Meta_Box_Sale_Pinned_Notes::output',
2235 'screen' => 'sale',
2236 'context' => 'normal',
2237 'priority' => 'high',
2238 );
2239 }
2240 }
2241 $meta_boxes[5] = array(
2242 'id' => 'propertyhive-sale-details',
2243 'title' => __( 'Sale Details', 'propertyhive' ),
2244 'callback' => 'PH_Meta_Box_Sale_Details::output',
2245 'screen' => 'sale',
2246 'context' => 'normal',
2247 'priority' => 'high'
2248 );
2249 $meta_boxes[10] = array(
2250 'id' => 'propertyhive-sale-property',
2251 'title' => __( 'Property Details', 'propertyhive' ),
2252 'callback' => 'PH_Meta_Box_Sale_Property::output',
2253 'screen' => 'sale',
2254 'context' => 'normal',
2255 'priority' => 'high'
2256 );
2257 $meta_boxes[15] = array(
2258 'id' => 'propertyhive-sale-property-owner-solicitor',
2259 'title' => __( 'Property Owner Solicitor Details', 'propertyhive' ),
2260 'callback' => 'PH_Meta_Box_Sale_Property_Owner_Solicitor::output',
2261 'screen' => 'sale',
2262 'context' => 'normal',
2263 'priority' => 'high'
2264 );
2265 $meta_boxes[20] = array(
2266 'id' => 'propertyhive-sale-applicant',
2267 'title' => __( 'Applicant Details', 'propertyhive' ),
2268 'callback' => 'PH_Meta_Box_Sale_Applicant::output',
2269 'screen' => 'sale',
2270 'context' => 'normal',
2271 'priority' => 'high'
2272 );
2273 $meta_boxes[25] = array(
2274 'id' => 'propertyhive-sale-applicant-solicitor',
2275 'title' => __( 'Applicant Solicitor Details', 'propertyhive' ),
2276 'callback' => 'PH_Meta_Box_Sale_Applicant_Solicitor::output',
2277 'screen' => 'sale',
2278 'context' => 'normal',
2279 'priority' => 'high'
2280 );
2281
2282 $meta_boxes = apply_filters( 'propertyhive_sale_summary_meta_boxes', $meta_boxes );
2283 ksort($meta_boxes);
2284
2285 $ids = array();
2286 foreach ($meta_boxes as $meta_box)
2287 {
2288 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
2289 $ids[] = $meta_box['id'];
2290 }
2291
2292 $tabs['tab_sale_summary'] = array(
2293 'name' => __( 'Summary', 'propertyhive' ),
2294 'metabox_ids' => $ids,
2295 'post_type' => 'sale'
2296 );
2297 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'sale' )
2298 {
2299 $tabs['tab_sale_summary']['ajax_actions'] = array( '^^ph_redraw_pinned_notes_grid(\'sale\')' );
2300 }
2301
2302 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'sale' )
2303 {
2304 $meta_boxes = array();
2305 $meta_boxes[5] = array(
2306 'id' => 'propertyhive-sale-history-notes',
2307 'title' => __( 'Sale History &amp; Notes', 'propertyhive' ),
2308 'callback' => 'PH_Meta_Box_Sale_Notes::output',
2309 'screen' => 'sale',
2310 'context' => 'normal',
2311 'priority' => 'high'
2312 );
2313
2314 $meta_boxes = apply_filters( 'propertyhive_sale_notes_meta_boxes', $meta_boxes );
2315 ksort($meta_boxes);
2316
2317 $ids = array();
2318 foreach ($meta_boxes as $meta_box)
2319 {
2320 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
2321 $ids[] = $meta_box['id'];
2322 }
2323
2324 $tabs['tab_sale_notes'] = array(
2325 'name' => __( 'History &amp; Notes', 'propertyhive' ),
2326 'metabox_ids' => $ids,
2327 'post_type' => 'sale',
2328 'ajax_actions' => array( '^^ph_redraw_notes_grid(\'sale\')' ),
2329 );
2330
2331 add_meta_box( 'propertyhive-sale-actions', __( 'Actions', 'propertyhive' ), 'PH_Meta_Box_Sale_Actions::output', 'sale', 'side' );
2332 }
2333
2334 // TENANCY
2335 if (!isset($tabs)) $tabs = array();
2336
2337 /* TENANCY SUMMARY META BOXES */
2338 $meta_boxes = array();
2339 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'tenancy' )
2340 {
2341 if ( !empty($pinned_notes) )
2342 {
2343 $meta_boxes[1] = array(
2344 'id' => 'propertyhive-tenancy-pinned-notes',
2345 'title' => __( 'Pinned Notes', 'propertyhive' ),
2346 'callback' => 'PH_Meta_Box_Tenancy_Pinned_Notes::output',
2347 'screen' => 'tenancy',
2348 'context' => 'normal',
2349 'priority' => 'high',
2350 );
2351 }
2352 }
2353 $meta_boxes[5] = array(
2354 'id' => 'propertyhive-tenancy-details',
2355 'title' => __( 'Tenancy Details', 'propertyhive' ),
2356 'callback' => 'PH_Meta_Box_Tenancy_Details::output',
2357 'screen' => 'tenancy',
2358 'context' => 'normal',
2359 'priority' => 'high'
2360 );
2361 $meta_boxes[10] = array(
2362 'id' => 'propertyhive-tenancy-property',
2363 'title' => __( 'Property', 'propertyhive' ),
2364 'callback' => 'PH_Meta_Box_Tenancy_Property::output',
2365 'screen' => 'tenancy',
2366 'context' => 'normal',
2367 'priority' => 'high'
2368 );
2369 $meta_boxes[15] = array(
2370 'id' => 'propertyhive-tenancy-applicant',
2371 'title' => __( 'Tenants', 'propertyhive' ),
2372 'callback' => 'PH_Meta_Box_Tenancy_Applicant::output',
2373 'screen' => 'tenancy',
2374 'context' => 'normal',
2375 'priority' => 'high'
2376 );
2377
2378 $meta_boxes = apply_filters( 'propertyhive_tenancy_summary_meta_boxes', $meta_boxes );
2379 ksort($meta_boxes);
2380
2381 $ids = array();
2382 foreach ($meta_boxes as $meta_box)
2383 {
2384 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
2385 $ids[] = $meta_box['id'];
2386 }
2387
2388 $tabs['tab_tenancy_summary'] = array(
2389 'name' => __( 'Summary', 'propertyhive' ),
2390 'metabox_ids' => $ids,
2391 'post_type' => 'tenancy'
2392 );
2393 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'tenancy' )
2394 {
2395 $tabs['tab_tenancy_summary']['ajax_actions'] = array( '^^ph_redraw_pinned_notes_grid(\'tenancy\')' );
2396 }
2397
2398 /* TENANCY DEPOSIT SCHEME META BOXES */
2399 $meta_boxes = array();
2400 $meta_boxes[5] = array(
2401 'id' => 'propertyhive-tenancy-deposit-scheme',
2402 'title' => __( 'Deposit Scheme Details', 'propertyhive' ),
2403 'callback' => 'PH_Meta_Box_Tenancy_Deposit_Scheme::output',
2404 'screen' => 'tenancy',
2405 'context' => 'normal',
2406 'priority' => 'high'
2407 );
2408
2409 $meta_boxes = apply_filters( 'propertyhive_tenancy_deposit_meta_boxes', $meta_boxes );
2410 ksort($meta_boxes);
2411
2412 $ids = array();
2413 foreach ($meta_boxes as $meta_box)
2414 {
2415 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
2416 $ids[] = $meta_box['id'];
2417 }
2418
2419 $tabs['tab_tenancy_deposit_scheme'] = array(
2420 'name' => __( 'Deposit Scheme', 'propertyhive' ),
2421 'metabox_ids' => $ids,
2422 'post_type' => 'tenancy'
2423 );
2424
2425 /* MANAGEMENT META BOXES */
2426 $meta_boxes = array();
2427 $meta_boxes[5] = array(
2428 'id' => 'propertyhive-tenancy-management',
2429 'title' => __( 'Management Details', 'propertyhive' ),
2430 'callback' => 'PH_Meta_Box_Tenancy_Management::output',
2431 'screen' => 'tenancy',
2432 'context' => 'normal',
2433 'priority' => 'high'
2434 );
2435
2436 $meta_boxes[10] = array(
2437 'id' => 'propertyhive-management-dates',
2438 'title' => __( 'Management Dates', 'propertyhive' ),
2439 'callback' => 'PH_Meta_Box_Management_Dates::output',
2440 'screen' => 'tenancy',
2441 'context' => 'normal',
2442 'priority' => 'high'
2443 );
2444
2445 $meta_boxes = apply_filters( 'propertyhive_tenancy_management_meta_boxes', $meta_boxes );
2446 ksort($meta_boxes);
2447
2448 $ids = array();
2449 foreach ($meta_boxes as $meta_box)
2450 {
2451 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
2452 $ids[] = $meta_box['id'];
2453 }
2454
2455 $tabs['tab_tenancy_management'] = array(
2456 'name' => __( 'Management', 'propertyhive' ),
2457 'metabox_ids' => $ids,
2458 'post_type' => 'tenancy'
2459 );
2460
2461 /* TENANCY METER READINGS META BOXES */
2462 $meta_boxes = array();
2463 $meta_boxes[5] = array(
2464 'id' => 'propertyhive-tenancy-meter-readings',
2465 'title' => __( 'Meter Readings', 'propertyhive' ),
2466 'callback' => 'PH_Meta_Box_Tenancy_Meter_Readings::output',
2467 'screen' => 'tenancy',
2468 'context' => 'normal',
2469 'priority' => 'high'
2470 );
2471
2472 $meta_boxes = apply_filters( 'propertyhive_tenancy_meter_readings_meta_boxes', $meta_boxes );
2473 ksort($meta_boxes);
2474
2475 $ids = array();
2476 foreach ($meta_boxes as $meta_box)
2477 {
2478 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
2479 $ids[] = $meta_box['id'];
2480 }
2481
2482 $tabs['tab_tenancy_meter_readings'] = array(
2483 'name' => __( 'Meter Readings', 'propertyhive' ),
2484 'metabox_ids' => $ids,
2485 'post_type' => 'tenancy'
2486 );
2487
2488 if ( $pagenow != 'post-new.php' && get_post_type($post->ID) == 'tenancy' )
2489 {
2490 /* HISTORY & NOTES META BOXES */
2491 $meta_boxes = array();
2492 $meta_boxes[5] = array(
2493 'id' => 'propertyhive-tenancy-history-notes',
2494 'title' => __( 'Tenancy History &amp; Notes', 'propertyhive' ),
2495 'callback' => 'PH_Meta_Box_Tenancy_Notes::output',
2496 'screen' => 'tenancy',
2497 'context' => 'normal',
2498 'priority' => 'high'
2499 );
2500
2501 $meta_boxes = apply_filters( 'propertyhive_tenancy_notes_meta_boxes', $meta_boxes );
2502 ksort($meta_boxes);
2503
2504 $ids = array();
2505 foreach ($meta_boxes as $meta_box)
2506 {
2507 add_meta_box( $meta_box['id'], $meta_box['title'], $meta_box['callback'], $meta_box['screen'], $meta_box['context'], $meta_box['priority'] );
2508 $ids[] = $meta_box['id'];
2509 }
2510
2511 $tabs['tab_tenancy_notes'] = array(
2512 'name' => __( 'History &amp; Notes', 'propertyhive' ),
2513 'metabox_ids' => $ids,
2514 'post_type' => 'tenancy',
2515 'ajax_actions' => array( '^^ph_redraw_notes_grid(\'tenancy\')' ),
2516 );
2517 }
2518
2519 $tabs = apply_filters( 'propertyhive_tabs', $tabs );
2520
2521 // Force order of meta boxes
2522 $meta_box_ids = array();
2523 if (
2524 in_array(
2525 get_post_type($post->ID),
2526 apply_filters( 'propertyhive_post_types_with_tabs', array('property', 'contact', 'enquiry', 'appraisal', 'viewing', 'offer', 'sale', 'tenancy') )
2527 )
2528 )
2529 {
2530 foreach ( $tabs as $tab_id => $tab_options)
2531 {
2532 if ( isset($tab_options['post_type']) && $tab_options['post_type'] == get_post_type($post->ID) )
2533 {
2534 $meta_box_ids = array_merge( $meta_box_ids, $tab_options['metabox_ids'] );
2535 }
2536 }
2537 }
2538
2539 if (!empty($meta_box_ids) )
2540 {
2541 $existing_meta_box_order = get_user_meta( get_current_user_id(), 'meta-box-order_' . get_post_type($post->ID), TRUE );
2542 if ( $existing_meta_box_order == '' )
2543 {
2544 $existing_meta_box_order = array();
2545 $existing_meta_box_order['side'] = '';
2546 $existing_meta_box_order['advanced'] = '';
2547 }
2548 $existing_meta_box_order['normal'] = implode(",", $meta_box_ids);
2549
2550 update_user_meta( get_current_user_id(), 'meta-box-order_' . get_post_type($post->ID), $existing_meta_box_order );
2551 }
2552
2553 // TO DO: move this so it works when in one column
2554 add_action( 'edit_form_after_title', array( $this, 'draw_meta_box_tabs' ), 31, 1);
2555 }
2556
2557 /**
2558 * Draw meta box tabs
2559 */
2560 public function draw_meta_box_tabs() {
2561
2562 global $post, $tabs;
2563
2564 if (
2565 !empty($tabs) &&
2566 in_array(
2567 $post->post_type,
2568 apply_filters( 'propertyhive_post_types_with_tabs', array('property', 'contact', 'enquiry', 'appraisal', 'viewing', 'offer', 'sale', 'tenancy') )
2569 )
2570 )
2571 {
2572 $meta_boxes_under_tabs = array();
2573
2574 $i = 0;
2575 echo '<div id="propertyhive_metabox_tabs" style="margin-top:15px">';
2576 foreach ($tabs as $tab_id => $tab)
2577 {
2578 if (isset($tab['post_type']) && $post->post_type == $tab['post_type'])
2579 {
2580 echo '<a href="' . esc_attr( '#' . implode( '|#', $tab['metabox_ids'] ) ) . '" id="' . esc_attr($tab_id) . '" class="button' . ( ($i == 0) ? ' button-primary' : '') . '"';
2581 if ( isset($tab['ajax_actions']) )
2582 {
2583 echo ' data-ajax-actions="' . esc_attr(implode("|", $tab['ajax_actions'])) . '"';
2584 }
2585 echo '>' . esc_html($tab['name']) . '</a> ';
2586
2587 $meta_boxes_under_tabs[] = $tab['metabox_ids'];
2588
2589 ++$i;
2590 }
2591 }
2592 echo '</div><br>';
2593
2594 // hidden field to keep track of selected hash
2595 echo '<input type="hidden" name="propertyhive_selected_metabox_tab" id="propertyhive_selected_metabox_tab" value="">';
2596
2597 if (!empty($meta_boxes_under_tabs))
2598 {
2599 echo '
2600 <script>
2601 var meta_boxes_under_tabs = ' . json_encode($meta_boxes_under_tabs) . ';
2602
2603 var ajax_actions_executed = new Array();
2604
2605 jQuery(document).ready(function()
2606 {
2607 // Hide all on page load
2608 hide_meta_box_tabs();
2609
2610 // Show first meta box
2611 //jQuery(\'#\' + meta_boxes_under_tabs[0][0] + \'\').show();
2612 for (var i in meta_boxes_under_tabs[0])
2613 {
2614 jQuery(\'#\' + meta_boxes_under_tabs[0][i] + \'\').show();
2615 }
2616 //jQuery(\'#propertyhive_metabox_tabs a:first-child\').trigger(\'click\');
2617
2618 // Set first button as primary
2619 jQuery(\'#propertyhive_metabox_tabs a:first-child\').addClass(\'button-primary\');
2620
2621 // Hide meta boxes and show correct one when tab clicked
2622 jQuery(\'#propertyhive_metabox_tabs a\').click(function(e)
2623 {
2624 e.preventDefault();
2625
2626 hide_meta_box_tabs();
2627
2628 var this_href = jQuery(this).attr(\'href\').split(\'|\');
2629
2630 for (var i in this_href)
2631 {
2632 jQuery(this_href[i]).show();
2633 }
2634
2635 jQuery(this).addClass(\'button-primary\');
2636
2637 ' . ( ( $post->post_type == 'property' ) ? 'if (jQuery(this).attr(\'id\') == \'tab_details\') { showHideDepartmentMetaBox(); }' : '' ) . '
2638 ' . ( ( $post->post_type == 'property' ) ? 'if (jQuery(this).attr(\'id\') == \'tab_descriptions\') { showHideRoomsMetaBox(); }' : '' ) . '
2639 ' . ( ( $post->post_type == 'property' ) ? 'if (jQuery(this).attr(\'id\') == \'tab_descriptions\') { showHideDescriptionsMetaBox(); }' : '' ) . '
2640
2641 if ( jQuery(this).attr(\'data-ajax-actions\') && jQuery(this).attr(\'data-ajax-actions\') != \'\' )
2642 {
2643 var ajax_actions = jQuery(this).attr(\'data-ajax-actions\').split(\'|\');
2644
2645 for ( var i in ajax_actions )
2646 {
2647 var ajax_action = ajax_actions[i].split(\'^\');
2648
2649 jQuery(\'#\' + ajax_action[0].replace(\'get_\', \'propertyhive_\')).html(\'Loading...\');
2650
2651 if ( ajax_action[2] ) // callback
2652 {
2653 eval(ajax_action[2]);
2654 }
2655 else
2656 {
2657 var data = {
2658 action: \'propertyhive_\' + ajax_action[0],
2659 post_id: ' . (int)$post->ID . ',
2660 security: ajax_action[1]
2661 }
2662
2663 jQuery.post( \'' . esc_url(admin_url('admin-ajax.php')) . '\', data, function(response)
2664 {
2665 jQuery(\'#\' + ajax_action[0].replace(\'get_\', \'propertyhive_\')).html(response);
2666 activateTipTip();
2667 }, \'html\');
2668 }
2669 }
2670 }
2671
2672 //window.location.hash = jQuery(this).attr(\'href\');
2673 history.pushState({}, \'\', \'#\' + jQuery(this).attr(\'href\').replace(/#/g, \'\').replace(/\|/g, \'%7C\'));
2674
2675 jQuery(\'#propertyhive_selected_metabox_tab\').val(jQuery(this).attr(\'href\').replace(/#/g, \'\').replace(/\|/g, \'%7C\'));
2676
2677 return false;
2678 });
2679
2680 // Set default tab if hash set
2681 if (window.location.hash != \'\')
2682 {
2683 var hash = window.location.hash;
2684 if ( window.location.hash.indexOf(\'%7C\') )
2685 {
2686 hash = window.location.hash.replace(/%7C/g, \'|#\');
2687 }
2688 jQuery("#propertyhive_metabox_tabs a[href*=\'" + hash + "\']").trigger(\'click\');
2689 }
2690 });
2691
2692 jQuery(window).on(\'load\', function()
2693 {
2694 if (window.location.hash == \'\')
2695 {
2696 if ( jQuery(\'#propertyhive_metabox_tabs a\').eq(0).attr(\'data-ajax-actions\') && jQuery(\'#propertyhive_metabox_tabs a\').eq(0).attr(\'data-ajax-actions\') != \'\' )
2697 {
2698 var ajax_actions = jQuery(\'#propertyhive_metabox_tabs a\').eq(0).attr(\'data-ajax-actions\').split(\'|\');
2699
2700 for ( var i in ajax_actions )
2701 {
2702 var ajax_action = ajax_actions[i].split(\'^\');
2703
2704 jQuery(\'#\' + ajax_action[0].replace(\'get_\', \'propertyhive_\')).html(\'Loading...\');
2705
2706 if ( ajax_action[2] ) // callback
2707 {
2708 eval(ajax_action[2]);
2709 }
2710 else
2711 {
2712 var data = {
2713 action: \'propertyhive_\' + ajax_action[0],
2714 post_id: ' . (int)$post->ID . ',
2715 security: ajax_action[1]
2716 }
2717
2718 jQuery.post( \'' . esc_url(admin_url('admin-ajax.php')) . '\', data, function(response)
2719 {
2720 jQuery(\'#\' + ajax_action[0].replace(\'get_\', \'propertyhive_\')).html(response);
2721 activateTipTip();
2722 }, \'html\');
2723 }
2724 }
2725 }
2726 }
2727 });
2728
2729 function hide_meta_box_tabs()
2730 {
2731 for (var i in meta_boxes_under_tabs)
2732 {
2733 for (var j in meta_boxes_under_tabs[i])
2734 {
2735 jQuery(\'#\' + meta_boxes_under_tabs[i][j] + \'\').hide();
2736 }
2737 }
2738
2739 jQuery(\'#propertyhive_metabox_tabs a\').removeClass(\'button-primary\');
2740 }
2741 </script>
2742 ';
2743 }
2744 }
2745
2746 }
2747
2748 /**
2749 * Remove bloat
2750 */
2751 public function remove_meta_boxes() {
2752 //remove_meta_box( 'submitdiv', 'property', 'side' );
2753 remove_meta_box( 'postexcerpt', 'property', 'normal' );
2754 remove_meta_box( 'pageparentdiv', 'property', 'side' );
2755 remove_meta_box( 'commentstatusdiv', 'property', 'normal' );
2756 remove_meta_box( 'commentstatusdiv', 'property', 'side' );
2757 remove_meta_box( 'commentsdiv', 'product', 'normal' );
2758 }
2759
2760 /**
2761 * Rename core meta boxes
2762 */
2763 public function rename_meta_boxes() {
2764 global $post;
2765
2766 // Comments/Reviews
2767 if ( isset( $post ) && ( 'publish' == $post->post_status || 'private' == $post->post_status ) ) {
2768 //remove_meta_box( 'commentsdiv', 'product', 'normal' );
2769
2770 //add_meta_box( 'commentsdiv', __( 'Reviews', 'propertyhive' ), 'post_comment_meta_box', 'product', 'normal' );
2771 }
2772 }
2773
2774 /**
2775 * Check if we're saving, then trigger an action based on the post type
2776 *
2777 * @param int $post_id
2778 * @param object $post
2779 */
2780 public function save_meta_boxes( $post_id, $post ) {
2781
2782 // $post_id and $post are required
2783 if ( empty( $post_id ) || empty( $post ) ) {
2784 return;
2785 }
2786
2787 // Dont' save meta boxes for revisions or autosaves
2788 if ( defined( 'DOING_AUTOSAVE' ) || is_int( wp_is_post_revision( $post ) ) || is_int( wp_is_post_autosave( $post ) ) ) {
2789 return;
2790 }
2791
2792 // Check the nonce
2793 if ( empty( $_POST['propertyhive_meta_nonce'] ) || ! is_string( $_POST['propertyhive_meta_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['propertyhive_meta_nonce'] ) ), 'propertyhive_save_data' ) ) {
2794 return;
2795 }
2796
2797 // Check the post being saved == the $post_id to prevent triggering this call for other save_post events
2798 if ( empty( $_POST['post_ID'] ) || $_POST['post_ID'] != $post_id ) {
2799 return;
2800 }
2801
2802 // Check user has permission to edit
2803 if ( ! current_user_can( 'manage_propertyhive' ) || ! current_user_can( 'edit_post', $post_id ) ) {
2804 return;
2805 }
2806
2807 // Check the post type
2808 if (
2809 ! in_array(
2810 $post->post_type,
2811 apply_filters( 'propertyhive_post_types_with_tabs', array('property', 'contact', 'enquiry', 'appraisal', 'viewing', 'offer', 'sale', 'tenancy') )
2812 )
2813 ) {
2814 return;
2815 }
2816
2817 if ( isset($_POST['post_parent']) && $_POST['post_parent'] != '' && $_POST['post_parent'] != '0' )
2818 {
2819 global $wpdb;
2820
2821 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Updating post_parent here avoids recursively re-entering save_post; the save flow already owns this post and WordPress refreshes its post cache after the save.
2822 $wpdb->update( $wpdb->posts, array( 'post_parent' => (int)$_POST['post_parent'] ), array( 'ID' => $post_id ) );
2823 }
2824
2825 do_action( 'propertyhive_process_' . $post->post_type . '_meta', $post_id, $post );
2826 }
2827
2828 }
2829
2830 new PH_Admin_Meta_Boxes();
2831
2832 }
2833