ccead50116
- Custom post type with likes, replies, moderation, shortcodes - Beep icon and logo assets - CSS and JS for frontend
145 lines
4.9 KiB
PHP
Executable File
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
|
|
));
|
|
}
|
|
}
|