1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
abstract class AMP_Base_Sanitizer { |
4
|
|
|
const FALLBACK_HEIGHT = 400; |
5
|
|
|
|
6
|
|
|
protected $DEFAULT_ARGS = array(); |
7
|
|
|
|
8
|
|
|
protected $dom; |
9
|
|
|
protected $args; |
10
|
|
|
protected $did_convert_elements = false; |
11
|
|
|
|
12
|
|
|
public function __construct( $dom, $args = array() ) { |
13
|
|
|
$this->dom = $dom; |
14
|
|
|
$this->args = array_merge( $this->DEFAULT_ARGS, $args ); |
15
|
|
|
} |
16
|
|
|
|
17
|
|
|
abstract public function sanitize(); |
18
|
|
|
|
19
|
|
|
public function get_scripts() { |
20
|
|
|
return array(); |
21
|
|
|
} |
22
|
|
|
|
23
|
|
|
public function get_styles() { |
24
|
|
|
return array(); |
25
|
|
|
} |
26
|
|
|
|
27
|
|
|
protected function get_body_node() { |
28
|
|
|
return $this->dom->getElementsByTagName( 'body' )->item( 0 ); |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
public function sanitize_dimension( $value, $dimension ) { |
32
|
|
|
if ( empty( $value ) ) { |
33
|
|
|
return $value; |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
if ( false !== filter_var( $value, FILTER_VALIDATE_INT ) ) { |
37
|
|
|
return absint( $value ); |
38
|
|
|
} |
39
|
|
|
|
40
|
|
|
if ( AMP_String_Utils::endswith( $value, 'px' ) ) { |
41
|
|
|
return absint( $value ); |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
if ( AMP_String_Utils::endswith( $value, '%' ) ) { |
45
|
|
|
if ( 'width' === $dimension && isset( $this->args[ 'content_max_width'] ) ) { |
46
|
|
|
$percentage = absint( $value ) / 100; |
47
|
|
|
return round( $percentage * $this->args[ 'content_max_width'] ); |
48
|
|
|
} |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
return ''; |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
public function enforce_fixed_height( $attributes ) { |
55
|
|
|
if ( empty( $attributes['height'] ) ) { |
56
|
|
|
unset( $attributes['width'] ); |
57
|
|
|
$attributes['height'] = self::FALLBACK_HEIGHT; |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
if ( empty( $attributes['width'] ) ) { |
61
|
|
|
$attributes['layout'] = 'fixed-height'; |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
return $attributes; |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* This is our workaround to enforce max sizing with layout=responsive. |
69
|
|
|
* |
70
|
|
|
* We want elements to not grow beyond their width and shrink to fill the screen on viewports smaller than their width. |
71
|
|
|
* |
72
|
|
|
* See https://github.com/ampproject/amphtml/issues/1280#issuecomment-171533526 |
73
|
|
|
* See https://github.com/Automattic/amp-wp/issues/101 |
74
|
|
|
*/ |
75
|
|
|
public function enforce_sizes_attribute( $attributes ) { |
76
|
|
|
if ( ! isset( $attributes['width'], $attributes['height'] ) ) { |
77
|
|
|
return $attributes; |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
$max_width = $attributes['width']; |
81
|
|
|
if ( isset( $this->args['content_max_width'] ) && $max_width >= $this->args['content_max_width'] ) { |
82
|
|
|
$max_width = $this->args['content_max_width']; |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
$attributes['sizes'] = sprintf( '(min-width: %1$dpx) %1$dpx, 100vw', absint( $max_width ) ); |
86
|
|
|
|
87
|
|
|
$this->add_or_append_attribute( $attributes, 'class', 'amp-wp-enforced-sizes' ); |
88
|
|
|
|
89
|
|
|
return $attributes; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
public function add_or_append_attribute( &$attributes, $key, $value, $separator = ' ' ) { |
93
|
|
|
if ( isset( $attributes[ $key ] ) ) { |
94
|
|
|
$attributes[ $key ] .= $separator . $value; |
95
|
|
|
} else { |
96
|
|
|
$attributes[ $key ] = $value; |
97
|
|
|
} |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Decide if we should remove a src attribute if https is required. |
102
|
|
|
* If not required, the implementing class may want to try and force https instead. |
103
|
|
|
* |
104
|
|
|
* @param string $src |
105
|
|
|
* @param boolean $force_https |
106
|
|
|
* @return string |
107
|
|
|
*/ |
108
|
|
|
public function maybe_enforce_https_src( $src, $force_https = false ) { |
109
|
|
|
$protocol = strtok( $src, ':' ); |
110
|
|
|
if ( 'https' !== $protocol ) { |
111
|
|
|
// Check if https is required |
112
|
|
|
if ( isset( $this->args['require_https_src'] ) && true === $this->args['require_https_src'] ) { |
113
|
|
|
// Remove the src. Let the implementing class decide what do from here. |
114
|
|
|
$src = ''; |
115
|
|
|
} elseif ( ( ! isset( $this->args['require_https_src'] ) || false === $this->args['require_https_src'] ) |
116
|
|
|
&& true === $force_https ) { |
117
|
|
|
// Don't remove the src, but force https instead |
118
|
|
|
$src = set_url_scheme( $src, 'https' ); |
119
|
|
|
} |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
return $src; |
123
|
|
|
} |
124
|
|
|
} |
125
|
|
|
|