public function test__is_node_empty__no__has_child() { $source = '<p><b></b></p>'; $dom = AMP_DOM_Utils::get_dom_from_content($source); $node = $dom->getElementsByTagName('p')->item(0); $this->assertFalse(AMP_DOM_Utils::is_node_empty($node)); }
public function sanitize() { $nodes = $this->dom->getElementsByTagName(self::$tag); $num_nodes = $nodes->length; if (0 === $num_nodes) { return; } for ($i = $num_nodes - 1; $i >= 0; $i--) { $node = $nodes->item($i); $old_attributes = AMP_DOM_Utils::get_node_attributes_as_assoc_array($node); $new_attributes = $this->filter_attributes($old_attributes); if (!isset($new_attributes['width'], $new_attributes['height'])) { $new_attributes['height'] = self::FALLBACK_HEIGHT; $new_attributes['layout'] = 'fixed-height'; } $new_attributes = $this->enforce_sizes_attribute($new_attributes); $new_node = AMP_DOM_Utils::create_node($this->dom, 'amp-video', $new_attributes); // TODO: limit child nodes too (only allowed: `source`; move rest to div+fallback) // TODO: `source` does not have closing tag, and DOMDocument doesn't handle it well. foreach ($node->childNodes as $child_node) { $new_child_node = $child_node->cloneNode(true); $new_node->appendChild($new_child_node); } $node->parentNode->replaceChild($new_node, $node); } }
public function sanitize($amp_attributes = array()) { $nodes = $this->dom->getElementsByTagName(self::$tag); $num_nodes = $nodes->length; if (0 === $num_nodes) { return; } for ($i = $num_nodes - 1; $i >= 0; $i--) { $node = $nodes->item($i); $old_attributes = AMP_DOM_Utils::get_node_attributes_as_assoc_array($node); if (!array_key_exists('src', $old_attributes)) { $node->parentNode->removeChild($node); continue; } $new_attributes = $this->filter_attributes($old_attributes); if (!isset($new_attributes['width']) || !isset($new_attributes['height'])) { $dimensions = AMP_Image_Dimension_Extractor::extract($new_attributes['src']); if ($dimensions) { $new_attributes['width'] = $dimensions[0]; $new_attributes['height'] = $dimensions[1]; } } $new_attributes = $this->enforce_sizes_attribute($new_attributes); $new_attributes = array_merge($new_attributes, $amp_attributes); if ($this->is_gif_url($new_attributes['src'])) { $this->did_convert_elements = true; $new_tag = 'amp-anim'; } else { $new_tag = 'amp-img'; } $new_node = AMP_DOM_Utils::create_node($this->dom, $new_tag, $new_attributes); $node->parentNode->replaceChild($new_node, $node); } }
public function sanitize() { $nodes = $this->dom->getElementsByTagName(self::$tag); $num_nodes = $nodes->length; if (0 === $num_nodes) { return; } for ($i = $num_nodes - 1; $i >= 0; $i--) { $node = $nodes->item($i); $old_attributes = AMP_DOM_Utils::get_node_attributes_as_assoc_array($node); $new_attributes = $this->filter_attributes($old_attributes); $new_node = AMP_DOM_Utils::create_node($this->dom, 'amp-audio', $new_attributes); // TODO: `source` does not have closing tag, and DOMDocument doesn't handle it well. foreach ($node->childNodes as $child_node) { $new_child_node = $child_node->cloneNode(true); $old_child_attributes = AMP_DOM_Utils::get_node_attributes_as_assoc_array($new_child_node); $new_child_attributes = $this->filter_attributes($old_child_attributes); // Only append source tags with a valid src attribute if (!empty($new_child_attributes['src']) && 'source' === $new_child_node->tagName) { $new_node->appendChild($new_child_node); } } // If the node has at least one valid source, replace the old node with it. // Otherwise, just remove the node. // // TODO: Add a fallback handler. // See: https://github.com/ampproject/amphtml/issues/2261 if (0 === $new_node->childNodes->length && empty($new_attributes['src'])) { $node->parentNode->removeChild($node); } else { $node->parentNode->replaceChild($new_node, $node); } $this->did_convert_elements = true; } }
/** * @dataProvider get_data */ public function test_sanitizer($source, $expected) { $dom = AMP_DOM_Utils::get_dom_from_content($source); $sanitizer = new AMP_Blacklist_Sanitizer($dom); $sanitizer->sanitize(); $content = AMP_DOM_Utils::get_content_from_dom($dom); $this->assertEquals($expected, $content); }
public function test_add_attributes_to_node__attribute_with_value() { $dom = AMP_DOM_Utils::get_dom_from_content('<p>Hello World</p>'); $node = $dom->createElement('div'); $attributes = array('class' => 'myClass', 'id' => 'myId'); AMP_DOM_Utils::add_attributes_to_node($node, $attributes); $this->assertTrue($node->hasAttributes()); $this->check_node_has_attributes($node, $attributes); }
public function test_get_scripts__empty() { $source = '<video width="300" height="300" src="https://archive.org/download/WebmVp8Vorbis/webmvp8_512kb.mp4"></video>'; $expected = array(); $dom = AMP_DOM_Utils::get_dom_from_content($source); $sanitizer = new AMP_Video_Sanitizer($dom); $sanitizer->sanitize(); $scripts = $sanitizer->get_scripts(); $this->assertEquals($expected, $scripts); }
public function test__args__placeholder() { $source = '<iframe src="https://example.com/video/132886713" width="500" height="281"></iframe>'; $expected = '<amp-iframe src="https://example.com/video/132886713" width="500" height="281" sandbox="allow-scripts allow-same-origin" sizes="(min-width: 500px) 500px, 100vw" class="amp-wp-enforced-sizes"><div placeholder="" class="amp-wp-iframe-placeholder"></div></amp-iframe>'; $dom = AMP_DOM_Utils::get_dom_from_content($source); $sanitizer = new AMP_Iframe_Sanitizer($dom, array('add_placeholder' => true)); $sanitizer->sanitize(); $content = AMP_DOM_Utils::get_content_from_dom($dom); $this->assertEquals($expected, $content); }
public function test_get_scripts__did_convert() { $source = '<iframe src="https://player.vimeo.com/video/132886713" width="500" height="281"></iframe>'; $expected = array('amp-iframe' => 'https://cdn.ampproject.org/v0/amp-iframe-0.1.js'); $dom = AMP_DOM_Utils::get_dom_from_content($source); $sanitizer = new AMP_Iframe_Sanitizer($dom); $sanitizer->sanitize(); $scripts = $sanitizer->get_scripts(); $this->assertEquals($expected, $scripts); }
public function test_no_gif_image_scripts() { $source = '<img src="http://placehold.it/350x150.gif" width="350" height="150" alt="Placeholder!" />'; $expected = array('amp-anim' => 'https://cdn.ampproject.org/v0/amp-anim-0.1.js'); $dom = AMP_DOM_Utils::get_dom_from_content($source); $sanitizer = new AMP_Img_Sanitizer($dom); $sanitizer->sanitize(); $scripts = $sanitizer->get_scripts(); $this->assertEquals($expected, $scripts); }
public function test_get_scripts__did_convert() { $source = '<audio width="400" height="300" src="https://example.com/audio/file.ogg"></audio>'; $expected = array('amp-audio' => 'https://cdn.ampproject.org/v0/amp-audio-0.1.js'); $dom = AMP_DOM_Utils::get_dom_from_content($source); $sanitizer = new AMP_Audio_Sanitizer($dom); $sanitizer->sanitize(); $scripts = $sanitizer->get_scripts(); $this->assertEquals($expected, $scripts); }
public function test_get_scripts__empty() { $source = '<video width="300" height="300" src="https://example.com/video.mp4"></video>'; $expected = array(); $dom = AMP_DOM_Utils::get_dom_from_content($source); $sanitizer = new AMP_Video_Sanitizer($dom); $sanitizer->sanitize(); $scripts = $sanitizer->get_scripts(); $this->assertEquals($expected, $scripts); }
/** * @dataProvider get_data */ public function test_sanitizer($source, $expected_content, $expected_stylesheet) { $dom = AMP_DOM_Utils::get_dom_from_content($source); $sanitizer = new AMP_Style_Sanitizer($dom); $sanitizer->sanitize(); // Test content $content = AMP_DOM_Utils::get_content_from_dom($dom); $this->assertEquals($expected_content, $content); // Test stylesheet $stylesheet = $sanitizer->get_styles(); $this->assertEquals($expected_stylesheet, $stylesheet); }
private function sanitize($content) { $dom = AMP_DOM_Utils::get_dom_from_content($content); foreach ($this->sanitizer_classes as $sanitizer_class => $args) { $sanitizer = new $sanitizer_class($dom, array_merge($this->args, $args)); if (!is_subclass_of($sanitizer, 'AMP_Base_Sanitizer')) { _doing_it_wrong(__METHOD__, sprintf(__('Sanitizer (%s) must extend `AMP_Base_Sanitizer`', 'amp'), esc_html($sanitizer_class)), '0.1'); continue; } $sanitizer->sanitize(); $this->add_scripts($sanitizer->get_scripts()); } return AMP_DOM_Utils::get_content_from_dom($dom); }
/** * Make final modifications to DOMNode * * @param DOMNode $node The DOMNode to adjust and replace */ private function adjust_and_replace_node($node) { $old_attributes = AMP_DOM_Utils::get_node_attributes_as_assoc_array($node); $new_attributes = $this->filter_attributes($old_attributes); $new_attributes = $this->enforce_sizes_attribute($new_attributes); if ($this->is_gif_url($new_attributes['src'])) { $this->did_convert_elements = true; $new_tag = 'amp-anim'; } else { $new_tag = 'amp-img'; } $new_node = AMP_DOM_Utils::create_node($this->dom, $new_tag, $new_attributes); $node->parentNode->replaceChild($new_node, $node); }
private function strip_tags($node, $tag_names) { foreach ($tag_names as $tag_name) { $elements = $node->getElementsByTagName($tag_name); $length = $elements->length; if (0 === $length) { continue; } for ($i = $length - 1; $i >= 0; $i--) { $element = $elements->item($i); $parent_node = $element->parentNode; $parent_node->removeChild($element); if ('body' !== $parent_node->nodeName && AMP_DOM_Utils::is_node_empty($parent_node)) { $parent_node->parentNode->removeChild($parent_node); } } } }
public function sanitize() { $nodes = $this->dom->getElementsByTagName(self::$tag); $num_nodes = $nodes->length; if (0 === $num_nodes) { return; } for ($i = $num_nodes - 1; $i >= 0; $i--) { $node = $nodes->item($i); $old_attributes = AMP_DOM_Utils::get_node_attributes_as_assoc_array($node); // Added data-src for lazy-loaded imgs. if (!array_key_exists('src', $old_attributes) && !array_key_exists('data-src', $old_attributes)) { $node->parentNode->removeChild($node); continue; } $new_attributes = $this->filter_attributes($old_attributes); // Try to extract dimensions for the image, if not set. if (!isset($new_attributes['width']) || !isset($new_attributes['height'])) { $dimensions = AMP_Image_Dimension_Extractor::extract($new_attributes['src']); if (is_array($dimensions)) { $new_attributes['width'] = $dimensions[0]; $new_attributes['height'] = $dimensions[1]; } } // Final fallback when we have no dimensions. if (!isset($new_attributes['width']) || !isset($new_attributes['height'])) { $new_attributes['width'] = isset($this->args['content_max_width']) ? $this->args['content_max_width'] : self::FALLBACK_WIDTH; $new_attributes['height'] = self::FALLBACK_HEIGHT; $this->add_or_append_attribute($new_attributes, 'class', 'amp-wp-unknown-size'); } $new_attributes = $this->enforce_sizes_attribute($new_attributes); if ($this->is_gif_url($new_attributes['src'])) { $this->did_convert_elements = true; $new_tag = 'amp-anim'; } else { $new_tag = 'amp-img'; } $new_node = AMP_DOM_Utils::create_node($this->dom, $new_tag, $new_attributes); $node->parentNode->replaceChild($new_node, $node); } }
public function transform() { $content = $this->original_content; $twitter_embed = new AMP_Twitter_Embed_Handler(); $youtube_embed = new AMP_YouTube_Embed_Handler(); $gallery_embed = new AMP_Gallery_Embed_Handler(); $instagram_embed = new AMP_Instagram_Embed_Handler(); $content = apply_filters('the_content', $content); $this->add_scripts($twitter_embed->get_scripts()); $this->add_scripts($youtube_embed->get_scripts()); $this->add_scripts($gallery_embed->get_scripts()); $this->add_scripts($instagram_embed->get_scripts()); $dom = AMP_DOM_Utils::get_dom_from_content($content); $this->sanitize(new AMP_Blacklist_Sanitizer($dom, $this->args)); $this->sanitize(new AMP_Img_Sanitizer($dom, $this->args)); $this->sanitize(new AMP_Video_Sanitizer($dom, $this->args)); $this->sanitize(new AMP_Iframe_Sanitizer($dom, $this->args)); $this->sanitize(new AMP_Audio_Sanitizer($dom, $this->args)); $content = AMP_DOM_Utils::get_content_from_dom($dom); return $content; }
public function sanitize($amp_attributes = array()) { $nodes = $this->dom->getElementsByTagName(self::$tag); $num_nodes = $nodes->length; if (0 === $num_nodes) { return; } for ($i = $num_nodes - 1; $i >= 0; $i--) { $node = $nodes->item($i); $old_attributes = AMP_DOM_Utils::get_node_attributes_as_assoc_array($node); if (!array_key_exists('src', $old_attributes)) { $node->parentNode->removeChild($node); continue; } $this->did_convert_elements = true; $new_attributes = $this->filter_attributes($old_attributes); $new_attributes = $this->enforce_sizes_attribute($new_attributes); $new_attributes = array_merge($new_attributes, $amp_attributes); $new_node = AMP_DOM_Utils::create_node($this->dom, 'amp-iframe', $new_attributes); $node->parentNode->replaceChild($new_node, $node); } }
public function sanitize() { $nodes = $this->dom->getElementsByTagName(self::$tag); $num_nodes = $nodes->length; if (0 === $num_nodes) { return; } for ($i = $num_nodes - 1; $i >= 0; $i--) { $node = $nodes->item($i); $old_attributes = AMP_DOM_Utils::get_node_attributes_as_assoc_array($node); $new_attributes = $this->filter_attributes($old_attributes); $new_node = AMP_DOM_Utils::create_node($this->dom, 'amp-audio', $new_attributes); // TODO: limit child nodes too (only allowed: `source`; move rest to div+fallback) // TODO: `source` does not have closing tag, and DOMDocument doesn't handle it well. foreach ($node->childNodes as $child_node) { $new_child_node = $child_node->cloneNode(true); $new_node->appendChild($new_child_node); } $node->parentNode->replaceChild($new_node, $node); $this->did_convert_elements = true; } }
private function build_placeholder($parent_attributes) { $placeholder_node = AMP_DOM_Utils::create_node($this->dom, 'div', array('layout' => 'fill', 'placeholder' => '', 'class' => 'amp-wp-iframe-placeholder')); return $placeholder_node; }
public function test__recursive_force_closing_tags__force_close_with_children() { $dom = new DOMDocument(); $node = $dom->createElement('div'); $child_with_closing = $dom->createElement('amp-img'); $child_self_closing = $dom->createElement('br'); $node->appendChild($child_with_closing); $node->appendChild($child_self_closing); $expected = '<div><amp-img></amp-img><br/></div>'; AMP_DOM_Utils::recursive_force_closing_tags($dom, $node); $this->assertEquals($expected, $dom->saveXML($node)); }
public static function sanitize($content, $sanitizer_classes, $args = array()) { $scripts = array(); $styles = array(); $dom = AMP_DOM_Utils::get_dom_from_content($content); foreach ($sanitizer_classes as $sanitizer_class => $args) { if (!class_exists($sanitizer_class)) { _doing_it_wrong(__METHOD__, sprintf(__('Sanitizer (%s) class does not exist', 'amp'), esc_html($sanitizer_class)), '0.4.1'); continue; } $sanitizer = new $sanitizer_class($dom, array_merge($args, $args)); if (!is_subclass_of($sanitizer, 'AMP_Base_Sanitizer')) { _doing_it_wrong(__METHOD__, sprintf(__('Sanitizer (%s) must extend `AMP_Base_Sanitizer`', 'amp'), esc_html($sanitizer_class)), '0.1'); continue; } $sanitizer->sanitize(); $scripts = array_merge($scripts, $sanitizer->get_scripts()); $styles = array_merge($styles, $sanitizer->get_styles()); } $sanitized_content = AMP_DOM_Utils::get_content_from_dom($dom); return array($sanitized_content, $scripts, $styles); }