2024-12-15 02:13:38 +01:00

401 lines
11 KiB
PHP

<?php
// No direct access!
defined( 'ABSPATH' ) OR exit;
// =============================================================================
// REPLACEMENT FUNCTIONS
// =============================================================================
/**
* Returns the user avatar URL.
*
* @since 5.27.0
*
* @param stdClass $user User object.
* @param int $size Optional. Size of the avatar. Default 96.
*
* @return string The URL or an empty string.
*/
function ffcnr_get_avatar_url( $user, $size = 96 ) {
if ( ! $user ) {
return '';
}
$options = ffcnr_load_options( ['avatar_default'] );
$default = $options['avatar_default'] ?? 'mystery';
$meta = ffcnr_load_user_meta( $user->ID, 'fictioneer' );
$email = $user->user_email ?? 'nonexistentemail@example.com';
$disabled = ( $meta['fictioneer_disable_avatar'] ?? 0 ) || ( $meta['fictioneer_admin_disable_avatar'] ?? 0 );
$filtered = apply_filters( 'ffcnr_get_avatar_url', '', $user, $size, $meta, $options );
if ( ! empty( $filtered ) ) {
return $filtered;
}
// Custom avatar
if (
! $disabled &&
! ( $meta['fictioneer_enforce_gravatar'] ?? 0 ) &&
( $meta['fictioneer_external_avatar_url'] ?? 0 )
) {
return $meta['fictioneer_external_avatar_url'];
}
// Gravatar
if ( $email ) {
$gravatar_styles = array(
'mystery' => 'mm',
'blank' => 'blank',
'gravatar_default' => '',
'identicon' => 'identicon',
'wavatar' => 'wavatar',
'monsterid' => 'monsterid',
'retro' => 'retro'
);
$default = $gravatar_styles[ $default ];
$email_hash = $disabled ? 'foobar' : md5( mb_strtolower( trim( $user->user_email ) ) );
return "https://www.gravatar.com/avatar/{$email_hash}?s={$size}&d={$default}";
}
}
/**
* Checks if an user is an administrator.
*
* @since 5.27.0
*
* @param stdClass $user User object.
*
* @return boolean To be or not to be.
*/
function ffcnr_is_admin( $user ) {
return $user->caps['manage_options'] ?? false;
}
/**
* Checks if an user is an author.
*
* @since 5.27.0
*
* @param stdClass $user User object.
*
* @return boolean To be or not to be.
*/
function ffcnr_is_author( $user ) {
return ($user->caps['publish_posts'] ?? false) ||
($user->caps['publish_fcn_stories'] ?? false) ||
($user->caps['publish_fcn_chapters'] ?? false) ||
($user->caps['publish_fcn_collections'] ?? false);
}
/**
* Checks if an user is a moderator.
*
* @since 5.27.0
*
* @param stdClass $user User object.
*
* @return boolean To be or not to be.
*/
function ffcnr_is_moderator( $user ) {
return $user->caps['moderate_comments'] ?? false;
}
/**
* Checks if an user is an editor.
*
* @since 5.27.0
*
* @param stdClass $user User object.
*
* @return boolean To be or not to be.
*/
function ffcnr_is_editor( $user ) {
return $user->caps['edit_others_posts'] ?? false;
}
/**
* Returns an user's Follows
*
* @since 5.27.0
* @see includes/functions/users/_follows.php
*
* @param stdClass $user User to get the Follows for.
*
* @return array Follows.
*/
function fictioneer_load_follows( $user ) {
// Setup
$follows = ffcnr_get_user_meta( $user->ID, 'fictioneer_user_follows', 'fictioneer' );
$timestamp = time() * 1000;
// Validate/Initialize
if ( empty( $follows ) || ! is_array( $follows ) || ! array_key_exists( 'data', $follows ) ) {
$follows = array( 'data' => [], 'seen' => $timestamp, 'updated' => $timestamp );
ffcnr_update_user_meta( $user->ID, 'fictioneer_user_follows', $follows );
}
if ( ! array_key_exists( 'updated', $follows ) ) {
$follows['updated'] = $timestamp;
ffcnr_update_user_meta( $user->ID, 'fictioneer_user_follows', $follows );
}
if ( ! array_key_exists( 'seen', $follows ) ) {
$follows['seen'] = $timestamp;
ffcnr_update_user_meta( $user->ID, 'fictioneer_user_follows', $follows );
}
// Return
return $follows;
}
/**
* Query count of new chapters for followed stories
*
* @since 5.27.0
* @see includes/functions/users/_follows.php
*
* @param array $story_ids IDs of the followed stories.
* @param string|null $after_date Optional. Only return chapters after this date,
* e.g. wp_date( 'Y-m-d H:i:s', $timestamp ).
* @param int $count Optional. Maximum number of chapters. Default 99.
*
* @return array Number of new chapters found.
*/
function fictioneer_query_new_followed_chapters_count( $story_ids, $after_date = null, $count = 99 ) {
global $wpdb;
$story_ids = array_map( 'absint', $story_ids );
if ( empty( $story_ids ) ) {
return 0;
}
$story_ids_placeholder = implode( ',', array_fill( 0, count( $story_ids ), '%d' ) );
$sql = "
SELECT COUNT(p.ID) as count
FROM {$wpdb->posts} p
INNER JOIN {$wpdb->postmeta} pm_story ON p.ID = pm_story.post_id
LEFT JOIN {$wpdb->postmeta} pm_hidden ON p.ID = pm_hidden.post_id AND pm_hidden.meta_key = 'fictioneer_chapter_hidden'
WHERE p.post_type = 'fcn_chapter'
AND p.post_status = 'publish'
AND pm_story.meta_key = 'fictioneer_chapter_story'
AND pm_story.meta_value IN ({$story_ids_placeholder})
AND (pm_hidden.meta_key IS NULL OR pm_hidden.meta_value = '0')
";
if ( $after_date ) {
$sql .= " AND p.post_date > %s";
}
$query_args = array_merge( $story_ids, $after_date ? [ $after_date ] : [] );
return min( (int) $wpdb->get_var( $wpdb->prepare( $sql, $query_args ) ), $count );
}
/**
* Returns an user's Reminders
*
* Get an user's Reminders array from the database or creates a new one if it
* does not yet exist.
*
* @since 5.27.0
* @see includes/functions/users/_reminders.php
*
* @param stdClass $user User to get the Reminders for.
*
* @return array Reminders.
*/
function fictioneer_load_reminders( $user ) {
// Setup
$reminders = ffcnr_get_user_meta( $user->ID, 'fictioneer_user_reminders', 'fictioneer' );
$timestamp = time() * 1000; // Compatible with Date.now() in JavaScript
// Validate/Initialize
if ( empty( $reminders ) || ! is_array( $reminders ) || ! array_key_exists( 'data', $reminders ) ) {
$reminders = array( 'data' => [], 'updated' => $timestamp );
ffcnr_update_user_meta( $user->ID, 'fictioneer_user_reminders', $reminders );
}
if ( ! array_key_exists( 'updated', $reminders ) ) {
$reminders['updated'] = $timestamp;
ffcnr_update_user_meta( $user->ID, 'fictioneer_user_reminders', $reminders );
}
// Return
return $reminders;
}
/**
* Returns an user's Checkmarks
*
* Get an user's Checkmarks array from the database or creates a new one if it
* does not yet exist.
*
* @since 5.27.0
* @see includes/functions/users/_checkmarks.php
*
* @param stdClass $user User to get the checkmarks for.
*
* @return array Checkmarks.
*/
function fictioneer_load_checkmarks( $user ) {
// Setup
$checkmarks = ffcnr_get_user_meta( $user->ID, 'fictioneer_user_checkmarks', 'fictioneer' );
$timestamp = time() * 1000;
// Validate/Initialize
if ( empty( $checkmarks ) || ! is_array( $checkmarks ) || ! array_key_exists( 'data', $checkmarks ) ) {
$checkmarks = array( 'data' => [], 'updated' => $timestamp );
ffcnr_update_user_meta( $user->ID, 'fictioneer_user_checkmarks', $checkmarks );
}
if ( ! array_key_exists( 'updated', $checkmarks ) ) {
$checkmarks['updated'] = $timestamp;
ffcnr_update_user_meta( $user->ID, 'fictioneer_user_checkmarks', $checkmarks );
}
// Return
return $checkmarks;
}
/**
* Returns an unique MD5 hash for the user.
*
* @since 5.27.0
* @see includes/functions/_helpers-users.php
*
* @param stdClass $user User to get the fingerprint for.
*
* @return string The unique fingerprint hash or empty string if not found.
*/
function fictioneer_get_user_fingerprint( $user ) {
if ( ! $user ) {
return '';
}
$fingerprint = ffcnr_get_user_meta( $user->ID, 'fictioneer_user_fingerprint', 'fictioneer' );
if ( empty( $fingerprint ) ) {
$fingerprint = md5( $user->user_login . $user->ID );
ffcnr_update_user_meta( $user->ID, 'fictioneer_user_fingerprint', $fingerprint );
}
return $fingerprint;
}
// =============================================================================
// GET USER DATA
// =============================================================================
function ffcnr_get_user_data() {
// Load options
$options = ffcnr_load_options([
'fictioneer_enable_reminders', 'fictioneer_enable_checkmarks',
'fictioneer_enable_bookmarks', 'fictioneer_enable_follows'
]);
// Setup
$user = ffcnr_get_current_user( $options );
$logged_in = !!($user ? $user->ID : 0);
$nonce = ffcnr_create_nonce( 'fictioneer_nonce', $logged_in ? $user->ID : 0 );
$data = array(
'user_id' => $logged_in ? $user->ID : 0,
'timestamp' => time() * 1000, // Compatible with Date.now() in JavaScript
'loggedIn' => $logged_in,
'follows' => false,
'reminders' => false,
'checkmarks' => false,
'bookmarks' => '{}',
'fingerprint' => fictioneer_get_user_fingerprint( $user ),
'avatarUrl' => '',
'isAdmin' => false,
'isModerator' => false,
'isAuthor' => false,
'isEditor' => false,
'nonce' => $nonce,
'nonceHtml' => '<input id="fictioneer-ajax-nonce" name="fictioneer-ajax-nonce" type="hidden" value="' . $nonce . '">'
);
if ( $logged_in ) {
$data = array_merge(
$data,
array(
'isAdmin' => ffcnr_is_admin( $user ),
'isModerator' => ffcnr_is_moderator( $user ),
'isAuthor' => ffcnr_is_author( $user ),
'isEditor' => ffcnr_is_editor( $user ),
'avatarUrl' => ffcnr_get_avatar_url( $user )
)
);
}
// --- FOLLOWS ---------------------------------------------------------------
if ( $logged_in && $options['fictioneer_enable_follows'] ) {
$follows = fictioneer_load_follows( $user );
$follows['new'] = false;
// New notifications?
if ( count( $follows['data'] ) > 0 ) {
$latest_count = fictioneer_query_new_followed_chapters_count(
array_keys( $follows['data'] ),
wp_date( 'Y-m-d H:i:s', $follows['seen'] / 1000 )
);
if ( $latest_count > 0 ) {
$follows['new'] = $latest_count;
}
}
$data['follows'] = $follows;
}
// --- REMINDERS -------------------------------------------------------------
if ( $logged_in && $options['fictioneer_enable_reminders'] ) {
$data['reminders'] = fictioneer_load_reminders( $user );
}
// --- CHECKMARKS ------------------------------------------------------------
if ( $logged_in && $options['fictioneer_enable_checkmarks'] ) {
$data['checkmarks'] = fictioneer_load_checkmarks( $user );
}
// --- BOOKMARKS -------------------------------------------------------------
if ( $logged_in && $options['fictioneer_enable_bookmarks'] ) {
$bookmarks = ffcnr_get_user_meta( $user->ID, 'fictioneer_bookmarks', 'fictioneer' );
$data['bookmarks'] = $bookmarks ? $bookmarks : '{}';
}
// --- FILTER ----------------------------------------------------------------
$data = apply_filters( 'ffcnr_get_user_data', $data, $user );
// ---------------------------------------------------------------------------
// Response
header( 'Content-Type: application/json; charset=utf-8' );
header( 'HTTP/1.1 200 OK' );
echo json_encode( array( 'success' => true, 'data' => $data ) );
exit;
}
ffcnr_get_user_data();