/wp-includes/class-wp-metadata-lazyloader.php

  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. * @access protected 
  37. * @var array 
  38. */ 
  39. protected $pending_objects; 
  40.  
  41. /** 
  42. * Settings for supported object types. 
  43. * 
  44. * @since 4.5.0 
  45. * @access protected 
  46. * @var array 
  47. */ 
  48. protected $settings = array(); 
  49.  
  50. /** 
  51. * Constructor. 
  52. * 
  53. * @since 4.5.0 
  54. * @access public 
  55. */ 
  56. public function __construct() { 
  57. $this->settings = array( 
  58. 'term' => array( 
  59. 'filter' => 'get_term_metadata',  
  60. 'callback' => array( $this, 'lazyload_term_meta' ),  
  61. ),  
  62. 'comment' => array( 
  63. 'filter' => 'get_comment_metadata',  
  64. 'callback' => array( $this, 'lazyload_comment_meta' ),  
  65. ),  
  66. ); 
  67.  
  68. /** 
  69. * Adds objects to the metadata lazy-load queue. 
  70. * 
  71. * @since 4.5.0 
  72. * @access public 
  73. * 
  74. * @param string $object_type Type of object whose meta is to be lazy-loaded. Accepts 'term' or 'comment'. 
  75. * @param array $object_ids Array of object IDs. 
  76. * @return bool|WP_Error True on success, WP_Error on failure. 
  77. */ 
  78. public function queue_objects( $object_type, $object_ids ) { 
  79. if ( ! isset( $this->settings[ $object_type ] ) ) { 
  80. return new WP_Error( 'invalid_object_type', __( 'Invalid object type' ) ); 
  81.  
  82. $type_settings = $this->settings[ $object_type ]; 
  83.  
  84. if ( ! isset( $this->pending_objects[ $object_type ] ) ) { 
  85. $this->pending_objects[ $object_type ] = array(); 
  86.  
  87. foreach ( $object_ids as $object_id ) { 
  88. // Keyed by ID for faster lookup. 
  89. if ( ! isset( $this->pending_objects[ $object_type ][ $object_id ] ) ) { 
  90. $this->pending_objects[ $object_type ][ $object_id ] = 1; 
  91.  
  92. add_filter( $type_settings['filter'], $type_settings['callback'] ); 
  93.  
  94. /** 
  95. * Fires after objects are added to the metadata lazy-load queue. 
  96. * 
  97. * @since 4.5.0 
  98. * 
  99. * @param array $object_ids Object IDs. 
  100. * @param string $object_type Type of object being queued. 
  101. * @param WP_Metadata_Lazyloader $lazyloader The lazy-loader object. 
  102. */ 
  103. do_action( 'metadata_lazyloader_queued_objects', $object_ids, $object_type, $this ); 
  104.  
  105. /** 
  106. * Resets lazy-load queue for a given object type. 
  107. * 
  108. * @since 4.5.0 
  109. * @access public 
  110. * 
  111. * @param string $object_type Object type. Accepts 'comment' or 'term'. 
  112. * @return bool|WP_Error True on success, WP_Error on failure. 
  113. */ 
  114. public function reset_queue( $object_type ) { 
  115. if ( ! isset( $this->settings[ $object_type ] ) ) { 
  116. return new WP_Error( 'invalid_object_type', __( 'Invalid object type' ) ); 
  117.  
  118. $type_settings = $this->settings[ $object_type ]; 
  119.  
  120. $this->pending_objects[ $object_type ] = array(); 
  121. remove_filter( $type_settings['filter'], $type_settings['callback'] ); 
  122.  
  123. /** 
  124. * Lazy-loads term meta for queued terms. 
  125. * 
  126. * This method is public so that it can be used as a filter callback. As a rule, there 
  127. * is no need to invoke it directly. 
  128. * 
  129. * @since 4.5.0 
  130. * @access public 
  131. * 
  132. * @param mixed $check The `$check` param passed from the 'get_term_metadata' hook. 
  133. * @return mixed In order not to short-circuit `get_metadata()`. Generally, this is `null`, but it could be 
  134. * another value if filtered by a plugin. 
  135. */ 
  136. public function lazyload_term_meta( $check ) { 
  137. if ( ! empty( $this->pending_objects['term'] ) ) { 
  138. update_termmeta_cache( array_keys( $this->pending_objects['term'] ) ); 
  139.  
  140. // No need to run again for this set of terms. 
  141. $this->reset_queue( 'term' ); 
  142.  
  143. return $check; 
  144.  
  145. /** 
  146. * Lazy-loads comment meta for queued comments. 
  147. * 
  148. * This method is public so that it can be used as a filter callback. As a rule, there is no need to invoke it 
  149. * directly, from either inside or outside the `WP_Query` object. 
  150. * 
  151. * @since 4.5.0 
  152. * 
  153. * @param mixed $check The `$check` param passed from the {@see 'get_comment_metadata'} hook. 
  154. * @return mixed The original value of `$check`, so as not to short-circuit `get_comment_metadata()`. 
  155. */ 
  156. public function lazyload_comment_meta( $check ) { 
  157. if ( ! empty( $this->pending_objects['comment'] ) ) { 
  158. update_meta_cache( 'comment', array_keys( $this->pending_objects['comment'] ) ); 
  159.  
  160. // No need to run again for this set of comments. 
  161. $this->reset_queue( 'comment' ); 
  162.  
  163. return $check; 
.