Geen omschrijving

tiled-gallery.php 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <?php //phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
  2. /**
  3. * Tiled Gallery block.
  4. * Relies on Photon, but can be used even when the module is not active.
  5. *
  6. * @since 6.9.0
  7. *
  8. * @package automattic/jetpack
  9. */
  10. namespace Automattic\Jetpack\Extensions;
  11. use Automattic\Jetpack\Blocks;
  12. use Automattic\Jetpack\Status;
  13. use Jetpack;
  14. use Jetpack_Gutenberg;
  15. use Jetpack_Plan;
  16. /**
  17. * Jetpack Tiled Gallery Block class
  18. *
  19. * @since 7.3
  20. */
  21. class Tiled_Gallery {
  22. const FEATURE_NAME = 'tiled-gallery';
  23. const BLOCK_NAME = 'jetpack/' . self::FEATURE_NAME;
  24. /* Values for building srcsets */
  25. const IMG_SRCSET_WIDTH_MAX = 2000;
  26. const IMG_SRCSET_WIDTH_MIN = 600;
  27. const IMG_SRCSET_WIDTH_STEP = 300;
  28. /**
  29. * Register the block
  30. */
  31. public static function register() {
  32. if (
  33. ( defined( 'IS_WPCOM' ) && IS_WPCOM )
  34. || Jetpack::is_connection_ready()
  35. || ( new Status() )->is_offline_mode()
  36. ) {
  37. Blocks::jetpack_register_block(
  38. self::BLOCK_NAME,
  39. array(
  40. 'render_callback' => array( __CLASS__, 'render' ),
  41. )
  42. );
  43. }
  44. }
  45. /**
  46. * Tiled gallery block registration
  47. *
  48. * @param array $attr Array containing the block attributes.
  49. * @param string $content String containing the block content.
  50. *
  51. * @return string
  52. */
  53. public static function render( $attr, $content ) {
  54. Jetpack_Gutenberg::load_assets_as_required( self::FEATURE_NAME );
  55. $is_squareish_layout = self::is_squareish_layout( $attr );
  56. // Jetpack_Plan does not exist on WordPress.com.
  57. if ( class_exists( 'Jetpack_Plan' ) ) {
  58. $jetpack_plan = Jetpack_Plan::get();
  59. wp_localize_script( 'jetpack-gallery-settings', 'jetpack_plan', array( 'data' => $jetpack_plan['product_slug'] ) );
  60. }
  61. if ( preg_match_all( '/<img [^>]+>/', $content, $images ) ) {
  62. /**
  63. * This block processes all of the images that are found and builds $find and $replace.
  64. *
  65. * The original img is added to the $find array and the replacement is made and added
  66. * to the $replace array. This is so that the same find and replace operations can be
  67. * made on the entire $content.
  68. */
  69. $find = array();
  70. $replace = array();
  71. foreach ( $images[0] as $image_html ) {
  72. if (
  73. preg_match( '/data-width="([0-9]+)"/', $image_html, $img_width )
  74. && preg_match( '/data-height="([0-9]+)"/', $image_html, $img_height )
  75. && preg_match( '/src="([^"]+)"/', $image_html, $img_src )
  76. ) {
  77. // Drop img src query string so it can be used as a base to add photon params
  78. // for the srcset.
  79. $src_parts = explode( '?', $img_src[1], 2 );
  80. $orig_src = $src_parts[0];
  81. $orig_height = absint( $img_height[1] );
  82. $orig_width = absint( $img_width[1] );
  83. // Because URLs are already "photon", the photon function used short-circuits
  84. // before ssl is added. Detect ssl and add is if necessary.
  85. $is_ssl = ! empty( $src_parts[1] ) && false !== strpos( $src_parts[1], 'ssl=1' );
  86. if ( ! $orig_width || ! $orig_height || ! $orig_src ) {
  87. continue;
  88. }
  89. $srcset_parts = array();
  90. if ( $is_squareish_layout ) {
  91. $min_width = min( self::IMG_SRCSET_WIDTH_MIN, $orig_width, $orig_height );
  92. $max_width = min( self::IMG_SRCSET_WIDTH_MAX, $orig_width, $orig_height );
  93. for ( $w = $min_width; $w <= $max_width; $w = min( $max_width, $w + self::IMG_SRCSET_WIDTH_STEP ) ) {
  94. $srcset_src = add_query_arg(
  95. array(
  96. 'resize' => $w . ',' . $w,
  97. 'strip' => 'info',
  98. ),
  99. $orig_src
  100. );
  101. if ( $is_ssl ) {
  102. $srcset_src = add_query_arg( 'ssl', '1', $srcset_src );
  103. }
  104. $srcset_parts[] = esc_url( $srcset_src ) . ' ' . $w . 'w';
  105. if ( $w >= $max_width ) {
  106. break;
  107. }
  108. }
  109. } else {
  110. $min_width = min( self::IMG_SRCSET_WIDTH_MIN, $orig_width );
  111. $max_width = min( self::IMG_SRCSET_WIDTH_MAX, $orig_width );
  112. for ( $w = $min_width; $w <= $max_width; $w = min( $max_width, $w + self::IMG_SRCSET_WIDTH_STEP ) ) {
  113. $srcset_src = add_query_arg(
  114. array(
  115. 'strip' => 'info',
  116. 'w' => $w,
  117. ),
  118. $orig_src
  119. );
  120. if ( $is_ssl ) {
  121. $srcset_src = add_query_arg( 'ssl', '1', $srcset_src );
  122. }
  123. $srcset_parts[] = esc_url( $srcset_src ) . ' ' . $w . 'w';
  124. if ( $w >= $max_width ) {
  125. break;
  126. }
  127. }
  128. }
  129. if ( ! empty( $srcset_parts ) ) {
  130. $srcset = 'srcset="' . esc_attr( implode( ',', $srcset_parts ) ) . '"';
  131. $find[] = $image_html;
  132. $replace[] = str_replace( '<img', '<img ' . $srcset, $image_html );
  133. }
  134. }
  135. }
  136. if ( ! empty( $find ) ) {
  137. $content = str_replace( $find, $replace, $content );
  138. }
  139. }
  140. /**
  141. * Filter the output of the Tiled Galleries content.
  142. *
  143. * @module tiled-gallery
  144. *
  145. * @since 6.9.0
  146. *
  147. * @param string $content Tiled Gallery block content.
  148. */
  149. return apply_filters( 'jetpack_tiled_galleries_block_content', $content );
  150. }
  151. /**
  152. * Determines whether a Tiled Gallery block uses square or circle images (1:1 ratio)
  153. *
  154. * Layouts are block styles and will be available as `is-style-[LAYOUT]` in the className
  155. * attribute. The default (rectangular) will be omitted.
  156. *
  157. * @param {Array} $attr Attributes key/value array.
  158. * @return {boolean} True if layout is squareish, otherwise false.
  159. */
  160. private static function is_squareish_layout( $attr ) {
  161. return isset( $attr['className'] )
  162. && (
  163. 'is-style-square' === $attr['className']
  164. || 'is-style-circle' === $attr['className']
  165. );
  166. }
  167. }
  168. Tiled_Gallery::register();