1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
<?php /** * Class AMP_TikTok_Embed_Handler * * @package AMP */
use AmpProject\Dom\Document;
/** * Class AMP_TikTok_Embed_Handler * * @internal */ class AMP_TikTok_Embed_Handler extends AMP_Base_Embed_Handler {
/** * Registers embed. */ public function register_embed() { // Not implemented. }
/** * Unregisters embed. */ public function unregister_embed() { // Not implemented. }
/** * Sanitize TikTok embeds to be AMP compatible. * * @param Document $dom DOM. */ public function sanitize_raw_embeds( Document $dom ) { $nodes = $dom->xpath->query( '//blockquote[ contains( @class, "tiktok-embed" ) ]' );
foreach ( $nodes as $node ) { if ( ! $this->is_raw_embed( $node ) ) { continue; }
$this->make_embed_amp_compatible( $node ); } }
/** * Determine if the node has already been sanitized. * * @param DOMElement $node The DOMNode. * @return bool Whether the node is a raw embed. */ protected function is_raw_embed( DOMElement $node ) { return ! $node->firstChild || ( $node->firstChild && 'amp-embedly-card' !== $node->firstChild->nodeName ); }
/** * Make TikTok embed AMP compatible. * * @param DOMElement $blockquote_node The <blockquote> node to make AMP compatible. */ protected function make_embed_amp_compatible( DOMElement $blockquote_node ) { $dom = $blockquote_node->ownerDocument; $video_url = $blockquote_node->getAttribute( 'cite' );
// If there is no video ID, stop here as its needed for the `data-url` parameter. if ( empty( $video_url ) ) { return; }
$this->remove_embed_script( $blockquote_node );
$amp_node = AMP_DOM_Utils::create_node( Document::fromNode( $dom ), 'amp-embedly-card', [ 'layout' => 'responsive', 'height' => 700, 'width' => 340, 'data-card-controls' => 0, 'data-url' => $video_url, ] );
// Find existing <section> node to use as the placeholder. foreach ( iterator_to_array( $blockquote_node->childNodes ) as $child ) { if ( ! ( $child instanceof DOMElement ) ) { continue; }
// Append the placeholder if it was found. if ( 'section' === $child->nodeName ) { /** * Placeholder to append to the AMP component. * * @var DOMElement $placeholder_node */ $placeholder_node = $blockquote_node->removeChild( $child ); $placeholder_node->setAttribute( 'placeholder', '' ); $amp_node->appendChild( $placeholder_node ); break; } }
$blockquote_node->parentNode->replaceChild( $amp_node, $blockquote_node ); }
/** * Remove the TikTok embed script if it exists. * * @param DOMElement $node The DOMNode to make AMP compatible. */ protected function remove_embed_script( DOMElement $node ) { $next_element_sibling = $node->nextSibling; while ( $next_element_sibling && ! ( $next_element_sibling instanceof DOMElement ) ) { $next_element_sibling = $next_element_sibling->nextSibling; }
$script_src = 'tiktok.com/embed.js';
// Handle case where script is wrapped in paragraph by wpautop. if ( $next_element_sibling instanceof DOMElement && 'p' === $next_element_sibling->nodeName ) { $children = $next_element_sibling->getElementsByTagName( '*' ); if ( 1 === $children->length && 'script' === $children->item( 0 )->nodeName && false !== strpos( $children->item( 0 )->getAttribute( 'src' ), $script_src ) ) { $next_element_sibling->parentNode->removeChild( $next_element_sibling ); return; } }
// Handle case where script is immediately following. $is_embed_script = ( $next_element_sibling instanceof DOMElement && 'script' === strtolower( $next_element_sibling->nodeName ) && false !== strpos( $next_element_sibling->getAttribute( 'src' ), $script_src ) ); if ( $is_embed_script ) { $next_element_sibling->parentNode->removeChild( $next_element_sibling ); } } }
|