Completed
Push — add/amp-pwa-experiment ( efea12 )
by
unknown
11:53
created

AMP_Iframe_Sanitizer   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 128
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 0
loc 128
rs 10
c 0
b 0
f 0
wmc 25
lcom 1
cbo 2

4 Methods

Rating   Name   Duplication   Size   Complexity  
A get_scripts() 0 7 2
C sanitize() 0 50 7
C filter_attributes() 0 46 15
A build_placeholder() 0 8 1
1
<?php
2
3
require_once( AMP__ROOT__ . '/includes/sanitizers/class-amp-base-sanitizer.php' );
4
5
/**
6
 * Converts <iframe> tags to <amp-iframe>
7
 */
8
class AMP_Iframe_Sanitizer extends AMP_Base_Sanitizer {
9
	const FALLBACK_HEIGHT = 400;
10
	const SANDBOX_DEFAULTS = 'allow-scripts allow-same-origin';
11
12
	public static $tag = 'iframe';
13
14
	private static $script_slug = 'amp-iframe';
15
	private static $script_src = 'https://cdn.ampproject.org/v0/amp-iframe-0.1.js';
16
17
	protected $DEFAULT_ARGS = array(
18
		'add_placeholder' => false,
19
	);
20
21
	public function get_scripts() {
22
		if ( ! $this->did_convert_elements ) {
23
			return array();
24
		}
25
26
		return array( self::$script_slug => self::$script_src );
27
	}
28
29
	public function sanitize() {
30
		$nodes = $this->dom->getElementsByTagName( self::$tag );
31
		$num_nodes = $nodes->length;
32
		if ( 0 === $num_nodes ) {
33
			return;
34
		}
35
36
		for ( $i = $num_nodes - 1; $i >= 0; $i-- ) {
37
			$node = $nodes->item( $i );
38
			$old_attributes = AMP_DOM_Utils::get_node_attributes_as_assoc_array( $node );
39
40
			$new_attributes = $this->filter_attributes( $old_attributes );
41
42
			// If the src doesn't exist, remove the node.
43
			// This means that it never existed or was invalidated
44
			// while filtering attributes above.
45
			//
46
			// TODO: add a filter to allow for a fallback element in this instance.
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
47
			// See: https://github.com/ampproject/amphtml/issues/2261
48
			if ( empty( $new_attributes['src'] ) ) {
49
				$node->parentNode->removeChild( $node );
50
				continue;
51
			}
52
53
			$this->did_convert_elements = true;
54
55
			$new_attributes = $this->enforce_fixed_height( $new_attributes );
56
			$new_attributes = $this->enforce_sizes_attribute( $new_attributes );
57
58
			$new_node = AMP_DOM_Utils::create_node( $this->dom, 'amp-iframe', $new_attributes );
59
60
			if ( true === $this->args['add_placeholder'] ) {
61
				$placeholder_node = $this->build_placeholder( $new_attributes );
62
				$new_node->appendChild( $placeholder_node );
63
			}
64
65
			$parent_node = $node->parentNode;
66
			if ( 'p' === strtolower( $parent_node->tagName ) ) {
67
				// AMP does not like iframes in p tags
68
				$parent_node->removeChild( $node );
69
				$parent_node->parentNode->insertBefore( $new_node, $parent_node->nextSibling );
70
71
				if ( AMP_DOM_Utils::is_node_empty( $parent_node ) ) {
72
					$parent_node->parentNode->removeChild( $parent_node );
73
				}
74
			} else {
75
				$parent_node->replaceChild( $new_node, $node );
76
			}
77
		}
78
	}
79
80
	private function filter_attributes( $attributes ) {
81
		$out = array();
82
83
		foreach ( $attributes as $name => $value ) {
84
			switch ( $name ) {
85
				case 'sandbox':
86
				case 'class':
87
				case 'sizes':
88
					$out[ $name ] = $value;
89
					break;
90
91
				case 'src':
92
					$out[ $name ] = $this->maybe_enforce_https_src( $value, true );
93
					break;
94
95
				case 'width':
96
				case 'height':
97
					$out[ $name ] = $this->sanitize_dimension( $value, $name );
98
					break;
99
100
101
				case 'frameborder':
102
					if ( '0' !== $value && '1' !== $value ) {
103
						$value = '0';
104
					}
105
					$out[ $name ] = $value;
106
					break;
107
108
				case 'allowfullscreen':
109
				case 'allowtransparency':
110
					if ( 'false' !== $value ) {
111
						$out[ $name ] = '';
112
					}
113
					break;
114
115
				default;
0 ignored issues
show
Coding Style introduced by
DEFAULT statements must be defined using a colon

As per the PSR-2 coding standard, default statements should not be wrapped in curly braces.

switch ($expr) {
    default: { //wrong
        doSomething();
        break;
    }
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
116
					break;
117
			}
118
		}
119
120
		if ( ! isset( $out[ 'sandbox' ] ) ) {
121
			$out[ 'sandbox' ] = self::SANDBOX_DEFAULTS;
122
		}
123
124
		return $out;
125
	}
126
127
	private function build_placeholder( $parent_attributes ) {
128
		$placeholder_node = AMP_DOM_Utils::create_node( $this->dom, 'div', array(
129
			'placeholder' => '',
130
			'class' => 'amp-wp-iframe-placeholder',
131
		) );
132
133
		return $placeholder_node;
134
	}
135
}
136