angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

class-wp-metadata-lazyloader.php (5352B)


      1 <?php
      2 /**
      3  * Meta API: WP_Metadata_Lazyloader class
      4  *
      5  * @package WordPress
      6  * @subpackage Meta
      7  * @since 4.5.0
      8  */
      9 
     10 /**
     11  * Core class used for lazy-loading object metadata.
     12  *
     13  * When loading many objects of a given type, such as posts in a WP_Query loop, it often makes
     14  * sense to prime various metadata caches at the beginning of the loop. This means fetching all
     15  * relevant metadata with a single database query, a technique that has the potential to improve
     16  * performance dramatically in some cases.
     17  *
     18  * In cases where the given metadata may not even be used in the loop, we can improve performance
     19  * even more by only priming the metadata cache for affected items the first time a piece of metadata
     20  * is requested - ie, by lazy-loading it. So, for example, comment meta may not be loaded into the
     21  * cache in the comments section of a post until the first time get_comment_meta() is called in the
     22  * context of the comment loop.
     23  *
     24  * WP uses the WP_Metadata_Lazyloader class to queue objects for metadata cache priming. The class
     25  * then detects the relevant get_*_meta() function call, and queries the metadata of all queued objects.
     26  *
     27  * Do not access this class directly. Use the wp_metadata_lazyloader() function.
     28  *
     29  * @since 4.5.0
     30  */
     31 class WP_Metadata_Lazyloader {
     32 	/**
     33 	 * Pending objects queue.
     34 	 *
     35 	 * @since 4.5.0
     36 	 * @var array
     37 	 */
     38 	protected $pending_objects;
     39 
     40 	/**
     41 	 * Settings for supported object types.
     42 	 *
     43 	 * @since 4.5.0
     44 	 * @var array
     45 	 */
     46 	protected $settings = array();
     47 
     48 	/**
     49 	 * Constructor.
     50 	 *
     51 	 * @since 4.5.0
     52 	 */
     53 	public function __construct() {
     54 		$this->settings = array(
     55 			'term'    => array(
     56 				'filter'   => 'get_term_metadata',
     57 				'callback' => array( $this, 'lazyload_term_meta' ),
     58 			),
     59 			'comment' => array(
     60 				'filter'   => 'get_comment_metadata',
     61 				'callback' => array( $this, 'lazyload_comment_meta' ),
     62 			),
     63 		);
     64 	}
     65 
     66 	/**
     67 	 * Adds objects to the metadata lazy-load queue.
     68 	 *
     69 	 * @since 4.5.0
     70 	 *
     71 	 * @param string $object_type Type of object whose meta is to be lazy-loaded. Accepts 'term' or 'comment'.
     72 	 * @param array  $object_ids  Array of object IDs.
     73 	 * @return void|WP_Error WP_Error on failure.
     74 	 */
     75 	public function queue_objects( $object_type, $object_ids ) {
     76 		if ( ! isset( $this->settings[ $object_type ] ) ) {
     77 			return new WP_Error( 'invalid_object_type', __( 'Invalid object type.' ) );
     78 		}
     79 
     80 		$type_settings = $this->settings[ $object_type ];
     81 
     82 		if ( ! isset( $this->pending_objects[ $object_type ] ) ) {
     83 			$this->pending_objects[ $object_type ] = array();
     84 		}
     85 
     86 		foreach ( $object_ids as $object_id ) {
     87 			// Keyed by ID for faster lookup.
     88 			if ( ! isset( $this->pending_objects[ $object_type ][ $object_id ] ) ) {
     89 				$this->pending_objects[ $object_type ][ $object_id ] = 1;
     90 			}
     91 		}
     92 
     93 		add_filter( $type_settings['filter'], $type_settings['callback'] );
     94 
     95 		/**
     96 		 * Fires after objects are added to the metadata lazy-load queue.
     97 		 *
     98 		 * @since 4.5.0
     99 		 *
    100 		 * @param array                  $object_ids  Array of object IDs.
    101 		 * @param string                 $object_type Type of object being queued.
    102 		 * @param WP_Metadata_Lazyloader $lazyloader  The lazy-loader object.
    103 		 */
    104 		do_action( 'metadata_lazyloader_queued_objects', $object_ids, $object_type, $this );
    105 	}
    106 
    107 	/**
    108 	 * Resets lazy-load queue for a given object type.
    109 	 *
    110 	 * @since 4.5.0
    111 	 *
    112 	 * @param string $object_type Object type. Accepts 'comment' or 'term'.
    113 	 * @return void|WP_Error WP_Error on failure.
    114 	 */
    115 	public function reset_queue( $object_type ) {
    116 		if ( ! isset( $this->settings[ $object_type ] ) ) {
    117 			return new WP_Error( 'invalid_object_type', __( 'Invalid object type.' ) );
    118 		}
    119 
    120 		$type_settings = $this->settings[ $object_type ];
    121 
    122 		$this->pending_objects[ $object_type ] = array();
    123 		remove_filter( $type_settings['filter'], $type_settings['callback'] );
    124 	}
    125 
    126 	/**
    127 	 * Lazy-loads term meta for queued terms.
    128 	 *
    129 	 * This method is public so that it can be used as a filter callback. As a rule, there
    130 	 * is no need to invoke it directly.
    131 	 *
    132 	 * @since 4.5.0
    133 	 *
    134 	 * @param mixed $check The `$check` param passed from the 'get_term_metadata' hook.
    135 	 * @return mixed In order not to short-circuit `get_metadata()`. Generally, this is `null`, but it could be
    136 	 *               another value if filtered by a plugin.
    137 	 */
    138 	public function lazyload_term_meta( $check ) {
    139 		if ( ! empty( $this->pending_objects['term'] ) ) {
    140 			update_termmeta_cache( array_keys( $this->pending_objects['term'] ) );
    141 
    142 			// No need to run again for this set of terms.
    143 			$this->reset_queue( 'term' );
    144 		}
    145 
    146 		return $check;
    147 	}
    148 
    149 	/**
    150 	 * Lazy-loads comment meta for queued comments.
    151 	 *
    152 	 * This method is public so that it can be used as a filter callback. As a rule, there is no need to invoke it
    153 	 * directly, from either inside or outside the `WP_Query` object.
    154 	 *
    155 	 * @since 4.5.0
    156 	 *
    157 	 * @param mixed $check The `$check` param passed from the {@see 'get_comment_metadata'} hook.
    158 	 * @return mixed The original value of `$check`, so as not to short-circuit `get_comment_metadata()`.
    159 	 */
    160 	public function lazyload_comment_meta( $check ) {
    161 		if ( ! empty( $this->pending_objects['comment'] ) ) {
    162 			update_meta_cache( 'comment', array_keys( $this->pending_objects['comment'] ) );
    163 
    164 			// No need to run again for this set of comments.
    165 			$this->reset_queue( 'comment' );
    166 		}
    167 
    168 		return $check;
    169 	}
    170 }