Completed
Push — update/tracking-assets ( 294fcb...ba0029 )
by
unknown
31:15 queued 15:24
created

WP_Test_Jetpack_Photon::tearDown()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 24
rs 9.536
c 0
b 0
f 0
1
<?php // phpcs:ignore WordPress.Files.FileName
2
/**
3
 * Tests for Jetpack's Photon class.
4
 *
5
 * @package Jetpack.
6
 */
7
8
// phpcs:disable WordPress.PHP.DevelopmentFunctions.error_log_print_r
9
10
/**
11
 * Class WP_Test_Jetpack_Photon
12
 */
13
class WP_Test_Jetpack_Photon extends Jetpack_Attachment_Test_Case {
14
	/**
15
	 * Test image.
16
	 *
17
	 * @var string
18
	 */
19
	protected static $test_image;
20
21
	/**
22
	 * Save the existing globals.
23
	 *
24
	 * @var array
25
	 */
26
	protected $protected_globals;
27
28
	/**
29
	 * ID for an author-level user created by this class.
30
	 *
31
	 * @var int
32
	 */
33
	protected static $author_id;
34
35
	/**
36
	 * Special setups.
37
	 *
38
	 * @param Object $factory Testing factory.
39
	 */
40
	public static function wpSetUpBeforeClass( $factory ) {
41
		self::$author_id = $factory->user->create(
42
			array(
43
				'role' => 'author',
44
			)
45
		);
46
	}
47
48
	/**
49
	 * Clean up the special sauce.
50
	 */
51
	public static function wpTearDownAfterClass() {
52
		self::delete_user( self::$author_id );
53
	}
54
55
	/**
56
	 * Sets up the test.
57
	 */
58
	public function setUp() {
59
		parent::setUp();
60
61
		// Preserving global variables.
62
		global $content_width;
63
		$this->protected_globals['content_width'] = $content_width;
64
65
		// Setup the Photon filters.
66
		// WP_UnitTestCase resets the action/filter state after every test:
67
		// https://core.trac.wordpress.org/browser/trunk/tests/phpunit/includes/testcase.php?rev=43005#L273
68
		// So we need to set these Photon filters for each test.
69
		// see ::tearDown() ...
70
		Jetpack_Photon::instance();
71
	}
72
73
	/**
74
	 * Clean up after the test.
75
	 */
76
	public function tearDown() {
77
		// Restoring global variables.
78
		global $content_width, $wp_the_query;
79
		$content_width = $this->protected_globals['content_width'];
80
		$wp_the_query  = new WP_Query(); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
81
82
		// ... see ::setUp()
83
		// Unfortunately Jetpack_Photon::instance() won't run Jetpack_Photon->setup()
84
		// each time Jetpack_Photon::instance() is called, since it's gated by a
85
		// static variable.
86
		// l337 h4X0Ring required:
87
		$instance = new ReflectionProperty( 'Jetpack_Photon', 'instance' );
88
		$instance->setAccessible( true );
89
		$instance->setValue( null );
90
91
		/**
92
		 * Reset the `image_sizes` property, as it persists between class instantiations, since it's static.
93
		 */
94
		$instance = new ReflectionProperty( 'Jetpack_Photon', 'image_sizes' );
95
		$instance->setAccessible( true );
96
		$instance->setValue( null );
97
98
		parent::tearDown();
99
	}
100
101
	/**
102
	 * Helper to get a query string part from the data returned by the filter_image_downsize method
103
	 *
104
	 * @author zinigor
105
	 * @since 3.8.2
106
	 * @param array $data an array of data returned by the filter.
107
	 * @return String $query_string
108
	 */
109
	protected function helper_get_query( $data ) {
110
		$fragments = explode( '?', $data[0], 2 );
111
		return $fragments[1];
112
	}
113
114
	/**
115
	 * Helper to get a new image object.
116
	 *
117
	 * @param string $size Test image size. Accepts 'large' (default) or 'medium'.
118
	 * @param bool   $meta Meta data to pass to _create_upload_object.
119
	 *
120
	 * @return int Post ID (attachment) of the image.
121
	 */
122
	protected function helper_get_image( $size = 'large', $meta = true ) {
123
		if ( 'large' === $size ) { // 1600x1200
124
			$filename = __DIR__ . '/modules/photon/sample-content/test-image-large.png';
125
		} elseif ( 'medium' === $size ) { // 1024x768
126
			$filename = __DIR__ . '/modules/photon/sample-content/test-image-medium.png';
127
		}
128
		// Add sizes that exist before uploading the file.
129
		add_image_size( 'jetpack_soft_defined', 700, 500, false ); // Intentionally not a 1.33333 ratio.
130
		add_image_size( 'jetpack_soft_undefined', 700, 99999, false );
131
		add_image_size( 'jetpack_soft_undefined_zero', 700, 0, false );
132
		add_image_size( 'jetpack_hard_defined', 700, 500, true );
133
		add_image_size( 'jetpack_hard_undefined', 700, 99999, true );
134
		add_image_size( 'jetpack_hard_undefined_zero', 700, 0, true );
135
		add_image_size( 'jetpack_soft_oversized', 2000, 2000, false );
136
137
		$test_image = self::_create_upload_object( $filename, 0, $meta );
0 ignored issues
show
Bug introduced by
The variable $filename does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
138
139
		// add sizes that did not exist when the file was uploaded.
140
		// These perfectly match the above and Photon should treat them the same.
141
		add_image_size( 'jetpack_soft_defined_after_upload', 700, 500, false ); // Intentionally not a 1.33333 ratio.
142
		add_image_size( 'jetpack_soft_undefined_after_upload', 700, 99999, false );
143
		add_image_size( 'jetpack_soft_undefined_zero_after_upload', 700, 0, false );
144
		add_image_size( 'jetpack_hard_defined_after_upload', 700, 500, true );
145
		add_image_size( 'jetpack_hard_undefined_after_upload', 700, 99999, true );
146
		add_image_size( 'jetpack_hard_undefined_zero_after_upload', 700, 0, true );
147
		add_image_size( 'jetpack_soft_oversized_after_upload', 2000, 2000, false );
148
149
		return $test_image;
150
	}
151
152
	/**
153
	 * Helper to remove image sizes added in helper_get_image().
154
	 */
155
	protected function helper_remove_image_sizes() {
156
		remove_image_size( 'jetpack_soft_defined' );
157
		remove_image_size( 'jetpack_soft_undefined' );
158
		remove_image_size( 'jetpack_soft_undefined_zero' );
159
		remove_image_size( 'jetpack_hard_defined' );
160
		remove_image_size( 'jetpack_hard_undefined' );
161
		remove_image_size( 'jetpack_hard_undefined_zero' );
162
		remove_image_size( 'jetpack_soft_defined_after_upload' );
163
		remove_image_size( 'jetpack_soft_undefined_after_upload' );
164
		remove_image_size( 'jetpack_soft_undefined_zero_after_upload' );
165
		remove_image_size( 'jetpack_hard_defined_after_upload' );
166
		remove_image_size( 'jetpack_hard_undefined_after_upload' );
167
		remove_image_size( 'jetpack_hard_undefined_zero_after_upload' );
168
		remove_image_size( 'jetpack_soft_oversized' );
169
		remove_image_size( 'jetpack_soft_oversized_after_upload' );
170
	}
171
172
	/**
173
	 * Tests that Photon creates a Photon instance.
174
	 *
175
	 * @author scotchfield
176
	 * @covers Jetpack_Photon::instance
177
	 * @since 3.2
178
	 */
179
	public function test_photon_instance() {
180
		$this->assertInstanceOf( 'Jetpack_Photon', Jetpack_Photon::instance() );
181
	}
182
183
	/**
184
	 * Tests that Photon creates a singleton.
185
	 *
186
	 * @author scotchfield
187
	 * @covers Jetpack_Photon::instance
188
	 * @since 3.2
189
	 */
190
	public function test_photon_instance_singleton() {
191
		$photon = Jetpack_Photon::instance();
192
193
		$this->assertEquals( $photon, Jetpack_Photon::instance() );
194
	}
195
196
	/**
197
	 * Tests Photon's HTML parsing when there is nothing to parse.
198
	 *
199
	 * @author scotchfield
200
	 * @covers Jetpack_Photon::parse_images_from_html
201
	 * @since 3.2
202
	 */
203
	public function test_photon_parse_images_from_html_empty() {
204
		$content = '';
205
206
		$this->assertEmpty( Jetpack_Photon::parse_images_from_html( $content ) );
207
	}
208
209
	/**
210
	 * Helper function to get sample content files.
211
	 *
212
	 * @author scotchfield
213
	 * @return array
214
	 * @since 3.2
215
	 *
216
	 * @param string $filename File name for sample content.
217
	 */
218
	private function get_photon_sample_content( $filename ) {
219
		$full_filename = __DIR__ . '/modules/photon/sample-content/' . $filename;
220
221
		// Local files only.
222
		$file_contents = file_get_contents( $full_filename ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
223
224
		return explode( "\n--RESULTS--\n", $file_contents, 2 );
225
	}
226
227
	/**
228
	 * Tests Photon's HTML parsing.
229
	 *
230
	 * @author scotchfield
231
	 * @covers Jetpack_Photon::parse_images_from_html
232
	 * @since 3.2
233
	 */
234
	public function test_photon_parse_images_from_html_a_tags_without_images() {
235
		list( $sample_html, $expected ) = $this->get_photon_sample_content( 'a-tags-without-images.html' );
236
237
		$this->assertEquals( $expected, print_r( Jetpack_Photon::parse_images_from_html( $sample_html ), true ) );
238
	}
239
240
	/**
241
	 * Tests Photon's HTML parsing.
242
	 *
243
	 * @author biskobe
244
	 * @covers Jetpack_Photon::filter_the_content
245
	 * @since 3.2
246
	 */
247
	public function test_photon_parse_images_from_html_a_tags_with_hash_in_href() {
248
		list( $sample_html, $expected ) = $this->get_photon_sample_content( 'a-tags-with-hash-href.html' );
249
250
		// Make sure we're not going to get any weird modifications due to auto-detected widths/heights and other props.
251
		$args_reset_callback = function () {
252
			return array();
253
		};
254
		add_filter( 'jetpack_photon_post_image_args', $args_reset_callback, 10, 0 );
255
256
		$this->assertEquals( trim( $expected ), trim( Jetpack_Photon::instance()->filter_the_content( $sample_html ) ) );
257
258
		remove_filter( 'jetpack_photon_post_image_args', $args_reset_callback );
259
	}
260
261
	/**
262
	 * Tests Photon's HTML parsing.
263
	 *
264
	 * @author scotchfield
265
	 * @covers Jetpack_Photon::parse_images_from_html
266
	 * @since 3.2
267
	 */
268
	public function test_photon_parse_images_from_html_empty_a_tag() {
269
		list( $sample_html, $expected ) = $this->get_photon_sample_content( 'empty-a-tag.html' );
270
271
		$this->assertEquals( $expected, print_r( Jetpack_Photon::parse_images_from_html( $sample_html ), true ) );
272
	}
273
274
	/**
275
	 * Tests Photon's HTML parsing.
276
	 *
277
	 * @author scotchfield
278
	 * @covers Jetpack_Photon::parse_images_from_html
279
	 * @since 3.2
280
	 */
281
	public function test_photon_parse_images_from_html_extra_attributes() {
282
		list( $sample_html, $expected ) = $this->get_photon_sample_content( 'extra-attributes.html' );
283
284
		$this->assertEquals( $expected, print_r( Jetpack_Photon::parse_images_from_html( $sample_html ), true ) );
285
	}
286
287
	/**
288
	 * Tests Photon's HTML parsing.
289
	 *
290
	 * @author scotchfield
291
	 * @covers Jetpack_Photon::parse_images_from_html
292
	 * @since 3.2
293
	 */
294
	public function test_photon_parse_images_from_html_minimum_multiple_with_links() {
295
		list( $sample_html, $expected ) = $this->get_photon_sample_content( 'minimum-multiple-with-links.html' );
296
297
		$this->assertEquals( $expected, print_r( Jetpack_Photon::parse_images_from_html( $sample_html ), true ) );
298
	}
299
300
	/**
301
	 * Tests Photon's HTML parsing.
302
	 *
303
	 * @author scotchfield
304
	 * @covers Jetpack_Photon::parse_images_from_html
305
	 * @since 3.2
306
	 */
307
	public function test_photon_parse_images_from_html_minimum_multiple() {
308
		list( $sample_html, $expected ) = $this->get_photon_sample_content( 'minimum-multiple.html' );
309
310
		$this->assertEquals( $expected, print_r( Jetpack_Photon::parse_images_from_html( $sample_html ), true ) );
311
	}
312
313
	/**
314
	 * Tests Photon's HTML parsing.
315
	 *
316
	 * @author scotchfield
317
	 * @covers Jetpack_Photon::parse_images_from_html
318
	 * @since 3.2
319
	 */
320
	public function test_photon_parse_images_from_html_minimum() {
321
		list( $sample_html, $expected ) = $this->get_photon_sample_content( 'minimum.html' );
322
323
		$this->assertEquals( $expected, print_r( Jetpack_Photon::parse_images_from_html( $sample_html ), true ) );
324
	}
325
326
	/**
327
	 * Tests that Photon will parse a multiline html snippet.
328
	 *
329
	 * @author scotchfield
330
	 * @covers Jetpack_Photon::parse_images_from_html
331
	 * @since 3.2
332
	 */
333
	public function test_photon_parse_images_from_html_multiline() {
334
		list( $sample_html, $expected ) = $this->get_photon_sample_content( 'multiline.html' );
335
336
		$this->assertEquals( $expected, print_r( Jetpack_Photon::parse_images_from_html( $sample_html ), true ) );
337
	}
338
339
	/**
340
	 * Tests Photon's parse of the src attribute.
341
	 *
342
	 * @author ccprog
343
	 * @covers Jetpack_Photon::parse_images_from_html
344
	 */
345
	public function test_photon_parse_images_from_html_src_attribute() {
346
		list( $sample_html, $expected ) = $this->get_photon_sample_content( 'src-attribute.html' );
347
348
		$this->assertEquals( $expected, print_r( Jetpack_Photon::parse_images_from_html( $sample_html ), true ) );
349
	}
350
351
	/**
352
	 * Tests Photon will parse the dimensions from a filename when there is no value.
353
	 *
354
	 * @author scotchfield
355
	 * @covers Jetpack_Photon::parse_dimensions_from_filename
356
	 * @since 3.2
357
	 */
358
	public function test_photon_parse_dimensions_from_filename_no_dimensions() {
359
		$image_url = 'http://' . WP_TESTS_DOMAIN . '/no-dimensions-here.jpg';
360
361
		$this->assertEquals( array( false, false ), Jetpack_Photon::parse_dimensions_from_filename( $image_url ) );
362
	}
363
364
	/**
365
	 * Tests Photon will parse the dimensions from a filename for an invalid value.
366
	 *
367
	 * @author scotchfield
368
	 * @covers Jetpack_Photon::parse_dimensions_from_filename
369
	 * @since 3.2
370
	 */
371
	public function test_photon_parse_dimensions_from_filename_no_dimensions_letter() {
372
		$image_url = 'http://' . WP_TESTS_DOMAIN . '/no-dimensions-here-2xM.jpg';
373
374
		$this->assertEquals( array( false, false ), Jetpack_Photon::parse_dimensions_from_filename( $image_url ) );
375
	}
376
377
	/**
378
	 * Tests Photon will parse the dimensions from a filename for an invalid value.
379
	 *
380
	 * @author scotchfield
381
	 * @covers Jetpack_Photon::parse_dimensions_from_filename
382
	 * @since 3.2
383
	 */
384
	public function test_photon_parse_dimensions_from_filename_invalid_dimensions() {
385
		$image_url = 'http://' . WP_TESTS_DOMAIN . '/no-dimensions-here-0x4.jpg';
386
387
		$this->assertEquals( array( false, false ), Jetpack_Photon::parse_dimensions_from_filename( $image_url ) );
388
	}
389
390
	/**
391
	 * Tests Photon will parse the dimensions from a filename for a small value.
392
	 *
393
	 * @author scotchfield
394
	 * @covers Jetpack_Photon::parse_dimensions_from_filename
395
	 * @since 3.2
396
	 */
397
	public function test_photon_parse_dimensions_from_filename_valid_dimensions() {
398
		$image_url = 'http://' . WP_TESTS_DOMAIN . '/no-dimensions-here-148x148.jpg';
399
400
		$this->assertEquals( array( 148, 148 ), Jetpack_Photon::parse_dimensions_from_filename( $image_url ) );
401
	}
402
403
	/**
404
	 * Tests Photon will parse the dimensions from a filename for a large value.
405
	 *
406
	 * @author scotchfield
407
	 * @covers Jetpack_Photon::parse_dimensions_from_filename
408
	 * @since 3.2
409
	 */
410
	public function test_photon_parse_dimensions_from_filename_valid_large_dimensions() {
411
		$image_url = 'http://' . WP_TESTS_DOMAIN . '/no-dimensions-here-123456789x123456789.jpg';
412
413
		$this->assertEquals( array( 123456789, 123456789 ), Jetpack_Photon::parse_dimensions_from_filename( $image_url ) );
414
	}
415
416
	/**
417
	 * Tests Photon image_downsize filter will return accurate size for a full-size image.
418
	 *
419
	 * @author kraftbj
420
	 * @covers Jetpack_Photon::filter_image_downsize
421
	 * @since 3.8.2
422
	 */
423
	public function test_photon_return_full_size_dimensions() {
424
		$test_image = $this->helper_get_image();
425
426
		// Should be the same as the original image. No crop.
427
		$this->assertEquals(
428
			'fit=1600%2C1200',
429
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'full' ) )
430
		);
431
432
		wp_delete_attachment( $test_image );
433
		$this->helper_remove_image_sizes();
434
	}
435
436
	/**
437
	 * Tests Photon image_downsize filter will return accurate size for a known size.
438
	 *
439
	 * @author kraftbj
440
	 * @covers Jetpack_Photon::filter_image_downsize
441
	 * @since 3.8.2
442
	 */
443
	public function test_photon_return_large_size_dimensions() {
444
		global $content_width;
445
		$content_width = 0;
446
447
		$test_image = $this->helper_get_image();
448
449
		// Using the default "Large" size with a soft crop.
450
		$this->assertEquals(
451
			'fit=1024%2C768',
452
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'large' ) )
453
		);
454
455
		wp_delete_attachment( $test_image );
456
		$this->helper_remove_image_sizes();
457
	}
458
459
	/**
460
	 * Tests Photon image_downsize filter will return accurate size for a known size.
461
	 *
462
	 * @author emilyatmobtown
463
	 * @covers Jetpack_Photon::filter_image_downsize
464
	 */
465
	public function test_photon_return_medium_large_size_dimensions() {
466
		global $content_width;
467
		$content_width = 0;
468
469
		$test_image = $this->helper_get_image();
470
471
		// Using the default "Large" size with a soft crop.
472
		$this->assertEquals(
473
			'fit=768%2C576',
474
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'medium_large' ) )
475
		);
476
477
		wp_delete_attachment( $test_image );
478
		$this->helper_remove_image_sizes();
479
	}
480
481
	/**
482
	 * Tests Photon image_downsize filter will return accurate size for a known size.
483
	 *
484
	 * @author kraftbj
485
	 * @covers Jetpack_Photon::filter_image_downsize
486
	 * @since 3.8.2
487
	 */
488
	public function test_photon_return_jetpack_soft_defined_size_dimensions() {
489
		global $content_width;
490
		$content_width = 0;
491
492
		$test_image = $this->helper_get_image();
493
494
		// Using a custom size, declared before the file was uploaded (thus exists per WP), soft crop defined height and width.
495
		$this->assertEquals(
496
			'fit=667%2C500',
497
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_soft_defined' ) )
498
		);
499
500
		wp_delete_attachment( $test_image );
501
		$this->helper_remove_image_sizes();
502
	}
503
504
	/**
505
	 * Tests Photon image_downsize filter will return accurate size for a known size.
506
	 *
507
	 * @author kraftbj
508
	 * @covers Jetpack_Photon::filter_image_downsize
509
	 * @since 3.8.2
510
	 */
511
	public function test_photon_return_jetpack_soft_undefined_size_dimensions() {
512
		global $content_width;
513
		$content_width = 0;
514
515
		$test_image = $this->helper_get_image();
516
517
		// Using a custom size, declared before the file was uploaded (thus exists per WP), soft crop defined 700 width, any height.
518
		$this->assertEquals(
519
			'fit=700%2C525',
520
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_soft_undefined' ) )
521
		);
522
523
		wp_delete_attachment( $test_image );
524
		$this->helper_remove_image_sizes();
525
	}
526
527
	/**
528
	 * Tests Photon image_downsize filter will return accurate size for an known size.
529
	 *
530
	 * @author kraftbj
531
	 * @covers Jetpack_Photon::filter_image_downsize
532
	 * @since 3.8.2
533
	 */
534
	public function test_photon_return_jetpack_soft_undefined_zero_size_dimensions() {
535
		global $content_width;
536
		$content_width = 0;
537
538
		$test_image = $this->helper_get_image();
539
540
		// Using a custom size, declared before the file was uploaded (thus exists per WP), soft crop defined 700 width, any height.
541
		$this->assertEquals(
542
			'fit=700%2C525',
543
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_soft_undefined_zero' ) )
544
		);
545
546
		wp_delete_attachment( $test_image );
547
		$this->helper_remove_image_sizes();
548
	}
549
550
	/**
551
	 * Tests Photon image_downsize filter will return accurate size for a known size.
552
	 *
553
	 * @author kraftbj
554
	 * @covers Jetpack_Photon::filter_image_downsize
555
	 * @since 3.8.2
556
	 */
557
	public function test_photon_return_jetpack_hard_defined_size_dimensions() {
558
		global $content_width;
559
		$content_width = 0;
560
561
		$test_image = $this->helper_get_image();
562
563
		// Using a custom size, declared before the file was uploaded (thus exists per WP), hard crop defined height and width.
564
		$this->assertEquals(
565
			'resize=700%2C500',
566
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_hard_defined' ) )
567
		);
568
569
		wp_delete_attachment( $test_image );
570
		$this->helper_remove_image_sizes();
571
	}
572
573
	/**
574
	 * Tests Photon image_downsize filter will return accurate size for an unknown-when-uploading size.
575
	 *
576
	 * @author kraftbj
577
	 * @covers Jetpack_Photon::filter_image_downsize
578
	 * @since 3.8.2
579
	 */
580
	public function test_photon_return_jetpack_hard_undefined_size_dimensions() {
581
		global $content_width;
582
		$content_width = 0;
583
584
		$test_image = $this->helper_get_image();
585
586
		// Using a custom size, declared before the file was uploaded (thus exists per WP), hard crop defined 700 width.
587
		$this->assertEquals(
588
			'resize=700%2C1200',
589
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_hard_undefined' ) )
590
		);
591
592
		wp_delete_attachment( $test_image );
593
		$this->helper_remove_image_sizes();
594
	}
595
596
	/**
597
	 * Tests Photon image_downsize filter will return accurate size for a known size.
598
	 *
599
	 * @author kraftbj
600
	 * @covers Jetpack_Photon::filter_image_downsize
601
	 * @since 3.8.2
602
	 */
603
	public function test_photon_return_jetpack_hard_undefined_zero_size_dimensions() {
604
		global $content_width;
605
		$content_width = 0;
606
607
		$test_image = $this->helper_get_image();
608
609
		// Using a custom size, declared before the file was uploaded (thus exists per WP), hard crop defined 700 width, any height.
610
		$this->assertEquals(
611
			'resize=700%2C525',
612
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_hard_undefined_zero' ) )
613
		);
614
615
		wp_delete_attachment( $test_image );
616
		$this->helper_remove_image_sizes();
617
	}
618
619
	/**
620
	 * Tests Photon image_downsize filter will return accurate size for an unknown-when-uploading size.
621
	 *
622
	 * @author kraftbj
623
	 * @covers Jetpack_Photon::filter_image_downsize
624
	 * @since 3.8.2
625
	 */
626
	public function test_photon_return_jetpack_soft_defined_after_upload_size_dimensions() {
627
		global $content_width;
628
		$content_width = 0;
629
630
		$test_image = $this->helper_get_image();
631
632
		// Using a custom size, declared after the file was uploaded (thus unknown per WP,
633
		// relying solely on Photon), soft crop defined height and width.
634
		$this->assertEquals(
635
			'fit=667%2C500',
636
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_soft_defined_after_upload' ) )
637
		);
638
639
		wp_delete_attachment( $test_image );
640
		$this->helper_remove_image_sizes();
641
	}
642
643
	/**
644
	 * Tests Photon image_downsize filter will return accurate size for an unknown-when-uploading size.
645
	 *
646
	 * @author kraftbj
647
	 * @covers Jetpack_Photon::filter_image_downsize
648
	 * @since 3.8.2
649
	 */
650
	public function test_photon_return_jetpack_soft_undefined_after_upload_size_dimensions() {
651
		global $content_width;
652
		$content_width = 0;
653
654
		$test_image = $this->helper_get_image();
655
656
		// Using a custom size, declared after the file was uploaded (thus unknown per WP,
657
		// relying solely on Photon), soft crop defined 700 width, any height.
658
		$this->assertEquals(
659
			'fit=700%2C525',
660
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_soft_undefined_after_upload' ) )
661
		);
662
663
		wp_delete_attachment( $test_image );
664
		$this->helper_remove_image_sizes();
665
	}
666
667
	/**
668
	 * Tests Photon image_downsize filter will return accurate size for an unknown-when-uploading size.
669
	 *
670
	 * @author kraftbj
671
	 * @covers Jetpack_Photon::filter_image_downsize
672
	 * @since 3.8.2
673
	 */
674
	public function test_photon_return_jetpack_soft_undefined_zero_after_upload_size_dimensions() {
675
		global $content_width;
676
		$content_width = 0;
677
678
		$test_image = $this->helper_get_image();
679
680
		// Using a custom size, declared after the file was uploaded (thus unknown per WP,
681
		// relying solely on Photon), soft crop defined 700 width, any height.
682
		$this->assertEquals(
683
			'fit=700%2C525',
684
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_soft_undefined_zero_after_upload' ) )
685
		);
686
687
		wp_delete_attachment( $test_image );
688
		$this->helper_remove_image_sizes();
689
	}
690
691
	/**
692
	 * Tests Photon image_downsize filter will return accurate size for an unknown-when-uploading size.
693
	 *
694
	 * @author kraftbj
695
	 * @covers Jetpack_Photon::filter_image_downsize
696
	 * @since 3.8.2
697
	 */
698
	public function test_photon_return_jetpack_hard_defined_after_upload_size_dimensions() {
699
		global $content_width;
700
		$content_width = 0;
701
702
		$test_image = $this->helper_get_image();
703
704
		// Using a custom size, declared after the file was uploaded
705
		// (thus unknown per WP, relying solely on Photon), hard crop defined height and width.
706
		$this->assertEquals(
707
			'resize=700%2C500',
708
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_hard_defined_after_upload' ) )
709
		);
710
711
		wp_delete_attachment( $test_image );
712
		$this->helper_remove_image_sizes();
713
	}
714
715
	/**
716
	 * Tests Photon image_downsize filter will return accurate size for an unknown-when-uploading size.
717
	 *
718
	 * @author kraftbj
719
	 * @covers Jetpack_Photon::filter_image_downsize
720
	 * @since 3.8.2
721
	 */
722
	public function test_photon_return_jetpack_hard_undefined_after_upload_size_dimensions() {
723
		global $content_width;
724
		$content_width = 0;
725
726
		$test_image = $this->helper_get_image();
727
728
		// Using a custom size, declared after the file was uploaded
729
		// (thus unknown per WP, relying solely on Photon), hard crop defined 700 width.
730
		$this->assertEquals(
731
			'resize=700%2C1200',
732
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_hard_undefined_after_upload' ) )
733
		);
734
735
		wp_delete_attachment( $test_image );
736
		$this->helper_remove_image_sizes();
737
	}
738
739
	/**
740
	 * Tests Photon image_downsize filter will return accurate size for an unknown-when-uploading size.
741
	 *
742
	 * @author kraftbj
743
	 * @covers Jetpack_Photon::filter_image_downsize
744
	 * @since 3.8.2
745
	 */
746
	public function test_photon_return_jetpack_hard_undefined_zero_after_upload_size_dimensions() {
747
		global $content_width;
748
		$content_width = 0;
749
750
		$test_image = $this->helper_get_image();
751
752
		// Using a custom size, declared after the file was uploaded
753
		// (thus unknown per WP, relying solely on Photon), hard crop defined 700 width.
754
		$this->assertEquals(
755
			'resize=700%2C525',
756
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_hard_undefined_zero_after_upload' ) )
757
		);
758
759
		wp_delete_attachment( $test_image );
760
		$this->helper_remove_image_sizes();
761
	}
762
763
	/**
764
	 * Tests Photon image_downsize will return a custom-size image.
765
	 *
766
	 * @author kraftbj
767
	 * @covers Jetpack_Photon::filter_image_downsize
768
	 * @since 3.8.2
769
	 */
770
	public function test_photon_return_custom_size_array_dimensions() {
771
		global $content_width;
772
		$content_width = 0;
773
774
		$test_image = $this->helper_get_image();
775
776
		// Declaring the size array directly, unknown size of 400 by 400. Scaled, it should be 400 by 300.
777
		$this->assertEquals(
778
			'fit=400%2C300',
779
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, array( 400, 400 ) ) )
780
		);
781
782
		wp_delete_attachment( $test_image );
783
		$this->helper_remove_image_sizes();
784
	}
785
786
	/**
787
	 * Tests that Photon will not return an image larger than the original via image_downsize.
788
	 *
789
	 * @author kraftbj
790
	 * @covers Jetpack_Photon::filter_image_downsize
791
	 * @since 3.9.0
792
	 */
793 View Code Duplication
	public function test_photon_return_custom_size_array_dimensions_larger_than_original() {
794
		global $content_width;
795
		$content_width = 0;
796
797
		$test_image = $this->helper_get_image( 'medium' ); // Original 1024x768.
798
799
		// Declaring the size array directly, unknown size of 1200 by 1200. Should return original.
800
		$this->assertEquals(
801
			'fit=1024%2C768',
802
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, array( 1200, 1200 ) ) )
803
		);
804
805
		wp_delete_attachment( $test_image );
806
		$this->helper_remove_image_sizes();
807
	}
808
809
	/**
810
	 * Tests image_downsize filter for a defined size with no meta.
811
	 *
812
	 * @author dereksmart
813
	 * @covers Jetpack_Photon::filter_image_downsize
814
	 * @since 3.9.0
815
	 */
816
	public function test_photon_return_jetpack_soft_defined_size_dimensions_no_meta() {
817
		global $content_width;
818
		$content_width = 0;
819
820
		$test_image = $this->helper_get_image( 'large', false );
821
822
		// Using a custom size, declared before the file was uploaded (thus exists per WP), soft crop defined height and width.
823
		$this->assertEquals(
824
			'fit=700%2C500',
825
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_soft_defined' ) )
826
		);
827
828
		wp_delete_attachment( $test_image );
829
		$this->helper_remove_image_sizes();
830
	}
831
832
	/**
833
	 * Tests image_downsize filter for a soft crop for an existing oversized image size.
834
	 *
835
	 * @author kraftbj
836
	 * @covers Jetpack_Photon::filter_image_downsize
837
	 * @since 3.9.0
838
	 */
839
	public function test_photon_return_jetpack_soft_oversized() {
840
		global $content_width;
841
		$content_width = 0;
842
843
		$test_image = $this->helper_get_image();
844
845
		// Using a custom size, declared after the file was uploaded.
846
		// (thus unknown per WP, relying solely on Photon), hard crop defined 700 width.
847
		$this->assertEquals(
848
			'fit=1600%2C1200',
849
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_soft_oversized' ) )
850
		);
851
852
		wp_delete_attachment( $test_image );
853
		$this->helper_remove_image_sizes();
854
	}
855
856
	/**
857
	 * Tests image_downsize filter for a soft crop for an undefined size.
858
	 *
859
	 * @author dereksmart
860
	 * @covers Jetpack_Photon::filter_image_downsize
861
	 * @since 3.9.0
862
	 */
863
	public function test_photon_return_jetpack_soft_undefined_size_dimensions_no_meta() {
864
		global $content_width;
865
		$content_width = 0;
866
867
		$test_image = $this->helper_get_image( 'large', false );
868
869
		// Using a custom size, declared before the file was uploaded (thus exists per WP), soft crop defined 700 width, any height.
870
		$this->assertEquals(
871
			'fit=700%2C99999',
872
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_soft_undefined' ) )
873
		);
874
875
		wp_delete_attachment( $test_image );
876
		$this->helper_remove_image_sizes();
877
	}
878
879
	/**
880
	 * Tests image_downsize filter for a soft crop after upload.
881
	 *
882
	 * @author kraftbj
883
	 * @covers Jetpack_Photon::filter_image_downsize
884
	 * @since 3.9.0
885
	 */
886
	public function test_photon_return_jetpack_soft_oversized_after_upload() {
887
		global $content_width;
888
		$content_width = 0;
889
890
		$test_image = $this->helper_get_image();
891
892
		// Using a custom size, declared after the file was uploaded
893
		// (thus unknown per WP, relying solely on Photon), hard crop defined 700 width.
894
		$this->assertEquals(
895
			'fit=1600%2C1200',
896
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_soft_oversized_after_upload' ) )
897
		);
898
899
		wp_delete_attachment( $test_image );
900
		$this->helper_remove_image_sizes();
901
	}
902
903
	/**
904
	 * Tests Photon's image_downsize on a known image size.
905
	 *
906
	 * @author dereksmart
907
	 * @covers Jetpack_Photon::filter_image_downsize
908
	 * @since 3.9.0
909
	 */
910
	public function test_photon_return_jetpack_hard_defined_size_dimensions_no_meta() {
911
		global $content_width;
912
		$content_width = 0;
913
914
		$test_image = $this->helper_get_image( 'large', false );
915
916
		// Using a custom size, declared before the file was uploaded (thus exists per WP), hard crop defined height and width.
917
		$this->assertEquals(
918
			'resize=700%2C500',
919
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_hard_defined' ) )
920
		);
921
922
		wp_delete_attachment( $test_image );
923
		$this->helper_remove_image_sizes();
924
	}
925
926
	/**
927
	 * Tests Photon's image_downsize filter with an undefined size.
928
	 *
929
	 * @author dereksmart
930
	 * @covers Jetpack_Photon::filter_image_downsize
931
	 * @since 3.9.0
932
	 */
933
	public function test_photon_return_jetpack_hard_undefined_size_dimensions_no_meta() {
934
		global $content_width;
935
		$content_width = 0;
936
937
		$test_image = $this->helper_get_image( 'large', false );
938
939
		// Using a custom size, declared before the file was uploaded (thus exists per WP), hard crop defined 700 width.
940
		$this->assertEquals(
941
			'resize=700%2C99999',
942
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, 'jetpack_hard_undefined' ) )
943
		);
944
945
		wp_delete_attachment( $test_image );
946
		$this->helper_remove_image_sizes();
947
	}
948
949
	/**
950
	 * Tests image_downsize filter when there is no meta information available.
951
	 *
952
	 * @author dereksmart
953
	 * @covers Jetpack_Photon::filter_image_downsize
954
	 * @since 3.9.0
955
	 */
956 View Code Duplication
	public function test_photon_return_custom_size_array_dimensions_no_meta() {
957
		global $content_width;
958
		$content_width = 0;
959
960
		$test_image = $this->helper_get_image( 'large', false );
961
962
		// Declaring the size array directly, unknown size of 400 by 400. Scaled, it should be 400 by 300.
963
		$this->assertEquals(
964
			'fit=400%2C400',
965
			$this->helper_get_query( Jetpack_Photon::instance()->filter_image_downsize( false, $test_image, array( 400, 400 ) ) )
966
		);
967
968
		wp_delete_attachment( $test_image );
969
		$this->helper_remove_image_sizes();
970
	}
971
972
	/**
973
	 * Tests Photon's filtering of the_content when both height/width are known.
974
	 *
975
	 * @author ebinnion
976
	 * @covers Jetpack_Photon::filter_the_content
977
	 * @since 5.6.0
978
	 */
979
	public function test_photon_filter_the_content_does_not_remove_width_height_when_both_known() {
980
		list( $sample_html ) = $this->get_photon_sample_content( 'a-tags-without-images.html' );
981
		$filtered_content    = Jetpack_Photon::filter_the_content( $sample_html );
982
		$first_line          = strtok( $filtered_content, "\n" ); // Should contain an image tag on the first line.
983
		$attributes          = wp_kses_hair( $first_line, wp_allowed_protocols() );
984
985
		$this->assertArrayHasKey( 'width', $attributes );
986
		$this->assertArrayHasKey( 'height', $attributes );
987
988
		// These values obtained from first image in sample content.
989
		$this->assertEquals( 631, $attributes['width']['value'] );
990
		$this->assertEquals( 376, $attributes['height']['value'] );
991
	}
992
993
	/**
994
	 * Test Photon's filtering of the_content when either width/height is not known.
995
	 *
996
	 * @author ebinnion
997
	 * @covers Jetpack_Photon::filter_the_content
998
	 * @since 5.6.0
999
	 */
1000
	public function test_photon_filter_the_content_does_not_have_width_height_when_at_least_one_not_known() {
1001
		$sample_html      = '<img class="aligncenter  wp-image-6372" title="Tube Bomber salmon dry fly" alt="Tube Bomber salmon dry fly" src="http://www.fishmadman.com/pages/wp-content/uploads/2012/02/Rav-fra-2004-2009-11-1024x611.jpg" width="631" />';
1002
		$filtered_content = Jetpack_Photon::filter_the_content( $sample_html );
1003
		$attributes       = wp_kses_hair( $filtered_content, wp_allowed_protocols() );
1004
1005
		$this->assertArrayNotHasKey( 'width', $attributes );
1006
		$this->assertArrayNotHasKey( 'height', $attributes );
1007
		$this->assertContains( 'data-recalc-dims', $filtered_content );
1008
	}
1009
1010
	/**
1011
	 * Tests Photon's filtering of the_content with filtered args.
1012
	 *
1013
	 * @author ebinnion
1014
	 * @covers Jetpack_Photon::filter_the_content
1015
	 * @dataProvider photon_attributes_when_filtered_data_provider
1016
	 * @since 5.6.0
1017
	 *
1018
	 * @param callable $filter_callback Filter callback.
1019
	 * @param bool     $has_attributes If the attributes are filtered.
1020
	 * @param int      $width Image width in pixels.
1021
	 * @param int      $height Image height in pixels.
1022
	 */
1023
	public function test_photon_filter_the_content_width_height_attributes_when_image_args_filtered( $filter_callback, $has_attributes, $width, $height ) {
1024
		list( $sample_html ) = $this->get_photon_sample_content( 'a-tags-without-images.html' );
1025
1026
		add_filter( 'jetpack_photon_post_image_args', $filter_callback, 10, 2 );
1027
		$filtered_content = Jetpack_Photon::filter_the_content( $sample_html );
1028
		remove_filter( 'jetpack_photon_post_image_args', $filter_callback, 10, 2 );
0 ignored issues
show
Unused Code introduced by
The call to remove_filter() has too many arguments starting with 2.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1029
1030
		$first_line = strtok( $filtered_content, "\n" ); // Should contain an image tag on the first line.
1031
		$attributes = wp_kses_hair( $first_line, wp_allowed_protocols() );
1032
1033
		if ( $has_attributes ) {
1034
			$this->assertArrayHasKey( 'width', $attributes );
1035
			$this->assertArrayHasKey( 'height', $attributes );
1036
1037
			// These values obtained from first image in sample content.
1038
			$this->assertEquals( $width, $attributes['width']['value'] );
1039
			$this->assertEquals( $height, $attributes['height']['value'] );
1040
		} else {
1041
			$this->assertArrayNotHasKey( 'width', $attributes );
1042
			$this->assertArrayNotHasKey( 'height', $attributes );
1043
		}
1044
	}
1045
1046
	/**
1047
	 * Checks that Photon ignores data-width and data-height attributes when parsing the attributes.
1048
	 *
1049
	 * @author mmtr
1050
	 * @covers Jetpack_Photon::filter_the_content
1051
	 * @since 8.0.0
1052
	 */
1053 View Code Duplication
	public function test_photon_filter_the_content_ignores_data_width_and_data_height_attributes() {
1054
		$sample_html      = '<img src="http://example.com/test.png" class="test" data-width="100" data-height="200" />';
1055
		$filtered_content = Jetpack_Photon::filter_the_content( $sample_html );
1056
		$attributes       = wp_kses_hair( $filtered_content, wp_allowed_protocols() );
1057
		$query_str        = wp_parse_url( $attributes['src']['value'], PHP_URL_QUERY );
1058
		parse_str( $query_str, $query_params );
1059
1060
		$this->assertArrayNotHasKey( 'resize', $query_params );
1061
	}
1062
1063
	/**
1064
	 * Checks that Photon parses correctly the width and height attributes when they are not preceded by a space.
1065
	 *
1066
	 * @author mmtr
1067
	 * @covers Jetpack_Photon::filter_the_content
1068
	 * @since 8.0.0
1069
	 */
1070 View Code Duplication
	public function test_photon_filter_the_content_parses_width_height_when_no_spaces_between_attributes() {
1071
		$sample_html      = '<img src="http://example.com/test.png" class="test"width="100"height="200" />';
1072
		$filtered_content = Jetpack_Photon::filter_the_content( $sample_html );
1073
		$attributes       = wp_kses_hair( $filtered_content, wp_allowed_protocols() );
1074
		$query_str        = wp_parse_url( $attributes['src']['value'], PHP_URL_QUERY );
1075
		parse_str( $query_str, $query_params );
1076
1077
		$this->assertArrayHasKey( 'resize', $query_params );
1078
		$this->assertEquals( '100,200', $query_params['resize'] );
1079
	}
1080
1081
	/**
1082
	 * Data provider for filtered attributes.
1083
	 *
1084
	 * @return array[]
1085
	 */
1086
	public function photon_attributes_when_filtered_data_provider() {
1087
		$assert_details = function ( $details ) {
1088
			$this->assertInternalType( 'array', $details );
1089
			$this->assertArrayHasKey( 'tag', $details );
1090
			$this->assertArrayHasKey( 'src', $details );
1091
			$this->assertArrayHasKey( 'src_orig', $details );
1092
			$this->assertArrayHasKey( 'width', $details );
1093
			$this->assertArrayHasKey( 'width_orig', $details );
1094
			$this->assertArrayHasKey( 'height', $details );
1095
			$this->assertArrayHasKey( 'height_orig', $details );
1096
			$this->assertArrayHasKey( 'transform', $details );
1097
			$this->assertArrayHasKey( 'transform_orig', $details );
1098
		};
1099
1100
		return array(
1101
			'photon_post_image_args_force_resize'     => array(
1102
				function ( $args, $details ) use ( $assert_details ) {
1103
					$assert_details( $details );
1104
					return array(
1105
						'resize' => '300,250',
1106
					);
1107
				},
1108
				true,
1109
				300,
1110
				250,
1111
			),
1112
			'photon_post_image_args_force_fit'        => array(
1113
				function ( $args, $details ) use ( $assert_details ) {
1114
					$assert_details( $details );
1115
					return array(
1116
						'fit' => '600,600',
1117
					);
1118
				},
1119
				true,
1120
				600,
1121
				600,
1122
			),
1123
			'photon_post_image_args_force_lb'         => array(
1124
				function ( $args, $details ) use ( $assert_details ) {
1125
					$assert_details( $details );
1126
					return array(
1127
						'lb' => '800,100,000000',
1128
					);
1129
				},
1130
				true,
1131
				800,
1132
				100,
1133
			),
1134
			'photon_post_image_args_force_width_only' => array(
1135
				function ( $args, $details ) use ( $assert_details ) {
1136
					$assert_details( $details );
1137
					return array(
1138
						'w' => '104',
1139
					);
1140
				},
1141
				false,
1142
				false,
1143
				false,
1144
			),
1145
		);
1146
	}
1147
1148
	/**
1149
	 * Tests that Photon ignores percentage dimensions. It should fall back to e.g. a "size-foo" class.
1150
	 *
1151
	 * @covers Jetpack_Photon::filter_the_content
1152
	 */
1153
	public function test_photon_filter_the_content_percentage_width_and_height() {
1154
		$sample_html      = '<img src="http://example.com/test.png" class="test size-large" width="45%" height="55%" />';
1155
		$filtered_content = Jetpack_Photon::filter_the_content( $sample_html );
1156
		$attributes       = wp_kses_hair( $filtered_content, wp_allowed_protocols() );
1157
		$query_str        = wp_parse_url( $attributes['src']['value'], PHP_URL_QUERY );
1158
		parse_str( $query_str, $query_params );
1159
1160
		$this->assertArrayHasKey( 'width', $attributes );
1161
		$this->assertSame( '1024', $attributes['width']['value'] );
1162
		$this->assertArrayHasKey( 'height', $attributes );
1163
		$this->assertSame( '1024', $attributes['height']['value'] );
1164
1165
		$this->assertArrayHasKey( 'fit', $query_params );
1166
		$this->assertEquals( '1024,1024', $query_params['fit'] );
1167
	}
1168
1169
	/**
1170
	 * Tests that Photon will filter for an AMP response.
1171
	 *
1172
	 * @author westonruter
1173
	 * @covers Jetpack_Photon::filter_the_content
1174
	 * @dataProvider photon_attributes_when_amp_response
1175
	 * @since 7.6.0
1176
	 *
1177
	 * @param string $sample_html Sample HTML.
1178
	 * @param string $photon_src  Photon URL suffix (after the subdomain).
1179
	 */
1180
	public function test_photon_filter_the_content_for_amp_responses( $sample_html, $photon_src ) {
1181
		add_filter( 'jetpack_is_amp_request', '__return_true' );
1182
		$filtered_content = Jetpack_Photon::filter_the_content( $sample_html );
1183
		$attributes       = wp_kses_hair( $filtered_content, wp_allowed_protocols() );
1184
		$this->assertStringEndsWith( $photon_src, html_entity_decode( $attributes['src']['value'] ) );
1185
		$this->assertArrayHasKey( 'width', $attributes );
1186
		$this->assertArrayHasKey( 'height', $attributes );
1187
		$this->assertNotContains( 'data-recalc-dims', $filtered_content );
1188
	}
1189
1190
	/**
1191
	 * Data provider for testing AMP responses.
1192
	 *
1193
	 * @return array
1194
	 */
1195
	public function photon_attributes_when_amp_response() {
1196
		return array(
1197
			'amp-img'  => array(
1198
				'<amp-img class="aligncenter wp-image-6372" title="Tube Bomber salmon dry fly" alt="Tube Bomber salmon dry fly" src="http://www.fishmadman.com/pages/wp-content/uploads/2012/02/Rav-fra-2004-2009-11-1024x611.jpg" width="102" height="61"></amp-img>',
1199
				'.wp.com/www.fishmadman.com/pages/wp-content/uploads/2012/02/Rav-fra-2004-2009-11-1024x611.jpg?resize=102%2C61',
1200
			),
1201
			'amp-anim' => array(
1202
				'<amp-anim alt="LOL" src="https://example.com/lol.gif" width="32" height="32"></amp-anim>',
1203
				'.wp.com/example.com/lol.gif?resize=32%2C32&ssl=1',
1204
			),
1205
		);
1206
	}
1207
1208
	/**
1209
	 * Tests that Photon will filter for AMP stories.
1210
	 *
1211
	 * @author westonruter
1212
	 * @covers Jetpack_Photon::filter_the_content
1213
	 * @covers Jetpack_AMP_Support::filter_photon_post_image_args_for_stories
1214
	 * @since 7.6.0
1215
	 */
1216
	public function test_photon_filter_the_content_for_amp_story() {
1217
		$post_type = 'amp_story';
1218
		add_filter( 'jetpack_is_amp_request', '__return_true' );
1219
		register_post_type( $post_type, array( 'public' => true ) );
1220
		Jetpack_AMP_Support::init();
1221
		$post = $this->factory()->post->create_and_get( compact( 'post_type' ) );
1222
		$this->go_to( get_permalink( $post ) );
1223
		$this->assertTrue( is_singular( $post_type ) );
1224
1225
		$content = implode(
1226
			"\n",
1227
			array(
1228
				'<!-- wp:amp/amp-story-page {"mediaId":2414,"mediaType":"image","focalPoint":{"x":0.4900990099009901,"y":0.5131578947368421}} -->',
1229
				'<amp-story-page style="background-color:#ffffff" id="a6c81a13-14a0-464b-88fa-9612e86bacf7" class="wp-block-amp-amp-story-page"><amp-story-grid-layer template="fill"><amp-img layout="fill" src="https://example.com/wp-content/uploads/2019/06/huge.jpg" style="object-position:49.00990099009901% 51.31578947368421%"></amp-img></amp-story-grid-layer><amp-story-grid-layer template="fill"></amp-story-grid-layer></amp-story-page>',
1230
				'<!-- /wp:amp/amp-story-page -->',
1231
			)
1232
		);
1233
1234
		$filtered_content = apply_filters( 'the_content', $content, $post->ID );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $post->ID.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1235
1236
		$this->assertContains(
1237
			'.wp.com/example.com/wp-content/uploads/2019/06/huge.jpg?h=1280&#038;ssl=1',
1238
			$filtered_content
1239
		);
1240
1241
		unregister_post_type( $post_type );
1242
	}
1243
1244
	/**
1245
	 * Tests that Photon does filter the URLs on REST API media requests in the view context.
1246
	 *
1247
	 * @group rest-api
1248
	 */
1249
	public function test_photon_cdn_in_rest_response_with_view_context() {
1250
		$test_image = $this->helper_get_image();
1251
1252
		$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/media/%d', $test_image ) );
1253
		$request->set_query_params( array( 'context' => 'view' ) );
1254
		$response = rest_get_server()->dispatch( $request );
1255
		$data     = $response->get_data();
1256
1257
		$this->assertArrayHasKey( 'media_details', $data );
1258
		$this->assertArrayHasKey( 'sizes', $data['media_details'] );
1259
		$this->assertArrayHasKey( 'full', $data['media_details']['sizes'] );
1260
		$this->assertArrayHasKey( 'medium_large', $data['media_details']['sizes'] );
1261
		$this->assertArrayHasKey( 'source_url', $data['media_details']['sizes']['full'] );
1262
		$this->assertArrayHasKey( 'source_url', $data['media_details']['sizes']['medium_large'] );
1263
1264
		$this->assertContains( '?', $data['media_details']['sizes']['full']['source_url'] );
1265
		$this->assertContains( '?', $data['media_details']['sizes']['medium_large']['source_url'] );
1266
	}
1267
1268
	/**
1269
	 * Tests Photon does not filter the URL on REST API media requests in the edit context.
1270
	 *
1271
	 * @group rest-api
1272
	 */
1273
	public function test_photon_cdn_in_rest_response_with_edit_context() {
1274
		$test_image = $this->helper_get_image();
1275
1276
		$admin = $this->factory->user->create( array( 'role' => 'administrator' ) );
1277
		wp_set_current_user( $admin );
1278
1279
		$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/media/%d', $test_image ) );
1280
		$request->set_query_params( array( 'context' => 'edit' ) );
1281
		$response = rest_get_server()->dispatch( $request );
1282
		$data     = $response->get_data();
1283
1284
		$this->assertArrayHasKey( 'media_details', $data );
1285
		$this->assertArrayHasKey( 'sizes', $data['media_details'] );
1286
		$this->assertArrayHasKey( 'full', $data['media_details']['sizes'] );
1287
		$this->assertArrayHasKey( 'medium_large', $data['media_details']['sizes'] );
1288
		$this->assertArrayHasKey( 'source_url', $data['media_details']['sizes']['full'] );
1289
		$this->assertArrayHasKey( 'source_url', $data['media_details']['sizes']['medium_large'] );
1290
1291
		$this->assertNotContains( '?', $data['media_details']['sizes']['full']['source_url'] );
1292
		$this->assertNotContains( '?', $data['media_details']['sizes']['medium_large']['source_url'] );
1293
1294
		// Subsequent ?context=view requests should still be Photonized.
1295
		$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/media/%d', $test_image ) );
1296
		$request->set_query_params( array( 'context' => 'view' ) );
1297
		$response = rest_get_server()->dispatch( $request );
1298
		$data     = $response->get_data();
1299
1300
		$this->assertArrayHasKey( 'media_details', $data );
1301
		$this->assertArrayHasKey( 'sizes', $data['media_details'] );
1302
		$this->assertArrayHasKey( 'full', $data['media_details']['sizes'] );
1303
		$this->assertArrayHasKey( 'medium_large', $data['media_details']['sizes'] );
1304
		$this->assertArrayHasKey( 'source_url', $data['media_details']['sizes']['full'] );
1305
		$this->assertArrayHasKey( 'source_url', $data['media_details']['sizes']['medium_large'] );
1306
1307
		$this->assertContains( '?', $data['media_details']['sizes']['full']['source_url'] );
1308
		$this->assertContains( '?', $data['media_details']['sizes']['medium_large']['source_url'] );
1309
	}
1310
1311
	/**
1312
	 * Verifies that the REST API upload endpoint does not return with Photon URLs.
1313
	 *
1314
	 * The endpoint sets the context to edit, but not before the callback executes.
1315
1316
	 * @author kraftbj
1317
	 * @requires PHPUnit 7.5
1318
	 * @covers Jetpack_Photon::should_rest_photon_image_downsize_insert_attachment
1319
	 * @group rest-api
1320
	 */
1321
	public function test_photon_cdn_in_rest_response_with_created_item() {
1322
		$filename = __DIR__ . '/modules/photon/sample-content/test-image-large.png';
1323
1324
		wp_set_current_user( self::$author_id );
1325
1326
		$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
1327
		$request->set_header( 'Content-Type', 'image/jpeg' );
1328
		$request->set_header( 'Content-Disposition', 'attachment; filename=test-image-large.png' );
1329
1330
		$request->set_body( file_get_contents( $filename ) ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
1331
		// Make the REST API request.
1332
		$response = rest_get_server()->dispatch( $request );
1333
		// Pull the response from the API.
1334
		$data = $response->get_data();
1335
1336
		// This verifies the file has uploaded. Just a bit of defensive testing.
1337
		$this->assertEquals( 201, $response->get_status() );
1338
1339
		$large_url = isset( $data['media_details']['sizes']['large']['source_url'] ) ? $data['media_details']['sizes']['large']['source_url'] : false;
1340
1341
		if ( ! $large_url ) {
1342
			$this->fail( 'REST API media upload failed to return the expected data.' );
1343
		}
1344
1345
		$this->assertStringNotContainsString( 'wp.com', $large_url );
1346
	}
1347
1348
	/**
1349
	 * Verifies that the REST API external-media/copy endpoint does not return
1350
	 * Photonized URLs.
1351
	 *
1352
	 * @author ebinnion
1353
	 * @requires PHPUnit 7.5
1354
	 * @covers Jetpack_Photon::should_rest_photon_image_downsize_insert_attachment
1355
	 * @group rest-api
1356
	 */
1357
	public function test_photon_cdn_in_rest_response_external_media() {
1358
		wp_set_current_user( self::$author_id );
1359
1360
		$request = new WP_REST_Request( 'POST', '/wpcom/v2/external-media/copy/pexels' );
1361
		$request->set_header( 'Content-Type', 'application/json' );
1362
		$request->set_body( '{"media":[{"guid":"{\\"url\\":\\"https:\\\\\\/\\\\\\/images.pexels.com\\\\\\/photos\\\\\\/1693095\\\\\\/pexels-photo-1693095.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940\\",\\"name\\":\\"pexels-photo-1693095.jpeg\\",\\"title\\":\\"aurora lights\\",\\"caption\\":\\"Photo by Tobias Bj\\\\u00f8rkli on <a href=\\\\\\\\\\\\\\"https:\\\\\\/\\\\\\/www.pexels.com\\\\\\/photo\\\\\\/aurora-lights-1693095\\\\\\/\\\\\\\\\\\\\\" rel=\\\\\\\\\\\\\\"nofollow\\\\\\\\\\\\\\">Pexels.com<\\\\\\/a>\\"}","caption":"Photo by Tobias Bj\\u00f8rkli on <a href=\\"https:\\/\\/www.pexels.com\\/photo\\/aurora-lights-1693095\\/\\" rel=\\"nofollow\\">Pexels.com<\\/a>","title":"aurora lights"}]}' );
1363
1364
		add_filter( 'pre_http_request', array( $this, 'pre_http_request_mocked_download_url' ), 10, 2 );
1365
		$response = rest_get_server()->dispatch( $request );
1366
		remove_filter( 'pre_http_request', array( $this, 'pre_http_request_mocked_download_url' ), 10, 2 );
0 ignored issues
show
Unused Code introduced by
The call to remove_filter() has too many arguments starting with 2.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1367
1368
		$this->assertEquals( 200, $response->get_status() );
1369
1370
		$data = $response->get_data();
1371
1372
		$this->assertNotEmpty( $data );
1373
		$this->assertInternalType( 'array', $data[0] );
1374
		$this->assertArrayHasKey( 'url', $data[0] );
1375
		$this->assertStringNotContainsString( 'wp.com', $data[0]['url'] );
1376
	}
1377
1378
	/**
1379
	 * This function copies a file to an expected location and then returns a successful request to support mocking download_url().
1380
	 *
1381
	 * @param mixed $pre  By default, this is false. We can set it to any truthy value to pre-empty the request.
1382
	 * @param array $args An array of arguments for the request.
1383
	 * @return array
1384
	 */
1385
	public function pre_http_request_mocked_download_url( $pre, $args ) {
1386
		if ( empty( $args['filename'] ) ) {
1387
			return $pre;
1388
		}
1389
1390
		$filename = $args['filename'];
1391
1392
		// Delete the original file.
1393
		unlink( $filename );
1394
1395
		// Copy our test image over where the file is expected.
1396
		copy( __DIR__ . '/modules/photon/sample-content/test-image-large.png', $filename );
1397
1398
		// This is just a mocked response with a 200 code.
1399
		return array(
1400
			'headers'       => array(),
1401
			'body'          => '',
1402
			'response'      => array(
1403
				'code'    => 200,
1404
				'message' => '',
1405
			),
1406
			'cookies'       => array(),
1407
			'http_response' => null,
1408
		);
1409
	}
1410
1411
	/**
1412
	 * Tests that Photon will not strip the dimensions from an external URL.
1413
	 *
1414
	 * @covers Jetpack_Photon::strip_image_dimensions_maybe
1415
	 */
1416
	public function test_photon_strip_image_dimensions_maybe_ignores_external_files() {
1417
		$ext_domain = 'https://some.domain/wp-content/uploads/2019/1/test-image-300x300.jpg';
1418
1419
		$this->assertEquals( $ext_domain, Jetpack_Photon::strip_image_dimensions_maybe( $ext_domain ) );
1420
	}
1421
1422
	/**
1423
	 * Tests Photon stripping the image dimensions from filename.
1424
	 *
1425
	 * @covers Jetpack_Photon::strip_image_dimensions_maybe
1426
	 */
1427
	public function test_photon_strip_image_dimensions_maybe_strips_resized_string() {
1428
		$orig_filename = '2004-07-22-DSC_0007.jpg';
1429
		$filename      = '2004-07-22-DSC_0007-150x150.jpg';
1430
		$filepath      = DIR_TESTDATA . '/images/' . $orig_filename;
1431
		// Local file. Okay to file_get_contents.
1432
		$contents = file_get_contents( $filepath ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
1433
1434
		$upload = wp_upload_bits( basename( $filepath ), null, $contents );
1435
1436
		$upload_dir = wp_get_upload_dir();
1437
1438
		$id  = $this->_make_attachment( $upload );
1439
		$url = $upload_dir['url'] . '/' . $filename;
1440
1441
		$expected = wp_get_attachment_url( $id );
1442
1443
		$this->assertEquals( $expected, Jetpack_Photon::strip_image_dimensions_maybe( $url ) );
1444
1445
		wp_delete_attachment( $id );
1446
	}
1447
}
1448
1449
// phpcs:enable
1450