Completed
Push — add/jetpack-lazy-images-packag... ( 355d5e )
by
unknown
10:08
created

WP_Test_Lazy_Images   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 550
Duplicated Lines 7.27 %

Coupling/Cohesion

Components 0
Dependencies 1

Importance

Changes 0
Metric Value
dl 40
loc 550
rs 9.92
c 0
b 0
f 0
wmc 31
lcom 0
cbo 1

26 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 5 1
A get_process_image_test_data() 0 46 1
B get_process_image_attributes_data() 0 78 1
A test_process_image_attribute_filter() 0 15 1
A test_wp_get_attachment_image_gets_lazy_treatment() 0 12 1
A test_wp_get_attachment_image_does_not_get_lazy_treatment_when_skip_lazy_added() 0 19 1
A test_process_image() 0 5 1
A test_add_image_placeholders() 0 3 1
A test_process_image_attributes() 0 3 1
A test_compat_with_wp_kses_post() 0 34 2
A test_dont_process_images_with_classes() 10 10 2
A get_dont_process_images_with_classes_data() 0 14 1
A test_dont_process_images_with_skip_lazy_data_attribute() 10 10 2
A get_dont_process_images_with_skip_lazy_data_attribute_data() 0 13 1
A test_should_skip_image_with_blocked_class() 0 3 1
A get_should_skip_image_with_blocked_class_data() 0 16 1
A test_should_skip_image_with_filtered_empty_blocklist() 0 12 2
A get_should_skip_image_with_filtered_empty_blocked_data() 0 13 1
A test_jetpack_lazy_images_skip_image_with_attributes_filter() 0 15 1
A get_skip_image_with_attributes_data() 0 10 1
A override_image_placeholder() 0 3 1
A set_height_attribute() 0 7 2
A get_input_content() 10 10 1
A get_output_content() 10 10 1
A skip_if_srcset() 0 3 1
A add_skip_lazy_class_to_attributes() 0 4 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
3
require dirname( __FILE__ ) . '/../../src/lazy-images.php';
4
5
use Automattic\Jetpack\Jetpack_Lazy_Images;
6
7
/**
8
 * Class WP_Test_Lazy_Images
9
 */
10
class WP_Test_Lazy_Images extends WP_UnitTestCase {
11
12
	/**
13
	 * Setup.
14
	 */
15
	public function setUp() {
16
		parent::setUp();
17
18
		add_filter( 'lazyload_images_placeholder_image', array( $this, 'override_image_placeholder' ) );
19
	}
20
21
	/**
22
	 * Data provider for test.
23
	 *
24
	 * @return array
25
	 */
26
	public function get_process_image_test_data() {
27
		return array(
28
			'img_with_no_src'           => array(
29
				array(
30
					'<img id="img" />',
31
					'img',
32
					' id="img"',
33
				),
34
				'<img id="img" />',
35
			),
36
			'img_simple'                => array(
37
				array(
38
					'<img src="image.jpg" />',
39
					'img',
40
					' src="image.jpg"',
41
				),
42
				'<img src="image.jpg" data-lazy-src="http://image.jpg?is-pending-load=1" srcset="placeholder.jpg" class=" jetpack-lazy-image"><noscript><img src="image.jpg" /></noscript>',
43
			),
44
			'img_with_other_attributes' => array(
45
				array(
46
					'<img src="image.jpg" alt="Alt!" />',
47
					'img',
48
					' src="image.jpg" alt="Alt!"',
49
				),
50
				'<img src="image.jpg" alt="Alt!" data-lazy-src="http://image.jpg?is-pending-load=1" srcset="placeholder.jpg" class=" jetpack-lazy-image"><noscript><img src="image.jpg" alt="Alt!" /></noscript>',
51
			),
52
			'img_with_srcset'           => array(
53
				array(
54
					'<img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" />',
55
					'img',
56
					' src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w"',
57
58
				),
59
				'<img src="image.jpg" data-lazy-srcset="medium.jpg 1000w, large.jpg 2000w" data-lazy-src="http://image.jpg?is-pending-load=1" srcset="placeholder.jpg" class=" jetpack-lazy-image"><noscript><img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" /></noscript>',
60
			),
61
			'img_with_sizes'            => array(
62
				array(
63
					'<img src="image.jpg" sizes="(min-width: 36em) 33.3vw, 100vw" />',
64
					'img',
65
					' src="image.jpg" sizes="(min-width: 36em) 33.3vw, 100vw"',
66
67
				),
68
				'<img src="image.jpg" data-lazy-sizes="(min-width: 36em) 33.3vw, 100vw" data-lazy-src="http://image.jpg?is-pending-load=1" srcset="placeholder.jpg" class=" jetpack-lazy-image"><noscript><img src="image.jpg" sizes="(min-width: 36em) 33.3vw, 100vw" /></noscript>',
69
			),
70
		);
71
	}
72
73
	/**
74
	 * Data provider for test.
75
	 *
76
	 * @return array
77
	 */
78
	public function get_process_image_attributes_data() {
79
		return array(
80
			'img_with_no_src'              => array(
81
				array(
82
					'width'  => 10,
83
					'height' => 10,
84
				),
85
				array(
86
					'width'  => 10,
87
					'height' => 10,
88
				),
89
			),
90
			'img_simple'                   => array(
91
				array(
92
					'src'    => 'image.jpg',
93
					'width'  => 10,
94
					'height' => 10,
95
				),
96
				array(
97
					'src'           => 'image.jpg',
98
					'width'         => 10,
99
					'height'        => 10,
100
					'data-lazy-src' => 'http://image.jpg?is-pending-load=1',
101
					'srcset'        => 'placeholder.jpg',
102
					'class'         => ' jetpack-lazy-image',
103
				),
104
			),
105
			'img_with_srcset'              => array(
106
				array(
107
					'src'    => 'image.jpg',
108
					'width'  => 10,
109
					'height' => 10,
110
					'srcset' => 'medium.jpg 1000w, large.jpg 2000w',
111
				),
112
				array(
113
					'src'              => 'image.jpg',
114
					'width'            => 10,
115
					'height'           => 10,
116
					'data-lazy-srcset' => 'medium.jpg 1000w, large.jpg 2000w',
117
					'data-lazy-src'    => 'http://image.jpg?is-pending-load=1',
118
					'srcset'           => 'placeholder.jpg',
119
					'class'            => ' jetpack-lazy-image',
120
				),
121
			),
122
			'img_with_sizes'               => array(
123
				array(
124
					'src'    => 'image.jpg',
125
					'width'  => 10,
126
					'height' => 10,
127
					'sizes'  => '(min-width: 36em) 33.3vw, 100vw',
128
				),
129
				array(
130
					'src'             => 'image.jpg',
131
					'width'           => 10,
132
					'height'          => 10,
133
					'data-lazy-sizes' => '(min-width: 36em) 33.3vw, 100vw',
134
					'data-lazy-src'   => 'http://image.jpg?is-pending-load=1',
135
					'srcset'          => 'placeholder.jpg',
136
					'class'           => ' jetpack-lazy-image',
137
				),
138
			),
139
			'gazette_theme_featured_image' => array(
140
				array(
141
					'src'    => 'image.jpg',
142
					'width'  => 10,
143
					'height' => 10,
144
					'class'  => 'attachment-gazette-featured-content-thumbnail wp-post-image',
145
				),
146
				// Should be unmodified.
147
				array(
148
					'src'    => 'image.jpg',
149
					'width'  => 10,
150
					'height' => 10,
151
					'class'  => 'attachment-gazette-featured-content-thumbnail wp-post-image',
152
				),
153
			),
154
		);
155
	}
156
157
	/**
158
	 * Test the process image attribute filter.
159
	 */
160
	public function test_process_image_attribute_filter() {
161
		add_filter( 'jetpack_lazy_images_new_attributes', array( $this, 'set_height_attribute' ) );
162
163
		$html = Jetpack_Lazy_Images::process_image(
164
			array(
165
				'<img src="image.jpg" height="100px" />',
166
				'img',
167
				' src="image.jpg" height="100px"',
168
			)
169
		);
170
171
		remove_filter( 'jetpack_lazy_images_new_attributes', array( $this, 'set_height_attribute' ) );
172
173
		$this->assertContains( 'style="height: 100px;"', $html );
174
	}
175
176
	/**
177
	 * Test that the wp_get_attachment_image function output gets the lazy treatment.
178
	 */
179
	public function test_wp_get_attachment_image_gets_lazy_treatment() {
180
		$attachment_id = $this->factory->attachment->create_upload_object( dirname( __FILE__ ) . '/jetpack-icon.jpg', 0 );
181
		add_filter( 'wp_get_attachment_image_attributes', array( '\Automattic\Jetpack\Jetpack_Lazy_Images', 'process_image_attributes' ), PHP_INT_MAX );
182
		$image = wp_get_attachment_image( $attachment_id );
183
		remove_filter( 'wp_get_attachment_image_attributes', array( 'Automattic\\Jetpack\\Jetpack_Lazy_Images', 'process_image_attributes' ), PHP_INT_MAX );
184
185
		$this->assertContains( 'srcset="placeholder.jpg"', $image );
186
		$this->assertContains(
187
			sprintf( 'data-lazy-srcset="%s"', wp_get_attachment_image_srcset( $attachment_id, 'thumbnail' ) ),
188
			$image
189
		);
190
	}
191
192
	/**
193
	 * Test that the wp_get_attachment_image function output does not get the lazy treatment when lazy images feature is skipped.
194
	 */
195
	public function test_wp_get_attachment_image_does_not_get_lazy_treatment_when_skip_lazy_added() {
196
		$attachment_id = $this->factory->attachment->create_upload_object( dirname( __FILE__ ) . '/jetpack-icon.jpg', 0 );
197
		$content       = sprintf( '[gallery ids="%d"]', $attachment_id );
198
		$instance      = Jetpack_Lazy_Images::instance();
199
200
		$instance->setup_filters();
201
		$gallery_output = do_shortcode( $content );
202
		$instance->remove_filters();
203
204
		$this->assertContains( 'srcset="placeholder.jpg"', $gallery_output );
205
206
		$instance->setup_filters();
207
		add_filter( 'wp_get_attachment_image_attributes', array( $this, 'add_skip_lazy_class_to_attributes' ) );
208
		$gallery_output = do_shortcode( $content );
209
		remove_filter( 'wp_get_attachment_image_attributes', array( $this, 'add_skip_lazy_class_to_attributes' ) );
210
		$instance->remove_filters();
211
212
		$this->assertNotContains( 'srcset="placeholder.jpg"', $gallery_output );
213
	}
214
215
	/**
216
	 * Test the process_image method.
217
	 *
218
	 * @param array  $image_parts   Image parts.
219
	 * @param string $expected_html Expected HTML.
220
	 *
221
	 * @dataProvider get_process_image_test_data
222
	 */
223
	public function test_process_image( $image_parts, $expected_html ) {
224
		$actual_html = Jetpack_Lazy_Images::process_image( $image_parts );
225
226
		$this->assertEquals( $expected_html, $actual_html );
227
	}
228
229
	/**
230
	 * Test the add_image_placeholders method.
231
	 */
232
	public function test_add_image_placeholders() {
233
		$this->assertSame( $this->get_output_content(), Jetpack_Lazy_Images::instance()->add_image_placeholders( $this->get_input_content() ) );
234
	}
235
236
	/**
237
	 * Test the process_image_attributes method.
238
	 *
239
	 * @param array $input           Input attributes.
240
	 * @param array $expected_output Expected output.
241
	 *
242
	 * @dataProvider get_process_image_attributes_data
243
	 */
244
	public function test_process_image_attributes( $input, $expected_output ) {
245
		$this->assertSame( Jetpack_Lazy_Images::process_image_attributes( $input ), $expected_output );
246
	}
247
248
	/**
249
	 * Test compatibility with the wp_kses_post function.
250
	 */
251
	public function test_compat_with_wp_kses_post() {
252
		global $wp_version;
253
		if ( version_compare( $wp_version, 5.0, '>=' ) ) {
254
			$this->markTestSkipped( 'WP 5.0 allow all data attributes' );
255
			return;
256
		}
257
		$instance = Jetpack_Lazy_Images::instance();
258
		remove_filter( 'wp_kses_allowed_html', array( $instance, 'allow_lazy_attributes' ) );
259
260
		$sample_image_srcset = '<img src="placeholder.jpg" data-lazy-src="image.jpg" data-lazy-srcset="medium.jpg 1000w, large.jpg 2000w">';
261
		$sample_img_sizes    = '<img src="placeholder.jpg" data-lazy-src="image.jpg" data-lazy-sizes="(min-width: 36em) 33.3vw, 100vw">';
262
263
		$allowed = wp_kses_allowed_html();
0 ignored issues
show
Unused Code introduced by
$allowed is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
264
265
		// First, test existence of issue if we don't filter.
266
		$no_lazy_srcset = wp_kses_post( $sample_image_srcset );
267
		$no_lazy_sizes  = wp_kses_post( $sample_img_sizes );
268
269
		$this->assertNotContains( 'data-lazy-src', $no_lazy_srcset );
270
		$this->assertNotContains( 'data-lazy-src', $no_lazy_sizes );
271
		$this->assertNotContains( 'data-lazy-srcset', $no_lazy_srcset );
272
		$this->assertNotContains( 'data-lazy-size', $no_lazy_sizes );
273
274
		add_filter( 'wp_kses_allowed_html', array( $instance, 'allow_lazy_attributes' ) );
275
276
		// Second, test that the issue is fixed when we filter.
277
		$with_lazy_srcset = wp_kses_post( $sample_image_srcset );
278
		$with_lazy_sizes  = wp_kses_post( $sample_img_sizes );
279
280
		$this->assertContains( 'data-lazy-src', $with_lazy_srcset );
281
		$this->assertContains( 'data-lazy-src', $with_lazy_sizes );
282
		$this->assertContains( 'data-lazy-srcset', $with_lazy_srcset );
283
		$this->assertContains( 'data-lazy-size', $with_lazy_sizes );
284
	}
285
286
	/**
287
	 * Test that images with classes are not processed.
288
	 *
289
	 * @param string $input       Input content.
290
	 * @param bool   $should_skip Whether or not it lazy images treatment should be skipped.
291
	 *
292
	 * @dataProvider get_dont_process_images_with_classes_data
293
	 */
294 View Code Duplication
	public function test_dont_process_images_with_classes( $input, $should_skip = true ) {
295
		$instance = Jetpack_Lazy_Images::instance();
296
		$output   = $instance->add_image_placeholders( $input );
297
298
		if ( $should_skip ) {
299
			$this->assertNotContains( 'srcset="placeholder.jpg"', $output );
300
		} else {
301
			$this->assertContains( 'srcset="placeholder.jpg"', $output );
302
		}
303
	}
304
305
	/**
306
	 * Data provider for test.
307
	 *
308
	 * @return array
309
	 */
310
	public function get_dont_process_images_with_classes_data() {
311
		return array(
312
			'skip_lazy'                    => array(
313
				'<img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" class="skip-lazy"/>',
314
			),
315
			'gazette_theme_featured_image' => array(
316
				'<img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" class="attachment-gazette-featured-content-thumbnail wp-post-image"/>',
317
			),
318
			'does_not-skip'                => array(
319
				'<img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" class="wp-post-image"/>',
320
				false,
321
			),
322
		);
323
	}
324
325
	/**
326
	 * Test that images with the skip lazy data attribute are skipped.
327
	 *
328
	 * @param string $input       Input content.
329
	 * @param bool   $should_skip Whether or not it lazy images treatment should be skipped.
330
	 *
331
	 * @dataProvider get_dont_process_images_with_skip_lazy_data_attribute_data
332
	 */
333 View Code Duplication
	public function test_dont_process_images_with_skip_lazy_data_attribute( $input, $should_skip = true ) {
334
		$instance = Jetpack_Lazy_Images::instance();
335
		$output   = $instance->add_image_placeholders( $input );
336
337
		if ( $should_skip ) {
338
			$this->assertNotContains( 'srcset="placeholder.jpg"', $output );
339
		} else {
340
			$this->assertContains( 'srcset="placeholder.jpg"', $output );
341
		}
342
	}
343
344
	/**
345
	 * Data provider for test.
346
	 *
347
	 * @return array
348
	 */
349
	public function get_dont_process_images_with_skip_lazy_data_attribute_data() {
350
		return array(
351
			'skip_lazy_attr_only' => array(
352
				'<img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" data-skip-lazy/>',
353
			),
354
			'skip-lazy-attr-true' => array(
355
				'<img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" data-skip-lazy="true"/>',
356
			),
357
			'skip-lazy-attr-1'    => array(
358
				'<img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" data-skip-lazy="1"/>',
359
			),
360
		);
361
	}
362
363
	/**
364
	 * Test that images with the blocked class should be skipped
365
	 *
366
	 * @param bool   $expected Expected result.
367
	 * @param string $input  A string of space-separated classes.
368
	 * @param bool   $empty_blocked_classes Empty block classes.
369
	 *
370
	 * @dataProvider get_should_skip_image_with_blocked_class_data
371
	 */
372
	public function test_should_skip_image_with_blocked_class( $expected, $input, $empty_blocked_classes = false ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
373
		$this->assertSame( $expected, Jetpack_Lazy_Images::should_skip_image_with_blocked_class( $input ) );
374
	}
375
376
	/**
377
	 * Data provider for test.
378
	 *
379
	 * @return array
380
	 */
381
	public function get_should_skip_image_with_blocked_class_data() {
382
		return array(
383
			'wp-post-image'   => array(
384
				false,
385
				'wp-post-image',
386
			),
387
			'skip-lazy'       => array(
388
				true,
389
				'wp-post-image skip-lazy',
390
			),
391
			'gazette-feature' => array(
392
				true,
393
				'wp-post-image attachment-gazette-featured-content-thumbnail',
394
			),
395
		);
396
	}
397
398
	/**
399
	 * Test that images with filtered empty blocklist should be skipped.
400
	 *
401
	 * @param string $classes A string of space-separated classes. TODO: Check type.
402
	 *
403
	 * @dataProvider get_should_skip_image_with_filtered_empty_blocked_data
404
	 */
405
	public function test_should_skip_image_with_filtered_empty_blocklist( $classes ) {
406
		$filter_callbacks = array(
407
			'__return_empty_string',
408
			'__return_empty_array',
409
		);
410
411
		foreach ( $filter_callbacks as $callback ) {
412
			add_filter( 'jetpack_lazy_images_blocked_classes', $callback );
413
			$this->assertSame( false, Jetpack_Lazy_Images::should_skip_image_with_blocked_class( $classes ) );
414
			remove_filter( 'jetpack_lazy_images_blocked_classes', $callback );
415
		}
416
	}
417
418
	/**
419
	 * Data provider for test.
420
	 *
421
	 * @return array
422
	 */
423
	public function get_should_skip_image_with_filtered_empty_blocked_data() {
424
		return array(
425
			'wp-post-image'   => array(
426
				'wp-post-image',
427
			),
428
			'skip-lazy'       => array(
429
				'wp-post-image skip-lazy',
430
			),
431
			'gazette-feature' => array(
432
				'wp-post-image attachment-gazette-featured-content-thumbnail',
433
			),
434
		);
435
	}
436
437
	/**
438
	 * Test that Jetpack lazy images skip image with attributes filter.
439
	 *
440
	 * @param string $filter_name filter name.
441
	 *
442
	 * @dataProvider get_skip_image_with_attributes_data
443
	 */
444
	public function test_jetpack_lazy_images_skip_image_with_attributes_filter( $filter_name ) {
445
		$instance = Jetpack_Lazy_Images::instance();
446
		$src      = '<img src="image.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" class="wp-post-image"/>';
447
448
		$this->assertContains( 'srcset="placeholder.jpg"', $instance->add_image_placeholders( $src ) );
449
450
		add_filter( 'jetpack_lazy_images_skip_image_with_attributes', '__return_true' );
451
		$this->assertNotContains( 'srcset="placeholder.jpg"', $instance->add_image_placeholders( $src ) );
452
		remove_filter( 'jetpack_lazy_images_skip_image_with_attributes', '__return_true' );
453
454
		add_filter( 'jetpack_lazy_images_skip_image_with_attributes', array( $this, 'skip_if_srcset' ), 10, 2 );
455
		$this->assertNotContains( 'srcset="placeholder.jpg"', $instance->add_image_placeholders( $src ) );
456
		$this->assertContains( 'srcset="placeholder.jpg"', $instance->add_image_placeholders( '<img src="image.jpg" />' ) );
457
		remove_filter( 'jetpack_lazy_images_skip_image_with_attributes', array( $this, 'skip_if_srcset' ), 10, 2 );
458
	}
459
460
	/**
461
	 * Data provider for test.
462
	 *
463
	 * @return array
464
	 */
465
	public function get_skip_image_with_attributes_data() {
466
		return array(
467
			'deprecated_filter_name_with_typo' => array(
468
				'jetpack_lazy_images_skip_image_with_atttributes',
469
			),
470
			'correct_filter_name'              => array(
471
				'jetpack_lazy_images_skip_image_with_attributes',
472
			),
473
		);
474
	}
475
476
	/*
477
	 * Helpers
478
	 */
479
480
	/**
481
	 * Override image placeholder.
482
	 *
483
	 * @return string
484
	 */
485
	public function override_image_placeholder() {
486
		return 'placeholder.jpg';
487
	}
488
489
	/**
490
	 * Set height attribute.
491
	 *
492
	 * @param array $attributes Attributes.
493
	 *
494
	 * @return array
495
	 */
496
	public function set_height_attribute( $attributes ) {
497
		if ( ! empty( $attributes['height'] ) ) {
498
			$attributes['style'] = sprintf( 'height: %dpx;', $attributes['height'] );
499
			unset( $attributes['height'] );
500
		}
501
		return $attributes;
502
	}
503
504
	/**
505
	 * Get input content.
506
	 *
507
	 * @return string
508
	 */
509 View Code Duplication
	public function get_input_content() {
510
		ob_start();
511
512
		require_once dirname( __FILE__ ) . '/pre-image-placeholder-content.php';
513
514
		$contents = trim( ob_get_contents() );
515
		ob_end_clean();
516
517
		return trim( $contents );
518
	}
519
520
	/**
521
	 * Get output content.
522
	 *
523
	 * @return string
524
	 */
525 View Code Duplication
	public function get_output_content() {
526
		ob_start();
527
528
		require_once dirname( __FILE__ ) . '/post-image-placeholder-content.php';
529
530
		$contents = trim( ob_get_contents() );
531
		ob_end_clean();
532
533
		return trim( $contents );
534
	}
535
536
	/**
537
	 * Check is the srcset attribute it set.
538
	 *
539
	 * @param bool  $should_skip Whether or not it lazy images treatment should be skipped.
540
	 * @param array $attributes  Attributes.
541
	 *
542
	 * @return bool
543
	 */
544
	public function skip_if_srcset( $should_skip, $attributes ) {
545
		return isset( $attributes['srcset'] );
546
	}
547
548
	/**
549
	 * Add skip lazy class to attributes.
550
	 *
551
	 * @param array $attributes attributes.
552
	 *
553
	 * @return mixed
554
	 */
555
	public function add_skip_lazy_class_to_attributes( $attributes ) {
556
		$attributes['class'] .= ' skip-lazy';
557
		return $attributes;
558
	}
559
}
560