Completed
Push — add/post-images-package ( ff119f )
by Jeremy
12:24
created

Test_Post_Images::get_post_with_columns_block()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 25
rs 9.52
c 0
b 0
f 0
1
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
3
namespace Automattic\Jetpack;
4
5
use WorDBless\BaseTestCase;
6
7
/**
8
 * Test Post_Images class
9
 *
10
 * @package automattic/jetpack-post-images
11
 */
12
class Test_Post_Images extends BaseTestCase {
13
	/**
14
	 * Test Alt text.
15
	 *
16
	 * @var string
17
	 */
18
	private $alt_text = 'Alt Text.';
19
20
	/**
21
	 * Test fetching alt content of images from HTML.
22
	 *
23
	 * @covers \Automattic\Jetpack\Post_Images::from_html
24
	 *
25
	 * @dataProvider get_html_with_alt_content
26
	 *
27
	 * @since 2.7
28
	 *
29
	 * @param string $html         HTML markup.
30
	 * @param string $expected_alt Expected Alt content found in HTML content.
31
	 */
32
	public function test_alt_from_html( $html, $expected_alt ) {
33
		$result = Post_Images::from_html( $html );
34
35
		$this->assertIsArray( $result );
36
		$this->assertNotEmpty( $result );
37
		$this->assertEquals( $expected_alt, $result[0]['alt_text'] );
38
	}
39
40
	/**
41
	 * Sample HTML markup to be examined in test_alt_from_html
42
	 *
43
	 * @covers \Automattic\Jetpack\Post_Images::from_html
44
	 */
45
	public function get_html_with_alt_content() {
46
		return array(
47
			'Double quotes' => array(
48
				'<img ANYTHINGATALLHERE src="bob.jpg" MOREANYTHINGHERE width="200" height="200" alt="Alt Text." />',
49
				$this->alt_text,
50
			),
51
			'Single quotes' => array(
52
				"<img ANYTHINGATALLHERE src='bob.jpg' MOREANYTHINGHERE width='200' height='200' alt='Alt Text.' />",
53
				$this->alt_text,
54
			),
55
		);
56
	}
57
58
	/**
59
	 * Tests that images can be fetched from a gallery shortcode.
60
	 *
61
	 * @covers \Automattic\Jetpack\Post_Images::from_gallery
62
	 *
63
	 * @since 3.2
64
	 */
65
	public function test_from_gallery_is_array() {
66
		$post_id = wp_insert_post(
67
			array(
68
				'post_content' => '[gallery 1,2,3]',
69
			)
70
		);
71
72
		$images = Post_Images::from_gallery( $post_id );
73
74
		$this->assertIsArray( $images );
75
	}
76
77
	/**
78
	 * Test that we can get info about an image attached to a post.
79
	 *
80
	 * @author scotchfield
81
	 * @author Alda Vigdís <[email protected]>
82
	 * @covers \Automattic\Jetpack\Post_Images::from_attachment
83
	 * @since 3.2
84
	 */
85
	public function test_from_attachment_is_correct_array() {
86
		$post_id       = wp_insert_post(
87
			array(
88
				'post_title'   => 'hello',
89
				'post_content' => 'world',
90
				'post_status'  => 'publish',
91
			)
92
		);
93
		$attachment_id = $this->create_upload_object( __DIR__ . '/wp-logo.jpg', array(), $post_id );
94
95
		$img_url  = wp_get_attachment_url( $attachment_id );
96
		$img_html = '<img src="' . $img_url . '" width="250" height="250" alt="' . $this->alt_text . '"/>';
97
98
		wp_update_post(
99
			array(
100
				'ID'           => $post_id,
101
				'post_content' => $img_html,
102
			)
103
		);
104
105
		$images = Post_Images::from_attachment( $post_id );
106
107
		$this->assertCount( 1, $images );
108
		$this->assertEquals( $img_url, $images[0]['src'] );
109
		$this->assertEquals( $this->alt_text, $images[0]['alt_text'] );
110
	}
111
112
	/**
113
	 * Create a post with an image block containing a large image attached to another post.
114
	 *
115
	 * @since 6.9.0
116
	 *
117
	 * @return array $post_info {
118
	 * An array of information about our post.
119
	 *  @type int $post_id Post ID.
120
	 *  @type string $img_url Image URL we'll look to extract.
121
	 * }
122
	 */
123
	protected function get_post_with_image_block() {
124
		$post_id       = wp_insert_post(
125
			array(
126
				'post_title'   => 'hello',
127
				'post_content' => 'world',
128
				'post_status'  => 'publish',
129
			)
130
		);
131
		$attachment_id = $this->create_upload_object( __DIR__ . '/wp-logo.jpg', array(), $post_id );
132
133
		$img_url = wp_get_attachment_url( $attachment_id );
134
135
		// Create another post with that picture.
136
		$post_html = sprintf(
137
			'<!-- wp:image {"id":%2$d} --><div class="wp-block-image"><figure class="wp-block-image"><img src="%1$s" alt="" class="wp-image-%2$d"/></figure></div><!-- /wp:image -->',
138
			$img_url,
139
			$attachment_id
140
		);
141
142
		$second_post_id = wp_insert_post(
143
			array(
144
				'post_content' => $post_html,
145
			)
146
		);
147
148
		return array(
149
			'post_id'  => $second_post_id,
150
			'img_url'  => $img_url,
151
			'alt_text' => $this->alt_text,
152
		);
153
	}
154
155
	/**
156
	 * Test if an array can be extracted from Image blocks, and includes the image URL and alt text.
157
	 *
158
	 * @covers \Automattic\Jetpack\Post_Images::from_blocks
159
	 * @since 6.9.0
160
	 */
161 View Code Duplication
	public function test_from_image_block_from_post_id_is_correct_array() {
162
		$post_info = $this->get_post_with_image_block();
163
164
		$images = Post_Images::from_blocks( $post_info['post_id'] );
165
166
		$this->assertCount( 1, $images );
167
		$this->assertEquals( $post_info['img_url'], $images[0]['src'] );
168
		$this->assertEquals( $post_info['alt_text'], $images[0]['alt_text'] );
169
	}
170
171
	/**
172
	 * Test if an image block with an externally hosted image is not extracted by Post Images.
173
	 *
174
	 * @covers \Automattic\Jetpack\Post_Images::from_blocks
175
	 * @since 6.9.0
176
	 */
177
	public function test_from_image_block_from_html_is_empty_array() {
178
		$html = '<!-- wp:image --><div class="wp-block-image"><figure class="wp-block-image"><img src="https://example.com/image.jpg" alt=""/></figure></div><!-- /wp:image -->';
179
180
		$images = Post_Images::from_blocks( $html );
181
182
		$this->assertEmpty( $images );
183
	}
184
185
	/**
186
	 * Create a post with a gallery block containing a few images attached to another post.
187
	 *
188
	 * @since 6.9.0
189
	 *
190
	 * @return array $post_info {
191
	 * An array of information about our post.
192
	 *  @type int   $post_id  Post ID.
193
	 *  @type array $img_urls Image URLs we'll look to extract.
194
	 * }
195
	 */
196
	protected function get_post_with_gallery_block() {
197
		$img_urls = array(
198
			'image.jpg'  => __DIR__ . '/wp-logo.jpg',
199
			'image2.jpg' => __DIR__ . '/wp-logo.jpg',
200
		);
201
202
		// Create post.
203
		$post_id = wp_insert_post(
204
			array(
205
				'post_title'   => 'hello',
206
				'post_content' => 'world',
207
				'post_status'  => 'publish',
208
			)
209
		);
210
		// Attach images.
211
		foreach ( $img_urls as $img_name => $img_url ) {
212
			$attachment_id = $this->create_upload_object( $img_url, array(), $post_id );
213
214
			// Update our array to store attachment IDs. We'll need them later.
215
			$img_urls[ $attachment_id ] = wp_get_attachment_url( $attachment_id );
216
			unset( $img_urls[ $img_name ] );
217
		}
218
219
		// Gallery markup.
220
		$gallery_html = sprintf(
221
			'<!-- wp:gallery {"ids":[%s]} --><ul class="wp-block-gallery columns-3 is-cropped">',
222
			implode( ',', array_keys( $img_urls ) )
223
		);
224
		foreach ( $img_urls as $img_id => $img_url ) {
225
			$gallery_html .= sprintf(
226
				'<li class="blocks-gallery-item"><figure><img src="%1$s" alt="" data-id="%2$d" class="wp-image-%2$d"/></figure></li>',
227
				'https://example.org' . $img_url,
228
				$img_id
229
			);
230
		}
231
		$gallery_html .= '</ul><!-- /wp:gallery -->';
232
233
		// Create another post with those pictures.
234
		$second_post_id = wp_insert_post(
235
			array(
236
				'post_content' => $gallery_html,
237
			)
238
		);
239
240
		return array(
241
			'post_id'  => $second_post_id,
242
			'img_urls' => array_values( $img_urls ),
243
		);
244
	}
245
246
	/**
247
	 * Test if the array extracted from Gallery blocks include the image URL.
248
	 *
249
	 * @covers \Automattic\Jetpack\Post_Images::from_blocks
250
	 * @since 6.9.0
251
	 */
252 View Code Duplication
	public function test_from_gallery_block_from_post_id_is_correct_array() {
253
		$post_info = $this->get_post_with_gallery_block();
254
255
		$images = Post_Images::from_blocks( $post_info['post_id'] );
256
257
		$this->assertEquals( $post_info['img_urls'][0], $images[0]['src'] );
258
		$this->assertEquals( $post_info['img_urls'][1], $images[1]['src'] );
259
	}
260
261
	/**
262
	 * Test if the array extracted from Gallery blocks include the image URL.
263
	 *
264
	 * @covers \Automattic\Jetpack\Post_Images::get_attachment_data
265
	 * @since 6.9.0
266
	 */
267
	public function test_get_attachment_data_returns_false_on_unavailable_data() {
268
		$this->assertFalse( Post_Images::get_attachment_data( PHP_INT_MAX, '', 200, 200 ) );
269
270
		$post = $this->get_post_with_image_block();
271
272
		// Testing the height condition.
273
		$this->assertFalse( Post_Images::get_attachment_data( $post['post_id'], '', 200, PHP_INT_MAX ) );
274
275
		// Testing the width condition.
276
		$this->assertFalse( Post_Images::get_attachment_data( $post['post_id'], '', PHP_INT_MAX, 200 ) );
277
	}
278
279
	/**
280
	 * Create a post with a columns block that includes an image block, and some text.
281
	 *
282
	 * @since 7.8.0
283
	 *
284
	 * @return array $post_info {
285
	 * An array of information about our post.
286
	 * @type int $post_id Post ID.
287
	 * @type string $img_url Image URL we'll look to extract.
288
	 * }
289
	 */
290
	protected function get_post_with_columns_block() {
291
		$post_id       = wp_insert_post( array() );
292
		$attachment_id = $this->create_upload_object( __DIR__ . '/wp-logo.jpg', array(), $post_id );
293
294
		$img_url = wp_get_attachment_url( $attachment_id );
295
296
		// Create another post with that picture.
297
		$post_html = sprintf(
298
			'<!-- wp:columns --><div class="wp-block-columns has-2-columns"><!-- wp:column --><div class="wp-block-column"><!-- wp:image {"id":%2$d} --><figure class="wp-block-image"><img src="%1$s" alt="" class="wp-image-%2$d"/></figure><!-- /wp:image --></div><!-- /wp:column --><!-- wp:column --><div class="wp-block-column"><!-- wp:paragraph --><p>Some text</p><!-- /wp:paragraph --></div><!-- /wp:column --></div><!-- /wp:columns -->',
299
			$img_url,
300
			$attachment_id
301
		);
302
303
		$second_post_id = wp_insert_post(
304
			array(
305
				'post_content' => $post_html,
306
			)
307
		);
308
309
		return array(
310
			'post_id'  => $second_post_id,
311
			'img_url'  => $img_url,
312
			'alt_text' => $this->alt_text,
313
		);
314
	}
315
316
	/**
317
	 * Test if an array of images can be extracted from column blocks in the new block editor.
318
	 *
319
	 * @covers \Automattic\Jetpack\Post_Images::from_blocks
320
	 *
321
	 * @since 7.8.0
322
	 */
323
	public function test_from_columns_block_from_post_id_is_array() {
324
		$post_info = $this->get_post_with_columns_block();
325
326
		$images = Post_Images::from_blocks( $post_info['post_id'] );
327
328
		$this->assertCount( 1, $images );
329
	}
330
331
	/**
332
	 * Test if the array extracted from Colunms blocks include the image URL and alt text.
333
	 *
334
	 * @covers \Automattic\Jetpack\Post_Images::from_blocks
335
	 *
336
	 * @since 7.8.0
337
	 */
338 View Code Duplication
	public function test_from_columns_block_from_post_id_is_correct_array() {
339
		$post_info = $this->get_post_with_columns_block();
340
341
		$images = Post_Images::from_blocks( $post_info['post_id'] );
342
343
		$this->assertEquals( $post_info['img_url'], $images[0]['src'] );
344
		$this->assertEquals( $post_info['alt_text'], $images[0]['alt_text'] );
345
	}
346
347
	/**
348
	 * Test if a Colunms block with an externally hosted image is not extracted by Post Images.
349
	 *
350
	 * @covers \Automattic\Jetpack\Post_Images::from_blocks
351
	 * @since 6.9.0
352
	 */
353
	public function test_from_columns_block_from_html_is_empty_array() {
354
		$html = '<!-- wp:columns --><div class="wp-block-columns has-2-columns"><!-- wp:column --><div class="wp-block-column"><!-- wp:image --><figure class="wp-block-image"><img src="https://example.com/image.jpg" alt=""/></figure><!-- /wp:image --></div><!-- /wp:column --><!-- wp:column --><div class="wp-block-column"><!-- wp:paragraph --><p>Some text</p><!-- /wp:paragraph --></div><!-- /wp:column --></div><!-- /wp:columns -->';
355
356
		$images = Post_Images::from_blocks( $html );
357
358
		$this->assertEmpty( $images );
359
	}
360
361
	/**
362
	 * Create a post with an image block containing a large image attached to another post.
363
	 *
364
	 * @since 9.1.0
365
	 *
366
	 * @param array $story_media A representative array of the media in the story. Each is one of 'image', 'video', or 'videopress'.
367
	 * @param bool  $wpcom_mode  If true, handles VideoPress videos the way WP.com does. Defaults to false.
368
	 * @return array $post_info {
369
	 * An array of information about our post.
370
	 *  @type int $post_id Post ID.
371
	 *  @type array $img_urls Image URLs we'll look to extract.
372
	 * }
373
	 */
374
	protected function get_post_with_story_block( $story_media, $wpcom_mode = false ) {
375
		$media_items = array();
376
		foreach ( $story_media as $story_media ) {
377
			if ( 'image' === $story_media ) {
378
				$media_items[] = array(
379
					'name'      => 'image.jpg',
380
					'mime_type' => 'image/jpeg',
381
					'type'      => 'image',
382
				);
383
			} elseif ( 'videopress' === $story_media ) {
384
				$media_items[] = array(
385
					'name'      => 'video.mp4',
386
					'mime_type' => 'video/videopress',
387
					'type'      => 'video',
388
				);
389
			} elseif ( 'video' === $story_media ) {
390
				$media_items[] = array(
391
					'name'      => 'video.mp4',
392
					'mime_type' => 'video/mp4',
393
					'type'      => 'video',
394
				);
395
			}
396
		}
397
		$img_args = array(
398
			'width'  => 1080,
399
			'height' => 1920,
400
		);
401
		$post_id  = wp_insert_post( array() );
402
403
		foreach ( $media_items as $key => $media ) {
404
			$img_args['mime_type'] = $media['mime_type'];
405
			$attachment_id         = $this->create_upload_object( __DIR__ . '/wp-logo.jpg', $img_args, $post_id );
406
407
			if ( 'video/videopress' === $media['mime_type'] ) {
408
				if ( $wpcom_mode ) {
409
					$videopress_meta = array(
410
						'thumb' => str_replace( 'mp4', 'jpg', wp_basename( wp_get_attachment_url( $attachment_id ) ) ),
411
					);
412
				} else {
413
					$videopress_meta = array(
414
						'videopress' => array(
415
							'poster' => str_replace( 'mp4', 'jpg', wp_get_attachment_url( $attachment_id ) ),
416
							'width'  => $img_args['width'],
417
							'height' => $img_args['height'],
418
						),
419
					);
420
				}
421
422
				wp_update_attachment_metadata( $attachment_id, array_merge( $img_args, $videopress_meta ) ); // careful here, before instead of img_args we were using just image dimensions.
423
			}
424
425
			// Update our array to store attachment IDs. We'll need them later.
426
			$media['attachment_id'] = $attachment_id;
427
			$media['url']           = wp_get_attachment_url( $attachment_id );
428
			unset( $media['name'] );
429
			$media_items[ $key ] = $media;
430
		}
431
432
		$story_html = '<!-- wp:jetpack/story {"mediaFiles":[';
433
		foreach ( $media_items as $media_item ) {
434
			$story_html .= sprintf(
435
				'{"alt":"","id":%1$d,"type":"%2$s","mime":"%3$s","caption":"","width":%4$d,"height":%5$d,"url":"%6$s"},',
436
				$media_item['attachment_id'],
437
				$media_item['type'],
438
				$media_item['mime_type'],
439
				$media_item['url'],
440
				$img_args['width'],
441
				$img_args['height']
442
			);
443
		}
444
		$story_html  = rtrim( $story_html, ',' );
445
		$story_html .= ']} --><div class="wp-block-jetpack-story wp-story"></div><!-- /wp:jetpack/story -->';
446
447
		// Create another post with that story.
448
		$second_post_id = wp_insert_post( array( 'post_content' => $story_html ) );
449
450
		$image_urls = array_map(
451
			function ( $element ) {
452
				return $element['url'];
453
			},
454
			$media_items
455
		);
456
457
		return array(
458
			'post_id'  => $second_post_id,
459
			'img_urls' => $image_urls,
460
		);
461
	}
462
463
	/**
464
	 * Test if the array extracted from a Story block includes the correct image URLs.
465
	 *
466
	 * @covers \Automattic\Jetpack\Post_Images::from_blocks
467
	 * @since 9.1.0
468
	 */
469
	public function test_from_story_block_from_post_id_is_correct_array_no_videopress() {
470
		$media_types = array( 'image', 'video' );
471
		$post_info   = $this->get_post_with_story_block( $media_types );
472
473
		$images = Post_Images::from_blocks( $post_info['post_id'] );
474
475
		// We can't get a preview image for non-VideoPress video, so the video
476
		// should have been skipped and only the image extracted.
477
		$this->assertCount( 1, $images );
478
479
		$this->assertEquals( $post_info['img_urls'][0], $images[0]['src'] );
480
	}
481
482
	/**
483
	 * Test if the array extracted from a Story block includes the correct image URLs.
484
	 *
485
	 * For this test we simulate VideoPress being enabled for the site.
486
	 *
487
	 * @covers \Automattic\Jetpack\Post_Images::from_blocks
488
	 * @since 9.1.0
489
	 */
490 View Code Duplication
	public function test_from_story_block_from_post_id_is_correct_array_videopress() {
491
		$media_types = array( 'image', 'videopress' );
492
		$post_info   = $this->get_post_with_story_block( $media_types );
493
494
		$images = Post_Images::from_blocks( $post_info['post_id'] );
495
496
		$this->assertCount( 2, $images );
497
498
		$this->assertEquals( $post_info['img_urls'][0], $images[0]['src'] );
499
500
		// The second media is a VideoPress video, so expect a poster URL.
501
		$expected_poster_url = str_replace( 'mp4', 'jpg', $post_info['img_urls'][1] );
502
		$this->assertEquals( $expected_poster_url, $images[1]['src'] );
503
	}
504
505
	/**
506
	 * Test if the array extracted from a Story block includes the correct image URLs.
507
	 *
508
	 * For this test we simulate 'WP.com mode' for VideoPress, which has a different structure for attachment meta.
509
	 *
510
	 * @covers \Automattic\Jetpack\Post_Images::from_blocks
511
	 * @since 9.1.0
512
	 */
513 View Code Duplication
	public function test_from_story_block_from_post_id_is_correct_array_videopress_wpcom() {
514
		$media_types = array( 'image', 'videopress' );
515
		$post_info   = $this->get_post_with_story_block( $media_types, true );
516
517
		$images = Post_Images::from_blocks( $post_info['post_id'] );
518
519
		$this->assertCount( 2, $images );
520
521
		$this->assertEquals( $post_info['img_urls'][0], $images[0]['src'] );
522
523
		// The second media is a VideoPress video, so expect a poster URL.
524
		$expected_poster_url = str_replace( 'mp4', 'jpg', $post_info['img_urls'][1] );
525
		$this->assertEquals( $expected_poster_url, $images[1]['src'] );
526
	}
527
528
	/**
529
	 * Create a media attachment.
530
	 *
531
	 * @param string $file     File path.
532
	 * @param array  $img_args Array of extra info about image.
533
	 * @param int    $parent   Parent post ID.
534
	 *
535
	 * @return int Attachment ID.
536
	 */
537
	public function create_upload_object( $file, $img_args, $parent = 0 ) {
538
		$contents       = file_get_contents( $file ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
539
		$upload         = wp_upload_bits( basename( $file ), null, $contents );
540
		$img_dimensions = array(
541
			'width'  => ! empty( $img_args['width'] ) ? $img_args['width'] : 250,
542
			'height' => ! empty( $img_args['height'] ) ? $img_args['height'] : 250,
543
		);
544
545
		$type = '';
546 View Code Duplication
		if ( ! empty( $upload['type'] ) ) {
547
			$type = $upload['type'];
548
		} else {
549
			$mime = wp_check_filetype( $upload['file'], null );
550
			if ( $mime ) {
551
				$type = $mime['type'];
552
			}
553
		}
554
555
		$attachment = array(
556
			'post_title'     => basename( $upload['file'] ),
557
			'post_content'   => '',
558
			'post_type'      => 'attachment',
559
			'post_parent'    => $parent,
560
			'post_mime_type' => ! empty( $img_args['mime_type'] ) ? $img_args['mime_type'] : $type,
561
			'guid'           => 'https://example.org' . $upload['url'],
562
		);
563
564
		// Save the data.
565
566
		$id = wp_insert_attachment( $attachment, $upload['file'], $parent );
567
568
		// Update general metadata.
569
		wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $upload['file'] ) );
570
571
		// Update dimensions.
572
		wp_update_attachment_metadata( $id, $img_dimensions );
573
574
		// Update alt text.
575
		update_post_meta( $id, '_wp_attachment_image_alt', $this->alt_text );
576
577
		return $id;
578
	}
579
}
580