I have a WordPress website in which I list down all the users (based on MemberPress subscription), and users can save other users as favorites. The function works well when saving a user as favorite, it stores and updates as it should, and it's retreived when I check on a different place/browser.
But removing a user as favorite doesn't work. Here is what happens:
-
One page load, when I click on 'remove from favorites', it acts like I clicked on 'save to favorites', the text 'remove from favorites' doesn't change. On a second click on the same 'remove from favorites', the text changes, and the button is updated, it seems everything goes well accoding to the log, but on page reload, nothing is saved, and it's back to 'remove from favorites'.
-
A different situation, on page load, I click on 'save to favorites' of one user, and 'save to favorites' of another one afterwards, it seems to be fine. But on page reload, only the second one is actually saved, the first one is back to 'save to favorites'. Same goes for when i click on 3 or more 'save to favorites', and reload the page, only the last one is saved.
This is my users list in PHP
function display_users($args = array(), $show_all_users = true)
{
$default_args = array(
'orderby' => 'name',
'order' => 'ASC',
'role' => 'subscriber',
'search' => '',
);
$args = wp_parse_args($args, $default_args);
$wp_user_query = new WP_User_Query($args);
if (!empty($wp_user_query->results)) {
$output = '<div class="user-grid">';
foreach ($wp_user_query->results as $user) {
$mepr_user = new MeprUser($user->ID);
if (empty($mepr_user->active_product_subscriptions('ids'))) {
continue;
}
// Check if only favorites should be displayed
if (!$show_all_users) {
$user_id = get_current_user_id();
$favorites = get_user_meta($user_id, 'favorites', true);
if (!in_array($user->ID, $favorites)) {
// If user is not in favorites list, skip to the next user
continue;
}
}
$output .= '<div class="user">';
$output .= '<a href="' . get_author_posts_url($user->ID) . '">';
if (get_field('mepr_avatar_profile', 'user_' . $user->ID)) {
$avatar = get_field('mepr_avatar_profile', 'user_' . $user->ID);
$class = 'user-image-bw';
} else {
$avatar = '/wp-content/uploads/2023/04/new-color-community-1.png';
$class = 'default-image-avatar';
}
$output .= '<div class="user-image">';
$output .= '<img class="' . $class . '" src="' . esc_url($avatar) . '" alt="Author Avatar" />';
$output .= '</div>';
if (get_field('mepr_open_to_connect', 'user_' . $user->ID) == 'always-feel-free-to-reach-out') {
$output .= '<p class="user-connect">Let\'s connect</p>';
}
$output .= '<div class="user-name">' . get_field('first_name', 'user_' . $user->ID) . '</div>';
$output .= '<div class="user-info">';
$current_work = get_field('mepr_current_work', 'user_' . $user->ID)[0];
$current_work = str_replace('-', ' ', $current_work);
$output .= '<p class="user-current-work">' . $current_work . '</p>';
$output .= '</div>';
$output .= '</a>';
// Add favorite button
if (is_user_logged_in()) {
$user_id = get_current_user_id();
$favorites = get_user_meta($user_id, 'favorites', true);
if (!is_array($favorites)) {
$favorites = array(); // set $favorites to an empty array if it is not already an array
}
$nonce = wp_create_nonce('save_user_favorites');
$output .= '<button class="favorite-button" data-user-id="' . $user->ID . '" data-favorites="' . esc_attr(json_encode($favorites)) . '" data-is-favorite="' . (in_array($user->ID, $favorites) ? 'true' : 'false') . '" data-nonce="' . $nonce . '">' . (in_array($user->ID, $favorites) ? 'Remove from favorites' : 'Add to favorites') . '</button>';
}
$output .= '</div>';
}
$output .= '</div>';
} else {
$output = '<p>No users found.</p>';
}
return $output;
}
This is my PHP add to favorites function
// save favorites function
function save_user_favorites() {
if (!isset($_POST['favorites'])) {
wp_send_json_error('Favorites not provided');
}
// Verify nonce
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'save_user_favorites')) {
wp_send_json_error('Invalid nonce');
}
// Check if user is logged in
if (!is_user_logged_in()) {
wp_send_json_error('User not logged in');
}
// Get user ID
$user_id = get_current_user_id();
// Get favorites
$favorites = isset($_POST['favorites']) ? $_POST['favorites'] : array();
// Update user meta
update_user_meta($user_id, 'favorites', $favorites);
wp_send_json_success();
}
add_action( 'wp_ajax_nopriv_save_user_favorites', 'save_user_favorites' );
add_action( 'wp_ajax_save_user_favorites', 'save_user_favorites');
This is my jQuery
$('.favorite-button').click(function(e) {
e.preventDefault();
var button = $(this);
var userId = button.data('userId');
var nonce = button.data('nonce');
// get existing favorites from the data attribute of the button
var favorites = button.data('favorites') || [];
// Add or remove user from favorites
if (userId !== "") {
const indexToRemove = favorites.indexOf(userId);
if (!favorites.includes(userId)) {
favorites.push(userId);
console.log(`User ${userId} added to favorites.`);
} else {
favorites.splice(indexToRemove, 1);
console.log(`User ${userId} removed from favorites.`);
}
// Save favorites to the user metadata via AJAX
$.post(ajaxurl, {
'action': 'save_user_favorites',
'favorites': favorites,
'nonce': nonce,
'user_id': userId // add user ID to request parameters,
})
.done(function(response) {
console.log('Favorites saved:', response);
// update the favorites attribute of the button
button.data('favorites', favorites);
})
.fail(function(xhr, status, error) {
console.log('Failed to save favorites:', error);
console.log('Server response:', xhr.responseText);
});
} else {
console.log(`Cannot add/remove user with empty ID`);
}
// Toggle button text and data attribute
button.text(favorites.includes(userId) ? 'Remove from favorites' : 'Add to favorites');
});
Trying in a different way
I've also tried a different way for the ajax request, by first storing it as localstorage, and updating the list of favorites on page reload. This worked really well, and as it should (adding/removing users), but I get an error on page reload when it tries to store it in favorites (not localstorage).
What happens on reload is that it's not actualy saved on the server side, only locally, and I get an ouput like this on the console:
from the update user Array []
from the update user Array []
from the update user Array []
from the update user Array(4) [ 420, 442, 449, 447 ]
from the update user Array []
And that keeps going, with only an array with values of the ones I saved. Next to it, it says, also a lot of times in firefox:
Failed to save favorites:
Server response: undefined
Failed to save favorites:
Server response: undefined
In chrome:
Favorites saved: {success: false, data: 'Favorites not provided'}
data: "Favorites not provided"
success: false
[[Prototype]]: Object
This is my other jQuery that could be used instead of the above, for first saving it locally
// get existing favorites from localStorage, or initialize to empty array
var favorites = JSON.parse(localStorage.getItem('favorites') || '[]');
$('.favorite-button').click(function(e) {
e.preventDefault();
var button = $(this);
var userId = button.data('userId');
// Add or remove user from favorites if userId is not empty
if (userId !== "") {
var isFavorite = button.data('isFavorite');
var nonce = button.data('nonce');
const userIdToRemove = userId; // Replace with the actual user ID you want to remove
const indexToRemove = favorites.indexOf(userIdToRemove);
// Add or remove user from favorites
if (!favorites.includes(userId)) {
favorites.push(userId);
console.log('user added to favorites')
} else {
favorites.splice(indexToRemove, 1);
console.log('user deleted from favorites')
}
// Save favorites to localStorage
localStorage.setItem('favorites', JSON.stringify(favorites));
// Save favorites to user metadata
$.post(ajaxurl, {
'action': 'save_user_favorites',
'favorites': favorites,
'nonce': nonce,
'user_id': userId // add user ID to request parameters
})
.done(function(response) {
console.log('Favorites saved:', response);
})
.fail(function(xhr, status, error) {
console.log('Failed to save favorites:', error);
console.log('Server response:', xhr.responseText);
});
update_local_storage(userId, favorites)
console.log('favorites saved to local storage', favorites)
// Toggle button text and data attribute
button.text(favorites.includes(userId) ? 'Remove from favorites' : 'Add to favorites');
}
});
// on page load, update button text based on stored favorites
$('.favorite-button').each(function() {
var button = $(this);
var userId = button.data('userId');
var isFavorite = button.data('isFavorite');
// check if user is in favorites
var favorites = JSON.parse(localStorage.getItem('favorites') || '[]');
var isUserFavorite = favorites.includes(userId);
// set button text and data attribute based on result
button.text(isUserFavorite ? 'Remove from favorites' : 'Add to favorites');
button.data('isFavorite', isUserFavorite);
button.data('favorites', favorites);
});
// function to store favorites in localStorage
function update_local_storage(user_id, favorites) {
localStorage.setItem('favorites_' + user_id, JSON.stringify(favorites));
// console.log('localstorage', favorites)
}
function update_user_favorites(user_id, favorites, nonce) {
console.log('from the update user', favorites)
$.post(ajaxurl, {
'action': 'save_user_favorites',
'favorites': favorites,
'nonce': nonce,
'user_id': user_id // Use the user_id parameter instead of userId
})
.done(function(response) {
console.log('Favorites saved:', response);
})
.fail(function(xhr, status, error) {
console.log('Failed to save favorites:', error);
console.log('Server response:', xhr.responseText);
});
}
// update user metadata when page is unloaded
$(window).on('beforeunload', function() {
$('.favorite-button').each(function() {
var user_id = $(this).data('userId');
var nonce = $(this).data('nonce');
var favorites = JSON.parse(localStorage.getItem('favorites_' + user_id) || '[]');
// var favorites = [ 449, 487, 442, 474, 488, 457, 553, 559, 841]
// console.log({favorites})
update_user_favorites(user_id, favorites, nonce);
});
});
I've tried logging each step, and everytime is seems like the data is passed correctly, and I can't find out why it's not working. Any suggestions?
from How to update my jquery/PHP function to add/remove user as favorites in (WordPress) users list
No comments:
Post a Comment