/** * Clears any notifications for the specified user for the specified achievement. * * @param int $post_id int Optional. The post ID of the achievement to clear the notification for. * @param int $user_id int Optional. The ID for the user. * @since Achievements (3.0) */ function dpa_clear_notification($post_id = 0, $user_id = 0) { // Default to current user if (empty($user_id) && is_user_logged_in()) { $user_id = get_current_user_id(); } // Default to current post if (empty($post_id) && is_single()) { $post_id = get_the_ID(); } // No user or post ID to check if (empty($user_id) || empty($post_id)) { return; } // The notifications array is keyed by the achievement (post) ID. $notifications = dpa_get_user_notifications($user_id); // Is there a notification to clear? if (!isset($notifications[$post_id])) { return; } // Clear the notification unset($notifications[$post_id]); dpa_update_user_notifications($notifications, $user_id); // Tell other plugins that we've just cleared other plugins do_action('dpa_clear_notification', $post_id, $user_id); }
/** * The PHP side of Achievements' live notifications system using WordPress 3.6's heartbeat API; we grab the image, * post ID, permalink, and title of all achievements that have recently been unlocked, and send that back using * WordPress' heartbeat_recieved filter. * * The heartbeat JS makes periodic AJAX connections back to WordPress. WordPress sees those requests, and fires the * heartbeat_recieved filter. The filter allows plugins to change the server's response before it's sent back to * the originating user's browser. * * @param array $response The data we want to send back to user whose heart beat. * @param array $data An array of $_POST data received from the originating AJAX request. * @return array The data we want to send back to user. * @since Achievements (3.5) */ public static function notifications_heartbeat_response($response, $data) { // Bail if user is not active, or $data isn't in the expected format if (!dpa_is_user_active() || !isset($data['achievements']) || !is_array($data['achievements'])) { return $response; } $ids = array_keys(dpa_get_user_notifications()); if (empty($ids)) { return $response; } // If multisite and running network-wide, switch_to_blog to the data store site if (is_multisite() && dpa_is_running_networkwide()) { switch_to_blog(DPA_DATA_STORE); } $achievements = dpa_get_achievements(array('no_found_rows' => true, 'nopaging' => true, 'post__in' => $ids, 'post_status' => 'any')); $new_response = array(); foreach ($achievements as $achievement) { /** * Check that the post status is published or privately published. We need to check this here to work * around WP_Query not constructing the query correctly with private post statuses. */ if (!in_array($achievement->post_status, array('publish', 'private'))) { continue; } $item = array(); $item['ID'] = $achievement->ID; $item['title'] = esc_html(apply_filters('dpa_get_achievement_title', $achievement->post_title, $achievement->ID)); $item['permalink'] = esc_url_raw(home_url('/?p=' . $achievement->ID)); // Thumbnail is optional and may not be set $thumbnail = get_post_thumbnail_id($achievement->ID); if (!empty($thumbnail)) { $thumbnail = wp_get_attachment_image_src($thumbnail, 'medium'); if ($thumbnail) { $item['image_url'] = esc_url_raw($thumbnail[0]); $item['image_width'] = (int) $thumbnail[1]; } } // Achievements 3.5+ supports showing multiple unlock notifications at the same time $new_response[] = $item; } // If multisite and running network-wide, undo the switch_to_blog if (is_multisite() && dpa_is_running_networkwide()) { restore_current_blog(); } // Clear all pending notifications dpa_update_user_notifications(); $new_response = array_merge($response, array('achievements' => $new_response)); return apply_filters('dpa_theme_compat_notifications_heartbeat_response', $new_response, $ids, $response, $data); }
/** * Delete a user's progress for an achievement. Essentially, un-reward the achievement for this user. * * @param int $achievement_id Achievement ID * @param int $user_id User ID * @since Achievements (3.0) */ function dpa_delete_achievement_progress($achievement_id, $user_id) { $achievement_id = dpa_get_achievement_id($achievement_id); if (empty($achievement_id) || !dpa_is_achievement($achievement_id)) { return; } $progress_id = dpa_get_progress(array('author' => $user_id, 'fields' => 'ids', 'no_found_rows' => true, 'nopaging' => true, 'numberposts' => 1, 'post_parent' => $achievement_id)); if (empty($progress_id)) { return; } $progress_id = apply_filters('dpa_delete_achievement_progress', array_pop($progress_id), $achievement_id, $user_id); do_action('dpa_before_delete_achievement_progress', $progress_id, $achievement_id, $user_id); wp_delete_post($progress_id, true); // Check that the delete achievement isn't in the user's pending notifications $notifications = dpa_get_user_notifications($user_id); if (isset($notifications[$achievement_id])) { unset($notifications[$achievement_id]); } // Update the user's notifications in case we cleared any above dpa_update_user_notifications($notifications, $user_id); // Decrease user unlocked count dpa_update_user_unlocked_count($user_id, dpa_get_user_unlocked_count($user_id) - 1); /** * If the progress was linked to an achievement that is the same achievement that is stored in * this user's "last unlocked" meta, then clear the "last unlocked" meta, too. */ if ((int) dpa_get_user_last_unlocked($user_id) === $achievement_id) { dpa_update_user_last_unlocked($user_id, 0); } do_action('dpa_after_delete_achievement_progress', $progress_id, $achievement_id, $user_id); }