display_name : __('System', 'woonoow'); // Get object name $object_name = self::get_object_name($object_type, $object_id); // Get IP and user agent $ip_address = self::get_client_ip(); $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; // Prepare data $data = [ 'user_id' => $user_id, 'user_name' => $user_name, 'action' => $action, 'object_type' => $object_type, 'object_id' => $object_id, 'object_name' => $object_name, 'description' => $description, 'metadata' => json_encode($metadata), 'ip_address' => $ip_address, 'user_agent' => $user_agent, 'created_at' => current_time('mysql'), ]; // Insert $table_name = ActivityLogTable::get_table_name(); $result = $wpdb->insert($table_name, $data); if ($result === false) { return false; } return $wpdb->insert_id; } /** * Get object name based on type and ID * * @param string $object_type * @param int $object_id * @return string */ private static function get_object_name($object_type, $object_id) { switch ($object_type) { case 'order': return sprintf(__('Order #%d', 'woonoow'), $object_id); case 'product': $product = wc_get_product($object_id); return $product ? $product->get_name() : sprintf(__('Product #%d', 'woonoow'), $object_id); case 'customer': $customer = get_userdata($object_id); return $customer ? $customer->display_name : sprintf(__('Customer #%d', 'woonoow'), $object_id); case 'notification': return sprintf(__('Notification #%d', 'woonoow'), $object_id); case 'settings': return __('Settings', 'woonoow'); default: return sprintf(__('%s #%d', 'woonoow'), ucfirst($object_type), $object_id); } } /** * Get client IP address * * @return string */ private static function get_client_ip() { $ip_keys = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR']; foreach ($ip_keys as $key) { if (isset($_SERVER[$key]) && filter_var($_SERVER[$key], FILTER_VALIDATE_IP)) { return $_SERVER[$key]; } } return '0.0.0.0'; } /** * Get activities * * @param array $args Query arguments * @return array */ public static function get_activities($args = []) { global $wpdb; $defaults = [ 'page' => 1, 'per_page' => 20, 'action' => null, 'object_type' => null, 'object_id' => null, 'user_id' => null, 'date_from' => null, 'date_to' => null, 'search' => null, ]; $args = wp_parse_args($args, $defaults); $table_name = ActivityLogTable::get_table_name(); $where = ['1=1']; $where_values = []; // Filters if ($args['action']) { $where[] = 'action = %s'; $where_values[] = $args['action']; } if ($args['object_type']) { $where[] = 'object_type = %s'; $where_values[] = $args['object_type']; } if ($args['object_id']) { $where[] = 'object_id = %d'; $where_values[] = $args['object_id']; } if ($args['user_id']) { $where[] = 'user_id = %d'; $where_values[] = $args['user_id']; } if ($args['date_from']) { $where[] = 'created_at >= %s'; $where_values[] = $args['date_from']; } if ($args['date_to']) { $where[] = 'created_at <= %s'; $where_values[] = $args['date_to']; } if ($args['search']) { $where[] = '(description LIKE %s OR object_name LIKE %s OR user_name LIKE %s)'; $search_term = '%' . $wpdb->esc_like($args['search']) . '%'; $where_values[] = $search_term; $where_values[] = $search_term; $where_values[] = $search_term; } // Build query $where_clause = implode(' AND ', $where); $offset = ($args['page'] - 1) * $args['per_page']; // Count total $count_query = "SELECT COUNT(*) FROM {$table_name} WHERE {$where_clause}"; if (!empty($where_values)) { $count_query = $wpdb->prepare($count_query, $where_values); } $total = (int) $wpdb->get_var($count_query); // Get activities $query = "SELECT * FROM {$table_name} WHERE {$where_clause} ORDER BY created_at DESC LIMIT %d OFFSET %d"; $where_values[] = $args['per_page']; $where_values[] = $offset; $query = $wpdb->prepare($query, $where_values); $activities = $wpdb->get_results($query, ARRAY_A); // Parse metadata foreach ($activities as &$activity) { $activity['metadata'] = json_decode($activity['metadata'], true); } return [ 'activities' => $activities, 'total' => $total, 'page' => $args['page'], 'per_page' => $args['per_page'], 'total_pages' => ceil($total / $args['per_page']), ]; } /** * Get activity stats * * @param string $date_from * @param string $date_to * @return array */ public static function get_stats($date_from = null, $date_to = null) { global $wpdb; $table_name = ActivityLogTable::get_table_name(); $where = ['1=1']; $where_values = []; if ($date_from) { $where[] = 'created_at >= %s'; $where_values[] = $date_from; } if ($date_to) { $where[] = 'created_at <= %s'; $where_values[] = $date_to; } $where_clause = implode(' AND ', $where); // Total activities $total_query = "SELECT COUNT(*) FROM {$table_name} WHERE {$where_clause}"; if (!empty($where_values)) { $total_query = $wpdb->prepare($total_query, $where_values); } $total = (int) $wpdb->get_var($total_query); // By action $by_action_query = "SELECT action, COUNT(*) as count FROM {$table_name} WHERE {$where_clause} GROUP BY action ORDER BY count DESC LIMIT 10"; if (!empty($where_values)) { $by_action_query = $wpdb->prepare($by_action_query, $where_values); } $by_action = $wpdb->get_results($by_action_query, ARRAY_A); // By user $by_user_query = "SELECT user_id, user_name, COUNT(*) as count FROM {$table_name} WHERE {$where_clause} GROUP BY user_id ORDER BY count DESC LIMIT 10"; if (!empty($where_values)) { $by_user_query = $wpdb->prepare($by_user_query, $where_values); } $by_user = $wpdb->get_results($by_user_query, ARRAY_A); return [ 'total' => $total, 'by_action' => $by_action, 'by_user' => $by_user, ]; } /** * Delete old activities * * @param int $days Days to keep * @return int Number of deleted rows */ public static function cleanup($days = 90) { global $wpdb; $table_name = ActivityLogTable::get_table_name(); $date = date('Y-m-d H:i:s', strtotime("-{$days} days")); return $wpdb->query($wpdb->prepare( "DELETE FROM {$table_name} WHERE created_at < %s", $date )); } }