Compare commits
55 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d145405955 | ||
|
623d7ffa60 | ||
|
7463162a15 | ||
|
a1caff1ab7 | ||
|
cbc904e35b | ||
|
93f88321fa | ||
|
a78d54105e | ||
|
c8d286ed27 | ||
|
d81630c1c7 | ||
|
9be7dfbe21 | ||
|
0a98fcacc3 | ||
|
f958cca073 | ||
|
dfde0cc075 | ||
|
da1b854353 | ||
|
b5450f695c | ||
|
c6c64edc5d | ||
|
26047ab14d | ||
|
bb827ec1ef | ||
|
c9d3f526d8 | ||
|
b783d3cb9a | ||
|
9360506c2e | ||
|
d614b973c4 | ||
|
9b3913d0b9 | ||
|
9647f07524 | ||
|
32a0fea1c9 | ||
|
2f88220fa7 | ||
|
aa9a6e5459 | ||
|
7b4d2256e9 | ||
|
83a8500edb | ||
|
0948428500 | ||
|
9679d7d4fc | ||
|
42ae3a0224 | ||
|
0f5e890179 | ||
|
87af4114b7 | ||
|
f8cd013826 | ||
|
d1aee5e2ca | ||
|
e3b17c898b | ||
|
ed609f32b5 | ||
|
17df19a097 | ||
|
36aac5bd3e | ||
|
42367f0ae2 | ||
|
2326e7be0f | ||
|
78e68ffb9e | ||
|
2c2f541f9b | ||
|
e3ca8a0799 | ||
|
91b8083b0a | ||
|
0b9df8e84a | ||
|
ac71ecce7a | ||
|
691ed90d08 | ||
|
37561eb521 | ||
|
0f65c9f3d6 | ||
|
be32074540 | ||
|
6cb4670fa9 | ||
|
614a58a4a3 | ||
|
426ca24a2f |
58
ACTIONS.md
58
ACTIONS.md
@ -5,7 +5,7 @@ The following [action hooks](https://developer.wordpress.org/reference/functions
|
||||
This is an example of how to add a Discord invite link to the chapter top actions via the the `fictioneer_chapter_actions_top_center` hook. The link will feature a [Font Awesome Discord icon](https://fontawesome.com/icons/discord?f=brands) and be located between the formatting modal toggle (priority: 10) and fullscreen buttons (priority: 20). Note that no arguments of the hook are used because we do not need any of them here.
|
||||
|
||||
```php
|
||||
// Add this to your child theme's functions.php
|
||||
// Add this to your child theme’s functions.php
|
||||
function child_theme_discord_invite_link() {
|
||||
// Start HTML ---> ?>
|
||||
<a href="http://www.your-discord-invite-link.com" target="_blank" rel="noopener" class="button _secondary">
|
||||
@ -119,15 +119,28 @@ Fires after an user has been successfully created or logged-in via the OAuth 2.0
|
||||
* $user (WP_User) – The user object.
|
||||
|
||||
**$args:**
|
||||
* $channel (string) – Either `discord`, `patreon`, `twitch`, or `google`.
|
||||
* $uid (string) – External unique user ID from the linked account. Unsanitized.
|
||||
* $username (string) – The external username. Unsanitized.
|
||||
* $nickname (string) – The external nickname (or same as username). Unsanitized.
|
||||
* $email (string) – The external email address. Unsanitized.
|
||||
* $avatar_url (string) – The external avatar URL. Unsanitized.
|
||||
* $patreon_tiers (array) – The relevant Patreon tiers or an empty array. Unsanitized.
|
||||
* $new (boolean) – Whether this is a newly created user.
|
||||
* $merged (boolean) – Whether the account has been newly linked to an existing user.
|
||||
* 'channel' (string) – Either `discord`, `patreon`, `twitch`, or `google`.
|
||||
* 'uid' (string) – External unique user ID from the linked account. Unsanitized.
|
||||
* 'username' (string) – The external username. Unsanitized.
|
||||
* 'nickname' (string) – The external nickname (or same as username). Unsanitized.
|
||||
* 'email' (string) – The external email address. Unsanitized.
|
||||
* 'avatar_url' (string) – The external avatar URL. Unsanitized.
|
||||
* 'patreon_tiers' (array) – Associative array (Tier ID => Array) with the relevant Patreon tiers or an empty array. Unsanitized.
|
||||
* 'tier' (string) – Tier display title.
|
||||
* 'title' (string) – Tier display title.
|
||||
* 'description' (string) – Tier display description or empty.
|
||||
* 'published' (boolean) – Whether the tier is currently published.
|
||||
* 'amount_cents' (int) – Monetary amount associated with this tier (in U.S. cents).
|
||||
* 'timestamp' (int) – Unix timestamp (GMT) of the authentication in seconds.
|
||||
* 'id' (int) – Tier ID (also used as array key).
|
||||
* 'patreon_membership' (array) – Array with the Patreon membership data or an empty array. Unsanitized.
|
||||
* 'lifetime_support_cents' (int) – The total amount that the member has ever paid to the campaign in the campaign’s currency. `0` if never paid.
|
||||
* 'last_charge_date' (string|null) – Datetime (UTC ISO) of last attempted charge. `null` if never charged.
|
||||
* 'last_charge_status' (string|null) – The result of the last attempted charge. The only successful status is `'Paid'`. `null` if never charged. One of `'Paid'`, `'Declined'`, `'Deleted'`, `'Pending'`, `'Refunded'`, `'Fraud'`, `'Refunded by Patreon'`, `'Other'`, `'Partially Refunded'`, `'Free Trial'`.
|
||||
* 'next_charge_date' (string|null) – Datetime (UTC ISO) of next charge. `null` if annual pledge downgrade.
|
||||
* 'patron_status' (string|null) – One of `'active_patron'`, `'declined_patron'`, `'former_patron'`. A `null` value indicates the member has never pledged.
|
||||
* 'new' (boolean) – Whether this is a newly created user.
|
||||
* 'merged' (boolean) – Whether the account has been newly linked to an existing user.
|
||||
|
||||
---
|
||||
|
||||
@ -399,6 +412,23 @@ Fires right after the content section in the `single-fcn_chapter.php` template,
|
||||
* `fictioneer_chapter_support_links( $args )` – Support links set for the chapter/story/author. Priority 20.
|
||||
* `fictioneer_chapter_footer( $args )` – Chapter footer. Priority 99.
|
||||
|
||||
**Example:**
|
||||
```php
|
||||
function child_display_pw_expiration_date_in_chapter( $args ) {
|
||||
$password_expiration_date_utc = get_post_meta( $args['chapter_id'], 'fictioneer_post_password_expiration_date', true );
|
||||
|
||||
if ( empty( $password_expiration_date_utc ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$local_time = get_date_from_gmt( $password_expiration_date_utc );
|
||||
$formatted_datetime = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), strtotime( $local_time ) );
|
||||
|
||||
echo $formatted_datetime;
|
||||
}
|
||||
add_action( 'fictioneer_chapter_after_content', 'child_display_pw_expiration_date_in_chapter', 5 );
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `do_action( 'fictioneer_chapter_after_main', $args )`
|
||||
@ -607,6 +637,14 @@ List page template hook. Fires right at the top of an empty result list in the `
|
||||
|
||||
---
|
||||
|
||||
### `do_action( 'fictioneer_expired_post_password', $post )`
|
||||
Fires after a post password has been expired, which happens when a visitor tries to access the post.
|
||||
|
||||
**$args:**
|
||||
* $post (WP_Post) – The post that had its password expired.
|
||||
|
||||
---
|
||||
|
||||
### `do_action( 'fictioneer_footer', $args )`
|
||||
Fires outside the `#site` container and before the `wp_footer` hook, near the end of the document. Not to be confused with the `fictioneer_site_footer` hook.
|
||||
|
||||
|
@ -276,6 +276,7 @@ Fictioneer customizes WordPress by using as many standard action and filter hook
|
||||
| `admin_post_*` | `fictioneer_delete_all_epubs` (10), `fictioneer_tools_add_moderator_role` (10), `fictioneer_tools_move_story_tags_to_genres` (10), `fictioneer_tools_duplicate_story_tags_to_genres` (10), `fictioneer_tools_purge_theme_caches` (10), `fictioneer_tools_move_chapter_tags_to_genres` (10), `fictioneer_tools_duplicate_chapter_tags_to_genres` (10), `fictioneer_tools_append_default_genres` (10), `fictioneer_tools_append_default_tags` (10), `fictioneer_tools_remove_unused_tags` (10), `fictioneer_tools_reset_post_relationship_registry` (10), `fictioneer_admin_profile_unset_oauth` (10), `fictioneer_admin_profile_clear_data_node` (10), `fictioneer_update_frontend_profile` (10), `fictioneer_cancel_frontend_email_change` (10), `fictioneer_add_role` (10), `fictioneer_remove_role` (10), `fictioneer_rename_role` (10), `fictioneer_connection_get_patreon_tiers` (10), `fictioneer_connection_delete_patreon_tiers` (10)
|
||||
| `after_setup_theme` | `fictioneer_theme_setup` (10)
|
||||
| `bulk_edit_custom_box` | `fictioneer_add_patreon_bulk_edit_tiers` (10), `fictioneer_add_patreon_bulk_edit_amount` (10)
|
||||
| `bulk_edit_posts` | `fictioneer_save_chapter_bulk_edit` (10)
|
||||
| `comment_form_top` | `fictioneer_fix_comment_form_stimulus_controller` (10)
|
||||
| `comment_post` | `fictioneer_comment_post` (20), `fictioneer_post_comment_to_discord` (99)
|
||||
| `current_screen` | `fictioneer_restrict_admin_only_pages` (10), `fictioneer_restrict_comment_edit` (10)
|
||||
@ -303,14 +304,14 @@ Fictioneer customizes WordPress by using as many standard action and filter hook
|
||||
| `publish_to_draft` | `fictioneer_chapter_to_draft` (10)
|
||||
| `rest_api_init` | `fictioneer_register_endpoint_get_story_comments` (10)
|
||||
| `restrict_manage_posts` | `fictioneer_add_chapter_story_filter_dropdown` (10)
|
||||
| `save_post` | `fictioneer_refresh_chapters_schema` (20), `fictioneer_refresh_chapter_schema` (20), `fictioneer_refresh_collections_schema` (20), `fictioneer_refresh_post_caches` (20), `fictioneer_refresh_post_schema` (20), `fictioneer_refresh_recommendations_schema` (20), `fictioneer_refresh_recommendation_schema` (20), `fictioneer_refresh_stories_schema` (20), `fictioneer_refresh_story_schema` (20), `fictioneer_save_seo_metabox` (10), `fictioneer_save_word_count` (10), `fictioneer_track_chapter_and_story_updates` (10), `fictioneer_update_modified_date_on_story_for_chapter` (10), `fictioneer_update_shortcode_relationships` (10), `fictioneer_purge_transients_after_update` (10), `fictioneer_save_story_metaboxes` (10), `fictioneer_save_chapter_metaboxes` (10), `fictioneer_save_extra_metabox` (10), `fictioneer_save_support_links_metabox` (10), `fictioneer_save_collection_metaboxes` (10), `fictioneer_save_recommendation_metaboxes` (10), `fictioneer_save_post_metaboxes` (10), `fictioneer_delete_cached_story_card_after_update` (10), `fictioneer_rebuild_story_data_collection` (999), `fictioneer_post_chapter_to_discord` (99), `fictioneer_bulk_edit_save_patreon` (10), `fictioneer_bulk_edit_save_chapter_fields` (10)
|
||||
| `save_post` | `fictioneer_refresh_chapters_schema` (20), `fictioneer_refresh_chapter_schema` (20), `fictioneer_refresh_collections_schema` (20), `fictioneer_refresh_post_caches` (20), `fictioneer_refresh_post_schema` (20), `fictioneer_refresh_recommendations_schema` (20), `fictioneer_refresh_recommendation_schema` (20), `fictioneer_refresh_stories_schema` (20), `fictioneer_refresh_story_schema` (20), `fictioneer_save_seo_metabox` (10), `fictioneer_save_word_count` (10), `fictioneer_track_chapter_and_story_updates` (10), `fictioneer_update_modified_date_on_story_for_chapter` (10), `fictioneer_update_shortcode_relationships` (10), `fictioneer_purge_transients_after_update` (10), `fictioneer_save_story_metaboxes` (10), `fictioneer_save_chapter_metaboxes` (10), `fictioneer_save_extra_metabox` (10), `fictioneer_save_support_links_metabox` (10), `fictioneer_save_collection_metaboxes` (10), `fictioneer_save_recommendation_metaboxes` (10), `fictioneer_save_post_metaboxes` (10), `fictioneer_delete_cached_story_card_after_update` (10), `fictioneer_rebuild_story_data_collection` (999), `fictioneer_post_chapter_to_discord` (99), `fictioneer_post_story_to_discord` (99)
|
||||
| `send_headers` | `fictioneer_block_pages_from_indexing` (10)
|
||||
| `set_logged_in_cookie` | `fictioneer_set_logged_in_cookie` (10)
|
||||
| `show_user_profile` | `fictioneer_custom_profile_fields` (20)
|
||||
| `shutdown` | `fictioneer_save_story_card_cache` (10)
|
||||
| `switch_theme` | `fictioneer_theme_deactivation` (10)
|
||||
| `template_redirect` | `fictioneer_generate_epub` (10), `fictioneer_oauth2_process` (10), `fictioneer_logout` (10), `fictioneer_disable_attachment_pages` (10), `fictioneer_gate_unpublished_content` (10), `fictioneer_serve_sitemap` (10), `fictioneer_redirect_story` (10)
|
||||
| `transition_post_status` | `fictioneer_log_story_chapter_status_changes` (10), `fictioneer_chapter_future_to_publish` (10), `fictioneer_post_story_to_discord` (99)
|
||||
| `template_redirect` | `fictioneer_generate_epub` (10), `fictioneer_oauth2_process` (10), `fictioneer_logout` (10), `fictioneer_disable_attachment_pages` (10), `fictioneer_gate_unpublished_content` (10), `fictioneer_serve_sitemap` (10), `fictioneer_redirect_story` (10), `fictioneer_redirect_scheduled_chapter_404` (10)
|
||||
| `transition_post_status` | `fictioneer_log_story_chapter_status_changes` (10), `fictioneer_chapter_future_to_publish` (10)
|
||||
| `trashed_post` | `fictioneer_refresh_post_caches` (20), `fictioneer_track_chapter_and_story_updates` (10), `fictioneer_update_modified_date_on_story_for_chapter` (10), `fictioneer_purge_transients_after_update` (10), `fictioneer_remove_chapter_from_story` (10)
|
||||
| `untrash_post` | `fictioneer_refresh_post_caches` (20), `fictioneer_track_chapter_and_story_updates` (10), `fictioneer_update_modified_date_on_story_for_chapter` (10), `fictioneer_purge_transients_after_update` (10)
|
||||
| `update_option_*` | `fictioneer_update_option_disable_extended_chapter_list_meta_queries` (10), `fictioneer_update_option_disable_extended_story_list_meta_queries` (10)
|
||||
|
@ -799,6 +799,31 @@ Renders a subscribe button for the specified story.
|
||||
[fictioneer_subscribe_button story_id="228"]
|
||||
```
|
||||
|
||||
### Terms Shortcode
|
||||
|
||||
Renders a group of terms similar to those on story pages, either globally or for a specific post.
|
||||
|
||||
* **type:** The queried taxonomy. Choose between `category`, `tag`, `genre`, `fandom`, `character`, and `warning`. Default `tag`.
|
||||
* **post_id:** Query only terms for a specific post. Default `0` (none).
|
||||
* **count:** Limit the number of items. Default `-1` (all).
|
||||
* **order:** Either DESC (descending) or ASC (ascending). Default `desc`.
|
||||
* **orderby:** The default is `count`, but you can also use `name` and [more](https://developer.wordpress.org/reference/classes/wp_term_query/__construct/).
|
||||
* **show_empty:** Whether to show empty terms. Default `false`.
|
||||
* **show_count:** Whether to show the term count. Default `false`.
|
||||
* **class:** Additional CSS classes, separated by whitespace.
|
||||
* **inner_class:** Additional CSS classes for nested elements (if any), separated by whitespace.
|
||||
* **style:** Inline CSS style applied to the wrapping element.
|
||||
* **inner_style:** Inline CSS style applied to nested elements (if any).
|
||||
* **empty:** Override message for empty query results.
|
||||
|
||||
```
|
||||
[fictioneer_terms count="15"]
|
||||
```
|
||||
|
||||
```
|
||||
[fictioneer_terms type="genre" post_id="228" inner_class="_secondary" show_count="true" style="margin: 2rem 0;" empty=""]
|
||||
```
|
||||
|
||||
### Font Awesome Shortcode
|
||||
|
||||
Renders a *free* [Font Awesome](https://fontawesome.com/) icon, which you could technically do manually in the code editor as well. Somewhat more convenient, I guess? Just omit the shortcode block and write it directly into the text. This shortcode also works if your role lacks the shortcode capability.
|
||||
@ -815,6 +840,7 @@ Renders a multi-column grid of paginated medium cards ordered by publishing date
|
||||
|
||||
* **post_type:** Comma-separated list of post types to query. Default `post`.
|
||||
* **post_ids:** Comma-separated list of post IDs, if you want to pick from a curated pool.
|
||||
* **post_status:** Either `publish` or `future`, albeit others are possible (but why?). Note that by default, any post status except `publish` redirects to a 404 page for guests and users without higher permissions. Default `publish`.
|
||||
* **per_page:** Number of posts per page. Defaults to theme settings.
|
||||
* **count:** Limit articles to any positive number, disabling the pagination.
|
||||
* **order:** Either `desc` (descending) or `asc` (ascending). Default `desc`.
|
||||
@ -875,6 +901,7 @@ Renders paginated blog posts akin to the main blog page, but with options. Only
|
||||
* **ignore_sticky:** Whether sticky posts should be ignored or not. Default `false`.
|
||||
* **ignore_protected:** Whether protected posts should be ignored or not. Default `false`.
|
||||
* **only_protected:** Whether to query only protected posts or not. Default `false`.
|
||||
* **post_status:** Either `publish` or `future`, albeit others are possible (but why?). Note that by default, any post status except `publish` redirects to a 404 page for guests and users without higher permissions. Default `publish`.
|
||||
* **author:** Only show posts of a specific author. Make sure to use the url-safe nice_name.
|
||||
* **author_ids:** Only show posts of a comma-separated list of author IDs.
|
||||
* **exclude_author_ids:** Comma-separated list of author IDs to exclude.
|
||||
@ -926,6 +953,7 @@ Renders a multi-column grid of small bookmark cards, ordered by date of creation
|
||||
Renders a list of chapters identical to those on story pages, ordered by sequence in the source. Must have either the **story_id** or **chapter_ids** parameter, but not both.
|
||||
|
||||
* **story_id:** ID of a single story. You need either this or **chapters**.
|
||||
* **post_status:** Either `publish` or `future`, albeit others are possible (but why?). Note that by default, any post status except `publish` redirects to a 404 page for guests and users without higher permissions. Default `publish`.
|
||||
* **chapter_ids:** Comma-separated list of chapter IDs. You need either this or **story**.
|
||||
* **count:** Limit chapters to any positive number. Default `-1` (all).
|
||||
* **offset:** Skip a number of chapters, which can make sense if you query all.
|
||||
@ -998,6 +1026,7 @@ Renders a multi-column grid of small cards, showing the latest four chapters ord
|
||||
* **spoiler:** The excerpt is obfuscated, set `true` if you want to reveal it. Default `false`.
|
||||
* **source:** Whether to show the author and story nodes. Default `true`.
|
||||
* **post_ids:** Comma-separated list of chapter post IDs, if you want to pick from a curated pool.
|
||||
* **post_status:** Either `publish` or `future`, albeit others are possible (but why?). Note that by default, any post status except `publish` redirects to a 404 page for guests and users without higher permissions. Default `publish`.
|
||||
* **ignore_protected:** Whether protected posts should be ignored or not. Default `false`.
|
||||
* **only_protected:** Whether to query only protected posts or not. Default `false`.
|
||||
* **author_ids:** Only show posts of a comma-separated list of author IDs.
|
||||
@ -1064,6 +1093,7 @@ Renders the last blog post or a list of blog posts, ignoring sticky posts, order
|
||||
* **count:** Limit posts to any positive number, although you should keep it reasonable. Default `1`.
|
||||
* **author:** Only show posts of a specific author. Make sure to use the url-safe nice_name.
|
||||
* **post_ids:** Comma-separated list of post IDs, if you want to pick from a curated pool.
|
||||
* **post_status:** Either `publish` or `future`, albeit others are possible (but why?). Note that by default, any post status except `publish` redirects to a 404 page for guests and users without higher permissions. Default `publish`.
|
||||
* **ignore_protected:** Whether protected posts should be ignored or not. Default `false`.
|
||||
* **only_protected:** Whether to query only protected posts or not. Default `false`.
|
||||
* **author_ids:** Only show posts of a comma-separated list of author IDs.
|
||||
@ -1100,6 +1130,7 @@ Renders a multi-column grid of small cards, showing the latest four recommendati
|
||||
* **order:** Either `desc` (descending) or `asc` (ascending). Default `desc`.
|
||||
* **orderby:** The default is `date`, but you can also use `modified` and [more](https://developer.wordpress.org/reference/classes/wp_query/#order-orderby-parameters).
|
||||
* **post_ids:** Comma-separated list of post IDs, if you want to pick from a curated pool.
|
||||
* **post_status:** Either `publish` or `future`, albeit others are possible (but why?). Note that by default, any post status except `publish` redirects to a 404 page for guests and users without higher permissions. Default `publish`.
|
||||
* **ignore_protected:** Whether protected posts should be ignored or not. Default `false`.
|
||||
* **only_protected:** Whether to query only protected posts or not. Default `false`.
|
||||
* **author_ids:** Only show posts of a comma-separated list of author IDs.
|
||||
@ -1153,6 +1184,7 @@ Renders a multi-column grid of small cards, showing the latest four stories orde
|
||||
* **order:** Either `desc` (descending) or `asc` (ascending). Default `desc`.
|
||||
* **orderby:** The default is `date`, but you can also use `modified` and [more](https://developer.wordpress.org/reference/classes/wp_query/#order-orderby-parameters).
|
||||
* **post_ids:** Comma-separated list of story post IDs, if you want to pick from a curated pool.
|
||||
* **post_status:** Either `publish` or `future`, albeit others are possible (but why?). Note that by default, any post status except `publish` redirects to a 404 page for guests and users without higher permissions. Default `publish`.
|
||||
* **ignore_protected:** Whether protected posts should be ignored or not. Default `false`.
|
||||
* **only_protected:** Whether to query only protected posts or not. Default `false`.
|
||||
* **author_ids:** Only show posts of a comma-separated list of author IDs.
|
||||
@ -1231,6 +1263,7 @@ Renders a multi-column grid of small cards, showing the latest four updated stor
|
||||
* **author:** Only show updates of a specific author. Make sure to use the url-safe nice_name.
|
||||
* **order:** Either `desc` (descending) or `asc` (ascending). Default `desc`.
|
||||
* **post_ids:** Comma-separated list of post IDs, if you want to pick from a curated pool.
|
||||
* **post_status:** Either `publish` or `future`, albeit others are possible (but why?). Note that by default, any post status except `publish` redirects to a 404 page for guests and users without higher permissions. Default `publish`.
|
||||
* **ignore_protected:** Whether protected posts should be ignored or not. Default `false`.
|
||||
* **only_protected:** Whether to query only protected posts or not. Default `false`.
|
||||
* **author_ids:** Only show posts of a comma-separated list of author IDs.
|
||||
@ -1345,6 +1378,7 @@ Renders dynamic grid of thumbnails with title, showing the latest eight posts of
|
||||
* **order:** Either `desc` (descending) or `asc` (ascending). Default `desc`.
|
||||
* **orderby:** The default is `date`, but you can also use `rand` and [more](https://developer.wordpress.org/reference/classes/wp_query/#order-orderby-parameters).
|
||||
* **post_ids:** Comma-separated list of post IDs, if you want to pick from a curated pool.
|
||||
* **post_status:** Either `publish` or `future`, albeit others are possible (but why?). Note that by default, any post status except `publish` redirects to a 404 page for guests and users without higher permissions. Default `publish`.
|
||||
* **ignore_protected:** Whether protected posts should be ignored or not. Default `false`.
|
||||
* **only_protected:** Whether to query only protected posts or not. Default `false`.
|
||||
* **author_ids:** Only show posts of a comma-separated list of author IDs.
|
||||
|
121
FILTERS.md
121
FILTERS.md
@ -927,10 +927,11 @@ Filters the story message array passed to `fictioneer_discord_send_message()` in
|
||||
|
||||
---
|
||||
|
||||
### `apply_filters( 'fictioneer_filter_discord_chapter_webhook', $post, $story_id )`
|
||||
### `apply_filters( 'fictioneer_filter_discord_chapter_webhook', $webhook, $post, $story_id )`
|
||||
Filters the webhook used for the Discord notification about a new chapters.
|
||||
|
||||
**Parameters:**
|
||||
* $webhook (string) - The Discord webhook.
|
||||
* $post (WP_Post) - The chapter post.
|
||||
* $story_id (int|null) - The ID of the story post (if any). Unsafe.
|
||||
|
||||
@ -1073,11 +1074,46 @@ Filters the boolean return value of the `fictioneer_is_editor( $user_id )` funct
|
||||
|
||||
---
|
||||
|
||||
### `apply_filters( 'fictioneer_filter_list_chapter_prefix', $prefix )`
|
||||
### `apply_filters( 'fictioneer_filter_list_chapter_prefix', $prefix, $chapter_id, $context )`
|
||||
Filters the prefix string (if any) in front of a chapter title before it is rendered in the `_story-content.php` partial or `fictioneer_chapter_list` shortcode. Useful if you want to add a wrapper for styling purposes.
|
||||
|
||||
**Parameters:**
|
||||
* $prefix (string) – Chapter prefix.
|
||||
* $chapter_id (int) - Post ID of the chapter.
|
||||
* $context (string) – Either `'story'` or `'shortcode'`.
|
||||
|
||||
---
|
||||
|
||||
### `apply_filters( 'fictioneer_filter_list_chapter_title_row', $output, $chapter_id, $prefix, $has_password, $context )`
|
||||
Filters the intermediate output HTML of the chapter list title row before it is rendered in the `_story-content.php` partial or `fictioneer_chapter_list` shortcode.
|
||||
|
||||
**Parameters:**
|
||||
* $output (string) – The chapter title row HTML.
|
||||
* $chapter_id (int) - Post ID of the chapter.
|
||||
* $prefix (string) – Filtered chapter prefix.
|
||||
* $has_password (boolean) – Whether the chapter has a password.
|
||||
* $context (string) – Either `'story'` or `'shortcode'`.
|
||||
|
||||
**Example:**
|
||||
```php
|
||||
function child_display_pw_expiration_date_in_chapter_lists( $output, $chapter_id, $prefix, $has_password ) {
|
||||
if ( ! $has_password ) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
$password_expiration_date_utc = get_post_meta( $chapter_id, 'fictioneer_post_password_expiration_date', true );
|
||||
|
||||
if ( empty( $password_expiration_date_utc ) ) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
$local_time = get_date_from_gmt( $password_expiration_date_utc );
|
||||
$formatted_datetime = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), strtotime( $local_time ) );
|
||||
|
||||
return "[{$formatted_datetime}] {$output}";
|
||||
}
|
||||
add_filter( 'fictioneer_filter_list_chapter_title_row', 'child_display_pw_expiration_date_in_chapter_lists', 10, 4 );
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@ -1209,6 +1245,21 @@ Filters the HTML of the message displayed below the Patreon unlock button. The m
|
||||
|
||||
---
|
||||
|
||||
### `apply_filters( 'fictioneer_filter_patreon_tier_unlock', $required, $post, $user, $patreon_post_data )`
|
||||
Filters the boolean to determine whether a post is unlocked via Patreon tier.
|
||||
|
||||
**Parameters:**
|
||||
* $required (boolean) – Whether the post is unlocked.
|
||||
* $post (WP_Post) – The post object.
|
||||
* $user (WP_User) – The current user.
|
||||
* $patreon_post_data (array) – Relevant Patreon data for the post.
|
||||
* 'gated' (boolean) - Whether the post has tiers or a cent amount assigned.
|
||||
* 'gate_tiers' (array) - Tiers that unlock the post.
|
||||
* 'gated' (int) - Minimum cent amount that unlocks the post.
|
||||
* 'gate_lifetime_cents' (int) - Minimum lifetime cent amount that unlocks the post.
|
||||
|
||||
---
|
||||
|
||||
### `apply_filters( 'fictioneer_filter_post_card_footer', $footer_items, $post, $args )`
|
||||
Filters the intermediate output array in the `_card-post.php` partial before it is imploded and rendered. Contains statistics with icons such as the author, publishing date, and comments.
|
||||
|
||||
@ -1370,6 +1421,43 @@ Filters the RSS link returned by the `fictioneer_get_rss_link( $post_type, $post
|
||||
|
||||
---
|
||||
|
||||
### `apply_filters( 'fictioneer_filter_rss_main_query_args', $query_args )`
|
||||
Filters the query arguments for the main RSS feed in the `rss-rss-main.php` template.
|
||||
|
||||
**Parameters:**
|
||||
* $query_args (array) – Associative array of query arguments.
|
||||
|
||||
**Example:**
|
||||
```php
|
||||
function child_exclude_protected_posts_from_main_rss( $query_args ) {
|
||||
$query_args['has_password'] = false;
|
||||
|
||||
return $query_args;
|
||||
}
|
||||
add_filter( 'fictioneer_filter_rss_story_query_args', 'child_exclude_protected_posts_from_main_rss' );
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `apply_filters( 'fictioneer_filter_rss_story_query_args', $query_args, $story_id )`
|
||||
Filters the query arguments for the story RSS feed in the `rss-rss-story.php` template.
|
||||
|
||||
**Parameters:**
|
||||
* $query_args (array) – Associative array of query arguments.
|
||||
* $story_id (int) – Post ID of the story.
|
||||
|
||||
**Example:**
|
||||
```php
|
||||
function child_exclude_protected_posts_from_story_rss( $query_args ) {
|
||||
$query_args['has_password'] = false;
|
||||
|
||||
return $query_args;
|
||||
}
|
||||
add_filter( 'fictioneer_filter_rss_story_query_args', 'child_exclude_protected_posts_from_story_rss' );
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `apply_filters( 'fictioneer_filter_safe_title', $title, $post_id, $context, $args )`
|
||||
Filters the string returned by the `fictioneer_get_safe_title( $post_id )` function, after all tags and line breaks have been stripped. No further sanitization is applied here, so you can add HTML again.
|
||||
|
||||
@ -1487,7 +1575,7 @@ Filters the WP_Query arguments in the `fictioneer_blog` shortcode.
|
||||
* $posts_per_page (int) – `$args['posts_per_page']`
|
||||
* $tax_query (array|null) – `fictioneer_get_shortcode_tax_query( $args )`
|
||||
|
||||
**$attr:**
|
||||
**$args:**
|
||||
* $posts_per_page (int) – The number of posts per page. Defaults to WordPress.
|
||||
* $page (int) – Current main query page number. Default `1`.
|
||||
* $ignore_sticky (boolean) – Optional. Whether to ignore sticky posts. Default `false`.
|
||||
@ -1837,6 +1925,33 @@ Filters the WP_Query arguments in the `fictioneer_showcase` shortcode. The optio
|
||||
|
||||
---
|
||||
|
||||
### `apply_filters( 'fictioneer_filter_shortcode_terms_query_args', $query_args, $attr )`
|
||||
Filters the WP_Term_Query arguments in the `fictioneer_terms` shortcode.
|
||||
|
||||
**$query_args:**
|
||||
* 'fictioneer_query_name' (string) – `'terms_shortcode'`
|
||||
* 'taxonomy' (string) – As specified in the shortcode. Either `'category'`, `'post_tag'`, `'fcn_genre'`, `'fcn_fandom'`, `'fcn_character'`, or `'fcn_content_warning'`.
|
||||
* 'orderby' (string) – As specified in the shortcode. Default `'count'`.
|
||||
* 'order' (string) – As specified in the shortcode. Default `'desc'`.
|
||||
* 'number' (int|null) – As specified in the shortcode. Default `null`.
|
||||
* 'hide_empty' (bool) – As specified in the shortcode. Default `true`.
|
||||
|
||||
**$attr:**
|
||||
* 'term_type' (string|null) – Either `'category'`, `'tag'`, `'genre'`, `'fandom'`, `'character'`, or `'warning'`. Default `'tag'`.
|
||||
* 'post_id' (int|null) – Limit terms to a specific post. Default `0`.
|
||||
* 'count' (int|null) – Limit number of queried terms. Default `-1` (all).
|
||||
* 'orderby' (string|null) – Default `'count'`.
|
||||
* 'order' (string|null) – Default `'desc'`.
|
||||
* 'show_empty' (boolean|null) – Whether to query unused terms. Default `false`.
|
||||
* 'show_count' (boolean|null) – Whether to show the term counts. Default `false`.
|
||||
* 'classes' (string|null) – String of additional outer CSS classes. Default empty.
|
||||
* 'inner_classes' (string|null) – String of additional inner CSS classes. Default empty.
|
||||
* 'style' (string|null) – String of additional outer inline styles. Default empty.
|
||||
* 'inner_style' (string|null) – String of additional inner inline styles. Default empty.
|
||||
* 'empty' (string|null) – Override message for empty query result. Default empty.
|
||||
|
||||
---
|
||||
|
||||
### `apply_filters( 'fictioneer_filter_sitemap_page_template_excludes', $excludes )`
|
||||
Filters the exclusion array of page templates for the custom theme sitemap. By default, these are `'user-profile.php'`, `'singular-bookmarks.php'`, `'singular-bookshelf.php'`, and `'singular-bookshelf-ajax.php'`.
|
||||
|
||||
|
@ -7,6 +7,9 @@ You can migrate an existing database through several means. The easiest, albeit
|
||||
Add the following script to your `functions.php` file, for example via the **Theme File Editor** under **Appearance**. This serves as the base for the described migration methods and as a template if you want to write your own script. Make sure to remove the code once you are done; you do not want to leave this in a production environment. You can find a list of all story and chapter meta fields in the [development guide](DEVELOPMENT.md#story-meta-fields).
|
||||
|
||||
```php
|
||||
// This is just the base migration script to convert and assign chapters;
|
||||
// you also need to add one of the method scripts described afterwards!
|
||||
|
||||
function fictioneer_migrate_chapters( $query_args = [], $story_args = [], $preview = true ) {
|
||||
// Security check (only allow admins to execute script)
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
@ -160,7 +163,7 @@ function fictioneer_migrate_chapters( $query_args = [], $story_args = [], $previ
|
||||
}
|
||||
```
|
||||
|
||||
## Simple Migration
|
||||
## Method 1: Simple Migration
|
||||
|
||||
Add the following script to your `functions.php` file. This script will query ALL posts and convert them to chapters, optionally appending them to a prepared story post. You can customize the parameters if needed. The action can be called by opening `/wp-admin/admin-post.php?action=fictioneer_migrate` on your site. You will first get a preview of which chapters are about to be migrated; if you are happy with the preview, click the "Start migration!" link.
|
||||
|
||||
@ -168,7 +171,7 @@ Add the following script to your `functions.php` file. This script will query AL
|
||||
function fictioneer_migrate() {
|
||||
// Story data if you want to append the chapters
|
||||
$story_args = array(
|
||||
'story_id' => null, // Leave null if you only want to convert chapters
|
||||
'story_id' => null, // Existing story post ID; leave null if you only want to convert chapters
|
||||
'age_rating' => 'Everyone', // Choose: 'Everyone', 'Teen', 'Mature', or 'Adult' (capitalized and in English)
|
||||
'status' => 'Ongoing', // Choose: 'Ongoing', 'Completed', 'Oneshot', 'Hiatus', or 'Cancelled' (capitalized and in English)
|
||||
'description' => null, // Used on cards; falls back to excerpt
|
||||
@ -206,7 +209,7 @@ function fictioneer_migrate() {
|
||||
add_action( 'admin_post_fictioneer_migrate', 'fictioneer_migrate' );
|
||||
```
|
||||
|
||||
## Migrate by Author(s)
|
||||
## Method 2: Migrate by Author(s)
|
||||
|
||||
Add the following script to your `functions.php` file. Unlike the simple approach, this script will loop over a predefined set of author data (created by you) to migrate specific posts to specific stories. In this case, a category is used as a discriminator, but other attributes can work too. The action can be called by opening `/wp-admin/admin-post.php?action=fictioneer_migrate_by_author` on your site. Note that you will NOT get a preview; the migration happens immediately!
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -5,9 +5,9 @@
|
||||
// =============================================================================
|
||||
|
||||
// Version
|
||||
define( 'FICTIONEER_VERSION', '5.27.1' );
|
||||
define( 'FICTIONEER_VERSION', '5.27.2' );
|
||||
define( 'FICTIONEER_MAJOR_VERSION', '5' );
|
||||
define( 'FICTIONEER_RELEASE_TAG', 'v5.27.1' );
|
||||
define( 'FICTIONEER_RELEASE_TAG', 'v5.27.2' );
|
||||
|
||||
if ( ! defined( 'CHILD_VERSION' ) ) {
|
||||
define( 'CHILD_VERSION', null );
|
||||
@ -99,14 +99,14 @@ define(
|
||||
|
||||
// String: Font Awesome CDN URL
|
||||
if ( ! defined( 'FICTIONEER_FA_CDN' ) ) {
|
||||
define( 'FICTIONEER_FA_CDN', 'https://use.fontawesome.com/releases/v6.6.0/css/all.css' );
|
||||
define( 'FICTIONEER_FA_CDN', 'https://use.fontawesome.com/releases/v6.7.2/css/all.css' );
|
||||
}
|
||||
|
||||
// String: Font Awesome CDN integrity (generated by https://www.srihash.org/)
|
||||
if ( ! defined( 'FICTIONEER_FA_INTEGRITY' ) ) {
|
||||
define(
|
||||
'FICTIONEER_FA_INTEGRITY',
|
||||
'sha384-h/hnnw1Bi4nbpD6kE7nYfCXzovi622sY5WBxww8ARKwpdLj5kUWjRuyiXaD1U2JT'
|
||||
'sha384-nRgPTkuX86pH8yjPJUAFuASXQSSl2/bBUiNV47vSYpKFxHJhbcrGnmlYpYJMeD7a'
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1535,6 +1535,16 @@ function fictioneer_add_layout_customizer_settings( $manager ) {
|
||||
'right' => _x( 'Right', 'Customizer header sidebar option.', 'fictioneer' )
|
||||
);
|
||||
|
||||
if ( get_option( 'fictioneer_disable_all_widgets' ) ) {
|
||||
$description = sprintf(
|
||||
'%s <div style="margin: 10px 0;">%s</div>',
|
||||
__( 'Choose whether and where to render the sidebar. You can set it up under Widgets; it will not appear before that.', 'fictioneer' ),
|
||||
__( '<strong>Note:</strong> Widgets are currently disabled under Fictioneer > General > Performance. You need to enable them first.', 'fictioneer' )
|
||||
);
|
||||
} else {
|
||||
$description = __( 'Choose whether and where to render the sidebar. You can set it up under Widgets; it will not appear before that.', 'fictioneer' );
|
||||
}
|
||||
|
||||
$manager->add_control(
|
||||
'sidebar_style',
|
||||
array(
|
||||
@ -1542,12 +1552,12 @@ function fictioneer_add_layout_customizer_settings( $manager ) {
|
||||
'priority' => 6,
|
||||
'section' => 'layout',
|
||||
'label' => __( 'Sidebar', 'fictioneer' ),
|
||||
'description' => __( 'Choose whether and where to render the sidebar. You can set it up under Widgets.', 'fictioneer' ),
|
||||
'description' => $description,
|
||||
'choices' => apply_filters( 'fictioneer_filter_customizer_sidebar_style', $sidebar_styles )
|
||||
)
|
||||
);
|
||||
|
||||
// Disable story sidebar
|
||||
// Disable mobile sidebar
|
||||
$manager->add_setting(
|
||||
'sidebar_hide_on_mobile',
|
||||
array(
|
||||
|
@ -101,8 +101,8 @@ function fictioneer_generate_test_content() {
|
||||
|
||||
// Disable Discord
|
||||
remove_action( 'comment_post', 'fictioneer_post_comment_to_discord', 99 );
|
||||
remove_action( 'transition_post_status', 'fictioneer_post_story_to_discord', 99 );
|
||||
remove_action( 'transition_post_status', 'fictioneer_post_chapter_to_discord', 99 );
|
||||
remove_action( 'save_post', 'fictioneer_post_story_to_discord', 99 );
|
||||
remove_action( 'save_post', 'fictioneer_post_chapter_to_discord', 99 );
|
||||
|
||||
// Setup
|
||||
$user_count = absint( $_GET['users'] ?? 1 );
|
||||
|
@ -2786,7 +2786,7 @@ function fictioneer_render_skin_interface() {
|
||||
|
||||
<template data-css-skin-target="template">
|
||||
<div class="custom-skin" data-css-skin-finder="skin-item">
|
||||
<button type="button" class="custom-skin__toggle" data-action="click->css-skin#toggle">
|
||||
<button type="button" class="custom-skin__toggle" data-action="click->css-skin#toggle" data-fictioneer-target="dcjProtected" disabled>
|
||||
<i class="fa-regular fa-circle off"></i>
|
||||
<i class="fa-solid fa-circle-dot on"></i>
|
||||
</button>
|
||||
@ -2797,7 +2797,7 @@ function fictioneer_render_skin_interface() {
|
||||
<span class="custom-skin__spacer"></span>
|
||||
<span class="custom-skin__author" data-css-skin-finder="author">—</span>
|
||||
</div>
|
||||
<button type="button" class="custom-skin__delete" data-action="click->css-skin#delete"><i class="fa-solid fa-trash-can"></i></button>
|
||||
<button type="button" class="custom-skin__delete" data-action="click->css-skin#delete" data-fictioneer-target="dcjProtected" disabled><i class="fa-solid fa-trash-can"></i></button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -2824,8 +2824,8 @@ function fictioneer_render_skin_interface() {
|
||||
</div>
|
||||
|
||||
<div class="profile__actions custom-skin-actions">
|
||||
<button type="button" class="button" data-action="click->css-skin#upload" data-disable-with="<?php esc_attr_e( 'Uploading…', 'fictioneer' ); ?>"><?php _e( 'Sync Up', 'fictioneer' ); ?></button>
|
||||
<button type="button" class="button" data-action="click->css-skin#download" data-disable-with="<?php esc_attr_e( 'Downloading…', 'fictioneer' ); ?>"><?php _e( 'Sync Down', 'fictioneer' ); ?></button>
|
||||
<button type="button" class="button" data-action="click->css-skin#upload" data-disable-with="<?php esc_attr_e( 'Uploading…', 'fictioneer' ); ?>" data-fictioneer-target="dcjProtected" disabled><?php _e( 'Sync Up', 'fictioneer' ); ?></button>
|
||||
<button type="button" class="button" data-action="click->css-skin#download" data-disable-with="<?php esc_attr_e( 'Downloading…', 'fictioneer' ); ?>" data-fictioneer-target="dcjProtected" disabled><?php _e( 'Sync Down', 'fictioneer' ); ?></button>
|
||||
<div class="invisible custom-skin-action-status" data-css-skin-target="action-status-message"><span class="dashicons dashicons-saved"></span></div>
|
||||
</div>
|
||||
|
||||
|
@ -328,10 +328,10 @@ function fictioneer_patreon_tiers_valid( $user = null ) {
|
||||
// Setup
|
||||
$patreon_tiers = get_user_meta( $user_id, 'fictioneer_patreon_tiers', true );
|
||||
$patreon_tiers = is_array( $patreon_tiers ) ? $patreon_tiers : [];
|
||||
$last_updated = empty( $patreon_tiers ) ? 0 : ( $patreon_tiers[0]['timestamp'] ?? 0 );
|
||||
$last_updated = empty( $patreon_tiers ) ? 0 : ( reset( $patreon_tiers )['timestamp'] ?? 0 );
|
||||
|
||||
// Check
|
||||
$valid = time() <= $last_updated + FICTIONEER_PATREON_EXPIRATION_TIME;
|
||||
$valid = current_time( 'U', true ) <= ( $last_updated + FICTIONEER_PATREON_EXPIRATION_TIME );
|
||||
|
||||
// Filter and return
|
||||
return apply_filters( 'fictioneer_filter_user_patreon_validation', $valid, $user_id, $patreon_tiers );
|
||||
@ -345,7 +345,7 @@ function fictioneer_patreon_tiers_valid( $user = null ) {
|
||||
* @param int|WP_User|null $user The user object or user ID. Defaults to current user.
|
||||
*
|
||||
* @return array Empty array if not a patron, associative array otherwise. Includes the
|
||||
* keys 'valid', 'is_follower', 'lifetime_support_cents', 'last_charge_date',
|
||||
* keys 'valid', 'lifetime_support_cents', 'last_charge_date',
|
||||
* 'last_charge_status', 'next_charge_date', 'patron_status', and 'tiers'.
|
||||
* Tiers is an array of tiers with the keys 'id', 'title', 'description',
|
||||
* 'published', 'amount_cents', and 'timestamp'.
|
||||
|
@ -191,15 +191,29 @@ if ( get_option( 'fictioneer_discord_channel_comments_webhook' ) ) {
|
||||
*
|
||||
* @since 5.6.0
|
||||
* @since 5.21.2 - Refactored.
|
||||
* @since 5.27.2 - Switch back to save_post hook to ensure the thumbnail is saved.
|
||||
*
|
||||
* @param string $new_status New post status.
|
||||
* @param string $new_status Old post status.
|
||||
* @param int $post_id Post ID.
|
||||
* @param WP_Post $post Post object.
|
||||
* @param bool $update Whether this is an existing post being updated. Unreliable.
|
||||
*/
|
||||
|
||||
function fictioneer_post_story_to_discord( $new_status, $old_status, $post ) {
|
||||
// Only if story going from non-publish status to publish
|
||||
if ( $post->post_type !== 'fcn_story' || $new_status !== 'publish' || $old_status === 'publish' ) {
|
||||
function fictioneer_post_story_to_discord( $post_id, $post, $update ) {
|
||||
// Prevent multi-fire
|
||||
if ( fictioneer_multi_save_guard( $post_id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only if published chapter
|
||||
if ( $post->post_type !== 'fcn_story' || $post->post_status !== 'publish' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only if published less than 10 minutes ago
|
||||
$post_timestamp = get_post_time( 'U', true, $post_id );
|
||||
$current_timestamp = current_time( 'U', true );
|
||||
|
||||
if ( $update && ( $current_timestamp - $post_timestamp ) >= 600 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -210,14 +224,13 @@ function fictioneer_post_story_to_discord( $new_status, $old_status, $post ) {
|
||||
|
||||
// Data
|
||||
$title = html_entity_decode( get_the_title( $post ) );
|
||||
$url = get_permalink( $post->ID );
|
||||
|
||||
// Message
|
||||
$message = array(
|
||||
'content' => sprintf(
|
||||
_x( "New story published: [%s](%s)!\n_ _", 'Discord message for new story.', 'fictioneer' ),
|
||||
$title,
|
||||
$url
|
||||
get_permalink( $post_id )
|
||||
),
|
||||
'embeds' => array(
|
||||
array(
|
||||
@ -258,11 +271,11 @@ function fictioneer_post_story_to_discord( $new_status, $old_status, $post ) {
|
||||
update_post_meta( $post->ID, 'fictioneer_discord_post_trigger', true );
|
||||
|
||||
// Unhook if done to avoid additional triggers (if any)
|
||||
remove_action( 'transition_post_status', 'fictioneer_post_story_to_discord', 99 );
|
||||
remove_action( 'save_post', 'fictioneer_post_story_to_discord', 99 );
|
||||
}
|
||||
|
||||
if ( get_option( 'fictioneer_discord_channel_stories_webhook' ) ) {
|
||||
add_action( 'transition_post_status', 'fictioneer_post_story_to_discord', 99, 3 );
|
||||
add_action( 'save_post', 'fictioneer_post_story_to_discord', 99, 3 );
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
@ -278,7 +291,7 @@ if ( get_option( 'fictioneer_discord_channel_stories_webhook' ) ) {
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
* @param WP_Post $post Post object.
|
||||
* @param bool $update Whether this is an existing post being updated.
|
||||
* @param bool $update Whether this is an existing post being updated. Unreliable.
|
||||
*/
|
||||
|
||||
function fictioneer_post_chapter_to_discord( $post_id, $post, $update ) {
|
||||
|
@ -490,7 +490,8 @@ function fictioneer_oauth2_make_user( $user_data, $cookie ) {
|
||||
'nickname' => $user_data['nickname'],
|
||||
'email' => $user_data['email'],
|
||||
'avatar_url' => $user_data['avatar'],
|
||||
'patreon_tiers' => $user_data['patreon_tiers'] ?? [],
|
||||
'patreon_tiers' => $user_data['tiers'] ?? [],
|
||||
'patreon_membership' => $user_data['membership'] ?? [],
|
||||
'new' => $new,
|
||||
'merged' => $merged
|
||||
)
|
||||
@ -790,7 +791,7 @@ function fictioneer_oauth2_patreon( $token_response, $cookie ) {
|
||||
// Build params
|
||||
$params = '?fields' . urlencode( '[user]' ) . '=email,first_name,image_url,is_email_verified';
|
||||
$params .= '&fields' . urlencode( '[tier]' ) . '=title,amount_cents,published,description';
|
||||
$params .= '&fields' . urlencode( '[member]' ) . '=lifetime_support_cents,is_follower,last_charge_date,last_charge_status,next_charge_date,patron_status';
|
||||
$params .= '&fields' . urlencode( '[member]' ) . '=lifetime_support_cents,campaign_lifetime_support_cents,last_charge_date,last_charge_status,next_charge_date,patron_status';
|
||||
$params .= '&include=memberships.currently_entitled_tiers';
|
||||
|
||||
// Retrieve user data from Patreon
|
||||
@ -827,13 +828,13 @@ function fictioneer_oauth2_patreon( $token_response, $cookie ) {
|
||||
// Tiers data
|
||||
foreach ( $user->included as $node ) {
|
||||
if ( isset( $node->type ) && $node->type === 'tier' ) {
|
||||
$tiers[] = array(
|
||||
$tiers[ $node->id ] = array(
|
||||
'tier' => sanitize_text_field( $node->attributes->title ),
|
||||
'title' => sanitize_text_field( $node->attributes->title ),
|
||||
'description' => wp_kses_post( $node->attributes->description ?? '' ),
|
||||
'published' => filter_var( $node->attributes->published ?? 0, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ),
|
||||
'amount_cents' => absint( $node->attributes->amount_cents ?? 0 ),
|
||||
'timestamp' => time(),
|
||||
'timestamp' => current_time( 'U', true ),
|
||||
'id' => $node->id
|
||||
);
|
||||
$tier_ids[] = $node->id;
|
||||
@ -846,12 +847,10 @@ function fictioneer_oauth2_patreon( $token_response, $cookie ) {
|
||||
isset( $node->type ) &&
|
||||
$node->type === 'member' &&
|
||||
isset( $node->attributes ) &&
|
||||
isset( $node->attributes->lifetime_support_cents ) &&
|
||||
isset( $node->relationships->currently_entitled_tiers->data ) &&
|
||||
in_array( $node->relationships->currently_entitled_tiers->data[0]->id, $tier_ids )
|
||||
) {
|
||||
$membership['is_follower'] = $node->attributes->is_follower ?? 0;
|
||||
$membership['lifetime_support_cents'] = $node->attributes->lifetime_support_cents ?? 0;
|
||||
$membership['lifetime_support_cents'] = $node->attributes->lifetime_support_cents ?? $node->attributes->campaign_lifetime_support_cents ?? 0;
|
||||
$membership['last_charge_date'] = $node->attributes->last_charge_date ?? null;
|
||||
$membership['last_charge_status'] = $node->attributes->last_charge_status ?? null;
|
||||
$membership['next_charge_date'] = $node->attributes->next_charge_date ?? null;
|
||||
|
@ -383,6 +383,8 @@ function fictioneer_expire_post_password( $required, $post ) {
|
||||
fictioneer_refresh_post_caches( $post->ID );
|
||||
wp_update_post( array( 'ID' => $post->ID, 'post_password' => '' ) );
|
||||
|
||||
do_action( 'fictioneer_expired_post_password', $post );
|
||||
|
||||
$required = false;
|
||||
}
|
||||
}
|
||||
|
@ -4156,7 +4156,7 @@ add_action( 'save_post', 'fictioneer_save_recommendation_metaboxes' );
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Hide Patreon columns in list table views by default
|
||||
* Hides Patreon columns in list table views by default.
|
||||
*
|
||||
* @since 5.17.0
|
||||
*
|
||||
@ -4182,7 +4182,7 @@ function fictioneer_default_hide_patreon_posts_columns( $hidden, $screen ) {
|
||||
add_filter( 'default_hidden_columns', 'fictioneer_default_hide_patreon_posts_columns', 10, 2 );
|
||||
|
||||
/**
|
||||
* Add Patreon columns to list table views
|
||||
* Adds Patreon columns to list table views.
|
||||
*
|
||||
* @since 5.17.0
|
||||
*
|
||||
@ -4202,7 +4202,7 @@ function fictioneer_add_posts_columns_patreon( $post_columns ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Output Patreon values in list table views
|
||||
* Renders Patreon values in list table views.
|
||||
*
|
||||
* @since 5.17.0
|
||||
*
|
||||
@ -4249,7 +4249,7 @@ function fictioneer_manage_posts_column_patreon( $column_name, $post_id ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Patreon tiers to bulk edit
|
||||
* Adds Patreon tiers to bulk edit.
|
||||
*
|
||||
* @since 5.17.0
|
||||
*
|
||||
@ -4286,6 +4286,9 @@ function fictioneer_add_patreon_bulk_edit_tiers( $column_name, $post_type ) {
|
||||
);
|
||||
}
|
||||
|
||||
// Nonce
|
||||
wp_nonce_field( 'fictioneer_bulk_edit_patreon', 'fictioneer_bulk_edit_patreon_nonce', false );
|
||||
|
||||
// Start HTML ---> ?>
|
||||
<fieldset class="inline-edit-col-left">
|
||||
<div class="inline-edit-patreon-tiers-wrap">
|
||||
@ -4296,17 +4299,17 @@ function fictioneer_add_patreon_bulk_edit_tiers( $column_name, $post_type ) {
|
||||
|
||||
<div class="bulk-edit-box">
|
||||
|
||||
<input type="hidden" name="fictioneer_patreon_lock_tiers_bulk" value="no_change">
|
||||
<input type="hidden" name="fictioneer_bulk_edit_patreon_lock_tiers" value="no_change">
|
||||
|
||||
<label class="bulk-edit-checkbox-label-pair">
|
||||
<input type="checkbox" name="fictioneer_patreon_lock_tiers_bulk" value="remove">
|
||||
<input type="checkbox" name="fictioneer_bulk_edit_patreon_lock_tiers" value="remove">
|
||||
<span><?php _e( 'Remove Tiers', 'fictioneer' ); ?></span>
|
||||
</label>
|
||||
|
||||
<?php foreach ( $tier_options as $key => $tier ) : ?>
|
||||
|
||||
<label class="bulk-edit-checkbox-label-pair">
|
||||
<input type="checkbox" name="fictioneer_patreon_lock_tiers_bulk[]" value="<?php echo $key; ?>">
|
||||
<input type="checkbox" name="fictioneer_bulk_edit_patreon_lock_tiers[]" value="<?php echo $key; ?>">
|
||||
<span><?php echo $tier; ?></span>
|
||||
</label>
|
||||
|
||||
@ -4320,7 +4323,7 @@ function fictioneer_add_patreon_bulk_edit_tiers( $column_name, $post_type ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Patreon amount_cents to bulk edit
|
||||
* Adds Patreon amount_cents to bulk edit.
|
||||
*
|
||||
* @since 5.17.0
|
||||
*
|
||||
@ -4337,6 +4340,9 @@ function fictioneer_add_patreon_bulk_edit_amount( $column_name, $post_type ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Nonce
|
||||
wp_nonce_field( 'fictioneer_bulk_edit_patreon', 'fictioneer_bulk_edit_patreon_nonce', false );
|
||||
|
||||
// Start HTML ---> ?>
|
||||
<fieldset class="inline-edit-col-left">
|
||||
<div class="inline-edit-patreon-amount-cents-wrap">
|
||||
@ -4346,7 +4352,7 @@ function fictioneer_add_patreon_bulk_edit_amount( $column_name, $post_type ) {
|
||||
?></span>
|
||||
|
||||
<div>
|
||||
<input type="number" name="fictioneer_patreon_lock_amount_bulk" autocomplete="off" min="0">
|
||||
<input type="number" name="fictioneer_bulk_edit_patreon_lock_amount" autocomplete="off" min="0">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@ -4355,56 +4361,93 @@ function fictioneer_add_patreon_bulk_edit_amount( $column_name, $post_type ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Patreon bulk edit fields
|
||||
* Saves bulk edit Patreon meta.
|
||||
*
|
||||
* @since 5.17.0
|
||||
* @since 5.27.2
|
||||
* @link https://developer.wordpress.org/reference/hooks/bulk_edit_posts/
|
||||
*
|
||||
* @param int $post_id ID of the updated post.
|
||||
* @param int[] $updated_post_ids An array of updated post IDs.
|
||||
* @param int[] $shared_post_data Associative array containing the post data.
|
||||
*/
|
||||
|
||||
function fictioneer_bulk_edit_save_patreon( $post_id ) {
|
||||
// Abort if...
|
||||
function fictioneer_save_patreon_bulk_edit( $updated_post_ids, $shared_post_data ) {
|
||||
// Validate
|
||||
if (
|
||||
! wp_verify_nonce( $_REQUEST['_wpnonce'] ?? 0, 'bulk-posts' ) ||
|
||||
( $_REQUEST['action2'] ?? 0 ) === 'trash' ||
|
||||
! wp_verify_nonce( $shared_post_data['fictioneer_bulk_edit_patreon_nonce'] ?? 0, 'fictioneer_bulk_edit_patreon' ) ||
|
||||
( $shared_post_data['action2'] ?? 0 ) === 'trash' ||
|
||||
! in_array(
|
||||
get_post_type( $post_id ),
|
||||
$shared_post_data['post_type'] ?? 0,
|
||||
['post', 'page', 'fcn_story', 'fcn_chapter', 'fcn_collection', 'fcn_recommendation']
|
||||
) ||
|
||||
! ( current_user_can( 'manage_options' ) || current_user_can( 'fcn_assign_patreon_tiers' ) )
|
||||
! ( current_user_can( 'manage_options' ) || current_user_can( 'fcn_assign_patreon_tiers' ) ) ||
|
||||
empty( $updated_post_ids )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup
|
||||
$tiers = $_REQUEST['fictioneer_patreon_lock_tiers_bulk'] ?? 0;
|
||||
$amount = $_REQUEST['fictioneer_patreon_lock_amount_bulk'] ?? '';
|
||||
global $wpdb;
|
||||
|
||||
// Patreon tiers
|
||||
// Setup
|
||||
$tiers = $shared_post_data['fictioneer_bulk_edit_patreon_lock_tiers'] ?? 'no_change';
|
||||
$amount = sanitize_text_field( $shared_post_data['fictioneer_bulk_edit_patreon_lock_amount'] ?? '' );
|
||||
$user_id = get_current_user_id();
|
||||
|
||||
// Nothing to do?
|
||||
if ( $tiers === 'no_change' && $amount === '' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare post author map
|
||||
$post_author_map = [];
|
||||
|
||||
$posts_and_authors = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT ID, post_author
|
||||
FROM {$wpdb->posts}
|
||||
WHERE ID IN (" . implode( ',', array_fill( 0, count( $updated_post_ids ), '%d' ) ) . ")",
|
||||
$updated_post_ids
|
||||
), ARRAY_A
|
||||
);
|
||||
|
||||
foreach ( $posts_and_authors as $post ) {
|
||||
$post_author_map[ (int) $post['ID'] ] = (int) $post['post_author'];
|
||||
}
|
||||
|
||||
// Update Patreon tiers
|
||||
if ( $tiers !== 'no_change' ) {
|
||||
// Remove or update...
|
||||
foreach ( $updated_post_ids as $post_id ) {
|
||||
if ( ! current_user_can( 'manage_options' ) && $user_id !== $post_author_map[ (int) $post_id ] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $tiers === 'remove' ) {
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_patreon_lock_tiers', 0 );
|
||||
} else {
|
||||
} elseif ( is_array( $tiers ) ) {
|
||||
$allowed_tiers = get_option( 'fictioneer_connection_patreon_tiers' );
|
||||
$allowed_tiers = is_array( $allowed_tiers ) ? $allowed_tiers : [];
|
||||
|
||||
if ( ! empty( $allowed_tiers ) ) {
|
||||
$tiers = array_intersect( $tiers, array_keys( $allowed_tiers ) );
|
||||
$tiers = array_map( 'absint', $tiers );
|
||||
$tiers = array_unique( $tiers );
|
||||
$tiers = array_map( 'strval', $tiers ); // Safer to match with LIKE in SQL
|
||||
$tiers = array_unique( $tiers );
|
||||
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_patreon_lock_tiers', $tiers );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Patreon amount cents
|
||||
// Update Patreon amount cents
|
||||
if ( $amount !== '' ) {
|
||||
foreach ( $updated_post_ids as $post_id ) {
|
||||
if ( ! current_user_can( 'manage_options' ) && $user_id !== $post_author_map[ (int) $post_id ] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_patreon_lock_amount', absint( $amount ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
get_option( 'fictioneer_enable_patreon_locks' ) &&
|
||||
@ -4417,8 +4460,7 @@ if (
|
||||
|
||||
add_action( 'bulk_edit_custom_box', 'fictioneer_add_patreon_bulk_edit_tiers', 10, 2 );
|
||||
add_action( 'bulk_edit_custom_box', 'fictioneer_add_patreon_bulk_edit_amount', 10, 2 );
|
||||
|
||||
add_action( 'save_post', 'fictioneer_bulk_edit_save_patreon' );
|
||||
add_action( 'bulk_edit_posts', 'fictioneer_save_patreon_bulk_edit', 10, 2 );
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
@ -4426,7 +4468,226 @@ if (
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Add chapter meta fields to bulk edit
|
||||
* Saves bulk edit chapter meta.
|
||||
*
|
||||
* @since 5.27.2
|
||||
* @link https://developer.wordpress.org/reference/hooks/bulk_edit_posts/
|
||||
*
|
||||
* @param int[] $updated_post_ids An array of updated post IDs.
|
||||
* @param int[] $shared_post_data Associative array containing the post data.
|
||||
*/
|
||||
|
||||
function fictioneer_save_chapter_bulk_edit( $updated_post_ids, $shared_post_data ) {
|
||||
// Validate
|
||||
if (
|
||||
! wp_verify_nonce( $shared_post_data['fictioneer_bulk_edit_chapters_nonce'] ?? 0, 'fictioneer_bulk_edit_chapters' ) ||
|
||||
( $shared_post_data['action2'] ?? 0 ) === 'trash' ||
|
||||
( $shared_post_data['screen'] ?? 0 ) !== 'edit-fcn_chapter' ||
|
||||
( $shared_post_data['post_type'] ?? 0 ) !== 'fcn_chapter' ||
|
||||
empty( $updated_post_ids )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
// Setup
|
||||
$story_id = sanitize_text_field( $shared_post_data['bulk_edit_fictioneer_chapter_story_id'] ?? '' );
|
||||
$icon = sanitize_text_field( $shared_post_data['bulk_edit_fictioneer_chapter_icon'] ?? '' );
|
||||
$text_icon = sanitize_text_field( $shared_post_data['bulk_edit_fictioneer_chapter_text_icon'] ?? '' );
|
||||
$prefix = sanitize_text_field( $shared_post_data['bulk_edit_fictioneer_chapter_prefix'] ?? '' );
|
||||
$group = sanitize_text_field( $shared_post_data['bulk_edit_fictioneer_chapter_group'] ?? '' );
|
||||
$user_id = get_current_user_id();
|
||||
$user_is_editor = current_user_can( 'edit_others_fcn_chapters' ) || current_user_can( 'manage_options' );
|
||||
|
||||
// Nothing to do?
|
||||
if ( $story_id === '' && $icon === '' && $text_icon === '' && $prefix === '' && $group === '' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare post author map
|
||||
$post_author_map = [];
|
||||
|
||||
$posts_and_authors = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT ID, post_author
|
||||
FROM {$wpdb->posts}
|
||||
WHERE ID IN (" . implode( ',', array_fill( 0, count( $updated_post_ids ), '%d' ) ) . ")",
|
||||
$updated_post_ids
|
||||
), ARRAY_A
|
||||
);
|
||||
|
||||
foreach ( $posts_and_authors as $post ) {
|
||||
$post_author_map[ (int) $post['ID'] ] = (int) $post['post_author'];
|
||||
}
|
||||
|
||||
// Update icon
|
||||
if ( $icon ) {
|
||||
foreach ( $updated_post_ids as $post_id ) {
|
||||
if ( ! $user_is_editor && $user_id !== $post_author_map[ (int) $post_id ] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( strpos( $icon, 'fa-' ) === 0 && $icon !== FICTIONEER_DEFAULT_CHAPTER_ICON ) {
|
||||
update_post_meta( $post_id, 'fictioneer_chapter_icon', $icon );
|
||||
} elseif ( $icon === '_remove' ) {
|
||||
delete_post_meta( $post_id, 'fictioneer_chapter_icon' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update text icon
|
||||
if ( $text_icon && get_option( 'fictioneer_enable_advanced_meta_fields' ) ) {
|
||||
foreach ( $updated_post_ids as $post_id ) {
|
||||
if ( ! $user_is_editor && $user_id !== $post_author_map[ (int) $post_id ] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $text_icon === '_remove' ) {
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_chapter_text_icon', 0 );
|
||||
} else {
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_chapter_text_icon', mb_substr( $text_icon, 0, 10, 'UTF-8' ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update prefix
|
||||
if ( $prefix && get_option( 'fictioneer_enable_advanced_meta_fields' ) ) {
|
||||
foreach ( $updated_post_ids as $post_id ) {
|
||||
if ( ! $user_is_editor && $user_id !== $post_author_map[ (int) $post_id ] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $prefix === '_remove' ) {
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_chapter_prefix', 0 );
|
||||
} else {
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_chapter_prefix', $prefix );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update chapter group
|
||||
if ( $group ) {
|
||||
foreach ( $updated_post_ids as $post_id ) {
|
||||
if ( ! $user_is_editor && $user_id !== $post_author_map[ (int) $post_id ] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $group === '_remove' ) {
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_chapter_group', 0 );
|
||||
} else {
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_chapter_group', $group );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update story ID
|
||||
if ( $story_id !== '' ) {
|
||||
$story_id = intval( $story_id );
|
||||
$story_author_id = (int) get_post_field( 'post_author', $story_id );
|
||||
|
||||
if ( $user_is_editor || $story_author_id === $user_id ) {
|
||||
if ( $story_id < 1 || fictioneer_validate_id( $story_id, 'fcn_story' ) ) {
|
||||
fictioneer_bulk_edit_chapter_story( $updated_post_ids, $story_id, $post_author_map );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear story meta caches (if not already done)
|
||||
if ( $story_id === '' ) {
|
||||
$updated_stories = [];
|
||||
|
||||
foreach ( $updated_post_ids as $chapter_id ) {
|
||||
$current_story_id = intval( fictioneer_get_chapter_story_id( $chapter_id ) );
|
||||
|
||||
if ( ! $current_story_id ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! in_array( $current_story_id, $updated_stories ) ) {
|
||||
wp_update_post( array( 'ID' => $current_story_id, 'post_type' => 'fcn_story' ) ); // Trigger hooks
|
||||
|
||||
$updated_stories[] = $current_story_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
add_action( 'bulk_edit_posts', 'fictioneer_save_chapter_bulk_edit', 10, 2 );
|
||||
|
||||
/**
|
||||
* Bulk edit chapter stories.
|
||||
*
|
||||
* @since 5.27.2
|
||||
*
|
||||
* @param int[] $chapter_ids Array of post IDs.
|
||||
* @param int $story_id ID of the story or 0 to unset.
|
||||
* @param int[] $author_map Array of post ID => author ID.
|
||||
*/
|
||||
|
||||
function fictioneer_bulk_edit_chapter_story( $chapter_ids, $story_id, $author_map ) {
|
||||
// Setup
|
||||
$user_id = get_current_user_id();
|
||||
$user_is_editor = current_user_can( 'edit_others_fcn_chapters' ) || current_user_can( 'manage_options' );
|
||||
$updated_stories = [];
|
||||
$allowed_chapter_ids = $user_is_editor
|
||||
? $chapter_ids
|
||||
: array_filter( $chapter_ids, fn( $post_id ) => $user_id === $author_map[ (int) $post_id ] );
|
||||
|
||||
// Unset old story
|
||||
foreach ( $allowed_chapter_ids as $chapter_id ) {
|
||||
$current_story_id = intval( fictioneer_get_chapter_story_id( $chapter_id ) );
|
||||
|
||||
if ( ! $current_story_id || $current_story_id === $story_id ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$other_story_chapters = fictioneer_get_story_chapter_ids( $current_story_id );
|
||||
$other_story_chapters = array_diff( $other_story_chapters, [ strval( $chapter_id ) ] );
|
||||
|
||||
update_post_meta( $current_story_id, 'fictioneer_story_chapters', $other_story_chapters );
|
||||
|
||||
if ( $story_id < 1 ) {
|
||||
delete_post_meta( $chapter_id, 'fictioneer_chapter_story' );
|
||||
fictioneer_set_chapter_story_parent( $chapter_id, 0 );
|
||||
}
|
||||
|
||||
if ( ! in_array( $current_story_id, $updated_stories ) ) {
|
||||
update_post_meta( $current_story_id, 'fictioneer_chapters_modified', current_time( 'mysql', 1 ) );
|
||||
wp_update_post( array( 'ID' => $current_story_id, 'post_type' => 'fcn_story' ) ); // Trigger hooks
|
||||
|
||||
$updated_stories[] = $current_story_id;
|
||||
}
|
||||
}
|
||||
|
||||
// Assign new story
|
||||
if ( $story_id > 0 ) {
|
||||
$previous_story_chapter_ids = fictioneer_get_story_chapter_ids( $story_id );
|
||||
$new_story_chapter_ids = $previous_story_chapter_ids;
|
||||
|
||||
foreach ( $allowed_chapter_ids as $chapter_id ) {
|
||||
if ( ! in_array( $chapter_id, $previous_story_chapter_ids ) ) {
|
||||
update_post_meta( $chapter_id, 'fictioneer_chapter_story', $story_id );
|
||||
fictioneer_set_chapter_story_parent( $chapter_id, $story_id );
|
||||
|
||||
if ( get_option( 'fictioneer_enable_chapter_appending' ) ) {
|
||||
$new_story_chapter_ids[] = $chapter_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$new_story_chapter_ids = array_unique( $new_story_chapter_ids );
|
||||
|
||||
if ( $previous_story_chapter_ids !== $new_story_chapter_ids ) {
|
||||
update_post_meta( $story_id, 'fictioneer_story_chapters', array_map( 'strval', $new_story_chapter_ids ) );
|
||||
update_post_meta( $story_id, 'fictioneer_chapters_modified', current_time( 'mysql', 1 ) );
|
||||
update_post_meta( $story_id, 'fictioneer_chapters_added', current_time( 'mysql', 1 ) );
|
||||
wp_update_post( array( 'ID' => $story_id, 'post_type' => 'fcn_story' ) ); // Trigger hooks
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds chapter meta fields to bulk edit.
|
||||
*
|
||||
* @since 5.24.1
|
||||
*
|
||||
@ -4435,21 +4696,30 @@ if (
|
||||
*/
|
||||
|
||||
function fictioneer_add_bulk_edit_chapter_meta( $column_name, $post_type ) {
|
||||
// Check post type
|
||||
if ( $post_type !== 'fcn_chapter' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure this function is only executed once
|
||||
static $added = false;
|
||||
|
||||
if ( $added ) {
|
||||
// Abort if...
|
||||
if ( $post_type !== 'fcn_chapter' || $added ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$added = true;
|
||||
|
||||
// Nonce
|
||||
wp_nonce_field( 'fictioneer_bulk_edit_chapters', 'fictioneer_bulk_edit_chapters_nonce', false );
|
||||
|
||||
// Start HTML ---> ?>
|
||||
<?php if ( current_user_can( 'edit_others_fcn_chapters' ) || current_user_can( 'manage_options' ) ) : ?>
|
||||
<fieldset class="inline-edit-col-right">
|
||||
<div class="inline-edit-chapter-story-wrap">
|
||||
<label class="inline-edit-chapter-story">
|
||||
<span class="title"><?php _ex( 'Story', 'Chapter story meta field label.', 'fictioneer' ); ?></span>
|
||||
<input type="text" name="bulk_edit_fictioneer_chapter_story_id" autocomplete="off" autocorrect="off" placeholder="<?php _e( 'Post ID (0 to remove)', 'fictioneer' ); ?>">
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
<?php endif; ?>
|
||||
|
||||
<p class="bulk-edit-help"><?php _e( 'Use <code>_remove</code> to remove current values.', 'fictioneer' ); ?></p>
|
||||
|
||||
<?php if ( ! get_option( 'fictioneer_hide_chapter_icons' ) ) : ?>
|
||||
@ -4496,72 +4766,6 @@ function fictioneer_add_bulk_edit_chapter_meta( $column_name, $post_type ) {
|
||||
}
|
||||
add_action( 'bulk_edit_custom_box', 'fictioneer_add_bulk_edit_chapter_meta', 10, 2 );
|
||||
|
||||
/**
|
||||
* Save chapter bulk edit fields
|
||||
*
|
||||
* @since 5.24.1
|
||||
*
|
||||
* @param int $post_id ID of the updated post.
|
||||
*/
|
||||
|
||||
function fictioneer_bulk_edit_save_chapter_fields( $post_id ) {
|
||||
// Abort if...
|
||||
if (
|
||||
! wp_verify_nonce( $_REQUEST['_wpnonce'] ?? 0, 'bulk-posts' ) ||
|
||||
( $_REQUEST['action2'] ?? 0 ) === 'trash' ||
|
||||
! fictioneer_validate_save_action_user( $post_id, 'fcn_chapter' )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup
|
||||
$icon = sanitize_text_field( $_REQUEST['bulk_edit_fictioneer_chapter_icon'] ?? '' );
|
||||
$text_icon = sanitize_text_field( $_REQUEST['bulk_edit_fictioneer_chapter_text_icon'] ?? '' );
|
||||
$prefix = sanitize_text_field( $_REQUEST['bulk_edit_fictioneer_chapter_prefix'] ?? '' );
|
||||
$group = sanitize_text_field( $_REQUEST['bulk_edit_fictioneer_chapter_group'] ?? '' );
|
||||
|
||||
// Update icon
|
||||
if ( $icon && ! get_option( 'fictioneer_hide_chapter_icons' ) ) {
|
||||
if ( strpos( $icon, 'fa-' ) === 0 && $icon !== FICTIONEER_DEFAULT_CHAPTER_ICON ) {
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_chapter_icon', $icon );
|
||||
} elseif ( $icon === '_remove' ) {
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_chapter_icon', 0 );
|
||||
}
|
||||
}
|
||||
|
||||
// Update text icon
|
||||
if (
|
||||
$text_icon &&
|
||||
! get_option( 'fictioneer_hide_chapter_icons' ) &&
|
||||
get_option( 'fictioneer_enable_advanced_meta_fields' )
|
||||
) {
|
||||
if ( $text_icon === '_remove' ) {
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_chapter_text_icon', 0 );
|
||||
} else {
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_chapter_text_icon', mb_substr( $text_icon, 0, 10, 'UTF-8' ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Update prefix
|
||||
if ( $prefix && get_option( 'fictioneer_enable_advanced_meta_fields' ) ) {
|
||||
if ( $prefix === '_remove' ) {
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_chapter_prefix', 0 );
|
||||
} else {
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_chapter_prefix', $prefix );
|
||||
}
|
||||
}
|
||||
|
||||
// Update group
|
||||
if ( $group ) {
|
||||
if ( $group === '_remove' ) {
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_chapter_group', 0 );
|
||||
} else {
|
||||
fictioneer_update_post_meta( $post_id, 'fictioneer_chapter_group', $group );
|
||||
}
|
||||
}
|
||||
}
|
||||
add_action( 'save_post', 'fictioneer_bulk_edit_save_chapter_fields' );
|
||||
|
||||
// =============================================================================
|
||||
// PASSWORD EXPIRATION NOTE IN POST TABLE
|
||||
// =============================================================================
|
||||
|
@ -546,6 +546,8 @@ function fictioneer_bypass_password( $required, $post ) {
|
||||
( $patreon_user_data['lifetime_support_cents'] ?? -1 ) >= $patreon_check_lifetime_amount_cents
|
||||
);
|
||||
|
||||
$required = apply_filters( 'fictioneer_filter_patreon_tier_unlock', $required, $post, $user, $patreon_post_data );
|
||||
|
||||
if ( ! $required ) {
|
||||
break;
|
||||
}
|
||||
|
@ -167,6 +167,7 @@ function fictioneer_get_default_shortcode_args( $attr, $def_count = -1 ) {
|
||||
'orderby' => $attr['orderby'] ?? '',
|
||||
'page' => max( 1, get_query_var( 'page' ) ?: get_query_var( 'paged' ) ),
|
||||
'posts_per_page' => absint( $attr['per_page'] ?? 0 ) ?: get_option( 'posts_per_page' ),
|
||||
'post_status' => sanitize_key( $attr['post_status'] ?? 'publish' ),
|
||||
'post_ids' => fictioneer_explode_list( $attr['post_ids'] ?? '' ),
|
||||
'author' => sanitize_title( $attr['author'] ?? '' ),
|
||||
'author_ids' => fictioneer_explode_list( $attr['author_ids'] ?? '' ),
|
||||
@ -411,6 +412,7 @@ function fictioneer_get_splide_inline_init() {
|
||||
* collections, recommendations, and stories.
|
||||
* @param string|null $attr['count'] Optional. Maximum number of items. Default 8.
|
||||
* @param string|null $attr['author'] Optional. Limit posts to a specific author.
|
||||
* @param string|null $attr['post_status'] Optional. Choose a valid post status. Default 'publish'.
|
||||
* @param string|null $attr['order'] Optional. Order direction. Default 'DESC'.
|
||||
* @param string|null $attr['orderby'] Optional. Order argument. Default 'date'.
|
||||
* @param string|null $attr['post_ids'] Optional. Limit posts to specific post IDs.
|
||||
@ -528,6 +530,7 @@ add_shortcode( 'fictioneer_showcase', 'fictioneer_shortcode_showcase' );
|
||||
* @param string|null $attr['count'] Optional. Maximum number of items. Default 4.
|
||||
* @param string|null $attr['author'] Optional. Limit posts to a specific author.
|
||||
* @param string|null $attr['type'] Optional. Choose between 'default', 'simple', and 'compact'.
|
||||
* @param string|null $attr['post_status'] Optional. Choose a valid post status. Default 'publish'.
|
||||
* @param string|null $attr['order'] Optional. Order argument. Default 'DESC'.
|
||||
* @param string|null $attr['orderby'] Optional. Orderby argument. Default 'date'.
|
||||
* @param string|null $attr['spoiler'] Optional. Whether to show spoiler content.
|
||||
@ -635,6 +638,7 @@ add_shortcode( 'fictioneer_latest_chapters', 'fictioneer_shortcode_latest_chapte
|
||||
* @param string|null $attr['count'] Optional. Maximum number of items. Default 4.
|
||||
* @param string|null $attr['author'] Optional. Limit posts to a specific author.
|
||||
* @param string|null $attr['type'] Optional. Choose between 'default' and 'compact'.
|
||||
* @param string|null $attr['post_status'] Optional. Choose a valid post status. Default 'publish'.
|
||||
* @param string|null $attr['order'] Optional. Order argument. Default 'DESC'.
|
||||
* @param string|null $attr['orderby'] Optional. Orderby argument. Default 'date'.
|
||||
* @param string|null $attr['post_ids'] Optional. Limit posts to specific post IDs.
|
||||
@ -746,6 +750,7 @@ add_shortcode( 'fictioneer_latest_stories', 'fictioneer_shortcode_latest_stories
|
||||
* @param string|null $attr['count'] Optional. Maximum number of items. Default 4.
|
||||
* @param string|null $attr['author'] Optional. Limit posts to a specific author.
|
||||
* @param string|null $attr['type'] Optional. Choose between 'default', 'simple', 'single', and 'compact'.
|
||||
* @param string|null $attr['post_status'] Optional. Choose a valid post status. Default 'publish'.
|
||||
* @param string|null $attr['single'] Optional. Whether to show only one chapter item. Default false.
|
||||
* @param string|null $attr['post_ids'] Optional. Limit posts to specific post IDs.
|
||||
* @param string|null $attr['ignore_protected'] Optional. Whether to ignore protected posts. Default false.
|
||||
@ -860,6 +865,7 @@ add_shortcode( 'fictioneer_latest_updates', 'fictioneer_shortcode_latest_story_u
|
||||
* @param string|null $attr['count'] Optional. Maximum number of items. Default 4.
|
||||
* @param string|null $attr['author'] Optional. Limit posts to a specific author.
|
||||
* @param string|null $attr['type'] Optional. Choose between 'default' and 'compact'.
|
||||
* @param string|null $attr['post_status'] Optional. Choose a valid post status. Default 'publish'.
|
||||
* @param string|null $attr['order'] Optional. Order argument. Default 'DESC'.
|
||||
* @param string|null $attr['orderby'] Optional. Orderby argument. Default 'date'.
|
||||
* @param string|null $attr['post_ids'] Optional. Limit posts to specific post IDs.
|
||||
@ -952,6 +958,7 @@ add_shortcode( 'fictioneer_latest_recommendations', 'fictioneer_shortcode_latest
|
||||
*
|
||||
* @param string|null $attr['count'] Optional. Maximum number of items. Default 1.
|
||||
* @param string|null $attr['author'] Optional. Limit posts to a specific author.
|
||||
* @param string|null $attr['post_status'] Optional. Choose a valid post status. Default 'publish'.
|
||||
* @param string|null $attr['post_ids'] Optional. Limit posts to specific post IDs.
|
||||
* @param string|null $attr['ignore_protected'] Optional. Whether to ignore protected posts. Default false.
|
||||
* @param string|null $attr['only_protected'] Optional. Whether to query only protected posts. Default false.
|
||||
@ -1108,6 +1115,7 @@ function fictioneer_shortcode_chapter_list_empty( $attr ) {
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param string $attr['story_id'] Either/Or. The ID of the story the chapters belong to.
|
||||
* @param string|null $attr['post_status'] Optional. Choose a valid post status. Default 'publish'.
|
||||
* @param string|null $attr['chapter_ids'] Either/Or. Comma-separated list of chapter IDs.
|
||||
* @param string|null $attr['count'] Optional. Maximum number of items. Default -1 (all).
|
||||
* @param string|null $attr['offset'] Optional. Skip a number of posts.
|
||||
@ -1133,6 +1141,7 @@ function fictioneer_shortcode_chapter_list( $attr ) {
|
||||
$offset = max( 0, intval( $attr['offset'] ?? 0 ) );
|
||||
$group = empty( $attr['group'] ) ? false : strtolower( trim( $attr['group'] ) );
|
||||
$heading = empty( $attr['heading'] ) ? false : $attr['heading'];
|
||||
$post_status = sanitize_key( $attr['post_status'] ?? 'publish' );
|
||||
$story_id = fictioneer_validate_id( $attr['story_id'] ?? -1, 'fcn_story' );
|
||||
$prefer_chapter_icon = get_option( 'fictioneer_override_chapter_status_icons' );
|
||||
$hide_icons = get_option( 'fictioneer_hide_chapter_icons' );
|
||||
@ -1181,7 +1190,7 @@ function fictioneer_shortcode_chapter_list( $attr ) {
|
||||
$query_args = array(
|
||||
'fictioneer_query_name' => 'fictioneer_shortcode_chapter_list',
|
||||
'post_type' => 'fcn_chapter',
|
||||
'post_status' => 'publish',
|
||||
'post_status' => $post_status,
|
||||
'post__in' => $chapters, // Cannot be empty!
|
||||
'ignore_sticky_posts' => true,
|
||||
'orderby' => 'post__in', // Preserve order from meta box
|
||||
@ -1300,12 +1309,20 @@ function fictioneer_shortcode_chapter_list( $attr ) {
|
||||
class="chapter-group__list-item-link truncate _1-1 <?php echo $has_password ? '_password' : ''; ?>"
|
||||
><?php
|
||||
|
||||
$title_output = '';
|
||||
$prefix = apply_filters( 'fictioneer_filter_list_chapter_prefix', $prefix, $chapter_id, 'shortcode' );
|
||||
|
||||
if ( ! empty( $prefix ) ) {
|
||||
// Mind space between prefix and title
|
||||
echo apply_filters( 'fictioneer_filter_list_chapter_prefix', $prefix ) . ' ';
|
||||
$title_output .= $prefix . ' ';
|
||||
}
|
||||
|
||||
echo $title;
|
||||
$title_output .= $title;
|
||||
|
||||
echo apply_filters(
|
||||
'fictioneer_filter_list_chapter_title_row',
|
||||
$title_output, $chapter_id, $prefix, $has_password, 'shortcode'
|
||||
);
|
||||
|
||||
?></a>
|
||||
|
||||
@ -1563,6 +1580,7 @@ add_shortcode( 'fictioneer_search', 'fictioneer_shortcode_search' );
|
||||
* @param string|null $attr['ignore_protected'] Optional. Whether to ignore protected posts. Default false.
|
||||
* @param string|null $attr['only_protected'] Optional. Whether to query only protected posts. Default false.
|
||||
* @param string|null $attr['author'] Optional. Limit posts to a specific author.
|
||||
* @param string|null $attr['post_status'] Optional. Choose a valid post status. Default 'publish'.
|
||||
* @param string|null $attr['author_ids'] Optional. Only include posts by these author IDs.
|
||||
* @param string|null $attr['exclude_author_ids'] Optional. Exclude posts with these author IDs.
|
||||
* @param string|null $attr['exclude_tag_ids'] Optional. Exclude posts with these tags.
|
||||
@ -1583,7 +1601,7 @@ function fictioneer_shortcode_blog( $attr ) {
|
||||
$query_args = array(
|
||||
'fictioneer_query_name' => 'blog_shortcode',
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'post_status' => $args['post_status'],
|
||||
'paged' => $args['page'],
|
||||
'posts_per_page' => $args['posts_per_page'],
|
||||
'ignore_sticky_posts' => $args['ignore_sticky']
|
||||
@ -1707,6 +1725,7 @@ add_shortcode( 'fictioneer_blog', 'fictioneer_shortcode_blog' );
|
||||
* @since 5.7.3
|
||||
*
|
||||
* @param string|null $attr['post_type'] Optional. The post types to query. Default 'post'.
|
||||
* @param string|null $attr['post_status'] Optional. Choose a valid post status. Default 'publish'.
|
||||
* @param string|null $attr['post_ids'] Optional. Limit posts to specific post IDs.
|
||||
* @param string|null $attr['per_page'] Optional. Number of posts per page.
|
||||
* @param string|null $attr['count'] Optional. Maximum number of posts. Default -1.
|
||||
@ -2456,3 +2475,121 @@ function fictioneer_shortcode_tooltip( $atts, $content = null ) {
|
||||
return $html;
|
||||
}
|
||||
add_shortcode( 'fcnt', 'fictioneer_shortcode_tooltip' );
|
||||
|
||||
// =============================================================================
|
||||
// TERMS SHORTCODE
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Shortcode to show taxonomies.
|
||||
*
|
||||
* @since 5.27.2
|
||||
*
|
||||
* @param string|null $attr['term_type'] Term type. Default 'post_tag'.
|
||||
* @param int|null $attr['post_id'] Post ID. Default 0.
|
||||
* @param int|null $attr['count'] Maximum number of terms. Default -1 (all).
|
||||
* @param string|null $attr['orderby'] Orderby argument. Default 'count'.
|
||||
* @param string|null $attr['order'] Order argument. Default 'DESC'.
|
||||
* @param bool|null $attr['show_empty'] Whether to show empty terms. Default false.
|
||||
* @param bool|null $attr['show_count'] Whether to show term counts. Default false.
|
||||
* @param string|null $attr['classes'] Additional section CSS classes. Default empty.
|
||||
* @param string|null $attr['inner_classes'] Additional term CSS classes. Default empty.
|
||||
* @param string|null $attr['style'] Inline section CSS style. Default empty.
|
||||
* @param string|null $attr['inner_style'] Inline term CSS style. Default empty.
|
||||
* @param string|null $attr['empty'] Override message for empty query result.
|
||||
*
|
||||
* @return string The shortcode HTML.
|
||||
*/
|
||||
|
||||
function fictioneer_shortcode_terms( $attr ) {
|
||||
// Setup
|
||||
$type = sanitize_key( $attr['type'] ?? 'tag' );
|
||||
$post_id = absint( $attr['post_id'] ?? 0 );
|
||||
$count = max( -1, intval( $attr['count'] ?? -1 ) );
|
||||
$orderby = sanitize_text_field( $attr['orderby'] ?? 'count' );
|
||||
$order = sanitize_text_field( $attr['order'] ?? 'DESC' );
|
||||
$show_empty = filter_var( $attr['show_empty'] ?? 0, FILTER_VALIDATE_BOOLEAN );
|
||||
$show_count = filter_var( $attr['show_count'] ?? 0, FILTER_VALIDATE_BOOLEAN );
|
||||
$classes = esc_attr( wp_strip_all_tags( $attr['classes'] ?? $attr['class'] ?? '' ) );
|
||||
$inner_classes = esc_attr( wp_strip_all_tags( $attr['inner_classes'] ?? $attr['inner_class'] ?? '' ) );
|
||||
$style = esc_attr( wp_strip_all_tags( $attr['style'] ?? '' ) );
|
||||
$inner_style = esc_attr( wp_strip_all_tags( $attr['inner_style'] ?? '' ) );
|
||||
$empty = sanitize_text_field( $attr['empty'] ?? __( 'No taxonomies specified yet.', 'fictioneer' ) );
|
||||
|
||||
$term_map = array(
|
||||
'tag' => 'post_tag',
|
||||
'genre' => 'fcn_genre',
|
||||
'fandom' => 'fcn_fandom',
|
||||
'character' => 'fcn_character',
|
||||
'warning' => 'fcn_content_warning'
|
||||
);
|
||||
|
||||
$term_type = $term_map[ $type ] ?? $type;
|
||||
|
||||
// Term exists?
|
||||
if ( ! taxonomy_exists( $term_type ) ) {
|
||||
return 'Error: Taxonomy does not exist.';
|
||||
}
|
||||
|
||||
// Post exists?
|
||||
if ( $post_id && ! get_post( $post_id ) ) {
|
||||
return 'Error: Post not found.';
|
||||
}
|
||||
|
||||
// Prepare query args
|
||||
$args = array(
|
||||
'fictioneer_query_name' => 'terms_shortcode',
|
||||
'taxonomy' => $term_type,
|
||||
'orderby' => $orderby,
|
||||
'order' => $order,
|
||||
'hide_empty' => ! $show_empty
|
||||
);
|
||||
|
||||
if ( $count > 0 ) {
|
||||
$args['number'] = $count;
|
||||
}
|
||||
|
||||
// Apply filters
|
||||
$args = apply_filters( 'fictioneer_filter_shortcode_terms_query_args', $args, $attr );
|
||||
|
||||
// Query terms
|
||||
if ( $post_id ) {
|
||||
$terms = wp_get_post_terms( $post_id, $term_type, $args );
|
||||
} else {
|
||||
$terms = get_terms( $args );
|
||||
}
|
||||
|
||||
// All good?
|
||||
if ( is_wp_error( $terms ) ) {
|
||||
return 'Error: ' . $terms->get_error_message();
|
||||
}
|
||||
|
||||
// Build and return HTML
|
||||
$html = '';
|
||||
|
||||
if ( ! empty( $terms ) ) {
|
||||
foreach ( $terms as $term ) {
|
||||
$html .= sprintf(
|
||||
'<a href="%s" class="tag-pill _taxonomy-%s _taxonomy-slug-%s %s" style="%s">%s</a>',
|
||||
get_tag_link( $term ),
|
||||
str_replace( 'fcn_', '', $term->taxonomy ),
|
||||
$term->slug,
|
||||
'tag-pill ' . $inner_classes,
|
||||
$inner_style,
|
||||
$show_count
|
||||
? sprintf( _x( '%1$s (%2$s)', 'Terms shortcode with count.', 'fictioneer' ), $term->name, $term->count )
|
||||
: $term->name
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$html = $empty;
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
'<section class="terms-shortcode tag-group %s" style="%s">%s</section>',
|
||||
"_{$term_type} {$classes} " . wp_unique_id( 'shortcode-id-' ),
|
||||
$style,
|
||||
$html
|
||||
);
|
||||
}
|
||||
add_shortcode( 'fictioneer_terms', 'fictioneer_shortcode_terms' );
|
||||
|
@ -1814,7 +1814,7 @@ function fictioneer_output_head_anti_flicker() {
|
||||
<?php // <--- End HTML
|
||||
|
||||
wp_print_inline_script_tag(
|
||||
'document.addEventListener("readystatechange", () => {if (document.readyState === "interactive") document.body.style.visibility = "visible";});console.log("foo");',
|
||||
'document.addEventListener("readystatechange", () => {if (document.readyState === "interactive") document.body.style.visibility = "visible";});',
|
||||
array(
|
||||
'id' => 'fictioneer-anti-flicker',
|
||||
'type' => 'text/javascript',
|
||||
|
@ -1684,7 +1684,7 @@ function fictioneer_replace_br_with_whitespace( $text ) {
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Add noindex and nofollow headers to certain requests
|
||||
* Adds noindex and nofollow headers to certain requests
|
||||
*
|
||||
* @since 5.23.1
|
||||
*/
|
||||
@ -1700,3 +1700,53 @@ function fictioneer_block_pages_from_indexing() {
|
||||
}
|
||||
}
|
||||
add_action( 'send_headers', 'fictioneer_block_pages_from_indexing' );
|
||||
|
||||
// =============================================================================
|
||||
// REDIRECT SCHEDULED CHAPTER 404
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Redirects scheduled chapter 404 to story or home
|
||||
*
|
||||
* @since 5.27.2
|
||||
*/
|
||||
|
||||
function fictioneer_redirect_scheduled_chapter_404() {
|
||||
if ( current_user_can( 'manage_options' ) || current_user_can( 'edit_others_fcn_chapters' ) ) {
|
||||
return; // Default behavior
|
||||
}
|
||||
|
||||
global $wp_query, $post;
|
||||
|
||||
if ( isset( $wp_query->query_vars['p'] ) && ( $wp_query->query_vars['post_type'] ?? 0 ) === 'fcn_chapter' ) {
|
||||
$post_id = absint( $wp_query->query_vars['p'] );
|
||||
$user_id = get_current_user_id();
|
||||
$author_id = (int) get_post_field( 'post_author', $post_id );
|
||||
|
||||
if ( $user_id && $user_id === $author_id ) {
|
||||
return; // Default behavior
|
||||
}
|
||||
|
||||
if ( ! $post ) {
|
||||
$post_status = get_post_status( $post_id );
|
||||
} else {
|
||||
$post_status = $post->post_status;
|
||||
}
|
||||
|
||||
if ( $post_status === 'future' ) {
|
||||
$story_id = fictioneer_get_chapter_story_id( $post_id );
|
||||
|
||||
if ( $story_id ) {
|
||||
wp_safe_redirect( get_permalink( $story_id ), 307 );
|
||||
} else {
|
||||
wp_safe_redirect( home_url(), 307 );
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( get_option( 'fictioneer_redirect_scheduled_chapter_404' ) ) {
|
||||
add_action( 'template_redirect', 'fictioneer_redirect_scheduled_chapter_404' );
|
||||
}
|
||||
|
@ -375,14 +375,16 @@ add_filter( 'wp_update_comment_data', 'fictioneer_track_comment_edit', 10, 2 );
|
||||
// RENDER COMMENT MODERATION MENU
|
||||
// =============================================================================
|
||||
|
||||
function fictioneer_comment_moderation_template() {
|
||||
// Abort if...
|
||||
if ( ! get_option( 'fictioneer_enable_ajax_comment_moderation' ) ) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Renders the comment moderation menu template
|
||||
*
|
||||
* @since 4.27.0
|
||||
*/
|
||||
|
||||
function fictioneer_comment_moderation_template() {
|
||||
// Start HTML ---> ?>
|
||||
<template id="template-comment-frontend-moderation-menu">
|
||||
<?php if ( get_option( 'fictioneer_enable_ajax_comment_moderation' ) ) : ?>
|
||||
<button data-action="click->fictioneer-comment#trash"><?php _e( 'Trash', 'fictioneer' ); ?></button>
|
||||
<button data-action="click->fictioneer-comment#spam"><?php _e( 'Spam', 'fictioneer' ); ?></button>
|
||||
<button data-action="click->fictioneer-comment#offensive"><?php _e( 'Offensive', 'fictioneer' ); ?></button>
|
||||
@ -396,6 +398,7 @@ function fictioneer_comment_moderation_template() {
|
||||
<button data-action="click->fictioneer-comment#sticky"><?php _e( 'Sticky', 'fictioneer' ); ?></button>
|
||||
<button data-action="click->fictioneer-comment#unsticky"><?php _e( 'Unsticky', 'fictioneer' ); ?></button>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<a class="comment-edit-link" data-fictioneer-comment-target="editLink"><?php _e( 'Edit' ); ?></a>
|
||||
|
||||
|
@ -772,8 +772,11 @@ function fictioneer_chapter_suggestion_tools() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup
|
||||
$hide_if_logged_out = get_option( 'comment_registration' ) ? 'hide-if-logged-out' : ''; // Safer for cached site
|
||||
|
||||
// Start HTML ---> ?>
|
||||
<div id="selection-tools" class="invisible suggestion-tools" data-nosnippet>
|
||||
<div id="selection-tools" class="invisible suggestion-tools <?php echo $hide_if_logged_out; ?>" data-nosnippet>
|
||||
<button id="button-add-suggestion" type="button" class="button button--suggestion">
|
||||
<i class="fa-solid fa-highlighter"></i>
|
||||
<span><?php _e( 'Add Suggestion', 'fictioneer' ); ?></span>
|
||||
|
@ -632,30 +632,42 @@ function fictioneer_story_chapters( $args ) {
|
||||
class="chapter-group__list-item-link truncate _1-1 <?php echo $chapter['password'] ? '_password' : ''; ?>"
|
||||
><?php
|
||||
|
||||
$title_output = '';
|
||||
|
||||
// Non-published chapter prefixes
|
||||
if ( in_array( $chapter['status'], ['future', 'trash', 'private'] ) ) {
|
||||
$status_prefix = fcntr( "{$chapter['status']}_prefix" );
|
||||
|
||||
if ( $status_prefix ) {
|
||||
echo '<span class="chapter-group__list-item-status">' . $status_prefix . '</span> '; // Mind the space
|
||||
$title_output .= '<span class="chapter-group__list-item-status">' . $status_prefix . '</span> '; // Mind the space
|
||||
}
|
||||
}
|
||||
|
||||
$chapter['prefix'] = apply_filters(
|
||||
'fictioneer_filter_list_chapter_prefix',
|
||||
$chapter['prefix'], $chapter['id'], 'story'
|
||||
);
|
||||
|
||||
if ( ! empty( $chapter['prefix'] ) ) {
|
||||
// Mind space between prefix and title
|
||||
echo apply_filters( 'fictioneer_filter_list_chapter_prefix', $chapter['prefix'] ) . ' ';
|
||||
$title_output .= $chapter['prefix'] . ' ';
|
||||
}
|
||||
|
||||
if ( ! empty( $chapter['list_title'] ) && $chapter['title'] !== $chapter['list_title'] ) {
|
||||
printf(
|
||||
$title_output .= sprintf(
|
||||
' <span class="chapter-group__list-item-title list-view">%s</span><span class="grid-view">%s</span>',
|
||||
$chapter['title'],
|
||||
wp_strip_all_tags( $chapter['list_title'] )
|
||||
);
|
||||
} else {
|
||||
echo $chapter['title'];
|
||||
$title_output .= $chapter['title'];
|
||||
}
|
||||
|
||||
echo apply_filters(
|
||||
'fictioneer_filter_list_chapter_title_row',
|
||||
$title_output, $chapter['id'], $chapter['prefix'], $chapter['password'], 'story'
|
||||
);
|
||||
|
||||
?></a>
|
||||
|
||||
<?php if ( $chapter['password'] ) : ?>
|
||||
|
@ -749,6 +749,12 @@ define( 'FICTIONEER_OPTIONS', array(
|
||||
'group' => 'fictioneer-settings-general-group',
|
||||
'sanitize_callback' => 'fictioneer_sanitize_checkbox',
|
||||
'default' => 0
|
||||
),
|
||||
'fictioneer_redirect_scheduled_chapter_404' => array(
|
||||
'name' => 'fictioneer_redirect_scheduled_chapter_404',
|
||||
'group' => 'fictioneer-settings-general-group',
|
||||
'sanitize_callback' => 'fictioneer_sanitize_checkbox',
|
||||
'default' => 0
|
||||
)
|
||||
),
|
||||
'integers' => array(
|
||||
@ -1225,6 +1231,7 @@ function fictioneer_get_option_label( $option ) {
|
||||
'fictioneer_enable_css_skins' => __( 'Enable CSS skins (requires account)', 'fictioneer' ),
|
||||
'fictioneer_exclude_non_stories_from_cloud_counts' => __( 'Only count stories in taxonomy clouds', 'fictioneer' ),
|
||||
'fictioneer_enable_ffcnr_auth' => __( 'Enable FFCNR user authentication', 'fictioneer' ),
|
||||
'fictioneer_redirect_scheduled_chapter_404' => __( 'Redirect scheduled chapters to story or home', 'fictioneer' ),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -313,6 +313,16 @@ $images = get_template_directory_uri() . '/img/documentation/';
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="fictioneer-card__row">
|
||||
<?php
|
||||
fictioneer_settings_label_checkbox(
|
||||
'fictioneer_redirect_scheduled_chapter_404',
|
||||
__( 'Redirect scheduled chapters to story or home', 'fictioneer' ),
|
||||
__( 'Without user permission, they show a 404 error page.', 'fictioneer' )
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="fictioneer-card__row">
|
||||
<?php
|
||||
fictioneer_settings_label_checkbox(
|
||||
@ -1156,7 +1166,7 @@ $images = get_template_directory_uri() . '/img/documentation/';
|
||||
fictioneer_settings_label_checkbox(
|
||||
'fictioneer_disable_all_widgets',
|
||||
__( 'Disable all widgets', 'fictioneer' ),
|
||||
__( 'The theme does not use widgets by default and removing them slightly boosts performance.', 'fictioneer' )
|
||||
__( 'Required for sidebar. If not used, removing widgets slightly boosts performance.', 'fictioneer' )
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
|
4
js/application.min.js
vendored
4
js/application.min.js
vendored
File diff suppressed because one or more lines are too long
2
js/checkmarks.min.js
vendored
2
js/checkmarks.min.js
vendored
@ -1 +1 @@
|
||||
function fcn_toggleCheckmark(e,t=null,a=null){const r=window.FictioneerApp.Controllers.fictioneerCheckmarks;if(!r)return void fcn_showNotification("Error: Checkmarks Controller not connected.",3,"warning");const s=FcnUtils.userData();let i="story";if((e=parseInt(e??0))<1)return void fcn_showNotification("Error: Invalid story ID.",3,"warning");if(null!==t){if((t=parseInt(t))<1)return void fcn_showNotification("Error: Invalid chapter ID.",3,"warning");i="chapter"}("object"!=typeof s.checkmarks.data||null===s.checkmarks.data||Array.isArray(s.checkmarks.data))&&(s.checkmarks.data={}),s.checkmarks.data[e]||(s.checkmarks.data[e]=[]),null===a&&(a="chapter"===i?!s.checkmarks.data[e]?.includes(t):!s.checkmarks.data[e]?.includes(e));const c="chapter"===i?t:e;a?s.checkmarks.data[e].push(c):(FcnUtils.removeArrayItemOnce(s.checkmarks.data[e],c),"chapter"===i&&FcnUtils.removeArrayItemOnce(s.checkmarks.data[e],e)),s.checkmarks.data[e]=s.checkmarks.data[e].filter(((e,t,a)=>a.indexOf(e)==t)),s.lastLoaded=0,FcnUtils.setUserData(s),r.refreshView(),clearTimeout(r.timeout),r.timeout=setTimeout((()=>{FcnUtils.remoteAction("fictioneer_ajax_set_checkmark",{payload:{update:s.checkmarks.data[e].join(" "),story_id:e}})}),FcnGlobals.debounceRate)}application.register("fictioneer-checkmarks",class extends Stimulus.Controller{static get targets(){return["chapterCheck","storyCheck","ribbon"]}timeout=0;initialize(){fcn()?.userReady?this.#e=!0:document.addEventListener("fcnUserDataReady",(()=>{this.refreshView(),this.#e=!0,this.#t()}))}connect(){window.FictioneerApp.Controllers.fictioneerCheckmarks=this,this.#e&&(this.refreshView(),this.#t())}data(){return this.checkmarksCachedData=FcnUtils.userData().checkmarks?.data,Array.isArray(this.checkmarksCachedData)&&0===this.checkmarksCachedData.length&&(this.checkmarksCachedData={}),this.checkmarksCachedData}toggleChapter({params:{chapter:e,story:t}}){fcn_toggleCheckmark(t,e)}toggleStory({params:{story:e}}){fcn_toggleCheckmark(e)}clear(){const e=FcnUtils.userData();e.checkmarks={data:{},updated:Date.now()},fcn().setUserData(e),this.refreshView()}refreshView(){const e=this.data();!e||Object.keys(e).length<1?this.uncheckAll():Object.entries(e).forEach((([e,t])=>{e=parseInt(e);const a=t?.includes(e);this.hasChapterCheckTarget&&(a?this.chapterCheckTargets.forEach((e=>{e.classList.toggle("marked",!0),e.setAttribute("aria-checked",!0)})):this.chapterCheckTargets.forEach((a=>{const r=parseInt(a.dataset.fictioneerCheckmarksChapterParam);if(parseInt(a.dataset.fictioneerCheckmarksStoryParam)===e){const e=t?.includes(r);a.classList.toggle("marked",e),a.setAttribute("aria-checked",e)}}))),this.hasStoryCheckTarget&&(this.storyCheckTarget.classList.toggle("marked",a),this.storyCheckTarget.setAttribute("aria-checked",a)),this.hasRibbonTarget&&this.ribbonTarget.classList.toggle("hidden",!a)}))}uncheckAll(){this.hasChapterCheckTarget&&this.chapterCheckTargets.forEach((e=>{e.classList.toggle("marked",!1),e.setAttribute("aria-checked",!1)})),this.hasStoryCheckTarget&&(this.storyCheckTarget.classList.toggle("marked",!1),this.storyCheckTarget.setAttribute("aria-checked",!1))}#e=!1;#a=!1;#r(){const e=FcnUtils.loggedIn();return e||(this.#s(),this.#a=!0),e}#i(){return this.#r()&&JSON.stringify(this.checkmarksCachedData??0)!==JSON.stringify(this.data())}#c(){this.refreshInterval||(this.refreshInterval=setInterval((()=>{!this.#a&&this.#i()&&this.refreshView()}),3e4+1e3*Math.random()))}#t(){this.#c(),this.visibilityStateCheck=()=>{this.#r()&&("visible"===document.visibilityState?(this.#a=!1,this.refreshView(),this.#c()):(this.#a=!0,clearInterval(this.refreshInterval),this.refreshInterval=null))},document.addEventListener("visibilitychange",this.visibilityStateCheck)}#s(){clearInterval(this.refreshInterval),document.removeEventListener("visibilitychange",this.visibilityStateCheck)}});
|
||||
function fcn_toggleCheckmark(e,t=null,a=null){const r=window.FictioneerApp.Controllers.fictioneerCheckmarks;if(!r)return void fcn_showNotification("Error: Checkmarks Controller not connected.",3,"warning");const s=FcnUtils.userData();let i="story";if((e=parseInt(e??0))<1)return void fcn_showNotification("Error: Invalid story ID.",3,"warning");if(null!==t){if((t=parseInt(t))<1)return void fcn_showNotification("Error: Invalid chapter ID.",3,"warning");i="chapter"}("object"!=typeof s.checkmarks.data||null===s.checkmarks.data||Array.isArray(s.checkmarks.data))&&(s.checkmarks.data={}),s.checkmarks.data[e]||(s.checkmarks.data[e]=[]),null===a&&(a="chapter"===i?!s.checkmarks.data[e]?.includes(t):!s.checkmarks.data[e]?.includes(e));const c="chapter"===i?t:e;a?s.checkmarks.data[e].push(c):(FcnUtils.removeArrayItemOnce(s.checkmarks.data[e],c),"chapter"===i&&FcnUtils.removeArrayItemOnce(s.checkmarks.data[e],e)),s.checkmarks.data[e]=s.checkmarks.data[e].filter(((e,t,a)=>a.indexOf(e)==t)),s.lastLoaded=0,FcnUtils.setUserData(s),r.refreshView(),clearTimeout(r.timeout),r.timeout=setTimeout((()=>{FcnUtils.remoteAction("fictioneer_ajax_set_checkmark",{payload:{update:s.checkmarks.data[e].join(" "),story_id:e}})}),FcnGlobals.debounceRate)}application.register("fictioneer-checkmarks",class extends Stimulus.Controller{static get targets(){return["chapterCheck","storyCheck","ribbon"]}timeout=0;initialize(){fcn()?.userReady?this.#e=!0:document.addEventListener("fcnUserDataReady",(()=>{this.refreshView(),this.#e=!0,this.#t()}))}connect(){window.FictioneerApp.Controllers.fictioneerCheckmarks=this,this.#e&&(this.refreshView(),this.#t())}data(){return this.checkmarksCachedData=FcnUtils.userData().checkmarks?.data,Array.isArray(this.checkmarksCachedData)&&0===this.checkmarksCachedData.length&&(this.checkmarksCachedData={}),this.checkmarksCachedData}toggleChapter({params:{chapter:e,story:t}}){fcn_toggleCheckmark(t,e)}toggleStory({params:{story:e}}){fcn_toggleCheckmark(e)}clear(){const e=FcnUtils.userData();e.checkmarks={data:{},updated:Date.now()},fcn().setUserData(e),this.refreshView()}refreshView(){const e=this.data();if(!e||Object.keys(e).length<1)return void this.uncheckAll();let t=!1;Object.entries(e).forEach((([e,a])=>{e=parseInt(e),this.hasStoryCheckTarget&&e==this.storyCheckTarget.dataset.fictioneerCheckmarksStoryParam&&(t=a?.includes(e)),this.hasChapterCheckTarget&&(t?this.chapterCheckTargets.forEach((e=>{e.classList.toggle("marked",!0),e.setAttribute("aria-checked",!0)})):this.chapterCheckTargets.forEach((t=>{const r=parseInt(t.dataset.fictioneerCheckmarksChapterParam);if(parseInt(t.dataset.fictioneerCheckmarksStoryParam)===e){const e=a?.includes(r);t.classList.toggle("marked",e),t.setAttribute("aria-checked",e)}}))),this.hasStoryCheckTarget&&(this.storyCheckTarget.classList.toggle("marked",t),this.storyCheckTarget.setAttribute("aria-checked",t)),this.hasRibbonTarget&&this.ribbonTarget.classList.toggle("hidden",!t)}))}uncheckAll(){this.hasChapterCheckTarget&&this.chapterCheckTargets.forEach((e=>{e.classList.toggle("marked",!1),e.setAttribute("aria-checked",!1)})),this.hasStoryCheckTarget&&(this.storyCheckTarget.classList.toggle("marked",!1),this.storyCheckTarget.setAttribute("aria-checked",!1))}#e=!1;#a=!1;#r(){const e=FcnUtils.loggedIn();return e||(this.#s(),this.#a=!0),e}#i(){return this.#r()&&JSON.stringify(this.checkmarksCachedData??0)!==JSON.stringify(this.data())}#c(){this.refreshInterval||(this.refreshInterval=setInterval((()=>{!this.#a&&this.#i()&&this.refreshView()}),3e4+1e3*Math.random()))}#t(){this.#c(),this.visibilityStateCheck=()=>{this.#r()&&("visible"===document.visibilityState?(this.#a=!1,this.refreshView(),this.#c()):(this.#a=!0,clearInterval(this.refreshInterval),this.refreshInterval=null))},document.addEventListener("visibilitychange",this.visibilityStateCheck)}#s(){clearInterval(this.refreshInterval),document.removeEventListener("visibilitychange",this.visibilityStateCheck)}});
|
10
js/complete.min.js
vendored
10
js/complete.min.js
vendored
File diff suppressed because one or more lines are too long
2
js/follows.min.js
vendored
2
js/follows.min.js
vendored
@ -1 +1 @@
|
||||
function fcn_toggleFollow(t,e=null){const s=window.FictioneerApp.Controllers.fictioneerFollows;if(!s)return void fcn_showNotification("Error: Follows Controller not connected.",3,"warning");const a=FcnUtils.userData();("object"!=typeof a.follows.data||null===a.follows.data||Array.isArray(a.follows.data))&&(a.follows.data={}),(e=e??!a.follows.data[t])?a.follows.data[t]={story_id:parseInt(t),timestamp:Date.now()}:delete a.follows.data[t],a.lastLoaded=0,FcnUtils.setUserData(a),s.refreshView(),clearTimeout(s.timeout),s.timeout=setTimeout((()=>{FcnUtils.remoteAction("fictioneer_ajax_toggle_follow",{payload:{set:e,story_id:t}})}),FcnGlobals.debounceRate)}application.register("fictioneer-follows",class extends Stimulus.Controller{static get targets(){return["toggleButton","newDisplay","scrollList","mobileScrollList","mobileMarkRead"]}followsLoaded=!1;markedRead=!1;timeout=0;initialize(){fcn()?.userReady?this.#t=!0:document.addEventListener("fcnUserDataReady",(()=>{this.refreshView(),this.#t=!0,this.#e()}))}connect(){window.FictioneerApp.Controllers.fictioneerFollows=this,this.#t&&(this.refreshView(),this.#e())}data(){return this.followsCachedData=FcnUtils.userData().follows?.data,Array.isArray(this.followsCachedData)&&0===this.followsCachedData.length&&(this.followsCachedData={}),this.followsCachedData}isFollowed(t){return!(!FcnUtils.loggedIn()||!this.data()?.[t])}unreadCount(){return parseInt(FcnUtils.userData()?.follows?.new??0)}toggleFollow({params:{id:t}}){this.#s()&&(fcn_toggleFollow(t,!this.isFollowed(t)),this.refreshView())}clear(){const t=FcnUtils.userData();t.follows={data:{}},fcn().setUserData(t),this.refreshView()}refreshView(){this.toggleButtonTargets.forEach((t=>{const e=t.dataset.storyId;t.classList.toggle("_followed",this.isFollowed(e))}));const t=this.unreadCount();this.newDisplayTargets.forEach((e=>{e.classList.toggle("_new",t>0),t>0&&(e.dataset.newCount=t,this.hasMobileMarkReadTarget&&this.mobileMarkReadTarget.classList.remove("hidden"))}))}loadFollowsHtml(){this.followsLoaded||FcnUtils.aGet({action:"fictioneer_ajax_get_follows_notifications",fcn_fast_ajax:1}).then((t=>{t.data.html&&(this.hasScrollListTarget&&(this.scrollListTarget.innerHTML=t.data.html),this.hasMobileScrollListTarget&&(this.mobileScrollListTarget.innerHTML=t.data.html),!1===FcnUtils.userData().loggedIn&&(fcn().removeUserData(),fcn().fetchUserData()))})).catch((t=>{429===t.status?fcn_showNotification(fictioneer_tl.notification.slowDown,3,"warning"):t.status&&t.statusText&&fcn_showNotification(`${t.status}: ${t.statusText}`,5,"warning"),this.hasScrollListTarget&&this.scrollListTarget.remove(),this.hasMobileScrollListTarget&&this.mobileScrollListTarget.remove()})).then((()=>{this.followsLoaded=!0,this.hasNewDisplayTarget&&this.newDisplayTargets.forEach((t=>{t.classList.add("_loaded")}))}))}markRead(){if(!this.followsLoaded&&this.unreadCount()>0||this.markedRead)return;this.markedRead=!0,this.newDisplayTargets.forEach((t=>{t.classList.remove("_new")})),this.hasMobileMarkReadTarget&&this.mobileMarkReadTarget.classList.add("hidden");const t=FcnUtils.userData();t.new=0,t.lastLoaded=0,FcnUtils.setUserData(t),FcnUtils.aPost({action:"fictioneer_ajax_mark_follows_read",fcn_fast_ajax:1}).catch((t=>{t.status&&t.statusText&&fcn_showNotification(`${t.status}: ${t.statusText}`,5,"warning")}))}#t=!1;#a=!1;#s(){const t=FcnUtils.loggedIn();return t||(this.#i(),this.#a=!0),t}#o(){return this.#s()&&JSON.stringify(this.followsCachedData??0)!==JSON.stringify(this.data())}#l(){this.refreshInterval||(this.refreshInterval=setInterval((()=>{!this.#a&&this.#o()&&this.refreshView()}),3e4+1e3*Math.random()))}#e(){this.#l(),this.visibilityStateCheck=()=>{this.#s()&&("visible"===document.visibilityState?(this.#a=!1,this.refreshView(),this.#l()):(this.#a=!0,clearInterval(this.refreshInterval),this.refreshInterval=null))},document.addEventListener("visibilitychange",this.visibilityStateCheck)}#i(){clearInterval(this.refreshInterval),document.removeEventListener("visibilitychange",this.visibilityStateCheck)}});
|
||||
function fcn_toggleFollow(t,e=null){const s=window.FictioneerApp.Controllers.fictioneerFollows;if(!s)return void fcn_showNotification("Error: Follows Controller not connected.",3,"warning");const a=FcnUtils.userData();("object"!=typeof a.follows.data||null===a.follows.data||Array.isArray(a.follows.data))&&(a.follows.data={}),(e=e??!a.follows.data[t])?a.follows.data[t]={story_id:parseInt(t),timestamp:Date.now()}:delete a.follows.data[t],a.lastLoaded=0,FcnUtils.setUserData(a),s.refreshView(),clearTimeout(s.timeout),s.timeout=setTimeout((()=>{FcnUtils.remoteAction("fictioneer_ajax_toggle_follow",{payload:{set:e,story_id:t}})}),FcnGlobals.debounceRate)}application.register("fictioneer-follows",class extends Stimulus.Controller{static get targets(){return["toggleButton","newDisplay","scrollList","mobileScrollList","mobileMarkRead"]}followsLoaded=!1;markedRead=!1;timeout=0;initialize(){fcn()?.userReady?this.#t=!0:document.addEventListener("fcnUserDataReady",(()=>{this.refreshView(),this.#t=!0,this.#e()}))}connect(){window.FictioneerApp.Controllers.fictioneerFollows=this,this.#t&&(this.refreshView(),this.#e())}data(){return this.followsCachedData=FcnUtils.userData().follows?.data,Array.isArray(this.followsCachedData)&&0===this.followsCachedData.length&&(this.followsCachedData={}),this.followsCachedData}isFollowed(t){return!(!FcnUtils.loggedIn()||!this.data()?.[t])}unreadCount(){return parseInt(FcnUtils.userData()?.follows?.new??0)}toggleFollow({params:{id:t}}){this.#s()&&(fcn_toggleFollow(t,!this.isFollowed(t)),this.refreshView())}clear(){const t=FcnUtils.userData();t.follows={data:{}},fcn().setUserData(t),this.refreshView()}refreshView(){this.toggleButtonTargets.forEach((t=>{const e=t.dataset.storyId;t.classList.toggle("_followed",this.isFollowed(e))}));const t=this.unreadCount();this.newDisplayTargets.forEach((e=>{e.classList.toggle("_new",t>0),t>0&&(e.dataset.newCount=t,this.hasMobileMarkReadTarget&&this.mobileMarkReadTarget.classList.remove("hidden"))}))}loadFollowsHtml(){this.followsLoaded||FcnUtils.aGet({action:"fictioneer_ajax_get_follows_notifications",fcn_fast_ajax:1}).then((t=>{t.data.html&&(this.hasScrollListTarget&&(this.scrollListTarget.innerHTML=t.data.html),this.hasMobileScrollListTarget&&(this.mobileScrollListTarget.innerHTML=t.data.html),!1===FcnUtils.userData().loggedIn&&(fcn().removeUserData(),fcn().fetchUserData()))})).catch((t=>{429===t.status?fcn_showNotification(fictioneer_tl.notification.slowDown,3,"warning"):t.status&&t.statusText&&fcn_showNotification(`${t.status}: ${t.statusText}`,5,"warning"),this.hasScrollListTarget&&this.scrollListTarget.remove(),this.hasMobileScrollListTarget&&this.mobileScrollListTarget.remove()})).then((()=>{this.followsLoaded=!0,this.hasNewDisplayTarget&&this.newDisplayTargets.forEach((t=>{t.classList.add("_loaded")}))}))}markRead(){if(!this.followsLoaded&&this.unreadCount()>0||this.markedRead)return;this.markedRead=!0,this.newDisplayTargets.forEach((t=>{t.classList.remove("_new")})),_$$(".follow-item").forEach((t=>{t.classList.remove("_new")})),this.hasMobileMarkReadTarget&&this.mobileMarkReadTarget.classList.add("hidden");const t=FcnUtils.userData();t.new=0,t.lastLoaded=0,FcnUtils.setUserData(t),FcnUtils.aPost({action:"fictioneer_ajax_mark_follows_read",fcn_fast_ajax:1}).catch((t=>{t.status&&t.statusText&&fcn_showNotification(`${t.status}: ${t.statusText}`,5,"warning")}))}#t=!1;#a=!1;#s(){const t=FcnUtils.loggedIn();return t||(this.#i(),this.#a=!0),t}#o(){return this.#s()&&JSON.stringify(this.followsCachedData??0)!==JSON.stringify(this.data())}#l(){this.refreshInterval||(this.refreshInterval=setInterval((()=>{!this.#a&&this.#o()&&this.refreshView()}),3e4+1e3*Math.random()))}#e(){this.#l(),this.visibilityStateCheck=()=>{this.#s()&&("visible"===document.visibilityState?(this.#a=!1,this.refreshView(),this.#l()):(this.#a=!0,clearInterval(this.refreshInterval),this.refreshInterval=null))},document.addEventListener("visibilitychange",this.visibilityStateCheck)}#i(){clearInterval(this.refreshInterval),document.removeEventListener("visibilitychange",this.visibilityStateCheck)}});
|
4
js/sortable.min.js
vendored
4
js/sortable.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
Binary file not shown.
2461
languages/pt_BR.po
2461
languages/pt_BR.po
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,7 @@
|
||||
* @internal $args['orderby'] Sorting of posts. Default 'date'.
|
||||
* @internal $args['page'] The current page. Default 1.
|
||||
* @internal $args['post_ids'] Array of post IDs. Default empty.
|
||||
* @internal $args['post_status'] Queried post status. Default 'publish'.
|
||||
* @internal $args['author_ids'] Array of author IDs. Default empty.
|
||||
* @internal $args['excluded_authors'] Array of author IDs to exclude. Default empty.
|
||||
* @internal $args['excluded_cats'] Array of category IDs to exclude. Default empty.
|
||||
@ -50,7 +51,7 @@ $show_terms = ! in_array( $args['terms'], ['none', 'false'] );
|
||||
$query_args = array(
|
||||
'fictioneer_query_name' => 'article_cards',
|
||||
'post_type' => $args['post_type'],
|
||||
'post_status' => 'publish',
|
||||
'post_status' => $args['post_status'],
|
||||
'post__in' => $args['post_ids'], // May be empty!
|
||||
'order' => $args['order'],
|
||||
'orderby' => $args['orderby'],
|
||||
@ -175,6 +176,8 @@ if ( $splide ) {
|
||||
}
|
||||
|
||||
// Extra classes
|
||||
$card_classes[] = '_' . $args['post_status'];
|
||||
|
||||
if ( get_theme_mod( 'card_style', 'default' ) !== 'default' ) {
|
||||
$card_classes[] = '_' . get_theme_mod( 'card_style' );
|
||||
}
|
||||
|
@ -97,7 +97,6 @@ $thumbnail_args = array(
|
||||
data-controller="fictioneer-large-card"
|
||||
data-fictioneer-large-card-post-id-value="<?php echo $post_id; ?>"
|
||||
data-fictioneer-large-card-story-id-value="<?php echo $story_id; ?>"
|
||||
data-fictioneer-large-card-chapter-id-value="<?php echo $post_id; ?>"
|
||||
data-action="click->fictioneer-large-card#cardClick"
|
||||
<?php echo $card_attributes; ?>
|
||||
>
|
||||
|
@ -17,6 +17,7 @@
|
||||
* @internal $args['spoiler'] Whether to obscure or show chapter excerpt.
|
||||
* @internal $args['source'] Whether to show author and story.
|
||||
* @internal $args['post_ids'] Array of post IDs. Default empty.
|
||||
* @internal $args['post_status'] Queried post status. Default 'publish'.
|
||||
* @internal $args['author_ids'] Array of author IDs. Default empty.
|
||||
* @internal $args['excluded_authors'] Array of author IDs to exclude. Default empty.
|
||||
* @internal $args['excluded_cats'] Array of category IDs to exclude. Default empty.
|
||||
@ -51,7 +52,7 @@ $card_counter = 0;
|
||||
$query_args = array(
|
||||
'fictioneer_query_name' => 'latest_chapters_compact',
|
||||
'post_type' => 'fcn_chapter',
|
||||
'post_status' => 'publish',
|
||||
'post_status' => $args['post_status'],
|
||||
'post__in' => $args['post_ids'], // May be empty!
|
||||
'order' => $args['order'],
|
||||
'orderby' => $args['orderby'],
|
||||
@ -156,7 +157,7 @@ if ( $splide ) {
|
||||
$post_id = $post->ID;
|
||||
$story_id = fictioneer_get_chapter_story_id( $post_id );
|
||||
|
||||
if ( get_post_status( $story_id ) !== 'publish' ) {
|
||||
if ( $story_id && get_post_status( $story_id ) !== 'publish' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -168,6 +169,8 @@ if ( $splide ) {
|
||||
$card_classes = [];
|
||||
|
||||
// Extra card classes
|
||||
$card_classes[] = '_' . $args['post_status'];
|
||||
|
||||
if ( ! empty( $post->post_password ) ) {
|
||||
$card_classes[] = '_password';
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
* @internal $args['orderby'] Sorting of posts. Default 'date'.
|
||||
* @internal $args['spoiler'] Whether to obscure or show chapter excerpt.
|
||||
* @internal $args['post_ids'] Array of post IDs. Default empty.
|
||||
* @internal $args['post_status'] Queried post status. Default 'publish'.
|
||||
* @internal $args['author_ids'] Array of author IDs. Default empty.
|
||||
* @internal $args['excluded_authors'] Array of author IDs to exclude. Default empty.
|
||||
* @internal $args['excluded_cats'] Array of category IDs to exclude. Default empty.
|
||||
@ -56,7 +57,7 @@ $content_list_style = get_theme_mod( 'content_list_style', 'default' );
|
||||
$query_args = array(
|
||||
'fictioneer_query_name' => 'latest_chapters_list',
|
||||
'post_type' => 'fcn_chapter',
|
||||
'post_status' => 'publish',
|
||||
'post_status' => $args['post_status'],
|
||||
'post__in' => $args['post_ids'], // May be empty!
|
||||
'orderby' => $args['orderby'],
|
||||
'order' => $args['order'],
|
||||
@ -160,9 +161,8 @@ if ( $splide ) {
|
||||
// Setup
|
||||
$post_id = $post->ID;
|
||||
$story_id = fictioneer_get_chapter_story_id( $post_id );
|
||||
$story = $story_id ? fictioneer_get_story_data( $story_id, false ) : null; // Does not refresh comment count!
|
||||
|
||||
if ( get_post_status( $story_id ) !== 'publish' || ! $story ) {
|
||||
if ( $story_id && get_post_status( $story_id ) !== 'publish' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -173,11 +173,12 @@ if ( $splide ) {
|
||||
|
||||
// Continue setup
|
||||
$title = fictioneer_get_safe_title( $post_id, 'shortcode-latest-chapters-list' );
|
||||
$story = $story_id ? fictioneer_get_story_data( $story_id, false ) : null; // Does not refresh comment count!
|
||||
$permalink = get_permalink( $post_id );
|
||||
$chapter_rating = get_post_meta( $post_id, 'fictioneer_chapter_rating', true );
|
||||
$words = fictioneer_get_word_count( $post_id );
|
||||
|
||||
if ( ! $chapter_rating && $story_id ) {
|
||||
if ( ! $chapter_rating && $story ) {
|
||||
$chapter_rating = get_post_meta( $story_id, 'fictioneer_story_rating', true );
|
||||
}
|
||||
|
||||
@ -200,7 +201,7 @@ if ( $splide ) {
|
||||
}
|
||||
|
||||
// Extra classes
|
||||
$classes = [];
|
||||
$classes = [ '_' . $args['post_status'] ];
|
||||
|
||||
if ( ! empty( $post->post_password ) ) {
|
||||
$classes[] = '_password';
|
||||
@ -249,7 +250,7 @@ if ( $splide ) {
|
||||
// Meta
|
||||
$meta = [];
|
||||
|
||||
if ( $args['source'] ) {
|
||||
if ( $story && $args['source'] ) {
|
||||
$meta['story'] = sprintf(
|
||||
_x(
|
||||
'<span class="post-list-item__meta-in-story"><span>in </span><a href="%1$s">%2$s</a></span>',
|
||||
@ -268,7 +269,7 @@ if ( $splide ) {
|
||||
) . '</span>';
|
||||
}
|
||||
|
||||
if ( $args['footer_status'] ) {
|
||||
if ( $story && $args['footer_status'] ) {
|
||||
$meta['status'] = '<span class="post-item-item__meta-status _' . strtolower( $story['status'] ) . '">' . fcntr( $story['status'] ) . '</span>';
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
* @internal $args['orderby'] Sorting of posts. Default 'date'.
|
||||
* @internal $args['spoiler'] Whether to obscure or show chapter excerpt.
|
||||
* @internal $args['post_ids'] Array of post IDs. Default empty.
|
||||
* @internal $args['post_status'] Queried post status. Default 'publish'.
|
||||
* @internal $args['author_ids'] Array of author IDs. Default empty.
|
||||
* @internal $args['excluded_authors'] Array of author IDs to exclude. Default empty.
|
||||
* @internal $args['excluded_cats'] Array of category IDs to exclude. Default empty.
|
||||
@ -56,7 +57,7 @@ $card_counter = 0;
|
||||
$query_args = array(
|
||||
'fictioneer_query_name' => 'latest_chapters',
|
||||
'post_type' => 'fcn_chapter',
|
||||
'post_status' => 'publish',
|
||||
'post_status' => $args['post_status'],
|
||||
'post__in' => $args['post_ids'], // May be empty!
|
||||
'orderby' => $args['orderby'],
|
||||
'order' => $args['order'],
|
||||
@ -161,22 +162,25 @@ if ( $splide ) {
|
||||
$post_id = $post->ID;
|
||||
$story_id = fictioneer_get_chapter_story_id( $post_id );
|
||||
|
||||
if ( get_post_status( $story_id ) !== 'publish' ) {
|
||||
if ( $story_id && get_post_status( $story_id ) !== 'publish' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$title = fictioneer_get_safe_title( $post_id, 'shortcode-latest-chapters' );
|
||||
$permalink = get_permalink();
|
||||
$chapter_rating = get_post_meta( $post_id, 'fictioneer_chapter_rating', true );
|
||||
$story = $story_id ? fictioneer_get_story_data( $story_id, false ) : null; // Does not refresh comment count!
|
||||
$text_icon = get_post_meta( $post_id, 'fictioneer_chapter_text_icon', true );
|
||||
$grid_or_vertical = $args['vertical'] ? '_vertical' : '_grid';
|
||||
$card_classes = [];
|
||||
|
||||
if ( ! $chapter_rating && $story_id ) {
|
||||
if ( ! $chapter_rating && $story ) {
|
||||
$chapter_rating = get_post_meta( $story_id, 'fictioneer_story_rating', true );
|
||||
}
|
||||
|
||||
// Extra card classes
|
||||
$card_classes[] = '_' . $args['post_status'];
|
||||
|
||||
if ( ! empty( $post->post_password ) ) {
|
||||
$card_classes[] = '_password';
|
||||
}
|
||||
@ -259,7 +263,7 @@ if ( $splide ) {
|
||||
'post_id' => $post_id,
|
||||
'title' => $title,
|
||||
'classes' => 'card__image cell-img',
|
||||
'permalink' => get_permalink(),
|
||||
'permalink' => $permalink,
|
||||
'lightbox' => $args['lightbox'],
|
||||
'vertical' => $args['vertical'],
|
||||
'seamless' => $args['seamless'],
|
||||
@ -270,7 +274,7 @@ if ( $splide ) {
|
||||
}
|
||||
?>
|
||||
|
||||
<h3 class="card__title _small cell-title"><a href="<?php the_permalink(); ?>" class="truncate _1-1"><?php
|
||||
<h3 class="card__title _small cell-title"><a href="<?php echo $permalink; ?>" class="truncate _1-1"><?php
|
||||
$list_title = get_post_meta( $post_id, 'fictioneer_chapter_list_title', true );
|
||||
$list_title = trim( wp_strip_all_tags( $list_title ) );
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
* @internal $args['author'] The author provided by the shortcode. Default false.
|
||||
* @internal $args['count'] The number of posts provided by the shortcode. Default 1.
|
||||
* @internal $args['post_ids'] Array of post IDs. Default empty.
|
||||
* @internal $args['post_status'] Queried post status. Default 'publish'.
|
||||
* @internal $args['author_ids'] Array of author IDs. Default empty.
|
||||
* @internal $args['excluded_authors'] Array of author IDs to exclude. Default empty.
|
||||
* @internal $args['excluded_cats'] Array of category IDs to exclude. Default empty.
|
||||
@ -32,7 +33,7 @@ defined( 'ABSPATH' ) OR exit;
|
||||
$query_args = array(
|
||||
'fictioneer_query_name' => 'latest_posts',
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'post_status' => $args['post_status'],
|
||||
'post__in' => $args['post_ids'], // May be empty!
|
||||
'order' => 'DESC',
|
||||
'orderby' => 'date',
|
||||
@ -88,6 +89,9 @@ $query_args = apply_filters( 'fictioneer_filter_shortcode_latest_posts_query_arg
|
||||
// Query post
|
||||
$latest_entries = fictioneer_shortcode_query( $query_args );
|
||||
|
||||
// Classes
|
||||
$args['classes'] .= ' _' . $args['post_status'];
|
||||
|
||||
?>
|
||||
|
||||
<section class="latest-posts <?php echo $args['classes']; ?>">
|
||||
|
@ -15,6 +15,7 @@
|
||||
* @internal $args['order'] Order of posts. Default 'DESC'.
|
||||
* @internal $args['orderby'] Sorting of posts. Default 'date'.
|
||||
* @internal $args['post_ids'] Array of post IDs. Default empty.
|
||||
* @internal $args['post_status'] Queried post status. Default 'publish'.
|
||||
* @internal $args['author_ids'] Array of author IDs. Default empty.
|
||||
* @internal $args['excluded_authors'] Array of author IDs to exclude. Default empty.
|
||||
* @internal $args['excluded_cats'] Array of category IDs to exclude. Default empty.
|
||||
@ -48,7 +49,7 @@ $show_terms = ! in_array( $args['terms'], ['none', 'false'] ) &&
|
||||
$query_args = array (
|
||||
'fictioneer_query_name' => 'latest_recommendations_compact',
|
||||
'post_type' => 'fcn_recommendation',
|
||||
'post_status' => 'publish',
|
||||
'post_status' => $args['post_status'],
|
||||
'post__in' => $args['post_ids'], // May be empty!
|
||||
'order' => $args['order'],
|
||||
'orderby' => $args['orderby'],
|
||||
@ -143,7 +144,9 @@ if ( $splide ) {
|
||||
$grid_or_vertical = $args['vertical'] ? '_vertical' : '_grid';
|
||||
$card_classes = [];
|
||||
|
||||
// Extra classes
|
||||
// Extra card classes
|
||||
$card_classes[] = '_' . $args['post_status'];
|
||||
|
||||
if ( $show_terms ) {
|
||||
$card_classes[] = '_info';
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
* @internal $args['order'] Order of posts. Default 'DESC'.
|
||||
* @internal $args['orderby'] Sorting of posts. Default 'date'.
|
||||
* @internal $args['post_ids'] Array of post IDs. Default empty.
|
||||
* @internal $args['post_status'] Queried post status. Default 'publish'.
|
||||
* @internal $args['author_ids'] Array of author IDs. Default empty.
|
||||
* @internal $args['excluded_authors'] Array of author IDs to exclude. Default empty.s
|
||||
* @internal $args['excluded_cats'] Array of category IDs to exclude. Default empty.
|
||||
@ -46,7 +47,7 @@ $show_terms = ! get_option( 'fictioneer_hide_taxonomies_on_recommendation_cards'
|
||||
$query_args = array (
|
||||
'fictioneer_query_name' => 'latest_recommendations',
|
||||
'post_type' => 'fcn_recommendation',
|
||||
'post_status' => 'publish',
|
||||
'post_status' => $args['post_status'],
|
||||
'post__in' => $args['post_ids'], // May be empty!
|
||||
'order' => $args['order'],
|
||||
'orderby' => $args['orderby'],
|
||||
@ -140,7 +141,9 @@ if ( $splide ) {
|
||||
$grid_or_vertical = $args['vertical'] ? '_vertical' : '_grid';
|
||||
$card_classes = [];
|
||||
|
||||
// Extra classes
|
||||
// Extra card classes
|
||||
$card_classes[] = '_' . $args['post_status'];
|
||||
|
||||
if ( get_theme_mod( 'card_style', 'default' ) !== 'default' ) {
|
||||
$card_classes[] = '_' . get_theme_mod( 'card_style' );
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
* @internal $args['order'] Order of posts. Default 'DESC'.
|
||||
* @internal $args['orderby'] Sorting of posts. Default 'date'.
|
||||
* @internal $args['post_ids'] Array of post IDs. Default empty.
|
||||
* @internal $args['post_status'] Queried post status. Default 'publish'.
|
||||
* @internal $args['author_ids'] Array of author IDs. Default empty.
|
||||
* @internal $args['excluded_authors'] Array of author IDs to exclude. Default empty.
|
||||
* @internal $args['excluded_cats'] Array of category IDs to exclude. Default empty.
|
||||
@ -56,7 +57,7 @@ $show_terms = ! in_array( $args['terms'], ['none', 'false'] ) &&
|
||||
$query_args = array(
|
||||
'fictioneer_query_name' => 'latest_stories_compact',
|
||||
'post_type' => 'fcn_story',
|
||||
'post_status' => 'publish',
|
||||
'post_status' => $args['post_status'],
|
||||
'post__in' => $args['post_ids'], // May be empty!
|
||||
'order' => $args['order'],
|
||||
'orderby' => $args['orderby'],
|
||||
@ -171,7 +172,9 @@ if ( $splide ) {
|
||||
);
|
||||
$short_description = mb_strlen( $short_description, 'UTF-8' ) < 30 ? get_the_excerpt() : $short_description;
|
||||
|
||||
// Extra classes
|
||||
// Extra card classes
|
||||
$card_classes[] = '_' . $args['post_status'];
|
||||
|
||||
if ( $show_terms ) {
|
||||
$card_classes[] = '_info';
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
* @internal $args['order'] Order of posts. Default 'DESC'.
|
||||
* @internal $args['orderby'] Sorting of posts. Default 'date'.
|
||||
* @internal $args['post_ids'] Array of post IDs. Default empty.
|
||||
* @internal $args['post_status'] Queried post status. Default 'publish'.
|
||||
* @internal $args['author_ids'] Array of author IDs. Default empty.
|
||||
* @internal $args['excluded_authors'] Array of author IDs to exclude. Default empty.
|
||||
* @internal $args['excluded_cats'] Array of category IDs to exclude. Default empty.
|
||||
@ -57,7 +58,7 @@ $content_list_style = get_theme_mod( 'content_list_style', 'default' );
|
||||
$query_args = array(
|
||||
'fictioneer_query_name' => 'latest_stories_list',
|
||||
'post_type' => 'fcn_story',
|
||||
'post_status' => 'publish',
|
||||
'post_status' => $args['post_status'],
|
||||
'post__in' => $args['post_ids'], // May be empty!
|
||||
'order' => $args['order'],
|
||||
'orderby' => $args['orderby'],
|
||||
@ -184,7 +185,7 @@ if ( $splide ) {
|
||||
}
|
||||
|
||||
// Extra classes
|
||||
$classes = [];
|
||||
$classes = [ '_' . $args['post_status'] ];
|
||||
|
||||
if ( $is_sticky ) {
|
||||
$classes[] = '_sticky';
|
||||
|
@ -16,6 +16,7 @@
|
||||
* @internal $args['order'] Order of posts. Default 'DESC'.
|
||||
* @internal $args['orderby'] Sorting of posts. Default 'date'.
|
||||
* @internal $args['post_ids'] Array of post IDs. Default empty.
|
||||
* @internal $args['post_status'] Queried post status. Default 'publish'.
|
||||
* @internal $args['author_ids'] Array of author IDs. Default empty.
|
||||
* @internal $args['excluded_authors'] Array of author IDs to exclude. Default empty.
|
||||
* @internal $args['excluded_cats'] Array of category IDs to exclude. Default empty.
|
||||
@ -57,7 +58,7 @@ $show_terms = ! in_array( $args['terms'], ['none', 'false'] ) &&
|
||||
$query_args = array(
|
||||
'fictioneer_query_name' => 'latest_stories',
|
||||
'post_type' => 'fcn_story',
|
||||
'post_status' => 'publish',
|
||||
'post_status' => $args['post_status'],
|
||||
'post__in' => $args['post_ids'], // May be empty!
|
||||
'order' => $args['order'],
|
||||
'orderby' => $args['orderby'],
|
||||
@ -167,6 +168,9 @@ if ( $splide ) {
|
||||
$grid_or_vertical = $args['vertical'] ? '_vertical' : '_grid';
|
||||
$card_classes = [];
|
||||
|
||||
// Extra card classes
|
||||
$card_classes[] = '_' . $args['post_status'];
|
||||
|
||||
if ( $is_sticky ) {
|
||||
$card_classes[] = '_sticky';
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
* @internal $args['author'] Author provided by the shortcode.
|
||||
* @internal $args['order'] Order of posts. Default 'DESC'.
|
||||
* @internal $args['post_ids'] Array of post IDs. Default empty.
|
||||
* @internal $args['post_status'] Queried post status. Default 'publish'.
|
||||
* @internal $args['author_ids'] Array of author IDs. Default empty.
|
||||
* @internal $args['excluded_authors'] Array of author IDs to exclude. Default empty.
|
||||
* @internal $args['excluded_cats'] Array of category IDs to exclude. Default empty.
|
||||
@ -59,7 +60,7 @@ $card_counter = 0;
|
||||
$query_args = array(
|
||||
'fictioneer_query_name' => 'latest_updates_compact',
|
||||
'post_type' => 'fcn_story',
|
||||
'post_status' => 'publish',
|
||||
'post_status' => $args['post_status'],
|
||||
'post__in' => $args['post_ids'], // May be empty!
|
||||
'order' => $args['order'],
|
||||
'orderby' => 'meta_value',
|
||||
@ -181,7 +182,9 @@ if ( $splide ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extra classes
|
||||
// Extra card classes
|
||||
$card_classes[] = '_' . $args['post_status'];
|
||||
|
||||
if ( ! empty( $post->post_password ) ) {
|
||||
$card_classes[] = '_password';
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
* @internal $args['author'] Author provided by the shortcode.
|
||||
* @internal $args['order'] Order of posts. Default 'DESC'.
|
||||
* @internal $args['post_ids'] Array of post IDs. Default empty.
|
||||
* @internal $args['post_status'] Queried post status. Default 'publish'.
|
||||
* @internal $args['author_ids'] Array of author IDs. Default empty.
|
||||
* @internal $args['excluded_authors'] Array of author IDs to exclude. Default empty.
|
||||
* @internal $args['excluded_cats'] Array of category IDs to exclude. Default empty.
|
||||
@ -62,7 +63,7 @@ $content_list_style = get_theme_mod( 'content_list_style', 'default' );
|
||||
$query_args = array(
|
||||
'fictioneer_query_name' => 'latest_updates_list',
|
||||
'post_type' => 'fcn_story',
|
||||
'post_status' => 'publish',
|
||||
'post_status' => $args['post_status'],
|
||||
'post__in' => $args['post_ids'], // May be empty!
|
||||
'order' => $args['order'],
|
||||
'orderby' => 'meta_value',
|
||||
@ -205,7 +206,7 @@ if ( $splide ) {
|
||||
}
|
||||
|
||||
// Extra classes
|
||||
$classes = [];
|
||||
$classes = [ '_' . $args['post_status'] ];
|
||||
|
||||
if ( ! empty( $post->post_password ) ) {
|
||||
$classes[] = '_password';
|
||||
|
@ -19,6 +19,7 @@
|
||||
* @internal $args['author'] Author provided by the shortcode.
|
||||
* @internal $args['order'] Order of posts. Default 'DESC'.
|
||||
* @internal $args['post_ids'] Array of post IDs. Default empty.
|
||||
* @internal $args['post_status'] Queried post status. Default 'publish'.
|
||||
* @internal $args['author_ids'] Array of author IDs. Default empty.
|
||||
* @internal $args['excluded_authors'] Array of author IDs to exclude. Default empty.
|
||||
* @internal $args['excluded_cats'] Array of category IDs to exclude. Default empty.
|
||||
@ -65,7 +66,7 @@ $show_terms = ! get_option( 'fictioneer_hide_taxonomies_on_story_cards' ) &&
|
||||
$query_args = array(
|
||||
'fictioneer_query_name' => 'latest_updates',
|
||||
'post_type' => 'fcn_story',
|
||||
'post_status' => 'publish',
|
||||
'post_status' => $args['post_status'],
|
||||
'post__in' => $args['post_ids'], // May be empty!
|
||||
'order' => $args['order'],
|
||||
'orderby' => 'meta_value',
|
||||
@ -186,7 +187,9 @@ if ( $splide ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extra classes
|
||||
// Extra card classes
|
||||
$card_classes[] = '_' . $args['post_status'];
|
||||
|
||||
if ( ! empty( $post->post_password ) ) {
|
||||
$card_classes[] = '_password';
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
* @internal $args['orderby'] Order argument. Default 'date'.
|
||||
* @internal $args['author'] Author provided by the shortcode.
|
||||
* @internal $args['post_ids'] Array of post IDs. Default empty.
|
||||
* @internal $args['post_status'] Queried post status. Default 'publish'.
|
||||
* @internal $args['author_ids'] Array of author IDs. Default empty.
|
||||
* @internal $args['excluded_authors'] Array of author IDs to exclude. Default empty.
|
||||
* @internal $args['excluded_cats'] Array of category IDs to exclude. Default empty.
|
||||
@ -46,7 +47,7 @@ $splide = $args['splide'] ?? 0;
|
||||
$query_args = array (
|
||||
'fictioneer_query_name' => 'showcase',
|
||||
'post_type' => $args['post_type'],
|
||||
'post_status' => 'publish',
|
||||
'post_status' => $args['post_status'],
|
||||
'post__in' => $args['post_ids'], // May be empty!
|
||||
'order' => $args['order'],
|
||||
'orderby' => $args['orderby'],
|
||||
@ -129,7 +130,7 @@ if ( $args['min_width'] ) {
|
||||
}
|
||||
|
||||
// Classes
|
||||
$classes = '';
|
||||
$classes = '_' . $args['post_status'];
|
||||
|
||||
if ( $args['aspect_ratio'] ) {
|
||||
$classes .= ' _aspect-ratio';
|
||||
|
@ -39,5 +39,5 @@ $delete_account_prompt = sprintf(
|
||||
<p class="profile__description"><?php _e( 'You can delete your account and associated user data with it. Submitted <em>content</em> such as comments and posts will remain under the “Deleted User” name unless you remove them <em>prior</em>. Be aware that once you delete your account, there is no going back.', 'fictioneer' ); ?></p>
|
||||
|
||||
<div class="profile__actions">
|
||||
<button id="button-delete-my-account" type="button" class="button _danger" data-nonce="<?php echo wp_create_nonce( 'fictioneer_delete_account' ); ?>" data-id="<?php echo $current_user->ID; ?>" data-confirm="<?php echo $confirmation; ?>" data-warning="<?php echo esc_attr( $delete_account_prompt ); ?>"><?php _e( 'Delete Account', 'fictioneer' ); ?></button>
|
||||
<button id="button-delete-my-account" type="button" class="button _danger" data-nonce="<?php echo wp_create_nonce( 'fictioneer_delete_account' ); ?>" data-id="<?php echo $current_user->ID; ?>" data-confirm="<?php echo $confirmation; ?>" data-warning="<?php echo esc_attr( $delete_account_prompt ); ?>" data-fictioneer-target="dcjProtected" disabled><?php _e( 'Delete Account', 'fictioneer' ); ?></button>
|
||||
</div>
|
||||
|
@ -130,7 +130,7 @@ $delete_bookmarks_prompt = sprintf(
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<button class="card__delete button-clear-comments" data-nonce="<?php echo wp_create_nonce( 'fictioneer_clear_comments' ); ?>" data-confirm="<?php echo $confirmation; ?>" data-warning="<?php echo esc_attr( $delete_comments_prompt ); ?>"><i class="fa-solid fa-trash-can"></i></button>
|
||||
<button class="card__delete button-clear-comments" data-nonce="<?php echo wp_create_nonce( 'fictioneer_clear_comments' ); ?>" data-confirm="<?php echo $confirmation; ?>" data-warning="<?php echo esc_attr( $delete_comments_prompt ); ?>" data-fictioneer-target="dcjProtected" disabled><i class="fa-solid fa-trash-can"></i></button>
|
||||
</div>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
@ -152,7 +152,7 @@ $delete_bookmarks_prompt = sprintf(
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<button class="card__delete button-clear-comment-subscriptions" data-nonce="<?php echo wp_create_nonce( 'fictioneer_clear_comment_subscriptions' ); ?>" data-confirm="<?php echo $confirmation; ?>" data-warning="<?php echo esc_attr( $delete_comment_subscriptions_prompt ); ?>"><i class="fa-solid fa-trash-can"></i></button>
|
||||
<button class="card__delete button-clear-comment-subscriptions" data-nonce="<?php echo wp_create_nonce( 'fictioneer_clear_comment_subscriptions' ); ?>" data-confirm="<?php echo $confirmation; ?>" data-warning="<?php echo esc_attr( $delete_comment_subscriptions_prompt ); ?>" data-fictioneer-target="dcjProtected" disabled><i class="fa-solid fa-trash-can"></i></button>
|
||||
</div>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
@ -183,7 +183,7 @@ $delete_bookmarks_prompt = sprintf(
|
||||
</div>
|
||||
</div>
|
||||
<?php if ( $follows_count > 0 ) : ?>
|
||||
<button class="card__delete button-clear-follows" data-nonce="<?php echo wp_create_nonce( 'fictioneer_clear_follows' ); ?>" data-confirm="<?php echo $confirmation; ?>" data-warning="<?php echo esc_attr( $delete_follows_prompt ); ?>"><i class="fa-solid fa-trash-can"></i></button>
|
||||
<button class="card__delete button-clear-follows" data-nonce="<?php echo wp_create_nonce( 'fictioneer_clear_follows' ); ?>" data-confirm="<?php echo $confirmation; ?>" data-warning="<?php echo esc_attr( $delete_follows_prompt ); ?>" data-fictioneer-target="dcjProtected" disabled><i class="fa-solid fa-trash-can"></i></button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</li>
|
||||
@ -215,7 +215,7 @@ $delete_bookmarks_prompt = sprintf(
|
||||
</div>
|
||||
</div>
|
||||
<?php if ( $reminders_count > 0 ) : ?>
|
||||
<button class="card__delete button-clear-reminders" data-nonce="<?php echo wp_create_nonce( 'fictioneer_clear_reminders' ); ?>" data-confirm="<?php echo $confirmation; ?>" data-warning="<?php echo esc_attr( $delete_reminders_prompt ); ?>"><i class="fa-solid fa-trash-can"></i></button>
|
||||
<button class="card__delete button-clear-reminders" data-nonce="<?php echo wp_create_nonce( 'fictioneer_clear_reminders' ); ?>" data-confirm="<?php echo $confirmation; ?>" data-warning="<?php echo esc_attr( $delete_reminders_prompt ); ?>" data-fictioneer-target="dcjProtected" disabled><i class="fa-solid fa-trash-can"></i></button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</li>
|
||||
@ -252,7 +252,7 @@ $delete_bookmarks_prompt = sprintf(
|
||||
</div>
|
||||
</div>
|
||||
<?php if ( $stories_count > 0 || $chapters_count > 0 ) : ?>
|
||||
<button class="card__delete button-clear-checkmarks" data-nonce="<?php echo wp_create_nonce( 'fictioneer_clear_checkmarks' ); ?>" data-confirm="<?php echo $confirmation; ?>" data-warning="<?php echo esc_attr( $delete_checkmarks_prompt ); ?>"><i class="fa-solid fa-trash-can"></i></button>
|
||||
<button class="card__delete button-clear-checkmarks" data-nonce="<?php echo wp_create_nonce( 'fictioneer_clear_checkmarks' ); ?>" data-confirm="<?php echo $confirmation; ?>" data-warning="<?php echo esc_attr( $delete_checkmarks_prompt ); ?>" data-fictioneer-target="dcjProtected" disabled><i class="fa-solid fa-trash-can"></i></button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</li>
|
||||
@ -275,7 +275,7 @@ $delete_bookmarks_prompt = sprintf(
|
||||
<?php _e( 'You have currently <strong>%s bookmark(s)</strong> set. Bookmarks are only processed in your browser.', 'fictioneer' ); ?>
|
||||
</div>
|
||||
</div>
|
||||
<button class="card__delete button-clear-bookmarks" data-confirm="<?php echo $confirmation; ?>" data-warning="<?php echo esc_attr( $delete_bookmarks_prompt ); ?>"><i class="fa-solid fa-trash-can"></i></button>
|
||||
<button class="card__delete button-clear-bookmarks" data-confirm="<?php echo $confirmation; ?>" data-warning="<?php echo esc_attr( $delete_bookmarks_prompt ); ?>" data-fictioneer-target="dcjProtected" disabled><i class="fa-solid fa-trash-can"></i></button>
|
||||
</div>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
|
@ -111,6 +111,8 @@ $unset_oauth_prompt = sprintf(
|
||||
data-channel="<?php echo $provider[0]; ?>"
|
||||
data-confirm="<?php echo $confirmation; ?>"
|
||||
data-warning="<?php echo esc_attr( $unset_oauth_prompt ); ?>"
|
||||
data-fictioneer-target="dcjProtected"
|
||||
disabled
|
||||
><?php fictioneer_icon( 'fa-xmark' ); ?></button>
|
||||
</div>
|
||||
<?php
|
||||
|
@ -209,7 +209,7 @@ $renaming_disabled = $current_user->fictioneer_admin_disable_renaming;
|
||||
<input name="user_id" type="hidden" value="<?php echo $current_user->ID; ?>">
|
||||
|
||||
<div class="profile__actions">
|
||||
<input name="submit" type="submit" value="<?php esc_attr_e( 'Update Profile', 'fictioneer' ); ?>" class="button">
|
||||
<input name="submit" type="submit" value="<?php esc_attr_e( 'Update Profile', 'fictioneer' ); ?>" class="button" data-fictioneer-target="dcjProtected" disabled>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
@ -7,7 +7,7 @@ Contributors: tetrakern
|
||||
Requires at least: 6.1.0
|
||||
Tested up to: 6.7.1
|
||||
Requires PHP: 7.4
|
||||
Stable tag: 5.27.1
|
||||
Stable tag: 5.27.2
|
||||
License: GNU General Public License v3.0 or later
|
||||
License URI: http://www.gnu.org/licenses/gpl.html
|
||||
|
||||
|
@ -8,9 +8,9 @@
|
||||
* @link https://github.com/WordPress/WordPress/blob/master/wp-includes/feed-rss2.php
|
||||
*/
|
||||
|
||||
// Query posts
|
||||
$posts = get_posts(
|
||||
array(
|
||||
|
||||
// Query
|
||||
$query_args = array(
|
||||
'fictioneer_query_name' => 'main_rss',
|
||||
'post_type' => ['post', 'fcn_story', 'fcn_chapter', 'fcn_recommendation'],
|
||||
'post_status' => 'publish',
|
||||
@ -20,10 +20,13 @@ $posts = get_posts(
|
||||
'posts_per_page' => get_option( 'posts_per_rss' ) + 8, // Buffer in case of invalid results
|
||||
'update_post_meta_cache' => true,
|
||||
'update_post_term_cache' => true,
|
||||
'no_found_rows' => true
|
||||
)
|
||||
'no_found_rows' => true // Improve performance
|
||||
);
|
||||
|
||||
$query_args = apply_filters( 'fictioneer_filter_rss_main_query_args', $query_args );
|
||||
|
||||
$posts = get_posts( $query_args );
|
||||
|
||||
// Filter out hidden posts (faster than meta query)
|
||||
$posts = array_filter( $posts, function ( $post ) {
|
||||
// Chapter hidden?
|
||||
|
@ -13,6 +13,7 @@
|
||||
* @link https://github.com/WordPress/WordPress/blob/master/wp-includes/feed-rss2.php
|
||||
*/
|
||||
|
||||
|
||||
// Get ID from parameter
|
||||
$story_id = fictioneer_validate_id( $_GET[ 'story_id' ] ?? 0, 'fcn_story' );
|
||||
$is_hidden = get_post_meta( $story_id ?: 0, 'fictioneer_story_hidden', true );
|
||||
@ -142,6 +143,8 @@ do_action( 'rss_tag_pre', 'rss2' );
|
||||
'no_found_rows' => true // Improve performance
|
||||
);
|
||||
|
||||
$query_args = apply_filters( 'fictioneer_filter_rss_story_query_args', $query_args, $story_id );
|
||||
|
||||
$chapter_query = new WP_Query( $query_args );
|
||||
|
||||
// Loop over chapters
|
||||
|
@ -136,7 +136,7 @@ if ( $show_advanced ) {
|
||||
type="button"
|
||||
class="search-form__advanced-toggle"
|
||||
tabindex="0"
|
||||
><?php _ex( 'Advanced', 'Advanced search toggle.', 'fictioneer' ); ?></button>
|
||||
><i class="fa-solid fa-sliders"></i></button>
|
||||
<?php endif; ?>
|
||||
<button type="submit" class="search-form__submit" aria-label="<?php echo esc_attr__( 'Submit search request', 'fictioneer' ); ?>"><i class="fa-solid fa-magnifying-glass"></i></button>
|
||||
</div>
|
||||
|
@ -128,7 +128,7 @@ window.FictioneerApp.Controllers = window.FictioneerApp.Controllers || {};
|
||||
|
||||
application.register('fictioneer', class extends Stimulus.Controller {
|
||||
static get targets() {
|
||||
return ['avatarWrapper', 'modal', 'mobileMenuToggle']
|
||||
return ['avatarWrapper', 'modal', 'mobileMenuToggle', 'dcjProtected']
|
||||
}
|
||||
|
||||
static values = {
|
||||
@ -145,6 +145,7 @@ application.register('fictioneer', class extends Stimulus.Controller {
|
||||
userReady = false;
|
||||
lastModalToggle = null;
|
||||
currentModal = null;
|
||||
dcjProtection = true;
|
||||
|
||||
/**
|
||||
* Stimulus Controller initialize lifecycle callback.
|
||||
@ -172,6 +173,19 @@ application.register('fictioneer', class extends Stimulus.Controller {
|
||||
// Fire event
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
if (this.hasDcjProtectedTarget) {
|
||||
['mousemove', 'touchstart', 'keydown'].forEach(event => {
|
||||
window.addEventListener(event, this.liftProtection.bind(this), { once: true });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
liftProtection() {
|
||||
if (this.dcjProtection && this.hasDcjProtectedTarget) {
|
||||
this.dcjProtectedTargets.forEach(element => element.disabled = false);
|
||||
this.dcjProtection = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2617,8 +2631,7 @@ application.register('fictioneer-large-card', class extends Stimulus.Controller
|
||||
|
||||
static values = {
|
||||
postId: Number,
|
||||
storyId: Number,
|
||||
chapterId: Number
|
||||
storyId: Number
|
||||
}
|
||||
|
||||
initialize() {
|
||||
@ -2680,7 +2693,7 @@ application.register('fictioneer-large-card', class extends Stimulus.Controller
|
||||
const checkmarks = this.#data()?.checkmarks?.data?.[this.storyIdValue];
|
||||
|
||||
return !!checkmarks &&
|
||||
(checkmarks.includes(this.chapterIdValue) || checkmarks.includes(this.storyIdValue));
|
||||
(checkmarks.includes(this.postIdValue) || checkmarks.includes(this.storyIdValue));
|
||||
}
|
||||
|
||||
cardClick(event) {
|
||||
@ -2717,7 +2730,7 @@ application.register('fictioneer-large-card', class extends Stimulus.Controller
|
||||
|
||||
toggleCheckmarks() {
|
||||
if (this.#loggedIn()) {
|
||||
fcn_toggleCheckmark(this.storyIdValue, this.chapterIdValue);
|
||||
fcn_toggleCheckmark(this.storyIdValue, this.postIdValue);
|
||||
this.#refreshCheckmarkState();
|
||||
} else {
|
||||
_$('[data-fictioneer-id-param="login-modal"]')?.click();
|
||||
@ -2979,6 +2992,7 @@ function fcn_loadConsentBanner() {
|
||||
|
||||
function fcn_showLightbox(target) {
|
||||
const lightbox = _$$$('fictioneer-lightbox');
|
||||
const loader = lightbox.querySelector('.loader');
|
||||
const lightboxContent = _$('.lightbox__content');
|
||||
|
||||
let valid = false;
|
||||
@ -2986,6 +3000,7 @@ function fcn_showLightbox(target) {
|
||||
|
||||
// Cleanup previous content (if any)
|
||||
lightboxContent.innerHTML = '';
|
||||
loader.style.opacity = 1;
|
||||
|
||||
// Bookmark source element for later use
|
||||
target.classList.add('lightbox-last-trigger');
|
||||
@ -3006,6 +3021,10 @@ function fcn_showLightbox(target) {
|
||||
lightboxContent.appendChild(img);
|
||||
lightbox.classList.add('show');
|
||||
|
||||
setTimeout(() => {
|
||||
loader.style.opacity = 0;
|
||||
}, 1000);
|
||||
|
||||
const close = lightbox.querySelector('.lightbox__close');
|
||||
|
||||
close?.focus();
|
||||
|
@ -65,10 +65,14 @@ application.register('fictioneer-checkmarks', class extends Stimulus.Controller
|
||||
return;
|
||||
}
|
||||
|
||||
let storyChecked = false;
|
||||
|
||||
Object.entries(checkmarks).forEach(([storyId, chapterArray]) => {
|
||||
storyId = parseInt(storyId);
|
||||
|
||||
const storyChecked = chapterArray?.includes(storyId);
|
||||
if (this.hasStoryCheckTarget && storyId == this.storyCheckTarget.dataset.fictioneerCheckmarksStoryParam) {
|
||||
storyChecked = chapterArray?.includes(storyId);
|
||||
}
|
||||
|
||||
if (this.hasChapterCheckTarget) {
|
||||
if (storyChecked) {
|
||||
|
@ -151,6 +151,10 @@ application.register('fictioneer-follows', class extends Stimulus.Controller {
|
||||
display.classList.remove('_new');
|
||||
});
|
||||
|
||||
_$$('.follow-item').forEach(element => {
|
||||
element.classList.remove('_new');
|
||||
});
|
||||
|
||||
if (this.hasMobileMarkReadTarget) {
|
||||
this.mobileMarkReadTarget.classList.add('hidden');
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
}
|
||||
|
||||
.small-card-block,
|
||||
.article-card-block,
|
||||
.article-card-block .pagination {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
@ -28,7 +28,7 @@
|
||||
.custom-logo {
|
||||
height: var(--header-logo-height);
|
||||
max-height: calc(var(--header-height) - 2rem);
|
||||
width: fit-content;
|
||||
width: auto;
|
||||
max-width: 99vw;
|
||||
object-fit: contain;
|
||||
pointer-events: none; // Prevents drag and Edge image function nonsense
|
||||
|
@ -45,5 +45,6 @@
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
transition: opacity .3s;
|
||||
}
|
||||
}
|
||||
|
@ -10,11 +10,7 @@
|
||||
|
||||
.search-form[data-advanced="true"] {
|
||||
.search-form__bar .search-form__advanced-toggle {
|
||||
color: var(--fg-500);
|
||||
|
||||
&:hover {
|
||||
color: var(--fg-300);
|
||||
}
|
||||
color: var(--button-primary-color-hover);
|
||||
}
|
||||
|
||||
.search-form__current {
|
||||
@ -44,6 +40,17 @@
|
||||
padding-right: 96px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
button {
|
||||
--button-primary-background: transparent;
|
||||
--button-primary-background-hover: transparent;
|
||||
--button-primary-color: var(--fg-900);
|
||||
--button-primary-color-hover: var(--fg-400);
|
||||
display: grid;
|
||||
place-content: center;
|
||||
font-size: 12px;
|
||||
min-width: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
&__current {
|
||||
@ -73,16 +80,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
&__submit:is(button) {
|
||||
--button-primary-background: transparent;
|
||||
--button-primary-background-hover: transparent;
|
||||
--button-primary-color: var(--fg-900);
|
||||
--button-primary-color-hover: var(--fg-400);
|
||||
display: grid;
|
||||
place-content: center;
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
&__select-group {
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
@ -146,15 +143,12 @@
|
||||
}
|
||||
|
||||
&-toggle {
|
||||
display: grid;
|
||||
place-content: center;
|
||||
color: var(--fg-700);
|
||||
font-size: 11px;
|
||||
height: 32px;
|
||||
color: var(--button-primary-color);
|
||||
padding-left: 32px;
|
||||
transition: color var(--transition-duration);
|
||||
|
||||
&:hover {
|
||||
color: var(--fg-400);
|
||||
color: var(--button-primary-color-hover);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -977,7 +977,7 @@ figure.wp-block-pullquote:where(:not(.no-theme-style)) {
|
||||
// LATEST COMMENTS
|
||||
// =============================================================================
|
||||
|
||||
.wp-block-latest-comments:where(:not(.no-theme-style)) {
|
||||
.wp-block-latest-comments:is(:not(.no-theme-style)) {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
|
||||
@ -1009,7 +1009,7 @@ figure.wp-block-pullquote:where(:not(.no-theme-style)) {
|
||||
|
||||
.wp-block-latest-comments__comment-avatar {
|
||||
float: left;
|
||||
margin: 3px 8px 4px 0;
|
||||
margin: 3px 8px 3px 0;
|
||||
border-radius: var(--layout-border-radius-small);
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
|
@ -711,7 +711,7 @@ body {
|
||||
// LATEST COMMENTS
|
||||
// =============================================================================
|
||||
|
||||
.wp-block-latest-comments:where(:not(.no-theme-style)) {
|
||||
.wp-block-latest-comments:is(:not(.no-theme-style)) {
|
||||
list-style: none;
|
||||
padding-left: 0 !important;
|
||||
|
||||
@ -734,7 +734,7 @@ body {
|
||||
|
||||
.wp-block-latest-comments__comment-avatar {
|
||||
float: left;
|
||||
margin: 3px 8px 4px 0;
|
||||
margin: 3px 8px 3px 0;
|
||||
border-radius: 2px;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
|
Loading…
x
Reference in New Issue
Block a user