Restore to commit 74e578279624c6045ca440a3459ebfa1f8d54191
This commit is contained in:
342
chat/templates/Community Suggestions/includes/class-database.php
Normal file
342
chat/templates/Community Suggestions/includes/class-database.php
Normal file
@@ -0,0 +1,342 @@
|
||||
<?php
|
||||
class PC_Community_Suggestions_Database {
|
||||
|
||||
public static function create_tables() {
|
||||
global $wpdb;
|
||||
|
||||
error_log('PC Community Suggestions: create_tables called');
|
||||
|
||||
$charset_collate = $wpdb->get_charset_collate();
|
||||
|
||||
$suggestions_table = $wpdb->prefix . 'pc_community_suggestions';
|
||||
$votes_table = $wpdb->prefix . 'pc_community_votes';
|
||||
$comments_table = $wpdb->prefix . 'pc_community_comments';
|
||||
|
||||
error_log('PC Community Suggestions: Creating tables - ' . $suggestions_table . ', ' . $votes_table . ', ' . $comments_table);
|
||||
|
||||
// Suggestions table
|
||||
$sql_suggestions = "CREATE TABLE IF NOT EXISTS $suggestions_table (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
user_id BIGINT UNSIGNED NOT NULL,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
upvotes INT DEFAULT 0,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
KEY user_id (user_id),
|
||||
KEY created_at (created_at),
|
||||
KEY upvotes (upvotes)
|
||||
) $charset_collate;";
|
||||
|
||||
// Votes table
|
||||
$sql_votes = "CREATE TABLE IF NOT EXISTS $votes_table (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
suggestion_id BIGINT UNSIGNED NOT NULL,
|
||||
user_id BIGINT UNSIGNED NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY user_suggestion (user_id, suggestion_id),
|
||||
KEY suggestion_id (suggestion_id)
|
||||
) $charset_collate;";
|
||||
|
||||
// Comments table
|
||||
$sql_comments = "CREATE TABLE IF NOT EXISTS $comments_table (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
suggestion_id BIGINT UNSIGNED NOT NULL,
|
||||
admin_id BIGINT UNSIGNED NOT NULL,
|
||||
comment TEXT NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
KEY suggestion_id (suggestion_id),
|
||||
KEY admin_id (admin_id)
|
||||
) $charset_collate;";
|
||||
|
||||
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
||||
|
||||
// Clear any previous errors
|
||||
$wpdb->last_error = '';
|
||||
|
||||
// Create tables directly using dbDelta
|
||||
dbDelta($sql_suggestions);
|
||||
dbDelta($sql_votes);
|
||||
dbDelta($sql_comments);
|
||||
|
||||
// Log any errors for debugging
|
||||
if (!empty($wpdb->last_error)) {
|
||||
error_log('PC Community Suggestions Table Creation Error: ' . $wpdb->last_error);
|
||||
} else {
|
||||
error_log('PC Community Suggestions: Tables created without database errors');
|
||||
}
|
||||
|
||||
// Verify tables were created
|
||||
$tables_created = true;
|
||||
$tables_to_check = array($suggestions_table, $votes_table, $comments_table);
|
||||
|
||||
foreach ($tables_to_check as $table) {
|
||||
$exists = $wpdb->get_var("SHOW TABLES LIKE '$table'");
|
||||
if (!$exists) {
|
||||
error_log('PC Community Suggestions: Failed to create table ' . $table);
|
||||
$tables_created = false;
|
||||
} else {
|
||||
error_log('PC Community Suggestions: Table exists - ' . $table);
|
||||
}
|
||||
}
|
||||
|
||||
return $tables_created;
|
||||
}
|
||||
|
||||
public static function add_suggestion($user_id, $title, $content) {
|
||||
global $wpdb;
|
||||
|
||||
$table_name = $wpdb->prefix . 'pc_community_suggestions';
|
||||
|
||||
error_log('PC Community Suggestions: add_suggestion called, table: ' . $table_name);
|
||||
error_log('PC Community Suggestions: user_id=' . $user_id . ', title=' . substr($title, 0, 50));
|
||||
|
||||
// Check if table exists
|
||||
$table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'");
|
||||
if (!$table_exists) {
|
||||
error_log('PC Community Suggestions: Table does not exist - ' . $table_name);
|
||||
error_log('PC Community Suggestions: Creating tables now...');
|
||||
self::create_tables();
|
||||
|
||||
// Check again
|
||||
$table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'");
|
||||
if (!$table_exists) {
|
||||
error_log('PC Community Suggestions: Still cannot find table after creation attempt');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$result = $wpdb->insert(
|
||||
$table_name,
|
||||
array(
|
||||
'user_id' => $user_id,
|
||||
'title' => sanitize_text_field($title),
|
||||
'content' => wp_kses_post($content)
|
||||
),
|
||||
array('%d', '%s', '%s')
|
||||
);
|
||||
|
||||
if ($result === false) {
|
||||
error_log('PC Community Suggestions: Failed to insert suggestion - ' . $wpdb->last_error);
|
||||
return false;
|
||||
}
|
||||
|
||||
$insert_id = $wpdb->insert_id;
|
||||
error_log('PC Community Suggestions: Suggestion inserted with ID: ' . $insert_id);
|
||||
return $insert_id;
|
||||
}
|
||||
|
||||
public static function get_suggestions($page = 1, $per_page = 10, $sort = 'popular') {
|
||||
global $wpdb;
|
||||
|
||||
$table_name = $wpdb->prefix . 'pc_community_suggestions';
|
||||
$offset = ($page - 1) * $per_page;
|
||||
|
||||
$order_by = $sort === 'newest' ? 'created_at DESC' : 'upvotes DESC, created_at DESC';
|
||||
|
||||
$query = $wpdb->prepare(
|
||||
"SELECT s.*, u.user_login, u.display_name
|
||||
FROM $table_name s
|
||||
LEFT JOIN {$wpdb->users} u ON s.user_id = u.ID
|
||||
ORDER BY $order_by
|
||||
LIMIT %d OFFSET %d",
|
||||
$per_page,
|
||||
$offset
|
||||
);
|
||||
|
||||
return $wpdb->get_results($query);
|
||||
}
|
||||
|
||||
public static function get_suggestion_count() {
|
||||
global $wpdb;
|
||||
|
||||
$table_name = $wpdb->prefix . 'pc_community_suggestions';
|
||||
|
||||
return $wpdb->get_var("SELECT COUNT(*) FROM $table_name");
|
||||
}
|
||||
|
||||
public static function get_suggestion_by_id($suggestion_id) {
|
||||
global $wpdb;
|
||||
|
||||
$table_name = $wpdb->prefix . 'pc_community_suggestions';
|
||||
|
||||
return $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT s.*, u.user_login, u.display_name
|
||||
FROM $table_name s
|
||||
LEFT JOIN {$wpdb->users} u ON s.user_id = u.ID
|
||||
WHERE s.id = %d",
|
||||
$suggestion_id
|
||||
));
|
||||
}
|
||||
|
||||
public static function add_vote($suggestion_id, $user_id) {
|
||||
global $wpdb;
|
||||
|
||||
$votes_table = $wpdb->prefix . 'pc_community_votes';
|
||||
$suggestions_table = $wpdb->prefix . 'pc_community_suggestions';
|
||||
|
||||
// Check if user already voted
|
||||
$existing_vote = $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"SELECT COUNT(*) FROM $votes_table WHERE suggestion_id = %d AND user_id = %d",
|
||||
$suggestion_id,
|
||||
$user_id
|
||||
)
|
||||
);
|
||||
|
||||
if ($existing_vote > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$wpdb->query('START TRANSACTION');
|
||||
|
||||
// Add vote
|
||||
$vote_result = $wpdb->insert(
|
||||
$votes_table,
|
||||
array(
|
||||
'suggestion_id' => $suggestion_id,
|
||||
'user_id' => $user_id
|
||||
),
|
||||
array('%d', '%d')
|
||||
);
|
||||
|
||||
if (!$vote_result) {
|
||||
$wpdb->query('ROLLBACK');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update suggestion upvote count
|
||||
$update_result = $wpdb->query(
|
||||
$wpdb->prepare(
|
||||
"UPDATE $suggestions_table SET upvotes = upvotes + 1 WHERE id = %d",
|
||||
$suggestion_id
|
||||
)
|
||||
);
|
||||
|
||||
if (!$update_result) {
|
||||
$wpdb->query('ROLLBACK');
|
||||
return false;
|
||||
}
|
||||
|
||||
$wpdb->query('COMMIT');
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function get_user_vote_count($user_id) {
|
||||
global $wpdb;
|
||||
|
||||
$votes_table = $wpdb->prefix . 'pc_community_votes';
|
||||
|
||||
return $wpdb->get_var(
|
||||
$wpdb->prepare("SELECT COUNT(*) FROM $votes_table WHERE user_id = %d", $user_id)
|
||||
);
|
||||
}
|
||||
|
||||
public static function has_user_voted($suggestion_id, $user_id) {
|
||||
global $wpdb;
|
||||
|
||||
$votes_table = $wpdb->prefix . 'pc_community_votes';
|
||||
|
||||
return (bool) $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"SELECT COUNT(*) FROM $votes_table WHERE suggestion_id = %d AND user_id = %d",
|
||||
$suggestion_id,
|
||||
$user_id
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function add_comment($suggestion_id, $admin_id, $comment) {
|
||||
global $wpdb;
|
||||
|
||||
$comments_table = $wpdb->prefix . 'pc_community_comments';
|
||||
|
||||
return $wpdb->insert(
|
||||
$comments_table,
|
||||
array(
|
||||
'suggestion_id' => $suggestion_id,
|
||||
'admin_id' => $admin_id,
|
||||
'comment' => wp_kses_post($comment)
|
||||
),
|
||||
array('%d', '%d', '%s')
|
||||
);
|
||||
}
|
||||
|
||||
public static function get_comments($suggestion_id) {
|
||||
global $wpdb;
|
||||
|
||||
$comments_table = $wpdb->prefix . 'pc_community_comments';
|
||||
|
||||
return $wpdb->get_results($wpdb->prepare(
|
||||
"SELECT c.*, u.user_login, u.display_name
|
||||
FROM $comments_table c
|
||||
LEFT JOIN {$wpdb->users} u ON c.admin_id = u.ID
|
||||
WHERE c.suggestion_id = %d
|
||||
ORDER BY c.created_at ASC",
|
||||
$suggestion_id
|
||||
));
|
||||
}
|
||||
|
||||
public static function delete_comment($comment_id) {
|
||||
global $wpdb;
|
||||
|
||||
$comments_table = $wpdb->prefix . 'pc_community_comments';
|
||||
|
||||
return $wpdb->delete(
|
||||
$comments_table,
|
||||
array('id' => $comment_id),
|
||||
array('%d')
|
||||
);
|
||||
}
|
||||
|
||||
public static function delete_suggestion($suggestion_id) {
|
||||
global $wpdb;
|
||||
|
||||
$suggestions_table = $wpdb->prefix . 'pc_community_suggestions';
|
||||
$votes_table = $wpdb->prefix . 'pc_community_votes';
|
||||
$comments_table = $wpdb->prefix . 'pc_community_comments';
|
||||
|
||||
$wpdb->query('START TRANSACTION');
|
||||
|
||||
// Delete votes first
|
||||
$wpdb->delete($votes_table, array('suggestion_id' => $suggestion_id), array('%d'));
|
||||
|
||||
// Delete comments
|
||||
$wpdb->delete($comments_table, array('suggestion_id' => $suggestion_id), array('%d'));
|
||||
|
||||
// Delete suggestion
|
||||
$result = $wpdb->delete($suggestions_table, array('id' => $suggestion_id), array('%d'));
|
||||
|
||||
if ($result === false) {
|
||||
$wpdb->query('ROLLBACK');
|
||||
return false;
|
||||
}
|
||||
|
||||
$wpdb->query('COMMIT');
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function verify_tables() {
|
||||
global $wpdb;
|
||||
|
||||
$suggestions_table = $wpdb->prefix . 'pc_community_suggestions';
|
||||
$votes_table = $wpdb->prefix . 'pc_community_votes';
|
||||
$comments_table = $wpdb->prefix . 'pc_community_comments';
|
||||
|
||||
$tables_to_check = array($suggestions_table, $votes_table, $comments_table);
|
||||
$all_exist = true;
|
||||
|
||||
foreach ($tables_to_check as $table) {
|
||||
$exists = $wpdb->get_var("SHOW TABLES LIKE '$table'");
|
||||
if (!$exists) {
|
||||
error_log('PC Community Suggestions: Missing table ' . $table);
|
||||
$all_exist = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $all_exist;
|
||||
}
|
||||
}
|
||||
401
chat/templates/Community Suggestions/includes/class-rest-api.php
Normal file
401
chat/templates/Community Suggestions/includes/class-rest-api.php
Normal file
@@ -0,0 +1,401 @@
|
||||
<?php
|
||||
class PC_Community_Suggestions_REST_API {
|
||||
|
||||
public function __construct() {
|
||||
add_action('rest_api_init', array($this, 'register_routes'));
|
||||
add_action('wp_ajax_pc_submit_suggestion', array($this, 'handle_suggestion_submission'));
|
||||
add_action('wp_ajax_pc_vote_suggestion', array($this, 'handle_vote'));
|
||||
add_action('wp_ajax_pc_get_suggestion', array($this, 'handle_get_suggestion'));
|
||||
add_action('wp_ajax_pc_get_stats', array($this, 'handle_get_stats'));
|
||||
add_action('wp_ajax_pc_add_comment', array($this, 'handle_add_comment'));
|
||||
add_action('wp_ajax_pc_delete_comment', array($this, 'handle_delete_comment'));
|
||||
add_action('wp_ajax_nopriv_pc_submit_suggestion', array($this, 'handle_not_logged_in'));
|
||||
add_action('wp_ajax_nopriv_pc_vote_suggestion', array($this, 'handle_not_logged_in'));
|
||||
}
|
||||
|
||||
public function register_routes() {
|
||||
register_rest_route('pc-community-suggestions/v1', '/suggestions', array(
|
||||
'methods' => 'POST',
|
||||
'callback' => array($this, 'create_suggestion'),
|
||||
'permission_callback' => array($this, 'check_user_permission'),
|
||||
'args' => array(
|
||||
'title' => array(
|
||||
'required' => true,
|
||||
'validate_callback' => array($this, 'validate_title'),
|
||||
'sanitize_callback' => 'sanitize_text_field'
|
||||
),
|
||||
'content' => array(
|
||||
'required' => true,
|
||||
'validate_callback' => array($this, 'validate_content'),
|
||||
'sanitize_callback' => 'wp_kses_post'
|
||||
)
|
||||
)
|
||||
));
|
||||
|
||||
register_rest_route('pc-community-suggestions/v1', '/suggestions/(?P<id>\d+)/vote', array(
|
||||
'methods' => 'POST',
|
||||
'callback' => array($this, 'vote_suggestion'),
|
||||
'permission_callback' => array($this, 'check_user_permission'),
|
||||
'args' => array(
|
||||
'id' => array(
|
||||
'required' => true,
|
||||
'validate_callback' => array($this, 'validate_suggestion_id')
|
||||
)
|
||||
)
|
||||
));
|
||||
|
||||
register_rest_route('pc-community-suggestions/v1', '/suggestions', array(
|
||||
'methods' => 'GET',
|
||||
'callback' => array($this, 'get_suggestions'),
|
||||
'permission_callback' => '__return_true',
|
||||
'args' => array(
|
||||
'page' => array(
|
||||
'default' => 1,
|
||||
'validate_callback' => array($this, 'validate_page')
|
||||
),
|
||||
'per_page' => array(
|
||||
'default' => 10,
|
||||
'validate_callback' => array($this, 'validate_per_page')
|
||||
),
|
||||
'sort' => array(
|
||||
'default' => 'popular',
|
||||
'validate_callback' => array($this, 'validate_sort')
|
||||
)
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
public function check_user_permission() {
|
||||
return is_user_logged_in();
|
||||
}
|
||||
|
||||
public function validate_title($title) {
|
||||
$title = sanitize_text_field($title);
|
||||
return !empty($title) && strlen($title) <= 255;
|
||||
}
|
||||
|
||||
public function validate_content($content) {
|
||||
$content = wp_kses_post($content);
|
||||
return !empty($content) && strlen($content) >= 10;
|
||||
}
|
||||
|
||||
public function validate_suggestion_id($id) {
|
||||
return is_numeric($id) && $id > 0;
|
||||
}
|
||||
|
||||
public function validate_page($page) {
|
||||
return is_numeric($page) && $page > 0;
|
||||
}
|
||||
|
||||
public function validate_per_page($per_page) {
|
||||
return is_numeric($per_page) && $per_page > 0 && $per_page <= 50;
|
||||
}
|
||||
|
||||
public function validate_sort($sort) {
|
||||
return in_array($sort, array('popular', 'newest'));
|
||||
}
|
||||
|
||||
public function create_suggestion(WP_REST_Request $request) {
|
||||
$title = $request->get_param('title');
|
||||
$content = $request->get_param('content');
|
||||
$user_id = get_current_user_id();
|
||||
|
||||
// Check for duplicate submissions
|
||||
$existing = $this->check_duplicate_suggestion($user_id, $title);
|
||||
if ($existing) {
|
||||
return new WP_Error('duplicate', __('You have already submitted a similar suggestion.', 'pc-community-suggestions-7d3f'), array('status' => 400));
|
||||
}
|
||||
|
||||
$suggestion_id = PC_Community_Suggestions_Database::add_suggestion($user_id, $title, $content);
|
||||
|
||||
if (!$suggestion_id) {
|
||||
return new WP_Error('database_error', __('Failed to create suggestion.', 'pc-community-suggestions-7d3f'), array('status' => 500));
|
||||
}
|
||||
|
||||
return rest_ensure_response(array(
|
||||
'success' => true,
|
||||
'suggestion_id' => $suggestion_id,
|
||||
'message' => __('Your suggestion has been published successfully.', 'pc-community-suggestions-7d3f')
|
||||
));
|
||||
}
|
||||
|
||||
private function check_duplicate_suggestion($user_id, $title) {
|
||||
global $wpdb;
|
||||
|
||||
$table_name = $wpdb->prefix . 'pc_community_suggestions';
|
||||
$similar_title = '%' . $wpdb->esc_like($title) . '%';
|
||||
|
||||
$count = $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"SELECT COUNT(*) FROM $table_name WHERE user_id = %d AND title LIKE %s AND created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)",
|
||||
$user_id,
|
||||
$similar_title
|
||||
)
|
||||
);
|
||||
|
||||
return $count > 0;
|
||||
}
|
||||
|
||||
public function vote_suggestion(WP_REST_Request $request) {
|
||||
$suggestion_id = $request->get_param('id');
|
||||
$user_id = get_current_user_id();
|
||||
|
||||
$result = PC_Community_Suggestions_Database::add_vote($suggestion_id, $user_id);
|
||||
|
||||
if (!$result) {
|
||||
return new WP_Error('already_voted', __('You have already voted for this suggestion.', 'pc-community-suggestions-7d3f'), array('status' => 400));
|
||||
}
|
||||
|
||||
return rest_ensure_response(array(
|
||||
'success' => true,
|
||||
'message' => __('Vote recorded successfully.', 'pc-community-suggestions-7d3f')
|
||||
));
|
||||
}
|
||||
|
||||
public function get_suggestions(WP_REST_Request $request) {
|
||||
$page = $request->get_param('page');
|
||||
$per_page = $request->get_param('per_page');
|
||||
$sort = $request->get_param('sort');
|
||||
|
||||
$suggestions = PC_Community_Suggestions_Database::get_suggestions($page, $per_page, $sort);
|
||||
$total = PC_Community_Suggestions_Database::get_suggestion_count();
|
||||
|
||||
$formatted_suggestions = array();
|
||||
foreach ($suggestions as $suggestion) {
|
||||
$formatted_suggestions[] = array(
|
||||
'id' => $suggestion->id,
|
||||
'title' => $suggestion->title,
|
||||
'content' => $suggestion->content,
|
||||
'upvotes' => $suggestion->upvotes,
|
||||
'author' => $suggestion->display_name ?: $suggestion->user_login,
|
||||
'created_at' => $suggestion->created_at,
|
||||
'human_date' => human_time_diff(strtotime($suggestion->created_at), current_time('timestamp'))
|
||||
);
|
||||
}
|
||||
|
||||
return rest_ensure_response(array(
|
||||
'suggestions' => $formatted_suggestions,
|
||||
'pagination' => array(
|
||||
'current_page' => $page,
|
||||
'per_page' => $per_page,
|
||||
'total' => $total,
|
||||
'total_pages' => ceil($total / $per_page)
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
public function handle_suggestion_submission() {
|
||||
error_log('PC Community Suggestions: handle_suggestion_submission called');
|
||||
|
||||
$nonce = isset($_POST['nonce']) ? $_POST['nonce'] : '';
|
||||
error_log('PC Community Suggestions: Nonce value: ' . substr($nonce, 0, 20) . '...');
|
||||
|
||||
if (!check_ajax_referer('pc_community_suggestions_nonce', 'nonce', false)) {
|
||||
error_log('PC Community Suggestions: Nonce check failed');
|
||||
wp_send_json_error(array('message' => __('Security check failed. Please try again.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
if (!is_user_logged_in()) {
|
||||
error_log('PC Community Suggestions: User not logged in');
|
||||
wp_send_json_error(array('message' => __('You must be logged in to submit suggestions.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
$title = isset($_POST['title']) ? sanitize_text_field($_POST['title']) : '';
|
||||
$content = isset($_POST['content']) ? wp_kses_post($_POST['content']) : '';
|
||||
|
||||
error_log('PC Community Suggestions: Title length: ' . strlen($title) . ', Content length: ' . strlen($content));
|
||||
|
||||
if (empty($title) || empty($content)) {
|
||||
wp_send_json_error(array('message' => __('Please fill in all required fields.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
if (strlen($title) > 255) {
|
||||
wp_send_json_error(array('message' => __('Title must be less than 255 characters.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
if (strlen($content) < 10) {
|
||||
wp_send_json_error(array('message' => __('Content must be at least 10 characters long.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
error_log('PC Community Suggestions: User ID: ' . $user_id);
|
||||
|
||||
try {
|
||||
$existing = $this->check_duplicate_suggestion($user_id, $title);
|
||||
if ($existing) {
|
||||
error_log('PC Community Suggestions: Duplicate suggestion detected');
|
||||
wp_send_json_error(array('message' => __('You have already submitted a similar suggestion recently.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
if (!PC_Community_Suggestions_Database::verify_tables()) {
|
||||
error_log('PC Community Suggestions: Tables do not exist, creating...');
|
||||
PC_Community_Suggestions_Database::create_tables();
|
||||
}
|
||||
|
||||
$suggestion_id = PC_Community_Suggestions_Database::add_suggestion($user_id, $title, $content);
|
||||
|
||||
if (!$suggestion_id) {
|
||||
global $wpdb;
|
||||
$last_error = $wpdb->last_error;
|
||||
error_log('PC Community Suggestions DB Error: ' . $last_error);
|
||||
wp_send_json_error(array('message' => __('Failed to submit suggestion. Database error.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
error_log('PC Community Suggestions: Suggestion created successfully with ID: ' . $suggestion_id);
|
||||
wp_send_json_success(array(
|
||||
'message' => __('Your suggestion has been published successfully.', 'pc-community-suggestions-7d3f')
|
||||
));
|
||||
} catch (Exception $e) {
|
||||
error_log('PC Community Suggestions Exception: ' . $e->getMessage());
|
||||
wp_send_json_error(array('message' => __('An error occurred: ', 'pc-community-suggestions-7d3f') . $e->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public function handle_vote() {
|
||||
if (!check_ajax_referer('pc_community_suggestions_nonce', 'nonce', false)) {
|
||||
wp_send_json_error(array('message' => __('Security check failed. Please try again.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
if (!is_user_logged_in()) {
|
||||
wp_send_json_error(array('message' => __('You must be logged in to vote.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
$suggestion_id = isset($_POST['suggestion_id']) ? intval($_POST['suggestion_id']) : 0;
|
||||
$user_id = get_current_user_id();
|
||||
|
||||
if ($suggestion_id <= 0) {
|
||||
wp_send_json_error(array('message' => __('Invalid suggestion.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
$result = PC_Community_Suggestions_Database::add_vote($suggestion_id, $user_id);
|
||||
|
||||
if (!$result) {
|
||||
wp_send_json_error(array('message' => __('You have already voted for this suggestion.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
wp_send_json_success(array('message' => __('Vote recorded successfully.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
public function handle_not_logged_in() {
|
||||
wp_send_json_error(array('message' => __('You must be logged in to perform this action.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
public function handle_get_suggestion() {
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error(array('message' => __('You do not have permission to view this suggestion.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
if (!check_ajax_referer('pc_admin_nonce', 'nonce', false)) {
|
||||
wp_send_json_error(array('message' => __('Security check failed. Please try again.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
$suggestion_id = isset($_POST['suggestion_id']) ? intval($_POST['suggestion_id']) : 0;
|
||||
|
||||
if ($suggestion_id <= 0) {
|
||||
wp_send_json_error(array('message' => __('Invalid suggestion ID.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'pc_community_suggestions';
|
||||
|
||||
$suggestion = $wpdb->get_row(
|
||||
$wpdb->prepare(
|
||||
"SELECT s.*, u.user_login, u.display_name
|
||||
FROM $table_name s
|
||||
LEFT JOIN {$wpdb->users} u ON s.user_id = u.ID
|
||||
WHERE s.id = %d",
|
||||
$suggestion_id
|
||||
)
|
||||
);
|
||||
|
||||
if (!$suggestion) {
|
||||
wp_send_json_error(array('message' => __('Suggestion not found.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
wp_send_json_success(array(
|
||||
'id' => $suggestion->id,
|
||||
'title' => $suggestion->title,
|
||||
'content' => wpautop($suggestion->content),
|
||||
'author' => $suggestion->display_name ?: $suggestion->user_login,
|
||||
'date' => date_i18n(get_option('date_format'), strtotime($suggestion->created_at)),
|
||||
'upvotes' => $suggestion->upvotes,
|
||||
));
|
||||
}
|
||||
|
||||
public function handle_get_stats() {
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error(array('message' => __('You do not have permission to view statistics.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
if (!check_ajax_referer('pc_admin_nonce', 'nonce', false)) {
|
||||
wp_send_json_error(array('message' => __('Security check failed. Please try again.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
wp_send_json_success(array(
|
||||
'total' => PC_Community_Suggestions_Database::get_suggestion_count()
|
||||
));
|
||||
}
|
||||
|
||||
public function handle_add_comment() {
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error(array('message' => __('You do not have permission to add comments.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
if (!check_ajax_referer('pc_admin_nonce', 'nonce', false)) {
|
||||
wp_send_json_error(array('message' => __('Security check failed. Please try again.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
$suggestion_id = isset($_POST['suggestion_id']) ? intval($_POST['suggestion_id']) : 0;
|
||||
$comment = isset($_POST['comment']) ? wp_kses_post($_POST['comment']) : '';
|
||||
$admin_id = get_current_user_id();
|
||||
|
||||
if ($suggestion_id <= 0 || empty($comment)) {
|
||||
wp_send_json_error(array('message' => __('Invalid data provided.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
$comment_id = PC_Community_Suggestions_Database::add_comment($suggestion_id, $admin_id, $comment);
|
||||
|
||||
if (!$comment_id) {
|
||||
wp_send_json_error(array('message' => __('Failed to add comment.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
$admin = get_userdata($admin_id);
|
||||
$admin_name = $admin->display_name ?: $admin->user_login;
|
||||
|
||||
wp_send_json_success(array(
|
||||
'message' => __('Comment added successfully.', 'pc-community-suggestions-7d3f'),
|
||||
'comment' => array(
|
||||
'id' => $comment_id,
|
||||
'content' => wpautop($comment),
|
||||
'author' => $admin_name,
|
||||
'date' => date_i18n(get_option('date_format'), current_time('timestamp'))
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
public function handle_delete_comment() {
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error(array('message' => __('You do not have permission to delete comments.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
if (!check_ajax_referer('pc_admin_nonce', 'nonce', false)) {
|
||||
wp_send_json_error(array('message' => __('Security check failed. Please try again.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
$comment_id = isset($_POST['comment_id']) ? intval($_POST['comment_id']) : 0;
|
||||
|
||||
if ($comment_id <= 0) {
|
||||
wp_send_json_error(array('message' => __('Invalid comment ID.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
$result = PC_Community_Suggestions_Database::delete_comment($comment_id);
|
||||
|
||||
if (!$result) {
|
||||
wp_send_json_error(array('message' => __('Failed to delete comment.', 'pc-community-suggestions-7d3f')));
|
||||
}
|
||||
|
||||
wp_send_json_success(array(
|
||||
'message' => __('Comment deleted successfully.', 'pc-community-suggestions-7d3f')
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
<?php
|
||||
class PC_Community_Suggestions_Shortcodes {
|
||||
|
||||
public function __construct() {
|
||||
add_shortcode('community_suggestions', array($this, 'render_suggestions_page'));
|
||||
}
|
||||
|
||||
public function render_suggestions_page($atts) {
|
||||
$current_suggestion = isset($_GET['suggestion']) ? intval($_GET['suggestion']) : 0;
|
||||
|
||||
ob_start();
|
||||
|
||||
if ($current_suggestion > 0) {
|
||||
$this->render_suggestion_detail($current_suggestion);
|
||||
} else {
|
||||
$this->render_suggestions_interface();
|
||||
}
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
private function render_suggestion_detail($suggestion_id) {
|
||||
$suggestion = PC_Community_Suggestions_Database::get_suggestion_by_id($suggestion_id);
|
||||
$comments = $suggestion ? PC_Community_Suggestions_Database::get_comments($suggestion_id) : array();
|
||||
|
||||
if (!$suggestion) {
|
||||
echo '<div class="pc-suggestions-card">';
|
||||
echo '<p>' . esc_html__('Suggestion not found.', 'pc-community-suggestions-7d3f') . '</p>';
|
||||
echo '<a href="' . esc_url(remove_query_arg('suggestion')) . '" class="pc-button">' . esc_html__('Back to Suggestions', 'pc-community-suggestions-7d3f') . '</a>';
|
||||
echo '</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<div class="pc-suggestions-container">
|
||||
<div class="pc-suggestions-header">
|
||||
<a href="<?php echo esc_url(remove_query_arg('suggestion')); ?>" class="pc-back-link">
|
||||
← <?php esc_html_e('Back to Suggestions', 'pc-community-suggestions-7d3f'); ?>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="pc-suggestion-detail">
|
||||
<?php $this->render_suggestion_card($suggestion, true); ?>
|
||||
|
||||
<div class="pc-comments-section">
|
||||
<h3><?php esc_html_e('Admin Comments', 'pc-community-suggestions-7d3f'); ?></h3>
|
||||
|
||||
<?php if (empty($comments)) : ?>
|
||||
<p class="pc-no-comments"><?php esc_html_e('No admin comments yet.', 'pc-community-suggestions-7d3f'); ?></p>
|
||||
<?php else : ?>
|
||||
<?php foreach ($comments as $comment) : ?>
|
||||
<div class="pc-comment-card">
|
||||
<div class="pc-comment-header">
|
||||
<span class="pc-comment-author"><?php echo esc_html($comment->display_name ?: $comment->user_login); ?></span>
|
||||
<span class="pc-comment-date">
|
||||
<?php echo date_i18n(get_option('date_format'), strtotime($comment->created_at)); ?>
|
||||
</span>
|
||||
</div>
|
||||
<div class="pc-comment-content">
|
||||
<?php echo wp_kses_post(wpautop($comment->comment)); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function render_suggestions_interface() {
|
||||
$current_page = max(1, get_query_var('paged', 1));
|
||||
$sort = isset($_GET['sort']) && in_array($_GET['sort'], ['popular', 'newest']) ? $_GET['sort'] : 'popular';
|
||||
$per_page = 10;
|
||||
|
||||
$suggestions = PC_Community_Suggestions_Database::get_suggestions($current_page, $per_page, $sort);
|
||||
$total_suggestions = PC_Community_Suggestions_Database::get_suggestion_count();
|
||||
$total_pages = ceil($total_suggestions / $per_page);
|
||||
|
||||
?>
|
||||
<div class="pc-community-suggestions-container">
|
||||
<div class="pc-suggestions-header">
|
||||
<div class="pc-suggestions-controls">
|
||||
<?php if (is_user_logged_in()) : ?>
|
||||
<button class="pc-button pc-button-primary" onclick="pcToggleSuggestionForm()">
|
||||
<?php esc_html_e('Add Suggestion', 'pc-community-suggestions-7d3f'); ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
<div class="pc-sort-dropdown">
|
||||
<select onchange="pcChangeSort(this.value)">
|
||||
<option value="popular" <?php selected($sort, 'popular'); ?>><?php esc_html_e('Most Upvoted', 'pc-community-suggestions-7d3f'); ?></option>
|
||||
<option value="newest" <?php selected($sort, 'newest'); ?>><?php esc_html_e('Newest', 'pc-community-suggestions-7d3f'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (is_user_logged_in()) : ?>
|
||||
<div id="pc-suggestion-form" class="pc-suggestion-form" style="display: none;">
|
||||
<div class="pc-form-card">
|
||||
<h3><?php esc_html_e('Add Your Suggestion', 'pc-community-suggestions-7d3f'); ?></h3>
|
||||
<form id="pc-new-suggestion-form">
|
||||
<div class="pc-form-group">
|
||||
<label for="pc-suggestion-title"><?php esc_html_e('Title', 'pc-community-suggestions-7d3f'); ?></label>
|
||||
<input type="text" id="pc-suggestion-title" name="title" required maxlength="255">
|
||||
</div>
|
||||
<div class="pc-form-group">
|
||||
<label for="pc-suggestion-content"><?php esc_html_e('Details', 'pc-community-suggestions-7d3f'); ?></label>
|
||||
<textarea id="pc-suggestion-content" name="content" rows="5" required></textarea>
|
||||
</div>
|
||||
<div class="pc-form-actions">
|
||||
<button type="button" class="pc-button" onclick="pcToggleSuggestionForm()">
|
||||
<?php esc_html_e('Cancel', 'pc-community-suggestions-7d3f'); ?>
|
||||
</button>
|
||||
<button type="submit" class="pc-button pc-button-primary">
|
||||
<?php esc_html_e('Submit Suggestion', 'pc-community-suggestions-7d3f'); ?>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="pc-suggestions-list">
|
||||
<?php if (empty($suggestions)) : ?>
|
||||
<div class="pc-no-suggestions">
|
||||
<p><?php esc_html_e('No suggestions yet. Be the first to share your idea!', 'pc-community-suggestions-7d3f'); ?></p>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<?php foreach ($suggestions as $suggestion) : ?>
|
||||
<?php $this->render_suggestion_card($suggestion); ?>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($total_pages > 1) : ?>
|
||||
<div class="pc-suggestions-pagination">
|
||||
<?php
|
||||
echo paginate_links(array(
|
||||
'base' => get_pagenum_link(1) . '%_%',
|
||||
'format' => 'page/%#%/',
|
||||
'current' => $current_page,
|
||||
'total' => $total_pages,
|
||||
'prev_text' => __('« Previous', 'pc-community-suggestions-7d3f'),
|
||||
'next_text' => __('Next »', 'pc-community-suggestions-7d3f'),
|
||||
'add_args' => array('sort' => $sort)
|
||||
));
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function render_suggestion_card($suggestion, $detail_view = false) {
|
||||
$user_has_voted = is_user_logged_in() ? PC_Community_Suggestions_Database::has_user_voted($suggestion->id, get_current_user_id()) : false;
|
||||
$vote_class = $user_has_voted ? 'pc-voted' : '';
|
||||
|
||||
if ($detail_view) {
|
||||
$vote_button_html = '';
|
||||
} else {
|
||||
$vote_button_html = 'onclick="pcVoteSuggestion(' . esc_attr($suggestion->id) . ')"';
|
||||
}
|
||||
|
||||
?>
|
||||
<div class="pc-suggestion-card <?php echo $detail_view ? 'pc-suggestion-card-detail' : ''; ?>" data-suggestion-id="<?php echo esc_attr($suggestion->id); ?>">
|
||||
<div class="pc-suggestion-vote">
|
||||
<?php if (is_user_logged_in()) : ?>
|
||||
<button class="pc-vote-button <?php echo esc_attr($vote_class); ?>"
|
||||
<?php echo $vote_button_html; ?>
|
||||
<?php echo $user_has_voted || $detail_view ? 'disabled' : ''; ?>>
|
||||
<span class="pc-vote-arrow">↑</span>
|
||||
<span class="pc-vote-count"><?php echo esc_html($suggestion->upvotes); ?></span>
|
||||
</button>
|
||||
<?php else : ?>
|
||||
<div class="pc-vote-button pc-vote-disabled">
|
||||
<span class="pc-vote-arrow">↑</span>
|
||||
<span class="pc-vote-count"><?php echo esc_html($suggestion->upvotes); ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="pc-suggestion-content">
|
||||
<h3 class="pc-suggestion-title">
|
||||
<?php if (!$detail_view) : ?>
|
||||
<a href="<?php echo esc_url(add_query_arg('suggestion', $suggestion->id, get_permalink())); ?>">
|
||||
<?php echo esc_html($suggestion->title); ?>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<?php echo esc_html($suggestion->title); ?>
|
||||
<?php endif; ?>
|
||||
</h3>
|
||||
<div class="pc-suggestion-body">
|
||||
<?php
|
||||
if ($detail_view) {
|
||||
echo wp_kses_post(wpautop($suggestion->content));
|
||||
} else {
|
||||
echo wp_kses_post(wpautop(wp_trim_words($suggestion->content, 30, '...')));
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php if (!$detail_view) : ?>
|
||||
<div class="pc-suggestion-actions">
|
||||
<a href="<?php echo esc_url(add_query_arg('suggestion', $suggestion->id, get_permalink())); ?>"
|
||||
class="pc-button pc-button-small">
|
||||
<?php esc_html_e('View Details', 'pc-community-suggestions-7d3f'); ?>
|
||||
</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="pc-suggestion-meta">
|
||||
<span class="pc-suggestion-author">
|
||||
<?php
|
||||
printf(
|
||||
__('By %s', 'pc-community-suggestions-7d3f'),
|
||||
esc_html($suggestion->display_name ?: $suggestion->user_login)
|
||||
);
|
||||
?>
|
||||
</span>
|
||||
<span class="pc-suggestion-date">
|
||||
<?php echo human_time_diff(strtotime($suggestion->created_at), current_time('timestamp')) . ' ' . __('ago', 'pc-community-suggestions-7d3f'); ?>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user