Add feature to unlock selected posts per user
This commit is contained in:
parent
4ac75cbd2f
commit
ffbf97644b
@ -88,6 +88,7 @@ Fires within the Fictioneer user profile section in the WordPress `wp-admin/prof
|
||||
* `fictioneer_admin_profile_fields_flags( $profile_user )` – User flags. Priority 6.
|
||||
* `fictioneer_admin_profile_fields_oauth( $profile_user )` – User OAuth connections. Priority 7.
|
||||
* `fictioneer_admin_profile_fields_data_nodes( $profile_user )` – User data nodes. Priority 8.
|
||||
* `fictioneer_admin_profile_post_unlocks( $profile_user )` - Unlock password-protected posts. Priority 9.
|
||||
* `fictioneer_admin_profile_moderation( $profile_user )` – Moderation flags and message. Priority 10.
|
||||
* `fictioneer_admin_profile_author( $profile_user )` – Author page select, support message, and support links. Priority 20.
|
||||
* `fictioneer_admin_profile_oauth( $profile_user )` – OAuth 2.0 account binding IDs. Priority 30.
|
||||
|
@ -221,13 +221,13 @@ Fictioneer customizes WordPress by using as many standard action and filter hook
|
||||
| `do_meta_boxes` | `fictioneer_remove_custom_fields_meta_boxes`
|
||||
| `edit_comment` | `fictioneer_comment_edit`, `fictioneer_edit_comment`
|
||||
| `edit_user_profile` | `fictioneer_custom_profile_fields`
|
||||
| `edit_user_profile_update` | `fictioneer_update_admin_user_profile`, `fictioneer_update_my_user_profile`
|
||||
| `edit_user_profile_update` | `fictioneer_update_admin_user_profile`, `fictioneer_update_my_user_profile`, `fictioneer_update_admin_unlocked_posts`
|
||||
| `get_header` | `fictioneer_maintenance_mode`
|
||||
| `init` | `fictioneer_add_character_taxonomy`, `fictioneer_add_content_warning_taxonomy`, `fictioneer_add_epub_download_endpoint`, `fictioneer_add_fandom_taxonomy`, `fictioneer_add_genre_taxonomy`, `fictioneer_add_logout_endpoint`, `fictioneer_add_oauth2_endpoint`, `fictioneer_restrict_admin_panel`, `fictioneer_disable_heartbeat`, `fictioneer_fcn_chapter_post_type`, `fictioneer_fcn_collection_post_type`, `fictioneer_fcn_recommendation_post_type`, `fictioneer_fcn_story_post_type`, `fictioneer_modify_allowed_tags`, `fictioneer_story_rss`, `fictioneer_remove_custom_fields_supports`, `fictioneer_add_sitemap_rewrite_rule`, `fictioneer_fast_ajax`
|
||||
| `login_form` | `fictioneer_after_logout_cleanup`
|
||||
| `login_head` | `fictioneer_wp_login_scripts`
|
||||
| `manage_comments_custom_column` | `fictioneer_add_comments_report_column_content`
|
||||
| `personal_options_update` | `fictioneer_update_admin_user_profile`, `fictioneer_update_my_user_profile`
|
||||
| `personal_options_update` | `fictioneer_update_admin_user_profile`, `fictioneer_update_my_user_profile`, `fictioneer_update_admin_unlocked_posts`
|
||||
| `pre_get_posts` | `fictioneer_extend_search_query`, `fictioneer_read_others_files`, `fictioneer_read_others_files_list_view`, `fictioneer_filter_chapters_by_story`
|
||||
| `private_to_draft` | `fictioneer_chapter_to_draft`
|
||||
| `profile_update` | `fictioneer_on_profile_change`
|
||||
@ -242,7 +242,7 @@ Fictioneer customizes WordPress by using as many standard action and filter hook
|
||||
| `trashed_post` | `fictioneer_refresh_post_caches`, `fictioneer_track_chapter_and_story_updates`, `fictioneer_update_modified_date_on_story_for_chapter`, `fictioneer_purge_transients`, `fictioneer_remove_chapter_from_story`
|
||||
| `untrash_post` | `fictioneer_refresh_post_caches`, `fictioneer_track_chapter_and_story_updates`, `fictioneer_update_modified_date_on_story_for_chapter`, `fictioneer_purge_transients`
|
||||
| `update_option_*` | `fictioneer_update_option_disable_extended_chapter_list_meta_queries`, `fictioneer_update_option_disable_extended_story_list_meta_queries`
|
||||
| `wp_ajax_*` | `fictioneer_ajax_clear_my_checkmarks`, `fictioneer_ajax_clear_my_comments`, `fictioneer_ajax_clear_my_comment_subscriptions`, `fictioneer_ajax_clear_my_follows`, `fictioneer_ajax_clear_my_reminders`, `fictioneer_ajax_delete_epub`, `fictioneer_ajax_delete_my_account`, `fictioneer_ajax_delete_my_comment`, `fictioneer_ajax_edit_comment`, `fictioneer_ajax_get_avatar`, `fictioneer_ajax_get_comment_form`, `fictioneer_ajax_get_comment_section`, `fictioneer_ajax_get_finished_checkmarks_list`, `fictioneer_ajax_get_follows_list`, `fictioneer_ajax_get_follows_notifications`, `fictioneer_ajax_get_reminders_list`, `fictioneer_ajax_mark_follows_read`, `fictioneer_ajax_moderate_comment`, `fictioneer_ajax_report_comment`, `fictioneer_ajax_save_bookmarks`, `fictioneer_ajax_set_checkmark`, `fictioneer_ajax_submit_comment`, `fictioneer_ajax_toggle_follow`, `fictioneer_ajax_toggle_reminder`, `fictioneer_ajax_unset_my_oauth`, `fictioneer_ajax_get_user_data`, `fictioneer_ajax_get_auth`, `fictioneer_ajax_purge_schema`, `fictioneer_ajax_purge_all_schemas`, `fictioneer_ajax_reset_theme_colors`
|
||||
| `wp_ajax_*` | `fictioneer_ajax_clear_my_checkmarks`, `fictioneer_ajax_clear_my_comments`, `fictioneer_ajax_clear_my_comment_subscriptions`, `fictioneer_ajax_clear_my_follows`, `fictioneer_ajax_clear_my_reminders`, `fictioneer_ajax_delete_epub`, `fictioneer_ajax_delete_my_account`, `fictioneer_ajax_delete_my_comment`, `fictioneer_ajax_edit_comment`, `fictioneer_ajax_get_avatar`, `fictioneer_ajax_get_comment_form`, `fictioneer_ajax_get_comment_section`, `fictioneer_ajax_get_finished_checkmarks_list`, `fictioneer_ajax_get_follows_list`, `fictioneer_ajax_get_follows_notifications`, `fictioneer_ajax_get_reminders_list`, `fictioneer_ajax_mark_follows_read`, `fictioneer_ajax_moderate_comment`, `fictioneer_ajax_report_comment`, `fictioneer_ajax_save_bookmarks`, `fictioneer_ajax_set_checkmark`, `fictioneer_ajax_submit_comment`, `fictioneer_ajax_toggle_follow`, `fictioneer_ajax_toggle_reminder`, `fictioneer_ajax_unset_my_oauth`, `fictioneer_ajax_get_user_data`, `fictioneer_ajax_get_auth`, `fictioneer_ajax_purge_schema`, `fictioneer_ajax_purge_all_schemas`, `fictioneer_ajax_reset_theme_colors`, `fictioneer_ajax_search_posts_to_unlock`
|
||||
| `wp_ajax_nopriv_*` | `fictioneer_ajax_get_comment_form`, `fictioneer_ajax_get_comment_section`, `fictioneer_ajax_submit_comment`, `fictioneer_ajax_get_auth`
|
||||
| `wp_before_admin_bar_render` | `fictioneer_remove_admin_bar_links`, `fictioneer_remove_dashboard_from_admin_bar`, `fictioneer_remove_comments_from_admin_bar`
|
||||
| `wp_dashboard_setup` | `fictioneer_remove_dashboard_widgets`
|
||||
|
@ -596,6 +596,7 @@ The integrated role manager to add and, edit, and remove roles. Not the most sop
|
||||
* **Read Others Files:** Allows you to see uploaded files from *other* users.
|
||||
* **Edit Others Files:** Allows you to edit uploaded files from *other* users.
|
||||
* **Delete Others Files:** Allows you to delete uploaded files from *other* users.
|
||||
* **Unlock Posts:** Allows you to unlock selected password-protected posts for users.
|
||||
* **Manage {Taxonomy}:** Lets you see the overview list table of the taxonomy.
|
||||
* **Assign {Taxonomy}:** Lets you assign the taxonomy to your posts.
|
||||
* **Edit {Taxonomy}:** Lets you create and edit taxonomies of this type.
|
||||
|
File diff suppressed because one or more lines are too long
@ -34,7 +34,8 @@ define(
|
||||
'fcn_ignore_page_passwords',
|
||||
'fcn_ignore_fcn_story_passwords',
|
||||
'fcn_ignore_fcn_chapter_passwords',
|
||||
'fcn_ignore_fcn_collection_passwords'
|
||||
'fcn_ignore_fcn_collection_passwords',
|
||||
'fcn_unlock_posts'
|
||||
)
|
||||
);
|
||||
|
||||
@ -95,9 +96,10 @@ function fictioneer_initialize_roles( $force = false ) {
|
||||
}
|
||||
|
||||
// If this capability is missing, the roles need to be updated
|
||||
if ( $administrator && ! in_array( 'fcn_custom_epub_upload', array_keys( $administrator->capabilities ) ) ) {
|
||||
if ( $administrator && ! in_array( 'fcn_unlock_posts', array_keys( $administrator->capabilities ) ) ) {
|
||||
get_role( 'administrator' )->add_cap( 'fcn_custom_page_header' );
|
||||
get_role( 'administrator' )->add_cap( 'fcn_custom_epub_upload' );
|
||||
get_role( 'administrator' )->add_cap( 'fcn_unlock_posts' );
|
||||
|
||||
if ( $editor = get_role( 'editor' ) ) {
|
||||
$editor->add_cap( 'fcn_custom_page_header' );
|
||||
@ -475,6 +477,17 @@ function fictioneer_bypass_password( $required, $post ) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Check user unlocks
|
||||
if ( $user && $required ) {
|
||||
$story_id = get_post_meta( $post->ID, 'fictioneer_chapter_story', true );
|
||||
$unlocks = get_user_meta( $user->ID, 'fictioneer_post_unlocks', true ) ?: [];
|
||||
$unlocks = is_array( $unlocks ) ? $unlocks : [];
|
||||
|
||||
if ( $unlocks && array_intersect( [ $post->ID, $story_id ], $unlocks ) ) {
|
||||
$required = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check Patreon tiers
|
||||
if ( $user && $required && get_option( 'fictioneer_enable_patreon_locks' ) && fictioneer_patreon_tiers_valid( $user ) ) {
|
||||
$patreon_post_data = fictioneer_get_patreon_data( $post );
|
||||
|
@ -73,6 +73,7 @@ $admin_caps = array(
|
||||
'create_users',
|
||||
'edit_users',
|
||||
'remove_users',
|
||||
'fcn_unlock_posts',
|
||||
'switch_themes',
|
||||
'edit_theme_options',
|
||||
'edit_themes',
|
||||
|
@ -732,6 +732,140 @@ function fictioneer_admin_profile_fields_data_nodes( $profile_user ) {
|
||||
}
|
||||
add_action( 'fictioneer_admin_user_sections', 'fictioneer_admin_profile_fields_data_nodes', 8 );
|
||||
|
||||
// =============================================================================
|
||||
// SHOW UNLOCKS SECTION
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Unlock password-protected posts for user
|
||||
*
|
||||
* @since 5.16.0
|
||||
*
|
||||
* @param WP_User $profile_user The profile user object. Not necessarily the one
|
||||
* currently editing the profile!
|
||||
*/
|
||||
|
||||
function fictioneer_admin_profile_post_unlocks( $profile_user ) {
|
||||
// Check permissions
|
||||
if ( ! current_user_can( 'manage_options' ) && ! current_user_can( 'fcn_unlock_posts' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'edit_users' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup
|
||||
$unlocks = get_user_meta( $profile_user->ID, 'fictioneer_post_unlocks', true ) ?: [];
|
||||
$unlocks = is_array( $unlocks ) ? $unlocks : [];
|
||||
|
||||
// Post data
|
||||
$posts = [];
|
||||
$post_type_labels = array(
|
||||
'post' => _x( 'Post', 'Post type label.', 'fictioneer' ),
|
||||
'page' => _x( 'Page', 'Post type label.', 'fictioneer' ),
|
||||
'fcn_story' => _x( 'Story', 'Post type label.', 'fictioneer' ),
|
||||
'fcn_chapter' => _x( 'Chapter', 'Post type label.', 'fictioneer' ),
|
||||
'fcn_collection' => _x( 'Collection', 'Post type label.', 'fictioneer' ),
|
||||
'fcn_recommendation' => _x( 'Rec', 'Post type label.', 'fictioneer' )
|
||||
);
|
||||
|
||||
if ( $unlocks ) {
|
||||
$query = new WP_Query(
|
||||
array(
|
||||
'post_type'=> 'any',
|
||||
'post_status'=> 'any',
|
||||
'posts_per_page' => -1,
|
||||
'post__in' => $unlocks,
|
||||
'update_post_meta_cache' => false, // Improve performance
|
||||
'update_post_term_cache' => false, // Improve performance
|
||||
'no_found_rows' => true // Improve performance
|
||||
)
|
||||
);
|
||||
|
||||
$posts = $query->posts;
|
||||
|
||||
// Prime author cache
|
||||
if ( function_exists( 'update_post_author_caches' ) ) {
|
||||
update_post_author_caches( $posts );
|
||||
}
|
||||
}
|
||||
|
||||
// Start HTML ---> ?>
|
||||
<tr class="user-unlock-posts-wrap">
|
||||
|
||||
<th><?php _e( 'Unlock Posts', 'fictioneer' ); ?></th>
|
||||
|
||||
<td class="unlock-posts" data-controller="fcn-unlock-posts">
|
||||
<fieldset>
|
||||
|
||||
<?php wp_nonce_field( 'search_posts', 'unlock_posts_nonce' ); ?>
|
||||
|
||||
<template data-target="fcn-unlock-posts-item-template">
|
||||
<div class="unlock-posts__item" title="" data-target="fcn-unlock-posts-item" data-post-id="0">
|
||||
<input type="hidden" name="fictioneer_post_unlocks[]" value="">
|
||||
<span class="unlock-posts__item-title"></span>
|
||||
<span class="unlock-posts__item-meta"></span>
|
||||
<button type="button" class="unlock-posts__delete" data-target="fcn-unlock-posts-delete"><span class="dashicons dashicons-no-alt"></span></button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<p>
|
||||
<?php _e( 'Allow the user to ignore the password of selected posts. Chapters inherit the unlock from the story.', 'fictioneer' ); ?>
|
||||
</p>
|
||||
|
||||
<div class="unlock-posts__search">
|
||||
|
||||
<div class="unlock-posts__search-form">
|
||||
<input type="search" class="unlock-posts__search-input regular-text" name="unlock_search" data-target="fcn-unlock-posts-search" placeholder="<?php _e( 'Search posts to unlock…', 'fictioneer' ); ?>">
|
||||
<select class="unlock-posts__search-select" name="unlock_select_type" data-target="fcn-unlock-posts-select" >
|
||||
<option value="0" selected><?php _e( 'Any', 'fictioneer' ); ?></option>
|
||||
<option value="post"><?php _e( 'Post', 'fictioneer' ); ?></option>
|
||||
<option value="page"><?php _e( 'Page', 'fictioneer' ); ?></option>
|
||||
<option value="fcn_story"><?php _e( 'Story', 'fictioneer' ); ?></option>
|
||||
<option value="fcn_chapter"><?php _e( 'Chapter', 'fictioneer' ); ?></option>
|
||||
<option value="fcn_collection"><?php _e( 'Collection', 'fictioneer' ); ?></option>
|
||||
<option value="fcn_recommendation"><?php _e( 'Recommendation', 'fictioneer' ); ?></option>
|
||||
</select>
|
||||
<i class="fa-solid fa-spinner fa-spin" style="--fa-animation-duration: .8s;"></i>
|
||||
</div>
|
||||
|
||||
<div class="unlock-posts__search-results" data-target="fcn-unlock-posts-search-results"></div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="unlock-posts__unlocked-posts" data-target="fcn-unlock-posts-selected">
|
||||
|
||||
<input type="hidden" name="fictioneer_post_unlocks" value="0">
|
||||
|
||||
<?php foreach ( $posts as $post ) : ?>
|
||||
<?php
|
||||
$type = $post_type_labels[ $post->post_type ] ?? '';
|
||||
$title = fictioneer_get_safe_title( $post->ID );
|
||||
$item_title = sprintf(
|
||||
_x( 'Author: %s | Title: %s', 'Unlock post item.', 'fictioneer' ),
|
||||
get_the_author_meta( 'display_name', $post->post_author ) ?: __( 'n/a', 'fictioneer' ),
|
||||
$title
|
||||
);
|
||||
?>
|
||||
<div class="unlock-posts__item" title="<?php echo esc_attr( $item_title ); ?>" data-target="fcn-unlock-posts-item" data-post-id="<?php echo $post->ID; ?>">
|
||||
<input type="hidden" name="fictioneer_post_unlocks[]" value="<?php echo $post->ID; ?>">
|
||||
<span class="unlock-posts__item-title"><?php echo $title; ?></span>
|
||||
<span class="unlock-posts__item-meta"><?php printf( _x( '(%s | %s)', 'Unlock post item meta: Type | ID.', 'fictioneer' ), $type, $post->ID ); ?></span>
|
||||
<button type="button" class="unlock-posts__delete" data-target="fcn-unlock-posts-delete"><span class="dashicons dashicons-no-alt"></span></button>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<?php // <--- End HTML
|
||||
}
|
||||
add_action( 'fictioneer_admin_user_sections', 'fictioneer_admin_profile_post_unlocks', 9 );
|
||||
|
||||
// =============================================================================
|
||||
// SHOW MODERATION SECTION
|
||||
// =============================================================================
|
||||
|
@ -1167,4 +1167,135 @@ function fictioneer_ajax_get_user_data() {
|
||||
}
|
||||
add_action( 'wp_ajax_fictioneer_ajax_get_user_data', 'fictioneer_ajax_get_user_data' );
|
||||
|
||||
?>
|
||||
// =============================================================================
|
||||
// UNLOCK POSTS - AJAX
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Searches for posts to unlock via AJAX
|
||||
*
|
||||
* @since 5.16.0
|
||||
*/
|
||||
|
||||
function fictioneer_ajax_search_posts_to_unlock() {
|
||||
// Validations
|
||||
$user = fictioneer_get_validated_ajax_user( 'nonce', 'search_posts' );
|
||||
|
||||
if ( ! $user ) {
|
||||
wp_send_json_error( array( 'error' => __( 'Request did not pass validation.', 'fictioneer' ) ) );
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'manage_options' ) && ! current_user_can( 'fcn_unlock_posts' ) ) {
|
||||
wp_send_json_error( array( 'error' => __( 'Insufficient permissions.', 'fictioneer' ) ) );
|
||||
}
|
||||
|
||||
// Setup
|
||||
$search = sanitize_text_field( $_REQUEST['search'] ?? '' );
|
||||
$type = sanitize_key( $_REQUEST['type'] ?? '' );
|
||||
$output = [];
|
||||
|
||||
// Empty?
|
||||
if ( empty( $search ) ) {
|
||||
wp_send_json_success( array( 'html' => '' ) );
|
||||
}
|
||||
|
||||
// Query
|
||||
$posts = new WP_Query(
|
||||
array(
|
||||
'post_type' => $type ?: ['post', 'page', 'fcn_story', 'fcn_chapter', 'fcn_collection', 'fcn_recommendation'],
|
||||
'post_status' => 'any',
|
||||
'orderby' => 'date',
|
||||
'order' => 'desc',
|
||||
'posts_per_page' => 20,
|
||||
's' => $search,
|
||||
'update_post_meta_cache' => false, // Improve performance
|
||||
'update_post_term_cache' => false, // Improve performance
|
||||
'no_found_rows' => true // Improve performance
|
||||
)
|
||||
);
|
||||
|
||||
// Prime author cache
|
||||
if ( function_exists( 'update_post_author_caches' ) ) {
|
||||
update_post_author_caches( $posts->posts );
|
||||
}
|
||||
|
||||
// Search result
|
||||
if ( ! $posts->posts ) {
|
||||
wp_send_json_success( array( 'html' => '' ) );
|
||||
} else {
|
||||
// Labels
|
||||
$post_type_labels = array(
|
||||
'post' => _x( 'Post', 'Post type label.', 'fictioneer' ),
|
||||
'page' => _x( 'Page', 'Post type label.', 'fictioneer' ),
|
||||
'fcn_story' => _x( 'Story', 'Post type label.', 'fictioneer' ),
|
||||
'fcn_chapter' => _x( 'Chapter', 'Post type label.', 'fictioneer' ),
|
||||
'fcn_collection' => _x( 'Collection', 'Post type label.', 'fictioneer' ),
|
||||
'fcn_recommendation' => _x( 'Rec', 'Post type label.', 'fictioneer' )
|
||||
);
|
||||
|
||||
foreach ( $posts->posts as $post ) {
|
||||
$type = $post_type_labels[ $post->post_type ] ?? '';
|
||||
$title = fictioneer_get_safe_title( $post->ID );
|
||||
$item_title = sprintf(
|
||||
_x( 'Author: %s | Title: %s', 'Unlock post item.', 'fictioneer' ),
|
||||
get_the_author_meta( 'display_name', $post->post_author ) ?: __( 'n/a', 'fictioneer' ),
|
||||
$title
|
||||
);
|
||||
|
||||
$output[] = '<div class="unlock-posts__item _searched" title="' . esc_attr( $item_title ) . '" data-target="fcn-unlock-posts-search-item" data-post-id="' . $post->ID . '"><span class="unlock-posts__item-title">' . $title . '</span> <span class="unlock-posts__item-meta">' . sprintf( _x( '(%s | %s)', 'Unlock post item meta: Type | ID.', 'fictioneer' ), $type, $post->ID ) . '</span></div>';
|
||||
}
|
||||
}
|
||||
|
||||
// Response
|
||||
wp_send_json_success( array( 'html' => implode( '', $output ) ) );
|
||||
}
|
||||
add_action( 'wp_ajax_fictioneer_ajax_search_posts_to_unlock', 'fictioneer_ajax_search_posts_to_unlock' );
|
||||
|
||||
/**
|
||||
* Update unlocked posts for user
|
||||
*
|
||||
* @since 5.16.0
|
||||
*
|
||||
* @param int $updated_user_id The ID of the updated user.
|
||||
*/
|
||||
|
||||
function fictioneer_update_admin_unlocked_posts( $updated_user_id ) {
|
||||
// Check permissions
|
||||
if ( ! current_user_can( 'manage_options' ) && ! current_user_can( 'fcn_unlock_posts' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'edit_users' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup
|
||||
$admin_protection = fictioneer_is_admin( $updated_user_id ) && get_current_user_id() !== $updated_user_id;
|
||||
|
||||
// Check if protected, sanitize, validate, and update...
|
||||
if ( ! $admin_protection && isset( $_POST['fictioneer_post_unlocks'] ) ) {
|
||||
$post_ids = $_POST['fictioneer_post_unlocks'];
|
||||
$post_ids = is_array( $post_ids ) ? $post_ids : [];
|
||||
$post_ids = array_map( 'absint', $post_ids );
|
||||
$post_ids = array_unique( $post_ids );
|
||||
|
||||
$query = new WP_Query(
|
||||
array(
|
||||
'post_type'=> ['post', 'page', 'fcn_story', 'fcn_chapter', 'fcn_collection', 'fcn_recommendation'],
|
||||
'post_status'=> 'any',
|
||||
'posts_per_page' => -1,
|
||||
'post__in' => $post_ids ?: [0],
|
||||
'fields' => 'ids',
|
||||
'update_post_meta_cache' => false, // Improve performance
|
||||
'update_post_term_cache' => false, // Improve performance
|
||||
'no_found_rows' => true // Improve performance
|
||||
)
|
||||
);
|
||||
|
||||
$post_ids = array_map( 'strval', $query->posts );
|
||||
|
||||
fictioneer_update_user_meta( $updated_user_id, 'fictioneer_post_unlocks', $post_ids );
|
||||
}
|
||||
}
|
||||
add_action( 'personal_options_update', 'fictioneer_update_admin_unlocked_posts' );
|
||||
add_action( 'edit_user_profile_update', 'fictioneer_update_admin_unlocked_posts' );
|
||||
|
2
js/admin.min.js
vendored
2
js/admin.min.js
vendored
File diff suppressed because one or more lines are too long
130
src/js/admin.js
130
src/js/admin.js
@ -1069,3 +1069,133 @@ function fcn_addRelationship(source, destination) {
|
||||
// Disable
|
||||
source.classList.add('disabled');
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// UNLOCK POSTS
|
||||
// =============================================================================
|
||||
|
||||
var /** @type {timeoutID} */ fcn_unlockPostsTimer;
|
||||
|
||||
_$('[data-controller="fcn-unlock-posts"]')?.addEventListener('click', event => {
|
||||
// Evaluate clicks on the interface
|
||||
fcn_unlockPostsHandleClicks(event.target.closest('[data-target]'));
|
||||
});
|
||||
|
||||
_$('[data-target="fcn-unlock-posts-search"]')?.addEventListener('input', () => {
|
||||
// Clear previous timer (if any)
|
||||
clearTimeout(fcn_unlockPostsTimer);
|
||||
|
||||
// Trigger search after delay
|
||||
fcn_unlockPostsTimer = setTimeout(() => {
|
||||
fcn_unlockPostsSearch();
|
||||
}, 800);
|
||||
});
|
||||
|
||||
_$('[data-target="fcn-unlock-posts-select"]')?.addEventListener('input', () => {
|
||||
// Clear previous timer (if any)
|
||||
clearTimeout(fcn_unlockPostsTimer);
|
||||
|
||||
// Start search
|
||||
fcn_unlockPostsSearch();
|
||||
});
|
||||
|
||||
/**
|
||||
* Handle clicks on the Unlock Posts interface.
|
||||
*
|
||||
* @since 5.16.0
|
||||
* @param {HTMLElement} target - The element that was clicked.
|
||||
*/
|
||||
|
||||
function fcn_unlockPostsHandleClicks(target) {
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Delegate or perform action...
|
||||
switch (target.dataset.target) {
|
||||
case 'fcn-unlock-posts-delete':
|
||||
target.closest('[data-target="fcn-unlock-posts-item"').remove();
|
||||
break;
|
||||
case 'fcn-unlock-posts-search-item':
|
||||
fcn_unlockPostsAdd(target);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search posts to unlock.
|
||||
*
|
||||
* @since 5.16.0
|
||||
*/
|
||||
|
||||
function fcn_unlockPostsSearch() {
|
||||
// Setup
|
||||
const container = _$('.unlock-posts');
|
||||
const search = _$('[data-target="fcn-unlock-posts-search"]');
|
||||
const results = _$('[data-target="fcn-unlock-posts-search-results"]');
|
||||
const selected = _$('[data-target="fcn-unlock-posts-selected"]');
|
||||
|
||||
// Abort if...
|
||||
if (!container || !search || (!search.value && !_$('[data-target="fcn-unlock-posts-search-item"]'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Payload
|
||||
const payload = {
|
||||
'action': 'fictioneer_ajax_search_posts_to_unlock',
|
||||
'search': search.value,
|
||||
'type': _$('[data-target="fcn-unlock-posts-select"]')?.value || 'any',
|
||||
'nonce': container.querySelector('[name="unlock_posts_nonce"]').value
|
||||
};
|
||||
|
||||
// Indicate process
|
||||
container.classList.add('ajax-in-progress');
|
||||
|
||||
// Request
|
||||
fcn_ajaxPost(payload)
|
||||
.then(response => {
|
||||
if (response.success) {
|
||||
results.innerHTML = response.data.html;
|
||||
} else {
|
||||
results.innerHTML = response.data.error;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
results.innerHTML = error;
|
||||
})
|
||||
.then(() => {
|
||||
container.classList.remove('ajax-in-progress');
|
||||
|
||||
results.querySelectorAll('[data-target="fcn-unlock-posts-search-item"]').forEach(item => {
|
||||
if (selected.querySelector(`[data-post-id="${item.dataset.postId}"]`)) {
|
||||
item.remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add post items to the Unlock Posts selection.
|
||||
*
|
||||
* @since 5.16.0
|
||||
* @param {HTMLElement} target - The element that was clicked.
|
||||
*/
|
||||
|
||||
function fcn_unlockPostsAdd(target) {
|
||||
// Setup
|
||||
const template = _$('[data-target="fcn-unlock-posts-item-template"]').content.cloneNode(true);
|
||||
const item = template.querySelector('.unlock-posts__item');
|
||||
|
||||
// Build node
|
||||
item.dataset.postId = target.dataset.postId;
|
||||
item.title = target.title;
|
||||
item.querySelector('input[type="hidden"]').value = target.dataset.postId;
|
||||
item.querySelector('.unlock-posts__item-title').innerText = target.querySelector('.unlock-posts__item-title').innerText;
|
||||
item.querySelector('.unlock-posts__item-meta').innerText = target.querySelector('.unlock-posts__item-meta').innerText;
|
||||
|
||||
// Append
|
||||
_$('[data-target="fcn-unlock-posts-selected"]').appendChild(template);
|
||||
|
||||
// Remove search node
|
||||
target.remove();
|
||||
}
|
||||
|
@ -1012,3 +1012,72 @@ td.comment {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.unlock-posts {
|
||||
&__unlocked-posts,
|
||||
&__search-results {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
|
||||
&:not(:empty) {
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
&__search-form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px 5px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
&__item {
|
||||
cursor: default;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
background: #ddd;
|
||||
font-size: 12px;
|
||||
line-height: 1.2;
|
||||
padding-left: 9px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
|
||||
&:hover {
|
||||
background: #d6d6d6;
|
||||
}
|
||||
|
||||
&._searched {
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
padding: 7px;
|
||||
border: 1px dashed #ccc;
|
||||
|
||||
&:hover {
|
||||
background: rgb(0 0 0 / 3%);
|
||||
}
|
||||
}
|
||||
|
||||
> span:first-of-type {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 160px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&__delete {
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
padding: 4px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
&:not(.ajax-in-progress) .fa-spinner {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user