Files
beep/includes/class-likes.php
Krystie ccead50116 Initial commit: Beep WordPress plugin
- Custom post type with likes, replies, moderation, shortcodes
- Beep icon and logo assets
- CSS and JS for frontend
2026-05-18 02:22:57 -07:00

145 lines
4.9 KiB
PHP
Executable File

<?php
if (!defined('ABSPATH')) {
exit;
}
class Beep_Likes {
public static function init() {
add_action('rest_api_init', [__CLASS__, 'register_routes']);
}
public static function table_name() {
global $wpdb;
return $wpdb->prefix . BEEP_LIKES_TABLE;
}
/**
* Create or migrate the likes table.
* The 'post_id' column historically only stored beep IDs; we now also
* use it for comment IDs (replies). 'object_type' distinguishes them.
*/
public static function create_table() {
global $wpdb;
$table = self::table_name();
$charset = $wpdb->get_charset_collate();
$sql = "CREATE TABLE $table (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
object_type VARCHAR(20) NOT NULL DEFAULT 'post',
post_id BIGINT(20) UNSIGNED NOT NULL,
user_id BIGINT(20) UNSIGNED NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY object_user (object_type, post_id, user_id),
KEY post_id (post_id),
KEY user_id (user_id)
) $charset;";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta($sql);
// Migration for installs from v1.0-1.3: add object_type column if missing.
$col = $wpdb->get_var($wpdb->prepare(
"SHOW COLUMNS FROM `$table` LIKE %s", 'object_type'
));
if (!$col) {
$wpdb->query("ALTER TABLE `$table` ADD COLUMN object_type VARCHAR(20) NOT NULL DEFAULT 'post' AFTER id");
}
}
public static function register_routes() {
// Like a beep (post).
register_rest_route('beep/v1', '/like/(?P<id>\d+)', [
'methods' => 'POST',
'callback' => [__CLASS__, 'toggle_post_like'],
'permission_callback' => [__CLASS__, 'can_interact'],
]);
// Like a reply (comment).
register_rest_route('beep/v1', '/reply-like/(?P<id>\d+)', [
'methods' => 'POST',
'callback' => [__CLASS__, 'toggle_reply_like'],
'permission_callback' => [__CLASS__, 'can_interact'],
]);
}
public static function can_interact() {
return is_user_logged_in() && !beep_user_is_banned(get_current_user_id());
}
public static function toggle_post_like($request) {
$id = (int) $request['id'];
if (get_post_type($id) !== Beep_CPT::POST_TYPE) {
return new WP_Error('beep_not_a_beep', 'Not a beep.', ['status' => 400]);
}
return rest_ensure_response(self::toggle($id, 'post'));
}
public static function toggle_reply_like($request) {
$id = (int) $request['id'];
$c = get_comment($id);
if (!$c || get_post_type($c->comment_post_ID) !== Beep_CPT::POST_TYPE) {
return new WP_Error('beep_not_a_reply', 'Not a reply.', ['status' => 400]);
}
return rest_ensure_response(self::toggle($id, 'reply'));
}
/**
* Toggle a like for current user on the given object.
* @return array {liked: bool, count: int}
*/
public static function toggle($object_id, $object_type) {
global $wpdb;
$table = self::table_name();
$user_id = get_current_user_id();
$existing = $wpdb->get_var($wpdb->prepare(
"SELECT id FROM $table WHERE object_type = %s AND post_id = %d AND user_id = %d",
$object_type, $object_id, $user_id
));
if ($existing) {
$wpdb->delete($table, ['id' => $existing], ['%d']);
$liked = false;
} else {
$wpdb->insert($table, [
'object_type' => $object_type,
'post_id' => $object_id,
'user_id' => $user_id,
'created_at' => current_time('mysql'),
], ['%s', '%d', '%d', '%s']);
$liked = true;
}
return [
'liked' => $liked,
'count' => self::get_count($object_id, $object_type),
];
}
public static function get_count($object_id, $object_type = 'post') {
global $wpdb;
$table = self::table_name();
return (int) $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM $table WHERE object_type = %s AND post_id = %d",
$object_type, $object_id
));
}
public static function user_has_liked($object_id, $object_type = 'post', $user_id = null) {
global $wpdb;
if (!$user_id) {
$user_id = get_current_user_id();
}
if (!$user_id) {
return false;
}
$table = self::table_name();
return (bool) $wpdb->get_var($wpdb->prepare(
"SELECT id FROM $table WHERE object_type = %s AND post_id = %d AND user_id = %d",
$object_type, $object_id, $user_id
));
}
}