PluginProbe
Property Hive / 2.4.0
Property Hive v2.4.0
2.4.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 All 262 releases
propertyhive / includes / admin / reports / class-ph-report-sales-property-popularity.php

class-ph-report-sales-property-popularity.php in Property Hive 2.4.0, at includes/admin/reports/class-ph-report-sales-property-popularity.php

343 lines 13.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 /**
8 * PH_Report_Sales_Property_Popularity
9 *
10 * @author PropertyHive
11 * @category Admin
12 * @package PropertyHive/Admin/Reports
13 * @version 1.0.0
14 */
15 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- Legacy public global class PH_Report_Sales_Property_Popularity; preserving the existing PH_* class name is required for plugin and extension compatibility.
16 class PH_Report_Sales_Property_Popularity extends PH_Admin_Report {
17
18 private function get_requested_date( $key, $default ) {
19 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Authorized read-only popularity range; require a real calendar date before statistics lookup.
20 $value = isset( $_GET[ $key ] ) && is_string( $_GET[ $key ] ) ? sanitize_text_field( wp_unslash( $_GET[ $key ] ) ) : '';
21 if ( preg_match( '/^(\d{4})-(\d{2})-(\d{2})$/', $value, $parts ) && checkdate( (int) $parts[2], (int) $parts[3], (int) $parts[1] ) ) {
22 return $value;
23 }
24 return $default;
25 }
26
27 private function get_property_view_data( $date_from, $date_to )
28 {
29 global $post;
30
31 $return = array();
32
33 $original_date_from = $date_from;
34 $original_date_to = $date_to;
35
36 $secs_diff = strtotime($date_to) - strtotime($date_from);
37
38 $args = array(
39 'post_type' => 'property',
40 'nopaging' => true,
41 'fields' => 'ids',
42 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Complete stock/report totals require all matching on-market properties in the fixed department, fetched as IDs through WordPress; optional office narrowing is retained.
43 'meta_query' => array(
44 array(
45 'key' => '_on_market',
46 'value' => 'yes'
47 ),
48 array(
49 'key' => '_department',
50 'value' => 'residential-sales'
51 )
52 )
53 );
54
55 $property_query = new WP_Query( $args );
56
57 if ( $property_query->have_posts() )
58 {
59 while ( $property_query->have_posts() )
60 {
61 $property_query->the_post();
62
63 $sources = array(
64 'Website' => '_view_statistics'
65 );
66
67 $sources = apply_filters( 'propertyhive_property_view_statistic_sources', $sources );
68
69 foreach ( $sources as $label => $meta_key )
70 {
71 $view_statistics = get_post_meta( get_the_ID(), $meta_key, TRUE );
72
73 $total_views = 0;
74 $previous_time_frame = false;
75
76 if ( is_array($view_statistics) && !empty($view_statistics) )
77 {
78 $date_from = $original_date_from;
79 $date_to = $original_date_to;
80
81 while (strtotime($date_from) <= strtotime($date_to))
82 {
83 if ( isset( $view_statistics[$date_from] ) )
84 {
85 $total_views += $view_statistics[$date_from];
86 }
87 $date_from = gmdate("Y-m-d", strtotime("+1 day", strtotime($date_from)));
88 }
89
90 $date_from = $original_date_from;
91 $date_to = $original_date_to;
92
93 $date_from = gmdate("Y-m-d", strtotime($original_date_from) - $secs_diff - 86400);
94 $date_to = gmdate("Y-m-d", strtotime($date_to) - $secs_diff - 86400);
95
96 while (strtotime($date_from) <= strtotime($date_to))
97 {
98 if ( isset( $view_statistics[$date_from] ) )
99 {
100 if ( $previous_time_frame === false ) { $previous_time_frame = 0; }
101 $previous_time_frame += $view_statistics[$date_from];
102 }
103 $date_from = gmdate("Y-m-d", strtotime("+1 day", strtotime($date_from)));
104 }
105 }
106
107 if ( !isset($return[$label]) ) { $return[$label] = array(); }
108
109 $return[$label][get_the_ID()] = array(
110 'total_views' => $total_views,
111 'previous_time_frame' => $previous_time_frame
112 );
113 }
114 }
115 }
116 return $return;
117 }
118
119 /**
120 * Output the report.
121 */
122 public function output_report() {
123
124 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Authorized read-only report range; malformed duration falls back to the existing seven-day default.
125 $requested_duration = isset( $_GET['duration'] ) && is_string( $_GET['duration'] ) ? sanitize_text_field( wp_unslash( $_GET['duration'] ) ) : '';
126 $duration = ctype_digit( $requested_duration ) && (int) $requested_duration > 0 ? (int) $requested_duration - 1 : 6;
127 $default_from = gmdate( 'Y-m-d', strtotime( ( $duration + 1 ) . ' days ago' ) );
128 $default_to = gmdate( 'Y-m-d', strtotime( 'yesterday' ) );
129 $date_from = $this->get_requested_date( 'date_from', $default_from );
130 $date_to = $this->get_requested_date( 'date_to', $default_to );
131 if ( $date_from > $date_to ) {
132 $date_from = $default_from;
133 $date_to = $default_to;
134 }
135
136 $properties_view_data = $this->get_property_view_data( $date_from, $date_to );
137
138 // Order by total views
139 $popular_order = array();
140 foreach ( $properties_view_data as $label => $property_view_data )
141 {
142 foreach ( $property_view_data as $property_id => $view_totals )
143 {
144 if ( !isset($popular_order[$label]) ) { $popular_order[$label] = array(); }
145
146 $popular_order[$label][$view_totals['total_views'].'.'.$property_id] = $property_id;
147 }
148 }
149 ?>
150
151 <style type="text/css">
152
153 .chart-tabs { }
154 .chart-tabs ul { list-style-type:none; margin:0; padding:0; }
155 .chart-tabs ul li { display:inline-block; margin:0; padding:0; }
156 .chart-tabs ul li a { display:block; line-height:40px; text-decoration:none; color:#333; padding:0 30px; text-align:center; border:1px solid #DDD; border-bottom:0; }
157 .chart-tabs ul li.active a { background:#FFF; font-weight:700; }
158 .chart-tabs ul li a:hover { background:#FFF; }
159 .chart-container { padding:12px 12px 12px 12px; background:#FFF; border:1px solid #DDD; }
160 .chart-panel { float:left; width:49%; border:1px solid #DDD; padding:0 12px 12px 12px; box-sizing:border-box; margin-bottom:20px; }
161 .chart-container .chart-panels { }
162 .chart-container .chart-panel:nth-child(even) { float:right; }
163 .chart-container .chart-panel ul li { padding:8px; margin:0; }
164 .chart-container .chart-panel ul li:nth-child(odd) { background:#EEE; }
165 .chart-container .chart-panel ul li:nth-child(1) { background:#FFF; font-weight:700; border-bottom:1px solid #DDD; }
166 .chart-container .chart-panel ul li .stat { float:right; font-weight:700; }
167 .chart-container .chart-panel ul li .stat span { font-weight:400; color:#999; }
168
169 </style>
170
171 <br>
172
173 <div class="chart-tabs">
174 <ul>
175 <li<?php if ( $duration == 0 ) { echo ' class="active"'; } ?>><a href="admin.php?page=ph-reports&tab=properties&report=sales_property_popularity&duration=1">Yesterday</a></li>
176 <li<?php if ( $duration == 6 ) { echo ' class="active"'; } ?>><a href="admin.php?page=ph-reports&tab=properties&report=sales_property_popularity&duration=7">Last 7 Days</a></li>
177 <li<?php if ( $duration == 29 ) { echo ' class="active"'; } ?>><a href="admin.php?page=ph-reports&tab=properties&report=sales_property_popularity&duration=30">Last 30 Days</a></li>
178 </ul>
179 </div>
180
181 <div class="chart-container">
182
183 <?php
184 foreach ( $popular_order as $label => $order )
185 {
186 $property_view_data = $properties_view_data[$label];
187
188 krsort($order);
189 ?>
190
191 <div class="chart-panels">
192
193 <div class="chart-panel">
194
195 <h3>Most Popular Properties - <?php echo esc_html($label); ?></h3>
196
197 <?php
198 if ( !empty($order) )
199 {
200 $slice_offset = min(10, ceil(count($order) / 2));
201 $most_popular = array_slice($order, 0, $slice_offset);
202
203 echo '<ul>
204 <li>
205 Property
206 <div class="stat">Views</div>
207 </li>';
208 foreach ( $most_popular as $key => $property_id )
209 {
210 if ( $property_view_data[$property_id]['total_views'] > 0 )
211 {
212 $property = new PH_Property($property_id);
213
214 echo '<li>
215 <a href="' . esc_url(get_edit_post_link($property_id)) . '">' . esc_html($property->get_formatted_full_address()) . '</a>
216 <div class="stat">' . esc_html($property_view_data[$property_id]['total_views']) . ' <span>';
217 if ( $property_view_data[$property_id]['total_views'] == $property_view_data[$property_id]['previous_time_frame'] )
218 {
219 echo '<span style="color:#999" title="No views"><span class="dashicons dashicons-arrow-right" style="color:#999"></span>-</span>';
220 }
221 elseif ( $property_view_data[$property_id]['previous_time_frame'] === false || $property_view_data[$property_id]['previous_time_frame'] == 0 )
222 {
223 echo '<span style="color:#090" title="No views in previous timeframe"><span class="dashicons dashicons-arrow-up" style="color:#090"></span>&#x221e;</span>';
224 }
225 else
226 {
227 if ( $property_view_data[$property_id]['total_views'] >= $property_view_data[$property_id]['previous_time_frame'] )
228 {
229 $percentage_difference = $property_view_data[$property_id]['total_views'] / $property_view_data[$property_id]['previous_time_frame'];
230 $percentage_difference = 100 - ($percentage_difference * 100);
231 if ( $percentage_difference < 0 ) { $percentage_difference = $percentage_difference * -1; }
232 $percentage_difference = number_format($percentage_difference, 1);
233
234 echo '<span style="color:#090" title="' . esc_attr($property_view_data[$property_id]['previous_time_frame']) . ' views in previous timeframe"><span class="dashicons dashicons-arrow-up" style="color:#090"></span>' . esc_html($percentage_difference) . '%</span>';
235 }
236 else
237 {
238 $percentage_difference = $property_view_data[$property_id]['total_views'] / $property_view_data[$property_id]['previous_time_frame'];
239 $percentage_difference = 100 - ($percentage_difference * 100);
240 if ( $percentage_difference < 0 ) { $percentage_difference = $percentage_difference * -1; }
241 $percentage_difference = number_format($percentage_difference, 1);
242
243 echo '<span style="color:#900" title="' . esc_attr($property_view_data[$property_id]['previous_time_frame']) . ' views in previous timeframe"><span class="dashicons dashicons-arrow-down" style="color:#900"></span>' . esc_html($percentage_difference) . '%</span>';
244 }
245 }
246 echo '</span></div>
247 </li>';
248
249 unset($order[$key]);
250 }
251 }
252 echo '</ul>';
253 }
254 else
255 {
256 echo '<p>No view statistics available for ' . esc_html($label) . '</p>';
257 }
258 ?>
259
260 </div>
261
262 <div class="chart-panel">
263
264 <h3>Least Popular Properties - <?php echo esc_html($label); ?></h3>
265
266 <?php
267 if ( !empty($order) )
268 {
269 ksort($order, SORT_NUMERIC);
270
271 $slice_offset = min(10, ceil(count($order) / 2));
272 $least_popular = array_slice($order, 0, $slice_offset);
273
274 echo '<ul>
275 <li>
276 Property
277 <div class="stat">Views</div>
278 </li>';
279 foreach ( $least_popular as $key => $property_id )
280 {
281 $property = new PH_Property($property_id);
282
283 echo '<li>
284 <a href="' . esc_url(get_edit_post_link($property_id)) . '">' . esc_html($property->get_formatted_full_address()) . '</a>
285 <div class="stat">' . esc_html($property_view_data[$property_id]['total_views']) . ' <span>';
286 if ( $property_view_data[$property_id]['total_views'] == $property_view_data[$property_id]['previous_time_frame'] )
287 {
288 echo '<span style="color:#999" title="No views"><span class="dashicons dashicons-arrow-right" style="color:#999"></span>-</span>';
289 }
290 elseif ( $property_view_data[$property_id]['previous_time_frame'] === false || $property_view_data[$property_id]['previous_time_frame'] == 0 )
291 {
292 echo '<span style="color:#090" title="No views in previous timeframe"><span class="dashicons dashicons-arrow-up" style="color:#090"></span>&#x221e;</span>';
293 }
294 else
295 {
296 if ( $property_view_data[$property_id]['total_views'] >= $property_view_data[$property_id]['previous_time_frame'] )
297 {
298 $percentage_difference = $property_view_data[$property_id]['total_views'] / $property_view_data[$property_id]['previous_time_frame'];
299 $percentage_difference = 100 - ($percentage_difference * 100);
300 if ( $percentage_difference < 0 ) { $percentage_difference = $percentage_difference * -1; }
301 $percentage_difference = number_format($percentage_difference, 1);
302
303 echo '<span style="color:#090" title="' . esc_attr($property_view_data[$property_id]['previous_time_frame']) . ' views in previous timeframe"><span class="dashicons dashicons-arrow-up" style="color:#090"></span>' . esc_html($percentage_difference) . '%</span>';
304 }
305 else
306 {
307 $percentage_difference = $property_view_data[$property_id]['total_views'] / $property_view_data[$property_id]['previous_time_frame'];
308 $percentage_difference = 100 - ($percentage_difference * 100);
309 if ( $percentage_difference < 0 ) { $percentage_difference = $percentage_difference * -1; }
310 $percentage_difference = number_format($percentage_difference, 1);
311
312 echo '<span style="color:#900" title="' . esc_attr($property_view_data[$property_id]['previous_time_frame']) . ' views in previous timeframe"><span class="dashicons dashicons-arrow-down" style="color:#900"></span>' . esc_html($percentage_difference) . '%</span>';
313 }
314 }
315 echo '</span></div>
316 </li>';
317
318 unset($order[$key]);
319 }
320 echo '</ul>';
321 }
322 else
323 {
324 echo '<p>No view statistics available ' . esc_html($label) . '</p>';
325 }
326 ?>
327
328 </div>
329
330 <div style="clear:both"></div>
331
332 </div>
333
334 <?php
335 }
336 ?>
337
338 </div>
339
340 <?php
341 }
342
343 }