Analytics_Manager.php
9 months ago
Browser_Detector.php
9 months ago
Content_Cache_Manager.php
9 months ago
Data_Collector.php
7 months ago
Email_Reports.php
9 months ago
Export_Manager.php
9 months ago
License_Manager.php
9 months ago
Milestone_Manager.php
9 months ago
Pro_Data_Collector.php
9 months ago
REST_API.php
9 months ago
Milestone_Manager.php
382 lines
| 1 | <?php |
| 2 | |
| 3 | namespace EmbedPress\Includes\Classes\Analytics; |
| 4 | |
| 5 | defined('ABSPATH') or die("No direct script access allowed."); |
| 6 | |
| 7 | /** |
| 8 | * EmbedPress Milestone Manager |
| 9 | * |
| 10 | * Handles milestone tracking and notifications for upsell features |
| 11 | * |
| 12 | * @package EmbedPress |
| 13 | * @author EmbedPress <help@embedpress.com> |
| 14 | * @copyright Copyright (C) 2023 WPDeveloper. All rights reserved. |
| 15 | * @license GPLv3 or later |
| 16 | * @since 4.2.7 |
| 17 | */ |
| 18 | class Milestone_Manager |
| 19 | { |
| 20 | /** |
| 21 | * Milestone thresholds |
| 22 | * |
| 23 | * @var array |
| 24 | */ |
| 25 | private $milestones = [ |
| 26 | 'total_views' => [100, 500, 1000, 5000, 10000, 50000, 100000], |
| 27 | 'total_embeds' => [10, 25, 50, 100, 250, 500, 1000], |
| 28 | 'daily_views' => [50, 100, 250, 500, 1000], |
| 29 | 'monthly_views' => [500, 1000, 2500, 5000, 10000, 25000, 50000] |
| 30 | ]; |
| 31 | |
| 32 | /** |
| 33 | * Check for milestone achievements |
| 34 | * |
| 35 | * @return void |
| 36 | */ |
| 37 | public function check_milestones() |
| 38 | { |
| 39 | $this->check_total_views_milestones(); |
| 40 | $this->check_total_embeds_milestones(); |
| 41 | $this->check_daily_views_milestones(); |
| 42 | $this->check_monthly_views_milestones(); |
| 43 | } |
| 44 | |
| 45 | /** |
| 46 | * Check total views milestones |
| 47 | * |
| 48 | * @return void |
| 49 | */ |
| 50 | private function check_total_views_milestones() |
| 51 | { |
| 52 | global $wpdb; |
| 53 | |
| 54 | $content_table = $wpdb->prefix . 'embedpress_analytics_content'; |
| 55 | $total_views = $wpdb->get_var("SELECT SUM(total_views) FROM $content_table"); |
| 56 | |
| 57 | if (!$total_views) { |
| 58 | return; |
| 59 | } |
| 60 | |
| 61 | foreach ($this->milestones['total_views'] as $milestone) { |
| 62 | if ($total_views >= $milestone && !$this->is_milestone_achieved('total_views', $milestone)) { |
| 63 | $this->record_milestone_achievement('total_views', $milestone, $total_views); |
| 64 | $this->trigger_milestone_notification('total_views', $milestone, $total_views); |
| 65 | } |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | /** |
| 70 | * Check total embeds milestones |
| 71 | * |
| 72 | * @return void |
| 73 | */ |
| 74 | private function check_total_embeds_milestones() |
| 75 | { |
| 76 | global $wpdb; |
| 77 | |
| 78 | $content_table = $wpdb->prefix . 'embedpress_analytics_content'; |
| 79 | $total_embeds = $wpdb->get_var("SELECT COUNT(*) FROM $content_table"); |
| 80 | |
| 81 | if (!$total_embeds) { |
| 82 | return; |
| 83 | } |
| 84 | |
| 85 | foreach ($this->milestones['total_embeds'] as $milestone) { |
| 86 | if ($total_embeds >= $milestone && !$this->is_milestone_achieved('total_embeds', $milestone)) { |
| 87 | $this->record_milestone_achievement('total_embeds', $milestone, $total_embeds); |
| 88 | $this->trigger_milestone_notification('total_embeds', $milestone, $total_embeds); |
| 89 | } |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | /** |
| 94 | * Check daily views milestones |
| 95 | * |
| 96 | * @return void |
| 97 | */ |
| 98 | private function check_daily_views_milestones() |
| 99 | { |
| 100 | global $wpdb; |
| 101 | |
| 102 | $views_table = $wpdb->prefix . 'embedpress_analytics_views'; |
| 103 | $today = date('Y-m-d'); |
| 104 | |
| 105 | $daily_views = $wpdb->get_var($wpdb->prepare( |
| 106 | "SELECT COUNT(*) FROM $views_table |
| 107 | WHERE interaction_type = 'view' AND DATE(created_at) = %s", |
| 108 | $today |
| 109 | )); |
| 110 | |
| 111 | if (!$daily_views) { |
| 112 | return; |
| 113 | } |
| 114 | |
| 115 | foreach ($this->milestones['daily_views'] as $milestone) { |
| 116 | if ($daily_views >= $milestone && !$this->is_milestone_achieved('daily_views', $milestone, $today)) { |
| 117 | $this->record_milestone_achievement('daily_views', $milestone, $daily_views); |
| 118 | $this->trigger_milestone_notification('daily_views', $milestone, $daily_views); |
| 119 | } |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | /** |
| 124 | * Check monthly views milestones |
| 125 | * |
| 126 | * @return void |
| 127 | */ |
| 128 | private function check_monthly_views_milestones() |
| 129 | { |
| 130 | global $wpdb; |
| 131 | |
| 132 | $views_table = $wpdb->prefix . 'embedpress_analytics_views'; |
| 133 | $start_of_month = date('Y-m-01'); |
| 134 | |
| 135 | $monthly_views = $wpdb->get_var($wpdb->prepare( |
| 136 | "SELECT COUNT(*) FROM $views_table |
| 137 | WHERE interaction_type = 'view' AND DATE(created_at) >= %s", |
| 138 | $start_of_month |
| 139 | )); |
| 140 | |
| 141 | if (!$monthly_views) { |
| 142 | return; |
| 143 | } |
| 144 | |
| 145 | foreach ($this->milestones['monthly_views'] as $milestone) { |
| 146 | if ($monthly_views >= $milestone && !$this->is_milestone_achieved('monthly_views', $milestone, $start_of_month)) { |
| 147 | $this->record_milestone_achievement('monthly_views', $milestone, $monthly_views); |
| 148 | $this->trigger_milestone_notification('monthly_views', $milestone, $monthly_views); |
| 149 | } |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | /** |
| 154 | * Check if milestone is already achieved |
| 155 | * |
| 156 | * @param string $type |
| 157 | * @param int $value |
| 158 | * @param string $date |
| 159 | * @return bool |
| 160 | */ |
| 161 | private function is_milestone_achieved($type, $value, $date = null) |
| 162 | { |
| 163 | global $wpdb; |
| 164 | |
| 165 | $table_name = $wpdb->prefix . 'embedpress_analytics_milestones'; |
| 166 | |
| 167 | $where_clause = "milestone_type = %s AND milestone_value = %d"; |
| 168 | $params = [$type, $value]; |
| 169 | |
| 170 | // For daily/monthly milestones, check for specific date |
| 171 | if ($date && in_array($type, ['daily_views', 'monthly_views'])) { |
| 172 | $where_clause .= " AND DATE(achieved_at) = %s"; |
| 173 | $params[] = $date; |
| 174 | } |
| 175 | |
| 176 | $exists = $wpdb->get_var($wpdb->prepare( |
| 177 | "SELECT id FROM $table_name WHERE $where_clause", |
| 178 | ...$params |
| 179 | )); |
| 180 | |
| 181 | return !empty($exists); |
| 182 | } |
| 183 | |
| 184 | /** |
| 185 | * Record milestone achievement |
| 186 | * |
| 187 | * @param string $type |
| 188 | * @param int $milestone_value |
| 189 | * @param int $achieved_value |
| 190 | * @return void |
| 191 | */ |
| 192 | private function record_milestone_achievement($type, $milestone_value, $achieved_value) |
| 193 | { |
| 194 | global $wpdb; |
| 195 | |
| 196 | $table_name = $wpdb->prefix . 'embedpress_analytics_milestones'; |
| 197 | |
| 198 | $data = [ |
| 199 | 'milestone_type' => $type, |
| 200 | 'milestone_value' => $milestone_value, |
| 201 | 'achieved_value' => $achieved_value, |
| 202 | 'achieved_at' => current_time('mysql') |
| 203 | ]; |
| 204 | |
| 205 | $wpdb->insert($table_name, $data); |
| 206 | } |
| 207 | |
| 208 | /** |
| 209 | * Trigger milestone notification |
| 210 | * |
| 211 | * @param string $type |
| 212 | * @param int $milestone_value |
| 213 | * @param int $achieved_value |
| 214 | * @return void |
| 215 | */ |
| 216 | private function trigger_milestone_notification($type, $milestone_value, $achieved_value) |
| 217 | { |
| 218 | // Store notification in WordPress transients for admin display |
| 219 | $notification_data = [ |
| 220 | 'type' => $type, |
| 221 | 'milestone_value' => $milestone_value, |
| 222 | 'achieved_value' => $achieved_value, |
| 223 | 'timestamp' => time() |
| 224 | ]; |
| 225 | |
| 226 | // Store multiple notifications |
| 227 | $existing_notifications = get_transient('embedpress_milestone_notifications'); |
| 228 | if (!is_array($existing_notifications)) { |
| 229 | $existing_notifications = []; |
| 230 | } |
| 231 | |
| 232 | $existing_notifications[] = $notification_data; |
| 233 | |
| 234 | // Keep only last 5 notifications |
| 235 | $existing_notifications = array_slice($existing_notifications, -5); |
| 236 | |
| 237 | set_transient('embedpress_milestone_notifications', $existing_notifications, DAY_IN_SECONDS); |
| 238 | |
| 239 | // Trigger action for other plugins/themes to hook into |
| 240 | do_action('embedpress_milestone_achieved', $type, $milestone_value, $achieved_value); |
| 241 | } |
| 242 | |
| 243 | /** |
| 244 | * Get milestone notifications |
| 245 | * |
| 246 | * @return array |
| 247 | */ |
| 248 | public function get_milestone_notifications() |
| 249 | { |
| 250 | $notifications = get_transient('embedpress_milestone_notifications'); |
| 251 | return is_array($notifications) ? $notifications : []; |
| 252 | } |
| 253 | |
| 254 | /** |
| 255 | * Mark notification as read |
| 256 | * |
| 257 | * @param int $timestamp |
| 258 | * @return void |
| 259 | */ |
| 260 | public function mark_notification_read($timestamp) |
| 261 | { |
| 262 | $notifications = $this->get_milestone_notifications(); |
| 263 | |
| 264 | foreach ($notifications as $key => $notification) { |
| 265 | if ($notification['timestamp'] == $timestamp) { |
| 266 | unset($notifications[$key]); |
| 267 | break; |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | set_transient('embedpress_milestone_notifications', array_values($notifications), DAY_IN_SECONDS); |
| 272 | } |
| 273 | |
| 274 | /** |
| 275 | * Get milestone data for dashboard |
| 276 | * |
| 277 | * @return array |
| 278 | */ |
| 279 | public function get_milestone_data() |
| 280 | { |
| 281 | global $wpdb; |
| 282 | |
| 283 | $table_name = $wpdb->prefix . 'embedpress_analytics_milestones'; |
| 284 | |
| 285 | // Get recent achievements |
| 286 | $recent_achievements = $wpdb->get_results( |
| 287 | "SELECT * FROM $table_name |
| 288 | ORDER BY achieved_at DESC |
| 289 | LIMIT 10", |
| 290 | ARRAY_A |
| 291 | ); |
| 292 | |
| 293 | // Get progress towards next milestones |
| 294 | $data_collector = new Data_Collector(); |
| 295 | $current_stats = $data_collector->get_analytics_data(); |
| 296 | |
| 297 | $progress = []; |
| 298 | |
| 299 | // Total views progress |
| 300 | $total_views = $current_stats['views_analytics']['total_views']; |
| 301 | $next_views_milestone = $this->get_next_milestone('total_views', $total_views); |
| 302 | if ($next_views_milestone) { |
| 303 | $progress['total_views'] = [ |
| 304 | 'current' => $total_views, |
| 305 | 'next_milestone' => $next_views_milestone, |
| 306 | 'progress_percentage' => ($total_views / $next_views_milestone) * 100 |
| 307 | ]; |
| 308 | } |
| 309 | |
| 310 | // Total embeds progress |
| 311 | $total_embeds = $current_stats['content_by_type']['total']; |
| 312 | $next_embeds_milestone = $this->get_next_milestone('total_embeds', $total_embeds); |
| 313 | if ($next_embeds_milestone) { |
| 314 | $progress['total_embeds'] = [ |
| 315 | 'current' => $total_embeds, |
| 316 | 'next_milestone' => $next_embeds_milestone, |
| 317 | 'progress_percentage' => ($total_embeds / $next_embeds_milestone) * 100 |
| 318 | ]; |
| 319 | } |
| 320 | |
| 321 | return [ |
| 322 | 'recent_achievements' => $recent_achievements, |
| 323 | 'progress' => $progress, |
| 324 | 'notifications' => $this->get_milestone_notifications() |
| 325 | ]; |
| 326 | } |
| 327 | |
| 328 | /** |
| 329 | * Get next milestone for a given type and current value |
| 330 | * |
| 331 | * @param string $type |
| 332 | * @param int $current_value |
| 333 | * @return int|null |
| 334 | */ |
| 335 | private function get_next_milestone($type, $current_value) |
| 336 | { |
| 337 | if (!isset($this->milestones[$type])) { |
| 338 | return null; |
| 339 | } |
| 340 | |
| 341 | foreach ($this->milestones[$type] as $milestone) { |
| 342 | if ($milestone > $current_value) { |
| 343 | return $milestone; |
| 344 | } |
| 345 | } |
| 346 | |
| 347 | return null; |
| 348 | } |
| 349 | |
| 350 | /** |
| 351 | * Get milestone message for notifications |
| 352 | * |
| 353 | * @param string $type |
| 354 | * @param int $milestone_value |
| 355 | * @param int $achieved_value |
| 356 | * @return string |
| 357 | */ |
| 358 | public function get_milestone_message($type, $milestone_value, $achieved_value) |
| 359 | { |
| 360 | $messages = [ |
| 361 | 'total_views' => sprintf( |
| 362 | __('🎉 Congratulations! Your embedded content has reached %s total views! Consider upgrading to EmbedPress Pro for advanced analytics and features.', 'embedpress'), |
| 363 | number_format($milestone_value) |
| 364 | ), |
| 365 | 'total_embeds' => sprintf( |
| 366 | __('🚀 Amazing! You\'ve created %s embedded content pieces! Unlock more embedding options with EmbedPress Pro.', 'embedpress'), |
| 367 | number_format($milestone_value) |
| 368 | ), |
| 369 | 'daily_views' => sprintf( |
| 370 | __('📈 Fantastic! You\'ve reached %s views today! Upgrade to Pro for detailed daily analytics and insights.', 'embedpress'), |
| 371 | number_format($milestone_value) |
| 372 | ), |
| 373 | 'monthly_views' => sprintf( |
| 374 | __('🏆 Incredible! %s views this month! Get advanced monthly reports with EmbedPress Pro.', 'embedpress'), |
| 375 | number_format($milestone_value) |
| 376 | ) |
| 377 | ]; |
| 378 | |
| 379 | return isset($messages[$type]) ? $messages[$type] : __('Milestone achieved!', 'embedpress'); |
| 380 | } |
| 381 | } |
| 382 |