PluginProbe
Property Hive / 2.3.1
Property Hive v2.3.1
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-cpt-viewing.php

class-ph-admin-cpt-viewing.php in Property Hive 2.3.1, at includes/admin/post-types/class-ph-admin-cpt-viewing.php

393 lines 13.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Admin functions for the viewing post type
4 *
5 * @author PropertyHive
6 * @category Admin
7 * @package PropertyHive/Admin/Post Types
8 * @version 1.0.0
9 */
10
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit; // Exit if accessed directly
13 }
14
15 if ( ! class_exists( 'PH_Admin_CPT' ) ) {
16 include( 'class-ph-admin-cpt.php' );
17 }
18
19 if ( ! class_exists( 'PH_Admin_CPT_Viewing' ) ) :
20
21 /**
22 * PH_Admin_CPT_Viewing Class
23 */
24 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- Legacy public global class PH_Admin_CPT_Viewing; preserving the existing PH_* class name is required for plugin and extension compatibility.
25 class PH_Admin_CPT_Viewing extends PH_Admin_CPT {
26
27 /**
28 * Constructor
29 */
30 public function __construct() {
31 $this->type = 'viewing';
32
33 // Admin notices
34 add_action( 'admin_notices', array( $this, 'viewing_admin_notices') );
35
36 // Before data updates
37 add_action( 'pre_post_update', array( $this, 'pre_post_update' ) );
38 add_filter( 'wp_insert_post_data', array( $this, 'wp_insert_post_data' ) );
39
40 // Admin Columns
41 add_filter( 'manage_edit-viewing_columns', array( $this, 'edit_columns' ) );
42 add_action( 'manage_viewing_posts_custom_column', array( $this, 'custom_columns' ), 2 );
43 add_filter( 'list_table_primary_column', array( $this, 'set_primary_column' ), 10, 2 );
44 add_filter( 'post_row_actions', array( $this, 'remove_actions' ), 10, 2 );
45 add_filter( 'manage_edit-viewing_sortable_columns', array( $this, 'custom_columns_sort' ) );
46 add_filter( 'request', array( $this, 'custom_columns_orderby' ) );
47
48 // Bulk / quick edit
49 add_filter( 'bulk_actions-edit-viewing', array( $this, 'remove_bulk_actions') );
50 /*add_action( 'bulk_edit_custom_box', array( $this, 'bulk_edit' ), 10, 2 );
51 add_action( 'quick_edit_custom_box', array( $this, 'quick_edit' ), 10, 2 );
52 add_action( 'save_post', array( $this, 'bulk_and_quick_edit_save_post' ), 10, 2 );*/
53
54 add_action( 'add_post_meta', array( $this, 'check_viewing_feedback_add' ), 10, 3 );
55 add_action( 'update_post_meta', array( $this, 'check_viewing_feedback_update' ), 10, 4 );
56
57 // Call PH_Admin_CPT constructor
58 parent::__construct();
59 }
60
61 /**
62 * Output admin notices relating to viewing
63 */
64 public function viewing_admin_notices()
65 {
66 global $post;
67
68 $screen = get_current_screen();
69
70 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only viewing screen context.
71 $viewing_id = isset( $_GET['post'] ) && is_string( $_GET['post'] ) ? absint( $_GET['post'] ) : 0;
72 if ( $screen && $screen->id == 'viewing' && 'viewing' === get_post_type( $viewing_id ) && current_user_can( 'edit_post', $viewing_id ) )
73 {
74 $viewing = new PH_Viewing( $viewing_id );
75 $related_viewings = $viewing->_related_viewings;
76
77 // There is either a previous or next viewing for this applicant/property combination
78 if (
79 !in_array( $viewing->_status, array('cancelled', 'no_show') )
80 &&
81 is_array($related_viewings)
82 &&
83 isset($related_viewings['previous']) && isset($related_viewings['next'])
84 &&
85 ( count($related_viewings['previous']) > 0 || count($related_viewings['next']) > 0 )
86 )
87 {
88 $message = sprintf(
89 /* translators: %s: viewing number (e.g. 1, 2, 3) */
90 __( 'This is viewing number %s for this applicant at this property.', 'propertyhive' ),
91 number_format_i18n( count( $related_viewings['previous'] ) + 1 )
92 ) . '<br>';
93
94 if ( count($related_viewings['previous']) > 0 )
95 {
96 $previous_viewing_id = end($related_viewings['previous']);
97 $message .= '<a href="' . esc_url(get_edit_post_link( $previous_viewing_id, '' )) . '"><< '. esc_html(__( 'Go to previous', 'propertyhive' )) . '</a>';
98 }
99
100 if ( count($related_viewings['next']) > 0 )
101 {
102 $next_viewing_id = $related_viewings['next'][0];
103
104 // If there are links to next and previous, show a divider
105 if ( isset($previous_viewing_id) )
106 {
107 $message .= ' | ';
108 }
109
110 $message .= '<a href="' . esc_url(get_edit_post_link( $next_viewing_id, '' )) . '">'. esc_html(__( 'Go to next', 'propertyhive' )) . ' >></a>';
111 }
112
113 echo '<div class="notice notice-info"><p>' . wp_kses_post( $message ) . '</p></div>';
114 }
115 }
116 }
117
118 /**
119 * Check if we're editing or adding a viewing
120 * @return boolean
121 */
122 private function is_editing_viewing() {
123 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only screen detection; mutations have separate save guards.
124 $post_type = isset( $_GET['post_type'] ) && is_string( $_GET['post_type'] ) ? sanitize_key( wp_unslash( $_GET['post_type'] ) ) : '';
125 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only screen detection.
126 $post_id = isset( $_GET['post'] ) && is_string( $_GET['post'] ) ? absint( $_GET['post'] ) : 0;
127 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only screen detection for AJAX requests.
128 $request_id = isset( $_REQUEST['post_id'] ) && is_string( $_REQUEST['post_id'] ) ? absint( $_REQUEST['post_id'] ) : 0;
129 return 'viewing' === $post_type || ( $post_id > 0 && 'viewing' === get_post_type( $post_id ) ) || ( $request_id > 0 && 'viewing' === get_post_type( $request_id ) );
130 }
131
132 /**
133 * @param int $post_id
134 */
135 public function pre_post_update( $post_id ) {
136
137 }
138
139 /**
140 * @param array $data
141 * @return array
142 */
143 public function wp_insert_post_data( $data ) {
144
145
146 return $data;
147 }
148
149 /**
150 * Change the columns shown in admin.
151 */
152 public function edit_columns( $existing_columns ) {
153
154 if ( empty( $existing_columns ) && ! is_array( $existing_columns ) ) {
155 $existing_columns = array();
156 }
157
158 unset( $existing_columns['title'], $existing_columns['comments'], $existing_columns['date'] );
159
160 $columns = array();
161 $columns['cb'] = '<input type="checkbox" />';
162 $columns['start_date_time'] = __( 'Viewing Date / Time', 'propertyhive' );
163 $columns['property'] = __( 'Property', 'propertyhive' );
164 $columns['applicant'] = __( 'Applicant(s)', 'propertyhive' );
165 $columns['status'] = __( 'Status', 'propertyhive' );
166 $columns['negotiators'] = __( 'Attending Negotiators', 'propertyhive' );
167
168 return array_merge( $columns, $existing_columns );
169 }
170
171 /**
172 * Define our custom columns shown in admin.
173 * @param string $column
174 */
175 public function custom_columns( $column ) {
176 global $post, $propertyhive, $the_viewing;
177
178 if ( empty( $the_viewing ) || $the_viewing->ID != $post->ID )
179 {
180 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Retain the legacy global name for compatibility with external admin column callbacks.
181 $the_viewing = new PH_Viewing( $post->ID );
182 }
183
184 switch ( $column ) {
185 case 'start_date_time' :
186
187 $edit_link = get_edit_post_link( $post->ID );
188 //$title = _draft_or_post_title();
189 $title = gmdate("H:i jS F Y", strtotime($the_viewing->start_date_time));
190
191 $post_type_object = get_post_type_object( $post->post_type );
192 $can_edit_post = current_user_can( $post_type_object->cap->edit_post, $post->ID );
193
194 echo '<strong><a class="row-title" href="' . esc_url( $edit_link ) .'">' . esc_html($title) . '</a></strong>';
195 break;
196 case 'property' :
197
198 if ( $the_viewing->property_id != '' )
199 {
200 $property = new PH_Property((int)$the_viewing->property_id);
201 echo esc_html($property->get_formatted_full_address());
202 }
203 else
204 {
205 echo '-';
206 }
207 break;
208 case 'applicant' :
209 $applicant_contact_ids = get_post_meta( $post->ID, '_applicant_contact_id' );
210 if ( is_array($applicant_contact_ids) && !empty($applicant_contact_ids) )
211 {
212 $applicants = array();
213 foreach ( $applicant_contact_ids as $applicant_contact_id )
214 {
215 $applicants[] = esc_html(get_the_title($applicant_contact_id));
216 }
217 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Every applicant title is escaped above; only literal br separators are added.
218 echo implode("<br>", $applicants);
219 }
220 else
221 {
222 echo '-';
223 }
224
225 break;
226 case 'status' :
227
228 echo esc_html(propertyhive_get_status_label( $the_viewing->status ));
229 if ( $the_viewing->status == 'pending' )
230 {
231 echo '<br>';
232 // confirmation status
233 if ( $the_viewing->all_confirmed == 'yes' )
234 {
235 echo esc_html(__( 'All Parties Confirmed', 'propertyhive' ));
236 }
237 else
238 {
239 echo esc_html(__( 'Awaiting Confirmation', 'propertyhive' ));
240 }
241 }
242 if ( $the_viewing->status == 'carried_out' )
243 {
244 echo '<br>';
245 switch ( $the_viewing->feedback_status )
246 {
247 case "interested": { echo esc_html(__( 'Applicant Interested', 'propertyhive' )); break; }
248 case "not_interested": { echo esc_html(__( 'Applicant Not Interested', 'propertyhive' )); break; }
249 case "not_required": { echo esc_html(__( 'Feedback Not Required', 'propertyhive' )); break; }
250 default: { echo esc_html(__( 'Awaiting Feedback', 'propertyhive' )); }
251 }
252
253 if ( $the_viewing->feedback_status == 'interested' || $the_viewing->feedback_status == 'not_interested' )
254 {
255 echo '<br>' . esc_html( $the_viewing->feedback_passed_on == 'yes' ? __( 'Feedback Passed On', 'propertyhive' ) : __( 'Feedback Not Passed On', 'propertyhive' ) );
256 }
257 }
258
259 // Add text if this a second, third etc viewing
260 $related_viewings = get_post_meta( $post->ID, '_related_viewings', TRUE );
261 if ( isset($related_viewings['previous']) && count($related_viewings['previous']) > 0 )
262 {
263 echo '<br>' . esc_html( ph_ordinal_suffix(count($related_viewings['previous'])+1) ) . ' Viewing' ;
264 }
265
266 break;
267 case 'negotiators' :
268 $negotiator_ids = get_post_meta( $post->ID, '_negotiator_id' );
269 if ( is_array($negotiator_ids) && !empty($negotiator_ids) )
270 {
271 $negotiators = array();
272 foreach ( $negotiator_ids as $negotiator_id )
273 {
274 $user_info = get_userdata($negotiator_id);
275 if ( $user_info === false )
276 {
277 $negotiators[] = __( 'Unknown negotiator', 'propertyhive' );
278 }
279 else
280 {
281 $negotiators[] = $user_info->display_name;
282 }
283 }
284 echo esc_html( implode(", ", $negotiators) );
285 }
286 else
287 {
288 echo '<em>- ' . esc_html(__( 'Unaccompanied', 'propertyhive' )) . ' -</em>';
289 }
290 break;
291 default :
292 break;
293 }
294 }
295
296 public function set_primary_column( $default, $screen ) {
297
298 if ( 'edit-viewing' === $screen )
299 {
300 $default = 'start_date_time';
301 }
302
303 return $default;
304 }
305
306 public function remove_actions($actions, $post) {
307
308 if ( $post->post_type !== 'viewing' )
309 {
310 return $actions;
311 }
312
313 // Remove 'Quick Edit' link
314 if ( isset($actions['inline hide-if-no-js']) )
315 {
316 unset($actions['inline hide-if-no-js']);
317 }
318
319 if ( isset($actions['trash']) )
320 {
321 unset($actions['trash']);
322 }
323
324 return $actions;
325 }
326
327 /**
328 * Make viewing columns sortable
329 *
330 * @access public
331 * @param mixed $columns
332 * @return array
333 */
334 public function custom_columns_sort( $columns ) {
335 $custom = array(
336 'start_date_time' => '_start_date_time',
337 );
338 return wp_parse_args( $custom, $columns );
339 }
340
341 /**
342 * Viewing column orderby
343 *
344 * @access public
345 * @param mixed $vars
346 * @return array
347 */
348 public function custom_columns_orderby( $vars ) {
349 if ( is_admin() && $vars['post_type'] == 'viewing' )
350 {
351 $vars = array_merge( $vars, array(
352 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- All these meta_key values are literal, supported CPT date/status/price keys used by paginated WordPress admin list ordering. Core admin post queries provide pagination; no arbitrary request key is copied into these lines.
353 'meta_key' => '_start_date_time',
354 'orderby' => 'meta_value'
355 ) );
356 }
357 return $vars;
358 }
359
360 /**
361 * Remove bulk edit option
362 * @param array $actions
363 */
364 public function remove_bulk_actions( $actions ) {
365 unset( $actions['edit'] );
366 return $actions;
367 }
368
369 public static function check_viewing_feedback_add( $object_id, $meta_key, $meta_value )
370 {
371 if ( get_post_type($object_id) == 'viewing' && $meta_key == '_feedback_status' && in_array($meta_value, array( 'interested', 'not_interested' )) )
372 {
373 update_post_meta( (int)$object_id, '_feedback_received_date', gmdate("Y-m-d H:i:s") );
374 }
375 }
376
377 public static function check_viewing_feedback_update( $meta_id, $object_id, $meta_key, $meta_value )
378 {
379 if ( get_post_type($object_id) == 'viewing' && $meta_key == '_feedback_status' && in_array($meta_value, array( 'interested', 'not_interested' )) )
380 {
381 $original_value = get_post_meta( $object_id, '_feedback_status', TRUE );
382 if ( in_array($original_value, array( '', 'not_required' )) )
383 {
384 update_post_meta( (int)$object_id, '_feedback_received_date', gmdate("Y-m-d H:i:s") );
385 }
386 }
387 }
388 }
389
390 endif;
391
392 return new PH_Admin_CPT_Viewing();
393