diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php index dd46e4c141..01543b9dcd 100644 --- a/src/wp-includes/media.php +++ b/src/wp-includes/media.php @@ -4725,7 +4725,7 @@ function get_post_galleries( $post, $html = true ) { return array(); } - if ( ! has_shortcode( $post->post_content, 'gallery' ) ) { + if ( ! has_shortcode( $post->post_content, 'gallery' ) && ! has_block( 'gallery', $post->post_content ) ) { return array(); } @@ -4767,6 +4767,95 @@ function get_post_galleries( $post, $html = true ) { } } + if ( has_block( 'gallery', $post->post_content ) ) { + $post_blocks = parse_blocks( $post->post_content ); + + while ( $block = array_shift( $post_blocks ) ) { + $has_inner_blocks = ! empty( $block['innerBlocks'] ); + + // Skip blocks with no blockName and no innerHTML. + if ( ! $block['blockName'] ) { + continue; + } + + // All blocks nested inside non-Gallery blocks should be in the root array. + if ( $has_inner_blocks && 'core/gallery' !== $block['blockName'] ) { + array_push( $post_blocks, ...$block['innerBlocks'] ); + continue; + } + + // New Gallery block format as HTML. + if ( $has_inner_blocks && $html ) { + $block_html = wp_list_pluck( $block['innerBlocks'], 'innerHTML' ); + $galleries[] = '
' . implode( ' ', $block_html ) . '
'; + continue; + } + + $srcs = array(); + + // New Gallery block format as an array. + if ( $has_inner_blocks ) { + $attrs = wp_list_pluck( $block['innerBlocks'], 'attrs' ); + $ids = wp_list_pluck( $attrs, 'id' ); + + foreach ( $ids as $id ) { + $url = wp_get_attachment_url( $id ); + + if ( is_string( $url ) && ! in_array( $url, $srcs, true ) ) { + $srcs[] = $url; + } + } + + $galleries[] = array( + 'ids' => implode( ',', $ids ), + 'src' => $srcs, + ); + + continue; + } + + // Old Gallery block format as HTML. + if ( $html ) { + $galleries[] = $block['innerHTML']; + continue; + } + + // Old Gallery block format as an array. + $ids = ! empty( $block['attrs']['ids'] ) ? $block['attrs']['ids'] : array(); + + // If present, use the image IDs from the JSON blob as canonical. + if ( ! empty( $ids ) ) { + foreach ( $ids as $id ) { + $url = wp_get_attachment_url( $id ); + + if ( is_string( $url ) && ! in_array( $url, $srcs, true ) ) { + $srcs[] = $url; + } + } + + $galleries[] = array( + 'ids' => implode( ',', $ids ), + 'src' => $srcs, + ); + + continue; + } + + // Otherwise, extract srcs from the innerHTML. + preg_match_all( '#src=([\'"])(.+?)\1#is', $block['innerHTML'], $found_srcs, PREG_SET_ORDER ); + + if ( ! empty( $found_srcs[0] ) ) { + foreach ( $found_srcs as $src ) { + if ( isset( $src[2] ) && ! in_array( $src[2], $srcs, true ) ) { + $srcs[] = $src[2]; + } + } + } + + $galleries[] = array( 'src' => $srcs ); + } + } + /** * Filters the list of all found galleries in the given post. * diff --git a/tests/phpunit/tests/media.php b/tests/phpunit/tests/media.php index c338a2baf7..5d92d9718b 100644 --- a/tests/phpunit/tests/media.php +++ b/tests/phpunit/tests/media.php @@ -512,7 +512,7 @@ https://w.org', public function test_post_galleries_images() { $ids1 = array(); $ids1_srcs = array(); - foreach ( range( 1, 3 ) as $i ) { + foreach ( range( 1, 6 ) as $i ) { $attachment_id = self::factory()->attachment->create_object( "image$i.jpg", 0, @@ -544,8 +544,8 @@ https://w.org', $ids2_srcs[] = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . "image$i.jpg"; } - $ids1_joined = implode( ',', $ids1 ); - $ids2_joined = implode( ',', $ids2 ); + $ids1_joined = join( ',', array_slice( $ids1, 0, 3 ) ); + $ids2_joined = join( ',', array_slice( $ids2, 3, 3 ) ); $blob = <<', BLOB; $post_id = self::factory()->post->create( array( 'post_content' => $blob ) ); $srcs = get_post_galleries_images( $post_id ); - $this->assertSame( $srcs, array( $ids1_srcs, $ids2_srcs ) ); - } - - /** - * @ticket 39304 - */ - public function test_post_galleries_images_without_global_post() { - // Set up an unattached image. - $this->factory->attachment->create_object( - array( - 'file' => 'test.jpg', - 'post_parent' => 0, - 'post_mime_type' => 'image/jpeg', - 'post_type' => 'attachment', - ) - ); - - $post_id = $this->factory->post->create( - array( - 'post_content' => '[gallery]', - ) - ); - - $galleries = get_post_galleries( $post_id, false ); - - $this->assertEmpty( $galleries[0]['src'] ); - } - - /** - * @ticket 39304 - */ - public function test_post_galleries_ignores_global_post() { - $global_post_id = $this->factory->post->create( - array( - 'post_content' => 'Global Post', - ) - ); - $post_id = $this->factory->post->create( - array( - 'post_content' => '[gallery]', - ) - ); - $this->factory->attachment->create_object( - array( - 'file' => 'test.jpg', - 'post_parent' => $post_id, - 'post_mime_type' => 'image/jpeg', - 'post_type' => 'attachment', - ) - ); - $expected_srcs = array( - 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test.jpg', - ); - - // Set the global $post context to the other post. - $GLOBALS['post'] = get_post( $global_post_id ); - - $galleries = get_post_galleries( $post_id, false ); - - $this->assertNotEmpty( $galleries[0]['src'] ); - $this->assertSame( $galleries[0]['src'], $expected_srcs ); - } - - /** - * @ticket 39304 - */ - public function test_post_galleries_respects_id_attrs() { - $post_id = $this->factory->post->create( - array( - 'post_content' => 'No gallery defined', - ) - ); - $post_id_two = $this->factory->post->create( - array( - 'post_content' => "[gallery id='$post_id']", - ) - ); - $this->factory->attachment->create_object( - array( - 'file' => 'test.jpg', - 'post_parent' => $post_id, - 'post_mime_type' => 'image/jpeg', - 'post_type' => 'attachment', - ) - ); - $expected_srcs = array( - 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test.jpg', - ); - - $galleries = get_post_galleries( $post_id_two, false ); - - // Set the global $post context. - $GLOBALS['post'] = get_post( $post_id_two ); - $galleries_with_global_context = get_post_galleries( $post_id_two, false ); - - // Check that the global post state doesn't affect the results. - $this->assertSame( $galleries, $galleries_with_global_context ); - - $this->assertNotEmpty( $galleries[0]['src'] ); - $this->assertSame( $galleries[0]['src'], $expected_srcs ); + $this->assertSameSetsWithIndex( $srcs, array( array_slice( $ids1_srcs, 0, 3 ), array_slice( $ids2_srcs, 3, 3 ) ) ); } /** @@ -707,6 +608,209 @@ BLOB; $this->assertSame( $srcs, $ids1_srcs ); } + /** + * @ticket 43826 + * @group blocks + */ + public function test_block_post_gallery_images() { + // Similar to test_post_gallery_images but with blocks instead of shortcodes + $ids = array(); + $imgs = array(); + $ids_srcs = array(); + foreach ( range( 1, 6 ) as $i ) { + $attachment_id = self::factory()->attachment->create_object( + "image$i.jpg", + 0 + ); + $metadata = array_merge( array( 'file' => "image$i.jpg" ), $this->img_meta ); + wp_update_attachment_metadata( $attachment_id, $metadata ); + $ids[] = $attachment_id; + $url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . "image$i.jpg"; + $ids_srcs[] = $url; + $imgs[] = '
'; + } + + $imgs1_joined = join( "\n", array_slice( $imgs, 0, 3 ) ); + $imgs2_joined = join( "\n", array_slice( $imgs, 3, 3 ) ); + + $blob = << +$imgs1_joined + + +$imgs2_joined + +BLOB; + $post_id = self::factory()->post->create( array( 'post_content' => $blob ) ); + $srcs = get_post_gallery_images( $post_id ); + $this->assertSameSetsWithIndex( array_slice( $ids_srcs, 0, 3 ), $srcs ); + } + + /** + * @ticket 43826 + * @group blocks + */ + public function test_block_post_gallery_images_json() { + // Similar to test_block_post_gallery_images, with IDs in the json blob + $ids = array(); + $imgs = array(); + $ids_srcs = array(); + foreach ( range( 1, 6 ) as $i ) { + $attachment_id = self::factory()->attachment->create_object( + "image$i.jpg", + 0 + ); + $metadata = array_merge( array( 'file' => "image$i.jpg" ), $this->img_meta ); + wp_update_attachment_metadata( $attachment_id, $metadata ); + $ids[] = $attachment_id; + $url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . "image$i.jpg"; + $ids_srcs[] = $url; + $imgs[] = '
'; + + } + + $ids1_joined = join( ',', array_slice( $ids, 0, 3 ) ); + $ids2_joined = join( ',', array_slice( $ids, 3, 3 ) ); + + $blob = << + + + + +BLOB; + $post_id = self::factory()->post->create( array( 'post_content' => $blob ) ); + $srcs = get_post_gallery_images( $post_id ); + $this->assertSameSetsWithIndex( array_slice( $ids_srcs, 0, 3 ), $srcs ); + } + + /** + * @ticket 43826 + * @group blocks + */ + public function test_mixed_post_gallery_images() { + // Similar to test_post_gallery_images but with a shortcode and a block in the same post + $ids = array(); + $imgs = array(); + $ids_srcs = array(); + foreach ( range( 1, 6 ) as $i ) { + $attachment_id = self::factory()->attachment->create_object( + "image$i.jpg", + 0, + array( + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + $metadata = array_merge( array( 'file' => "image$i.jpg" ), $this->img_meta ); + wp_update_attachment_metadata( $attachment_id, $metadata ); + $ids[] = $attachment_id; + $url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . "image$i.jpg"; + $ids_srcs[] = $url; + $imgs[] = '
'; + } + + $ids1_joined = join( "\n", array_slice( $ids, 0, 3 ) ); + $ids2_joined = join( "\n", array_slice( $ids, 3, 3 ) ); + $imgs2_joined = join( "\n", array_slice( $imgs, 3, 3 ) ); + + $blob = << +$imgs2_joined + +BLOB; + $post_id = self::factory()->post->create( array( 'post_content' => $blob ) ); + $srcs = get_post_gallery_images( $post_id ); + $this->assertSameSetsWithIndex( array_slice( $ids_srcs, 0, 3 ), $srcs ); + } + + /** + * @ticket 43826 + * @group blocks + */ + public function test_block_inner_post_gallery_images() { + // Make sure get_post_gallery_images() works with gallery blocks that are nested inside something else + $ids = array(); + $imgs = array(); + $ids_srcs = array(); + foreach ( range( 1, 3 ) as $i ) { + $attachment_id = self::factory()->attachment->create_object( + "image$i.jpg", + 0, + array( + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + $metadata = array_merge( array( 'file' => "image$i.jpg" ), $this->img_meta ); + wp_update_attachment_metadata( $attachment_id, $metadata ); + $ids[] = $attachment_id; + $url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . "image$i.jpg"; + $ids_srcs[] = $url; + $imgs[] = '
'; + + } + + $imgs_joined = join( "\n", $imgs ); + + $blob = << + + +$imgs_joined + + + +BLOB; + $post_id = self::factory()->post->create( array( 'post_content' => $blob ) ); + $srcs = get_post_gallery_images( $post_id ); + $this->assertSameSetsWithIndex( $ids_srcs, $srcs ); + } + + /** + * @ticket 43826 + * @group blocks + */ + public function test_block_post_gallery_innerblock_images() { + // Make sure get_post_gallery_images() works with new version of gallery block with nested image blocks. + $ids = array(); + $imgs = array(); + $ids_srcs = array(); + foreach ( range( 1, 3 ) as $i ) { + $attachment_id = self::factory()->attachment->create_object( + "image$i.jpg", + 0, + array( + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + $metadata = array_merge( array( 'file' => "image$i.jpg" ), $this->img_meta ); + wp_update_attachment_metadata( $attachment_id, $metadata ); + $ids[] = $attachment_id; + $url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . "image$i.jpg"; + $ids_srcs[] = $url; + $imgs[] = '
'; + + } + + $imgs_joined = join( "\n", $imgs ); + + $blob = << + + +BLOB; + $post_id = self::factory()->post->create( array( 'post_content' => $blob ) ); + $srcs = get_post_gallery_images( $post_id ); + $this->assertSameSetsWithIndex( $ids_srcs, $srcs ); + } + public function test_get_media_embedded_in_content() { $object = << diff --git a/tests/phpunit/tests/media/getPostGalleries.php b/tests/phpunit/tests/media/getPostGalleries.php new file mode 100644 index 0000000000..bd114b899f --- /dev/null +++ b/tests/phpunit/tests/media/getPostGalleries.php @@ -0,0 +1,969 @@ +img_meta = array( + 'width' => 100, + 'height' => 100, + 'sizes' => '', + ); + } + + /** + * Test that an empty array is returned for a post that does not exist. + * + * @ticket 43826 + */ + public function test_returns_empty_array_with_non_existent_post() { + $galleries = get_post_galleries( 99999, false ); + $this->assertEmpty( $galleries ); + } + + /** + * Test that an empty array is returned for a post that has no gallery. + * + * @ticket 43826 + */ + public function test_returns_empty_array_with_post_with_no_gallery() { + $post_id = $this->factory->post->create( + array( + 'post_content' => '

A post with no gallery

', + ) + ); + + $galleries = get_post_galleries( $post_id, false ); + $this->assertEmpty( $galleries ); + } + + /** + * Test that no srcs are returned for a shortcode gallery + * in a post with no attached images. + * + * @ticket 39304 + * + * @group shortcode + */ + public function test_returns_no_srcs_with_shortcode_in_post_with_no_attached_images() { + // Set up an unattached image. + $this->factory->attachment->create_object( + array( + 'file' => 'test.jpg', + 'post_parent' => 0, + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + + $post_id = $this->factory->post->create( + array( + 'post_content' => '[gallery]', + ) + ); + + $galleries = get_post_galleries( $post_id, false ); + + // The method can return an empty array. + $this->assertNotEmpty( + $galleries, + 'The galleries array is empty.' + ); + + // This prevents future changes from causing + // backwards compatibility breaks. + $this->assertArrayHasKey( + 'src', + $galleries[0], + 'A src key does not exist.' + ); + + $this->assertEmpty( + $galleries[0]['src'], + 'The src key is not empty.' + ); + } + + /** + * Test that no srcs are returned for a gallery block + * in a post with no attached images. + * + * @ticket 43826 + * + * @group blocks + */ + public function test_returns_no_srcs_with_block_in_post_with_no_attached_images() { + // Set up an unattached image. + $this->factory->attachment->create_object( + array( + 'file' => 'test.jpg', + 'post_parent' => 0, + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + + $post_id = $this->factory->post->create( + array( + 'post_content' => '', + ) + ); + + $galleries = get_post_galleries( $post_id, false ); + + // The method can return an empty array. + $this->assertNotEmpty( + $galleries, + 'The galleries array is empty.' + ); + + // The method can return an array of strings + // instead of an array of arrays. + $this->assertIsArray( + $galleries[0], + 'The returned data does not contain an array.' + ); + + // This prevents future changes from causing + // backwards compatibility breaks. + $this->assertArrayHasKey( + 'src', + $galleries[0], + 'A src key does not exist.' + ); + + $this->assertEmpty( + $galleries[0]['src'], + 'The src key of the first gallery is not empty.' + ); + } + + /** + * Test that no srcs are returned for a gallery block v2 + * in a post with no attached images. + * + * @ticket 43826 + * + * @group blocks + */ + public function test_returns_no_srcs_with_block_v2_in_post_with_no_attached_images() { + // Set up an unattached image. + $image_id = $this->factory->attachment->create_object( + array( + 'file' => 'test.jpg', + 'post_parent' => 0, + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + + $image_url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test.jpg'; + + $blob = <<< BLOB + + + +BLOB; + + $post_id = $this->factory->post->create( + array( + 'post_content' => $blob, + ) + ); + + $expected_srcs = array( $image_url ); + $galleries = get_post_galleries( $post_id, false ); + + // The method can return an empty array. + $this->assertNotEmpty( + $galleries, + 'The galleries array is empty.' + ); + + // The method can return an array of strings + // instead of an array of arrays. + $this->assertIsArray( + $galleries[0], + 'The returned data does not contain an array.' + ); + + // This prevents future changes from causing + // backwards compatibility breaks. + $this->assertArrayHasKey( + 'src', + $galleries[0], + 'A src key does not exist.' + ); + + $this->assertSameSetsWithIndex( + $expected_srcs, + $galleries[0]['src'], + 'The expected and actual srcs are not the same.' + ); + } + + /** + * Test that HTML is returned for a shortcode gallery. + * + * @ticket 43826 + * + * @group shortcode + */ + public function test_returns_html_with_shortcode_gallery() { + $post_id = $this->factory->post->create( + array( + 'post_content' => 'I have no gallery', + ) + ); + + $post_id_two = $this->factory->post->create( + array( + 'post_content' => "[gallery id='$post_id']", + ) + ); + + $this->factory->attachment->create_object( + array( + 'file' => 'test.jpg', + 'post_parent' => $post_id, + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + + $expected = 'src="http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test.jpg"'; + $galleries = get_post_galleries( $post_id_two ); + + // The method can return an empty array. + $this->assertNotEmpty( + $galleries, + 'The galleries array is empty.' + ); + + // The method can return an array of arrays + // instead of an array of strings. + $this->assertIsString( + $galleries[0], + 'Did not return the data as a string.' + ); + + $this->assertStringContainsString( + $expected, + $galleries[0], + 'The returned data did not contain a src attribute with the expected image URL.' + ); + } + + /** + * Test that HTML is returned for a block gallery. + * + * @ticket 43826 + * + * @group blocks + */ + public function test_returns_html_with_block_gallery() { + $post_id = $this->factory->post->create( + array( + 'post_content' => 'I have no gallery.', + ) + ); + + // Set up an unattached image. + $image_id = $this->factory->attachment->create( + array( + 'file' => 'test.jpg', + 'post_parent' => $post_id, + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + + $image_url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test.jpg'; + + $blob = <<< BLOB + +
+ +BLOB; + + $post_id_two = $this->factory->post->create( + array( + 'post_content' => $blob, + ) + ); + + $expected = 'src="http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test.jpg"'; + $galleries = get_post_galleries( $post_id_two ); + + // The method can return an empty array. + $this->assertNotEmpty( + $galleries, + 'The galleries array is empty.' + ); + + // The method can return an array of arrays + // instead of an array of strings. + $this->assertIsString( + $galleries[0], + 'Did not return the data as a string.' + ); + + $this->assertStringContainsString( + $expected, + $galleries[0], + 'The returned data did not contain a src attribute with the expected image URL.' + ); + } + + /** + * Test that HTML is returned for a block gallery v2. + * + * @ticket 43826 + * + * @group blocks + */ + public function test_returns_html_with_block_gallery_v2() { + $image_id = $this->factory->attachment->create_object( + array( + 'file' => 'test.jpg', + 'post_parent' => 0, + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + + $image_url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test.jpg'; + + $blob = <<< BLOB + + + +BLOB; + + $post_id = $this->factory->post->create( + array( + 'post_content' => $blob, + ) + ); + + $expected = 'src="http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test.jpg"'; + $galleries = get_post_galleries( $post_id ); + + // The method can return an empty array. + $this->assertNotEmpty( + $galleries, + 'The galleries array is empty.' + ); + + // The method can return an array of arrays + // instead of an array of strings. + $this->assertIsString( + $galleries[0], + 'Did not return the data as a string.' + ); + + $this->assertStringContainsString( + $expected, + $galleries[0], + 'The returned data did not contain a src attribute with the expected image URL.' + ); + } + + /** + * Test that the global post object does not override + * a provided post ID with a shortcode gallery. + * + * @ticket 39304 + * + * @group shortcode + */ + public function test_respects_post_id_with_shortcode_gallery() { + $global_post_id = $this->factory->post->create( + array( + 'post_content' => 'Global Post', + ) + ); + $post_id = $this->factory->post->create( + array( + 'post_content' => '[gallery]', + ) + ); + $this->factory->attachment->create_object( + array( + 'file' => 'test.jpg', + 'post_parent' => $post_id, + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + $expected_srcs = array( + 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test.jpg', + ); + + // Set the global $post context to the other post. + $GLOBALS['post'] = get_post( $global_post_id ); + + $galleries = get_post_galleries( $post_id, false ); + + // The method can return an empty array. + $this->assertNotEmpty( + $galleries, + 'The galleries array is empty.' + ); + + // This prevents future changes from causing + // backwards compatibility breaks. + $this->assertArrayHasKey( + 'src', + $galleries[0], + 'A src key does not exist.' + ); + + $this->assertSameSetsWithIndex( + $expected_srcs, + $galleries[0]['src'], + 'The expected and actual srcs are not the same.' + ); + } + + /** + * Test that the global post object does not override + * a provided post ID with a block gallery. + * + * @ticket 43826 + * + * @group block + */ + public function test_respects_post_id_with_block_gallery() { + $ids = array(); + $imgs = array(); + $ids_srcs = array(); + foreach ( range( 1, 3 ) as $i ) { + $attachment_id = self::factory()->attachment->create_object( + "image$i.jpg", + 0, + array( + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + $metadata = array_merge( array( 'file' => "image$i.jpg" ), $this->img_meta ); + wp_update_attachment_metadata( $attachment_id, $metadata ); + $ids[] = $attachment_id; + $url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . "image$i.jpg"; + $ids_srcs[] = $url; + $imgs[] = '
'; + + } + + $ids_joined = join( ',', $ids ); + + $global_post_id = $this->factory->post->create( + array( + 'post_content' => 'Global Post', + ) + ); + + $blob = <<< BLOB + + +BLOB; + + $post_id = $this->factory->post->create( + array( + 'post_content' => $blob, + ) + ); + $this->factory->attachment->create_object( + array( + 'file' => 'test.jpg', + 'post_parent' => $post_id, + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + $expected_srcs = array( + 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test.jpg', + ); + + // Set the global $post context to the other post. + $GLOBALS['post'] = get_post( $global_post_id ); + + $galleries = get_post_galleries( $post_id, false ); + + // The method can return an empty array. + $this->assertNotEmpty( + $galleries, + 'The galleries array is empty.' + ); + + // This prevents future changes from causing + // backwards compatibility breaks. + $this->assertArrayHasKey( + 'src', + $galleries[0], + 'A src key does not exist.' + ); + + $this->assertSameSetsWithIndex( + array( + array( + 'ids' => $ids_joined, + 'src' => $ids_srcs, + ), + ), + $galleries, + 'The expected and actual srcs are not the same.' + ); + } + + /** + * Test that the global post object does not override + * a provided post ID with a block gallery v2. + * + * @ticket 43826 + * + * @group block + */ + public function test_respects_post_id_with_block_gallery_v2() { + $attachment_id = self::factory()->attachment->create_object( + 'image1.jpg', + 0, + array( + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + $metadata = array_merge( array( 'file' => 'image1.jpg' ), $this->img_meta ); + $url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . 'image1.jpg'; + $global_post_id = $this->factory->post->create( + array( + 'post_content' => 'Global Post', + ) + ); + + wp_update_attachment_metadata( $attachment_id, $metadata ); + + $blob = <<< BLOB + + + +BLOB; + + $post_id = $this->factory->post->create( + array( + 'post_content' => $blob, + ) + ); + $this->factory->attachment->create_object( + array( + 'file' => 'test.jpg', + 'post_parent' => $post_id, + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + $expected_srcs = array( + 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test.jpg', + ); + + // Set the global $post context to the other post. + $GLOBALS['post'] = get_post( $global_post_id ); + + $galleries = get_post_galleries( $post_id, false ); + + // The method can return an empty array. + $this->assertNotEmpty( + $galleries, + 'The galleries array is empty.' + ); + + // This prevents future changes from causing + // backwards compatibility breaks. + $this->assertArrayHasKey( + 'src', + $galleries[0], + 'A src key does not exist.' + ); + + $this->assertSameSetsWithIndex( + array( + array( + 'ids' => (string) $attachment_id, + 'src' => array( $url ), + ), + ), + $galleries, + 'The expected and actual srcs are not the same.' + ); + } + + /** + * Test that the gallery only contains images specified in + * the shortcode's id attribute. + * + * @ticket 39304 + * + * @group shortcode + */ + public function test_respects_shortcode_id_attribute() { + $post_id = $this->factory->post->create( + array( + 'post_content' => 'No gallery defined', + ) + ); + $post_id_two = $this->factory->post->create( + array( + 'post_content' => "[gallery id='$post_id']", + ) + ); + $this->factory->attachment->create_object( + array( + 'file' => 'test.jpg', + 'post_parent' => $post_id, + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + $expected_srcs = array( + 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test.jpg', + ); + + $galleries = get_post_galleries( $post_id_two, false ); + + // Set the global $post context. + $GLOBALS['post'] = get_post( $post_id_two ); + $galleries_with_global_context = get_post_galleries( $post_id_two, false ); + + // Check that the global post state doesn't affect the results. + $this->assertSameSetsWithIndex( + $galleries, + $galleries_with_global_context, + 'The global post state affected the results.' + ); + + // The method can return an empty array. + $this->assertNotEmpty( + $galleries, + 'The galleries array is empty.' + ); + + // The method can return an array of strings + // instead of an array of arrays. + $this->assertIsArray( + $galleries[0], + 'The returned data does not contain an array.' + ); + + // This prevents future changes from causing + // backwards compatibility breaks. + $this->assertArrayHasKey( + 'src', + $galleries[0], + 'A src key does not exist.' + ); + + $this->assertSameSetsWithIndex( + $expected_srcs, + $galleries[0]['src'], + 'The expected and actual srcs are not the same.' + ); + } + + /** + * Test that galleries only contain images specified in the + * id attribute of their respective shortcode and block. + * + * @ticket 43826 + * + * @group blocks + * @group shortcode + */ + public function test_respects_shortcode_and_block_id_attributes() { + // Test the get_post_galleries() function in $html=false mode, with both shortcode and block galleries + $ids = array(); + $imgs = array(); + $ids_srcs = array(); + foreach ( range( 1, 6 ) as $i ) { + $attachment_id = self::factory()->attachment->create_object( + "image$i.jpg", + 0, + array( + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + $metadata = array_merge( array( 'file' => "image$i.jpg" ), $this->img_meta ); + wp_update_attachment_metadata( $attachment_id, $metadata ); + $ids[] = $attachment_id; + $url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . "image$i.jpg"; + $ids_srcs[] = $url; + $imgs[] = '
'; + + } + + $ids1_joined = join( ',', array_slice( $ids, 0, 3 ) ); + $ids2_joined = join( ',', array_slice( $ids, 3, 3 ) ); + + $blob = << + +BLOB; + + $post_id = self::factory()->post->create( array( 'post_content' => $blob ) ); + + $galleries = get_post_galleries( $post_id, false ); + $this->assertSameSetsWithIndex( + array( + array( + 'ids' => $ids1_joined, + 'src' => array_slice( $ids_srcs, 0, 3 ), + ), + array( + 'ids' => $ids2_joined, + 'src' => array_slice( $ids_srcs, 3, 3 ), + ), + ), + $galleries + ); + + } + + /** + * Test that galleries contain the additional attributes + * specified for their respective shortcode and block. + * + * @ticket 43826 + * + * @group blocks + * @group shortcode + */ + public function test_respects_additional_shortcode_and_block_attributes() { + // Test attributes returned by get_post_galleries() function in $html=false mode, with both shortcode and block galleries + $ids = array(); + $imgs = array(); + $ids_srcs = array(); + foreach ( range( 1, 6 ) as $i ) { + $attachment_id = self::factory()->attachment->create_object( + "image$i.jpg", + 0, + array( + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + $metadata = array_merge( array( 'file' => "image$i.jpg" ), $this->img_meta ); + wp_update_attachment_metadata( $attachment_id, $metadata ); + $ids[] = $attachment_id; + $url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . "image$i.jpg"; + $ids_srcs[] = $url; + $imgs[] = '
'; + + } + + $ids1_joined = join( ',', array_slice( $ids, 0, 3 ) ); + $ids2_joined = join( ',', array_slice( $ids, 3, 3 ) ); + $blob = << + +BLOB; + + $post_id = self::factory()->post->create( array( 'post_content' => $blob ) ); + + $galleries = get_post_galleries( $post_id, false ); + $this->assertSameSetsWithIndex( + array( + array( + 'ids' => $ids1_joined, + // The shortcode code passes arbitrary attributes + 'type' => 'type', + 'foo' => 'bar', + 'src' => array_slice( $ids_srcs, 0, 3 ), + ), + array( + 'ids' => $ids2_joined, + // The block only passes ids, no other attributes + 'src' => array_slice( $ids_srcs, 3, 3 ), + ), + ), + $galleries + ); + + } + + /** + * Test that srcs are retrieved from the HTML of a block gallery + * that has no JSON blob. + * + * @ticket 43826 + * + * @group blocks + */ + public function test_returns_srcs_from_html_with_block_with_no_json_blob() { + // Set up an unattached image. + $image_id = $this->factory->attachment->create_object( + array( + 'file' => 'test.jpg', + 'post_parent' => 0, + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + + $image_url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test.jpg'; + + $blob = <<< BLOB + + + +BLOB; + + $post_id = $this->factory->post->create( + array( + 'post_content' => $blob, + ) + ); + + $expected_srcs = array( $image_url ); + $galleries = get_post_galleries( $post_id, false ); + + // The method can return an empty array. + $this->assertNotEmpty( + $galleries, + 'The galleries array is empty.' + ); + + // The method can return an array of strings + // instead of an array of arrays. + $this->assertIsArray( + $galleries[0], + 'The returned data does not contain an array.' + ); + + // This prevents future changes from causing + // backwards compatibility breaks. + $this->assertArrayHasKey( + 'src', + $galleries[0], + 'A src key does not exist.' + ); + + $this->assertSameSetsWithIndex( + $expected_srcs, + $galleries[0]['src'], + 'The expected and actual srcs are not the same.' + ); + } + + /** + * Test that srcs are returned for a block gallery nested within + * other blocks. + * + * @ticket 43826 + * + * @group blocks + */ + public function test_returns_srcs_with_nested_block_gallery() { + $post_id = $this->factory->post->create( + array( + 'post_content' => 'I have no gallery.', + ) + ); + $image_id = $this->factory->attachment->create_object( + array( + 'file' => 'test.jpg', + 'post_parent' => $post_id, + 'post_mime_type' => 'image/jpeg', + 'post_type' => 'attachment', + ) + ); + + $blob = << + + + + + +BLOB; + + $post_id_two = $this->factory->post->create( array( 'post_content' => $blob ) ); + + $galleries = get_post_galleries( $post_id_two, false ); + + // The method can return an empty array. + $this->assertNotEmpty( + $galleries, + 'The galleries array is empty.' + ); + + // The method can return an array of strings + // instead of an array of arrays. + $this->assertIsArray( + $galleries[0], + 'The returned data does not contain an array.' + ); + + // This prevents future changes from causing + // backwards compatibility breaks. + $this->assertArrayHasKey( + 'src', + $galleries[0], + 'A src key does not exist.' + ); + + $this->assertNotEmpty( + $galleries[0]['src'], + 'The src key of the first gallery is empty.' + ); + } +}