Make WordPress Core


Ignore:
Timestamp:
09/18/2023 02:53:37 PM (22 months ago)
Author:
flixos90
Message:

Media: Enhance wp_get_loading_optimization_attributes() to support arbitrary context values.

The wp_get_loading_optimization_attributes() function, which was introduced in 6.3, based on the now deprecated wp_get_loading_attr_default() function introduced in 5.5, relies on a $context parameter based on which it may alter its behavior and the attributes returned. So far, it has only supported context values used within WordPress core.

This changeset decouples the behaviors of the function from specific contexts, allowing for more flexibility. Theme and plugin developers will be able to rely on their own context values when rendering images in non-standard ways, rather than being forced to use a core context, to get the loading optimization benefits the function provides.

As part of this change, a wp_loading_optimization_force_header_contexts filter is introduced, which allows filtering the map of context values and whether they should be considered header contexts, i.e. i.e. any image having one of these contexts will be assumed to appear above the fold.

Props mukesh27, costdev, flixos90.
Fixes #58894.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/media.php

    r56549 r56612  
    56535653     * high priority.
    56545654     */
    5655     switch ( $context ) {
    5656         case 'the_post_thumbnail':
    5657         case 'wp_get_attachment_image':
    5658         case 'widget_media_image':
    5659             if ( doing_filter( 'the_content' ) ) {
    5660                 return $loading_attrs;
    5661             }
     5655    // TODO: Handle shortcode images together with the content (see https://core.trac.wordpress.org/ticket/58853).
     5656    if ( 'the_content' !== $context && 'do_shortcode' !== $context && doing_filter( 'the_content' ) ) {
     5657        return $loading_attrs;
    56625658    }
    56635659
     
    57105706
    57115707    if ( null === $maybe_in_viewport ) {
    5712         switch ( $context ) {
    5713             // Consider elements with these header-specific contexts to be in viewport.
    5714             case 'template_part_' . WP_TEMPLATE_PART_AREA_HEADER:
    5715             case 'get_header_image_tag':
    5716                 $maybe_in_viewport    = true;
    5717                 $maybe_increase_count = true;
    5718                 break;
    5719             // Count main content elements and detect whether in viewport.
    5720             case 'the_content':
    5721             case 'the_post_thumbnail':
    5722             case 'do_shortcode':
    5723                 // Only elements within the main query loop have special handling.
    5724                 if ( ! is_admin() && in_the_loop() && is_main_query() ) {
    5725                     /*
    5726                      * Get the content media count, since this is a main query
    5727                      * content element. This is accomplished by "increasing"
    5728                      * the count by zero, as the only way to get the count is
    5729                      * to call this function.
    5730                      * The actual count increase happens further below, based
    5731                      * on the `$increase_count` flag set here.
    5732                      */
    5733                     $content_media_count = wp_increase_content_media_count( 0 );
    5734                     $increase_count      = true;
    5735 
    5736                     // If the count so far is below the threshold, `loading` attribute is omitted.
    5737                     if ( $content_media_count < wp_omit_loading_attr_threshold() ) {
    5738                         $maybe_in_viewport = true;
    5739                     } else {
    5740                         $maybe_in_viewport = false;
    5741                     }
    5742                 }
    5743                 /*
    5744                  * For the 'the_post_thumbnail' context, the following case
    5745                  * clause needs to be considered as well, therefore skip the
    5746                  * break statement here if the viewport has not been
    5747                  * determined.
    5748                  */
    5749                 if ( 'the_post_thumbnail' !== $context || null !== $maybe_in_viewport ) {
    5750                     break;
    5751                 }
    5752             // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect
    5753             // Consider elements before the loop as being in viewport.
    5754             case 'wp_get_attachment_image':
    5755             case 'widget_media_image':
    5756                 if (
    5757                     // Only apply for main query but before the loop.
    5758                     $wp_query->before_loop && $wp_query->is_main_query()
    5759                     /*
    5760                      * Any image before the loop, but after the header has started should not be lazy-loaded,
    5761                      * except when the footer has already started which can happen when the current template
    5762                      * does not include any loop.
    5763                      */
    5764                     && did_action( 'get_header' ) && ! did_action( 'get_footer' )
    5765                 ) {
    5766                     $maybe_in_viewport    = true;
    5767                     $maybe_increase_count = true;
    5768                 }
    5769                 break;
     5708        $header_enforced_contexts = array(
     5709            'template_part_' . WP_TEMPLATE_PART_AREA_HEADER => true,
     5710            'get_header_image_tag'                          => true,
     5711        );
     5712
     5713        /**
     5714         * Filters the header-specific contexts.
     5715         *
     5716         * @since 6.4.0
     5717         *
     5718         * @param array $default_header_enforced_contexts Map of contexts for which elements should be considered
     5719         *                                                in the header of the page, as $context => $enabled
     5720         *                                                pairs. The $enabled should always be true.
     5721         */
     5722        $header_enforced_contexts = apply_filters( 'wp_loading_optimization_force_header_contexts', $header_enforced_contexts );
     5723
     5724        // Consider elements with these header-specific contexts to be in viewport.
     5725        if ( isset( $header_enforced_contexts[ $context ] ) ) {
     5726            $maybe_in_viewport    = true;
     5727            $maybe_increase_count = true;
     5728        } elseif ( ! is_admin() && in_the_loop() && is_main_query() ) {
     5729            /*
     5730             * Get the content media count, since this is a main query
     5731             * content element. This is accomplished by "increasing"
     5732             * the count by zero, as the only way to get the count is
     5733             * to call this function.
     5734             * The actual count increase happens further below, based
     5735             * on the `$increase_count` flag set here.
     5736             */
     5737            $content_media_count = wp_increase_content_media_count( 0 );
     5738            $increase_count      = true;
     5739
     5740            // If the count so far is below the threshold, `loading` attribute is omitted.
     5741            if ( $content_media_count < wp_omit_loading_attr_threshold() ) {
     5742                $maybe_in_viewport = true;
     5743            } else {
     5744                $maybe_in_viewport = false;
     5745            }
     5746        } elseif (
     5747            // Only apply for main query but before the loop.
     5748            $wp_query->before_loop && $wp_query->is_main_query()
     5749            /*
     5750             * Any image before the loop, but after the header has started should not be lazy-loaded,
     5751             * except when the footer has already started which can happen when the current template
     5752             * does not include any loop.
     5753             */
     5754            && did_action( 'get_header' ) && ! did_action( 'get_footer' )
     5755            ) {
     5756            $maybe_in_viewport    = true;
     5757            $maybe_increase_count = true;
    57705758        }
    57715759    }
Note: See TracChangeset for help on using the changeset viewer.