Refactor custom theme sitemaps

This commit is contained in:
Tetrakern 2024-01-13 02:59:24 +01:00
parent 026176241d
commit fcd6952dbf
7 changed files with 251 additions and 215 deletions

View File

@ -237,7 +237,7 @@ Fictioneer customizes WordPress by using as many standard action and filter hook
| `edit_user_profile` | `fictioneer_custom_profile_fields`
| `edit_user_profile_update` | `fictioneer_update_admin_user_profile`, `fictioneer_update_my_user_profile`
| `get_header` | `fictioneer_maintenance_mode`
| `init` | `fictioneer_add_character_taxonomy`, `fictioneer_add_content_warning_taxonomy`, `fictioneer_add_epub_download_endpoint`, `fictioneer_add_fandom_taxonomy`, `fictioneer_add_genre_taxonomy`, `fictioneer_add_logout_endpoint`, `fictioneer_add_oauth2_endpoint`, `fictioneer_restrict_admin_panel`, `fictioneer_disable_heartbeat`, `fictioneer_fcn_chapter_post_type`, `fictioneer_fcn_collection_post_type`, `fictioneer_fcn_recommendation_post_type`, `fictioneer_fcn_story_post_type`, `fictioneer_modify_allowed_tags`, `fictioneer_story_rss`, `fictioneer_remove_custom_fields_supports`
| `init` | `fictioneer_add_character_taxonomy`, `fictioneer_add_content_warning_taxonomy`, `fictioneer_add_epub_download_endpoint`, `fictioneer_add_fandom_taxonomy`, `fictioneer_add_genre_taxonomy`, `fictioneer_add_logout_endpoint`, `fictioneer_add_oauth2_endpoint`, `fictioneer_restrict_admin_panel`, `fictioneer_disable_heartbeat`, `fictioneer_fcn_chapter_post_type`, `fictioneer_fcn_collection_post_type`, `fictioneer_fcn_recommendation_post_type`, `fictioneer_fcn_story_post_type`, `fictioneer_modify_allowed_tags`, `fictioneer_story_rss`, `fictioneer_remove_custom_fields_supports`, `fictioneer_legacy_cleanup`, `fictioneer_add_sitemap_rewrite_rule`
| `login_form` | `fictioneer_after_logout_cleanup`
| `login_head` | `fictioneer_wp_login_scripts`
| `manage_comments_custom_column` | `fictioneer_add_comments_report_column_content`
@ -248,10 +248,10 @@ Fictioneer customizes WordPress by using as many standard action and filter hook
| `publish_to_draft` | `fictioneer_chapter_to_draft`
| `rest_api_init` | `fictioneer_register_endpoint_get_story_comments`
| `restrict_manage_posts` | `fictioneer_add_chapter_story_filter_dropdown`
| `save_post` | `fictioneer_create_sitemap`, `fictioneer_refresh_chapters_schema`, `fictioneer_refresh_chapter_schema`, `fictioneer_refresh_collections_schema`, `fictioneer_refresh_post_caches`, `fictioneer_refresh_post_schema`, `fictioneer_refresh_recommendations_schema`, `fictioneer_refresh_recommendation_schema`, `fictioneer_refresh_stories_schema`, `fictioneer_refresh_story_schema`, `fictioneer_save_seo_metabox`, `fictioneer_save_word_count`, `fictioneer_track_chapter_and_story_updates`, `fictioneer_update_modified_date_on_story_for_chapter`, `fictioneer_update_shortcode_relationships`, `fictioneer_purge_transients`, `fictioneer_post_story_to_discord`, `fictioneer_post_chapter_to_discord`, `fictioneer_save_story_metaboxes`, `fictioneer_save_chapter_metaboxes`, `fictioneer_save_advanced_metabox`, `fictioneer_save_support_links_metabox`, `fictioneer_save_collection_metaboxes`, `fictioneer_save_recommendation_metaboxes`, `fictioneer_save_post_metaboxes`
| `save_post` | `fictioneer_refresh_chapters_schema`, `fictioneer_refresh_chapter_schema`, `fictioneer_refresh_collections_schema`, `fictioneer_refresh_post_caches`, `fictioneer_refresh_post_schema`, `fictioneer_refresh_recommendations_schema`, `fictioneer_refresh_recommendation_schema`, `fictioneer_refresh_stories_schema`, `fictioneer_refresh_story_schema`, `fictioneer_save_seo_metabox`, `fictioneer_save_word_count`, `fictioneer_track_chapter_and_story_updates`, `fictioneer_update_modified_date_on_story_for_chapter`, `fictioneer_update_shortcode_relationships`, `fictioneer_purge_transients`, `fictioneer_post_story_to_discord`, `fictioneer_post_chapter_to_discord`, `fictioneer_save_story_metaboxes`, `fictioneer_save_chapter_metaboxes`, `fictioneer_save_advanced_metabox`, `fictioneer_save_support_links_metabox`, `fictioneer_save_collection_metaboxes`, `fictioneer_save_recommendation_metaboxes`, `fictioneer_save_post_metaboxes`
| `show_user_profile` | `fictioneer_custom_profile_fields`
| `switch_theme` | `fictioneer_theme_deactivation`
| `template_redirect` | `fictioneer_disable_date_archives`, `fictioneer_generate_epub`, `fictioneer_handle_oauth`, `fictioneer_logout`, `fictioneer_disable_attachment_pages`, `fictioneer_gate_unpublished_content`
| `template_redirect` | `fictioneer_disable_date_archives`, `fictioneer_generate_epub`, `fictioneer_handle_oauth`, `fictioneer_logout`, `fictioneer_disable_attachment_pages`, `fictioneer_gate_unpublished_content`, `fictioneer_serve_sitemap`
| `transition_post_status` | `fictioneer_log_story_chapter_status_changes`
| `trashed_post` | `fictioneer_refresh_post_caches`, `fictioneer_track_chapter_and_story_updates`, `fictioneer_update_modified_date_on_story_for_chapter`, `fictioneer_purge_transients`, `fictioneer_remove_chapter_from_story`
| `untrash_post` | `fictioneer_refresh_post_caches`, `fictioneer_track_chapter_and_story_updates`, `fictioneer_update_modified_date_on_story_for_chapter`, `fictioneer_purge_transients`

View File

@ -1081,6 +1081,14 @@ Filters the boolean return value of the `fictioneer_enable_shortcode_transients(
---
### `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'`.
**Parameter:**
* $excludes (array) Array of excluded page templates.
---
### `apply_filters( 'fictioneer_filter_sof_date_options', $options, $current_url, $args )`
Filters the option array of URL/label tuples for the date popup menu in the `fictioneer_sort_order_filter_interface( $args )` function before it is rendered. Can be any positive integer (days) or [strtotime](https://www.php.net/manual/en/function.strtotime.php) compatible string. See `fictioneer_append_date_query(...)`. Includes '0', '1', '3', '1 week ago', '1 month ago', '3 months ago', '6 months ago', and '1 year ago'.

View File

@ -236,6 +236,7 @@ function fictioneer_removable_args( $args ) {
$args[] = 'data';
$args[] = 'fictioneer_nonce';
$args[] = 'fictioneer-notice';
return $args;
}
add_filter( 'removable_query_args', 'fictioneer_removable_args' );

View File

@ -1,5 +1,36 @@
<?php
// =============================================================================
// LEGACY CLEANUP
// =============================================================================
/**
* Clean up legacy fields, files, and settings
*
* This only runs on hardcoded cutoff dates, once. It will only run again if the
* date in this function is changed on an update.
*
* @since Fictioneer 5.8.7
*/
function fictioneer_legacy_cleanup() {
$cutoff = 202401130000; // YYYYMMDDHHMM
$last_cleanup = absint( get_option( 'fictioneer_last_cleanup' ) );
// Sitemap cleanup
if ( $last_cleanup < 202401130000 ) {
$old_sitemap = ABSPATH . '/sitemap.xml';
if ( file_exists( $old_sitemap ) ) {
unlink( $old_sitemap );
}
}
// Remember cleanup
update_option( 'fictioneer_last_cleanup', $cutoff );
}
add_action( 'init', 'fictioneer_legacy_cleanup' );
// =============================================================================
// THEME DEACTIVATION
// =============================================================================
@ -12,7 +43,8 @@
* well but otherwise preserved.
*
* @since Fictioneer 4.7
* @since Fictioneer 5.7.4 Updated to use SQL queries.
* @since Fictioneer 5.7.4 - Updated to use SQL queries.
*
* @global wpdb $wpdb WordPress database object.
*/

View File

@ -1,7 +1,52 @@
<?php
// =============================================================================
// (RE-) BUILD SITEMAP WHEN POST/PAGE IS SAVED
// SITEMAP REWRITE RULE & REDIRECT
// =============================================================================
/**
* Add rewrite rule for custom theme sitemap
*
* @since Fictioneer 5.8.7
*/
function fictioneer_add_sitemap_rewrite_rule() {
add_rewrite_rule( '^sitemap\.xml$', 'index.php?fictioneer_sitemap=1', 'top' );
}
if ( get_option( 'fictioneer_enable_sitemap' ) && ! fictioneer_seo_plugin_active() ) {
add_action( 'init', 'fictioneer_add_sitemap_rewrite_rule' );
}
/**
* Serve the custom theme sitemap.xml
*
* @since Fictioneer 5.8.7
*/
function fictioneer_serve_sitemap() {
// Check whether this is the sitemap route
if ( is_null( get_query_var( 'fictioneer_sitemap', null ) ) ) {
return;
}
// Setup
$sitemap_file = ABSPATH . '/fictioneer_sitemap.xml';
// Sitemap missing or older than 24 hours?
if ( ! file_exists( $sitemap_file ) || ( time() - filemtime( $sitemap_file ) ) > DAY_IN_SECONDS ) {
fictioneer_create_sitemap();
}
// Serve the sitemap file
header( 'Content-Type: application/xml' );
readfile( $sitemap_file );
exit;
}
add_action( 'template_redirect', 'fictioneer_serve_sitemap' );
// =============================================================================
// (RE-)BUILD SITEMAP
// =============================================================================
/**
@ -74,217 +119,158 @@ function fictioneer_url_node( $loc, $lastmod = null, $freq = null ) {
* Generate theme sitemap
*
* @since Fictioneer 4.0
*
* @param int $last_saved_id ID of the last saved post.
* @param WP_Post $last_saved_post The last saved post object.
* @since Fictioneer 5.8.7 - Create on demand, not on post save.
*/
function fictioneer_create_sitemap( $last_saved_id, $last_saved_post ) {
// Prevent multi-fire
if ( fictioneer_multi_save_guard( $last_saved_id ) ) {
return;
function fictioneer_create_sitemap() {
// Open
$sitemap = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
$sitemap .= '<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
// Blog and front page
$sitemap .= fictioneer_url_node( esc_url( home_url( '/' ) ), current_time( 'c' ), 'daily' );
$sitemap .= fictioneer_url_node( get_permalink( get_option( 'page_for_posts' ) ), current_time( 'c' ), 'daily' );
// Pages
$pages = get_posts(
array(
'post_type' => 'page',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'numberposts' => '1000',
'post__not_in' => [get_option( 'page_on_front' ), get_option( 'page_for_posts' )],
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'no_found_rows' => true
)
);
foreach( $pages as $post ) {
$template = get_page_template_slug( $post->ID );
$template_excludes = ['user-profile.php', 'singular-bookmarks.php', 'singular-bookshelf.php', 'singular-bookshelf-ajax.php'];
$template_excludes = apply_filters( 'fictioneer_filter_sitemap_page_template_excludes', $template_excludes );
if ( in_array( $template, $template_excludes ) ) {
continue;
}
$lastmod = get_the_modified_date( 'c', $post->ID );
$sitemap .= fictioneer_url_node( get_permalink( $post->ID ), $lastmod, 'monthly' );
}
// Only rebuild necessary part of the sitemap
$last_saved_type = $last_saved_post->post_type;
// Blogs
$blogs = get_posts(
array(
'post_type' => 'post',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'numberposts' => '1000',
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'no_found_rows' => true
)
);
// Only consider these post types
$allowed_types = ['page', 'post', 'fcn_story', 'fcn_chapter', 'fcn_recommendation', 'fcn_collection'];
if ( in_array( $last_saved_type, $allowed_types ) ) {
// Open
$sitemap = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
$sitemap .= '<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
// Blog and front page
$sitemap .= fictioneer_url_node( esc_url( home_url( '/' ) ), current_time( 'c' ), 'daily' );
$sitemap .= fictioneer_url_node( get_permalink( get_option( 'page_for_posts' ) ), current_time( 'c' ), 'daily' );
// Pages
$pages = $last_saved_type == 'page' ? null : get_transient( 'fictioneer_sitemap_pages' );
if ( ! $pages ) {
$pages = get_posts(
array(
'post_type' => 'page',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'numberposts' => '1000',
'post__not_in' => [get_option( 'page_on_front' ), get_option( 'page_for_posts' )],
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'no_found_rows' => true
)
);
set_transient( 'fictioneer_sitemap_pages', $pages );
}
foreach( $pages as $post ) {
$template = get_page_template_slug( $post->ID );
if (
in_array(
$template,
['user-profile.php', 'singular-bookmarks.php', 'singular-bookshelf.php', 'singular-bookshelf-ajax.php']
)
) {
continue;
}
$frequency = 'yearly';
$lastmod = get_the_modified_date( 'c', $post->ID );
$sitemap .= fictioneer_url_node( get_permalink( $post->ID ), $lastmod, 'yearly' );
}
// Blogs
$blogs = $last_saved_type == 'post' ? null : get_transient( 'fictioneer_sitemap_posts' );
if ( ! $blogs ) {
$blogs = get_posts(
array(
'post_type' => 'post',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'numberposts' => '1000',
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'no_found_rows' => true
)
);
set_transient( 'fictioneer_sitemap_posts', $blogs );
}
foreach( $blogs as $post ) {
$lastmod = get_the_modified_date( 'c', $post->ID );
$sitemap .= fictioneer_url_node( get_permalink( $post->ID ), $lastmod, 'never' );
}
// Collections
$collections = $last_saved_type == 'fcn_collection' ? null : get_transient( 'fictioneer_sitemap_collections' );
if ( ! $collections ) {
$collections = get_posts(
array(
'post_type' => 'fcn_collection',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'numberposts' => '1000',
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'no_found_rows' => true
)
);
set_transient( 'fictioneer_sitemap_collections', $collections );
}
foreach( $collections as $post ) {
$lastmod = get_the_modified_date( 'c', $post->ID );
$sitemap .= fictioneer_url_node( get_permalink( $post->ID ), $lastmod, 'monthly' );
}
// Stories
$stories = $last_saved_type == 'fcn_story' ? null : get_transient( 'fictioneer_sitemap_stories' );
if ( ! $stories ) {
$stories = get_posts(
array(
'post_type' => 'fcn_story',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'numberposts' => '2000',
'update_post_meta_cache' => true,
'update_post_term_cache' => false,
'no_found_rows' => true
)
);
set_transient( 'fictioneer_sitemap_stories', $stories );
}
foreach ( $stories as $post ) {
if ( get_post_meta( $post->ID, 'fictioneer_story_hidden', true ) ) {
continue;
}
$lastmod = get_the_modified_date( 'c', $post->ID );
$status = get_post_meta( $post->ID, 'fictioneer_story_status', true );
$frequency = $status == 'Ongoing' ? 'weekly' : 'monthly';
$sitemap .= fictioneer_url_node( get_permalink( $post->ID ), $lastmod, $frequency );
}
// Chapters
$chapters = $last_saved_type == 'fcn_chapter' ? null : get_transient( 'fictioneer_sitemap_chapters' );
if ( ! $chapters ) {
$chapters = get_posts(
array(
'post_type' => 'fcn_chapter',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'numberposts' => '10000',
'update_post_meta_cache' => true,
'update_post_term_cache' => false,
'no_found_rows' => true
)
);
set_transient( 'fictioneer_sitemap_chapters', $chapters );
}
foreach( $chapters as $post ) {
if ( get_post_meta( $post->ID, 'fictioneer_chapter_hidden', true ) ) {
continue;
}
$lastmod = get_the_modified_date( 'c', $post->ID );
$sitemap .= fictioneer_url_node( get_permalink( $post->ID ), $lastmod, 'monthly' );
}
// Recommendations
$recommendations = $last_saved_type == 'fcn_recommendation' ? null : get_transient( 'fictioneer_sitemap_recommendations' );
if ( ! $recommendations ) {
$recommendations = get_posts(
array(
'post_type' => 'fcn_recommendation',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'numberposts' => '1000',
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'no_found_rows' => true
)
);
set_transient( 'fictioneer_sitemap_recommendations', $recommendations );
}
foreach( $recommendations as $post ) {
$lastmod = get_the_modified_date( 'c', $post->ID );
$sitemap .= fictioneer_url_node( get_permalink( $post->ID ), $lastmod, 'yearly' );
}
// End
$sitemap .= "\n" . '</urlset>';
// Save
$file_path = fopen( ABSPATH . '/sitemap.xml', 'w' );
fwrite( $file_path, $sitemap );
fclose( $file_path );
foreach( $blogs as $post ) {
$lastmod = get_the_modified_date( 'c', $post->ID );
$sitemap .= fictioneer_url_node( get_permalink( $post->ID ), $lastmod, 'never' );
}
}
if ( get_option( 'fictioneer_enable_sitemap' ) && ! fictioneer_seo_plugin_active() ) {
add_action( 'save_post', 'fictioneer_create_sitemap', 99, 2 );
// Collections
$collections = get_posts(
array(
'post_type' => 'fcn_collection',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'numberposts' => '1000',
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'no_found_rows' => true
)
);
foreach( $collections as $post ) {
$lastmod = get_the_modified_date( 'c', $post->ID );
$sitemap .= fictioneer_url_node( get_permalink( $post->ID ), $lastmod, 'monthly' );
}
// Stories
$stories = get_posts(
array(
'post_type' => 'fcn_story',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'numberposts' => '2000',
'update_post_meta_cache' => true,
'update_post_term_cache' => false,
'no_found_rows' => true
)
);
foreach ( $stories as $post ) {
if ( get_post_meta( $post->ID, 'fictioneer_story_hidden', true ) ) {
continue;
}
$lastmod = get_the_modified_date( 'c', $post->ID );
$status = get_post_meta( $post->ID, 'fictioneer_story_status', true );
$frequency = $status == 'Ongoing' ? 'weekly' : 'monthly';
$sitemap .= fictioneer_url_node( get_permalink( $post->ID ), $lastmod, $frequency );
}
// Chapters
$chapters = get_posts(
array(
'post_type' => 'fcn_chapter',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'numberposts' => '10000',
'update_post_meta_cache' => true,
'update_post_term_cache' => false,
'no_found_rows' => true
)
);
foreach( $chapters as $post ) {
if ( get_post_meta( $post->ID, 'fictioneer_chapter_hidden', true ) ) {
continue;
}
$lastmod = get_the_modified_date( 'c', $post->ID );
$sitemap .= fictioneer_url_node( get_permalink( $post->ID ), $lastmod, 'monthly' );
}
// Recommendations
$recommendations = get_posts(
array(
'post_type' => 'fcn_recommendation',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'numberposts' => '1000',
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'no_found_rows' => true
)
);
foreach( $recommendations as $post ) {
$lastmod = get_the_modified_date( 'c', $post->ID );
$sitemap .= fictioneer_url_node( get_permalink( $post->ID ), $lastmod, 'monthly' );
}
// End
$sitemap .= "\n" . '</urlset>';
// Save
$file_path = fopen( ABSPATH . '/fictioneer_sitemap.xml', 'w' );
fwrite( $file_path, $sitemap );
fclose( $file_path );
}
?>

View File

@ -188,7 +188,7 @@ add_filter( 'is_protected_meta', 'fictioneer_make_theme_meta_protected', 10, 2 )
*/
function fictioneer_protect_reserved_post_slugs( $slug ) {
$protected = [FICTIONEER_OAUTH_ENDPOINT, FICTIONEER_EPUB_ENDPOINT, FICTIONEER_LOGOUT_ENDPOINT];
$protected = [FICTIONEER_OAUTH_ENDPOINT, FICTIONEER_EPUB_ENDPOINT, FICTIONEER_LOGOUT_ENDPOINT, 'fictioneer_sitemap'];
// Prevent slugs from being applied to posts
if ( in_array( $slug, $protected ) ) {

View File

@ -595,7 +595,7 @@ if ( get_option( 'fictioneer_enable_lightbox' ) ) {
/**
* Returns data-lightbox attribute if enabled
*
* @since 4.7
* @since 4.7.0
*
* @return string The attribute or an empty string.
*/
@ -610,6 +610,13 @@ function fictioneer_get_lightbox_attribute() {
/**
* Add custom query vars
*
* @since 4.0.0
* @since 5.8.7 - Appended 'fictioneer_sitemap'.
*
* @param array $qvars Allowed query variable names.
*
* @return array Updated allowed query variable names.
*/
function fictioneer_query_vars( $qvars ) {
@ -617,6 +624,8 @@ function fictioneer_query_vars( $qvars ) {
$qvars[] = 'commentcode';
$qvars[] = 'cp'; // e.g. custom/current page
$qvars[] = 'pg'; // e.g. page
$qvars[] = 'fictioneer_sitemap';
return $qvars;
}
add_filter( 'query_vars', 'fictioneer_query_vars' );
@ -632,7 +641,7 @@ add_filter( 'query_vars', 'fictioneer_query_vars' );
* performance and may get you in trouble on a shared host. So it may be better
* to turn it off and accept that there are no autosaves.
*
* @since 4.7
* @since 4.7.0
*/
function fictioneer_disable_heartbeat() {
@ -660,7 +669,7 @@ if ( get_option( 'fictioneer_remove_wp_svg_filters' ) ) {
/**
* Wraps embeds into a consent box that must be clicked to load the embed.
*
* @since Fictioneer 3.0
* @since Fictioneer 3.0.0
*
* @param string $content The content.
*
@ -798,7 +807,7 @@ if ( get_option( 'fictioneer_disable_application_passwords' ) ) {
/**
* Skip attachment pages and redirect to file
*
* @since 5.0
* @since 5.0.0
*/
function fictioneer_disable_attachment_pages() {
@ -821,7 +830,7 @@ if ( ! FICTIONEER_ATTACHMENT_PAGES ) {
/**
* Extend list of allowed protocols
*
* @since 4.0
* @since 4.0.0
*
* @param array $protocols Array of allowed protocols.
*