prefix . 'aumframe_user_interactions'; } public static function maybe_install(): void { if (\Aumframe\Storage::table_exists(self::table())) { return; } self::install(); } public static function install(): void { global $wpdb; $table = self::table(); $collate = $wpdb->get_charset_collate(); require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( "CREATE TABLE {$table} ( id bigint(20) NOT NULL AUTO_INCREMENT, user_id bigint(20) NOT NULL, target_id bigint(20) NOT NULL, interaction_type varchar(50) NOT NULL, target_type varchar(50) NOT NULL, created_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY user_id (user_id), KEY target_id (target_id), KEY interaction_type (interaction_type), UNIQUE KEY unique_interaction (user_id, target_id, interaction_type, target_type) ) {$collate};" ); } public static function add(int $user_id, int $target_id, string $type, string $target_type = 'post'): bool { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- A table owned by this plugin, for which core has no API. return false !== $wpdb->insert(self::table(), [ 'user_id' => $user_id, 'target_id' => $target_id, 'interaction_type' => $type, 'target_type' => $target_type, 'created_at' => current_time('mysql'), ], ['%d', '%d', '%s', '%s', '%s']); } public static function remove(int $user_id, int $target_id, string $type, string $target_type = 'post'): bool { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- A table owned by this plugin, for which core has no API. return false !== $wpdb->delete(self::table(), [ 'user_id' => $user_id, 'target_id' => $target_id, 'interaction_type' => $type, 'target_type' => $target_type, ], ['%d', '%d', '%s', '%s']); } public static function has(int $user_id, int $target_id, string $type, string $target_type = 'post'): bool { global $wpdb; if (!$user_id) { return false; } // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.NoCaching return (int) $wpdb->get_var($wpdb->prepare( 'SELECT COUNT(*) FROM %i WHERE user_id = %d AND target_id = %d AND interaction_type = %s AND target_type = %s', self::table(), $user_id, $target_id, $type, $target_type )) > 0; } public static function count(int $target_id, string $type, string $target_type = 'post'): int { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.NoCaching return (int) $wpdb->get_var($wpdb->prepare( 'SELECT COUNT(*) FROM %i WHERE target_id = %d AND interaction_type = %s AND target_type = %s', self::table(), $target_id, $type, $target_type )); } public static function counts(array $target_ids, string $type, string $target_type = 'post'): array { global $wpdb; $ids = array_values(array_unique(array_filter(array_map('intval', $target_ids)))); if (!$ids) { return []; } $in = implode(',', array_fill(0, count($ids), '%d')); // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $in is the run of %d placeholders built on the previous line from count($ids); every value is passed to prepare(). $rows = (array) $wpdb->get_results($wpdb->prepare( "SELECT target_id, COUNT(*) AS n FROM %i WHERE target_type = %s AND interaction_type = %s AND target_id IN ({$in}) GROUP BY target_id", self::table(), $target_type, $type, ...$ids ), ARRAY_A); $out = array_fill_keys($ids, 0); foreach ($rows as $r) { $out[(int) $r['target_id']] = (int) $r['n']; } return $out; } public static function for_user(int $user_id, string $type, string $target_type = 'post'): array { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.NoCaching return array_map('intval', (array) $wpdb->get_col($wpdb->prepare( 'SELECT target_id FROM %i WHERE user_id = %d AND interaction_type = %s AND target_type = %s ORDER BY created_at DESC', self::table(), $user_id, $type, $target_type ))); } public static function for_target(int $target_id, string $type, string $target_type = 'post'): array { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.NoCaching return array_map('intval', (array) $wpdb->get_col($wpdb->prepare( 'SELECT user_id FROM %i WHERE target_id = %d AND interaction_type = %s AND target_type = %s ORDER BY created_at DESC', self::table(), $target_id, $type, $target_type ))); } }