C:\xampp\htdocs\landing\wp-content\plugins\amp\includes\embeds\class-amp-core-block-handler.php


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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
<?php
/**
 * Class AMP_Core_Block_Handler
 *
 * @package AMP
 */

use AmpProject\Attribute;
use 
AmpProject\Dom\Document;

/**
 * Class AMP_Core_Block_Handler
 *
 * @since 1.0
 * @internal
 */
class AMP_Core_Block_Handler extends AMP_Base_Embed_Handler {

    
/**
     * Attribute to store the original width on a video or iframe just before WordPress removes it.
     *
     * @see AMP_Core_Block_Handler::preserve_widget_text_element_dimensions()
     * @see AMP_Core_Block_Handler::process_text_widgets()
     * @var string
     */
    
const AMP_PRESERVED_WIDTH_ATTRIBUTE_NAME 'amp-preserved-width';

    
/**
     * Attribute to store the original height on a video or iframe just before WordPress removes it.
     *
     * @see AMP_Core_Block_Handler::preserve_widget_text_element_dimensions()
     * @see AMP_Core_Block_Handler::process_text_widgets()
     * @var string
     */
    
const AMP_PRESERVED_HEIGHT_ATTRIBUTE_NAME 'amp-preserved-height';

    
/**
     * Count of the category widgets encountered.
     *
     * @var int
     */
    
private $category_widget_count 0;

    
/**
     * Methods to ampify blocks.
     *
     * @var array
     */
    
protected $block_ampify_methods = [
        
'core/categories' => 'ampify_categories_block',
        
'core/archives'   => 'ampify_archives_block',
        
'core/video'      => 'ampify_video_block',
        
'core/cover'      => 'ampify_cover_block',
    ];

    
/**
     * Register embed.
     */
    
public function register_embed() {
        
add_filter'render_block', [ $this'filter_rendered_block' ], 0);
        
add_filter'widget_text_content', [ $this'preserve_widget_text_element_dimensions' ], PHP_INT_MAX );
    }

    
/**
     * Unregister embed.
     */
    
public function unregister_embed() {
        
remove_filter'render_block', [ $this'filter_rendered_block' ], );
        
remove_filter'widget_text_content', [ $this'preserve_widget_text_element_dimensions' ], PHP_INT_MAX );
    }

    
/**
     * Filters the content of a single block to make it AMP valid.
     *
     * @param string $block_content The block content about to be appended.
     * @param array  $block         The full block, including name and attributes.
     * @return string Filtered block content.
     */
    
public function filter_rendered_block$block_content$block ) {
        if ( ! isset( 
$block['blockName'] ) ) {
            return 
$block_content;
        }

        if ( isset( 
$block['attrs'] ) && 'core/shortcode' !== $block['blockName'] ) {
            
$injected_attributes    '';
            
$prop_attribute_mapping = [
                
'ampCarousel'  => 'data-amp-carousel',
                
'ampLayout'    => 'data-amp-layout',
                
'ampLightbox'  => 'data-amp-lightbox',
                
'ampNoLoading' => 'data-amp-noloading',
            ];
            foreach ( 
$prop_attribute_mapping as $prop => $attr ) {
                if ( isset( 
$block['attrs'][ $prop ] ) ) {
                    
$property_value $block['attrs'][ $prop ];
                    if ( 
is_bool$property_value ) ) {
                        
$property_value $property_value 'true' 'false';
                    }

                    
$injected_attributes .= sprintf' %s="%s"'$attresc_attr$property_value ) );
                }
            }
            if ( 
$injected_attributes ) {
                
$block_content preg_replace'/(<\w+)/''$1' $injected_attributes$block_content);
            }
        }

        if ( isset( 
$this->block_ampify_methods$block['blockName'] ] ) ) {
            
$method_name   $this->block_ampify_methods$block['blockName'] ];
            
$block_content $this->{$method_name}( $block_content$block );
        } elseif ( 
'core/image' === $block['blockName'] || 'core/audio' === $block['blockName'] ) {
            
/*
             * While the video block placeholder just outputs an empty video element, the placeholders for image and
             * audio blocks output empty <img> and <audio> respectively. These will result in AMP validation errors,
             * so we need to empty out the block content to prevent this from happening. Note that <source> is used
             * for <img> because eventually the image block could use <picture>.
             */
            
if ( ! preg_match'/src=|<source/'$block_content ) ) {
                
$block_content '';
            }
        }
        return 
$block_content;
    }

    
/**
     * Fix rendering of categories block when displayAsDropdown.
     *
     * This excludes the disallowed JS scrips, adds <form> tags, and uses on:change for <select>.
     *
     * @see render_block_core_categories()
     *
     * @param string $block_content Block content.
     * @return string Rendered.
     */
    
public function ampify_categories_block$block_content ) {
        static 
$block_id 0;
        
$block_id++;

        
$form_id "wp-block-categories-dropdown-{$block_id}-form";

        
// Remove output of build_dropdown_script_block_core_categories().
        
$block_content preg_replace'#<script.+?</script>#s'''$block_content );

        
$form sprintf(
            
'<form action="%s" method="get" target="_top" id="%s">',
            
esc_urlhome_url() ),
            
esc_attr$form_id )
        );

        
$block_content preg_replace(
            
'#(<select)(.+</select>)#s',
            
$form '$1' sprintf' on="change:%1$s.submit"'esc_attr$form_id ) ) . '$2</form>',
            
$block_content,
            
1
        
);

        return 
$block_content;
    }

    
/**
     * Fix rendering of archives block when displayAsDropdown.
     *
     * This replaces disallowed script with the use of on:change for <select>.
     *
     * @see render_block_core_archives()
     *
     * @param string $block_content Block content.
     * @return string Rendered.
     */
    
public function ampify_archives_block$block_content ) {

        
// Eliminate use of uniqid(). Core should be using wp_unique_id() here.
        
static $block_id 0;
        
$block_id++;
        
$block_content preg_replace'/(?<="wp-block-archives-)\w+(?=")/'$block_id$block_content );

        
// Replace onchange with on attribute.
        
$block_content preg_replace(
            
'/onchange=".+?"/',
            
'on="change:AMP.navigateTo(url=event.value)"',
            
$block_content
        
);

        return 
$block_content;
    }

    
/**
     * Ampify video block.
     *
     * Inject the video attachment's dimensions if available. This prevents having to try to look up the attachment
     * post by the video URL in `\AMP_Video_Sanitizer::filter_video_dimensions()`.
     *
     * @see \AMP_Video_Sanitizer::filter_video_dimensions()
     *
     * @param string $block_content The block content about to be appended.
     * @param array  $block         The full block, including name and attributes.
     * @return string Filtered block content.
     */
    
public function ampify_video_block$block_content$block ) {
        if ( empty( 
$block['attrs']['id'] ) || 'attachment' !== get_post_type$block['attrs']['id'] ) ) {
            return 
$block_content;
        }

        
$meta_data wp_get_attachment_metadata$block['attrs']['id'] );
        if ( isset( 
$meta_data['width'], $meta_data['height'] ) ) {
            
$block_content preg_replace(
                
'/(?<=<video\s)/',
                
sprintf'width="%d" height="%d" '$meta_data['width'], $meta_data['height'] ),
                
$block_content
            
);
        }

        return 
$block_content;
    }

    
/**
     * Ampify cover block.
     *
     * This specifically fixes the layout of the block when a background video is assigned.
     *
     * @see \AMP_Video_Sanitizer::filter_video_dimensions()
     *
     * @param string $block_content The block content about to be appended.
     * @param array  $block         The full block, including name and attributes.
     * @return string Filtered block content.
     */
    
public function ampify_cover_block$block_content$block ) {
        if ( isset( 
$block['attrs']['backgroundType'] ) && 'video' === $block['attrs']['backgroundType'] ) {
            
$block_content preg_replace(
                
'/(?<=<video\s)/',
                
'layout="fill" object-fit="cover" ',
                
$block_content
            
);
        }
        return 
$block_content;
    }

    
/**
     * Sanitize widgets that are not added via Gutenberg.
     *
     * @param Document $dom  Document.
     * @param array    $args Args passed to sanitizer.
     */
    
public function sanitize_raw_embedsDocument $dom$args = [] ) {
        
$this->process_categories_widgets$dom );
        
$this->process_archives_widgets$dom$args );
        
$this->process_text_widgets$dom );
    }

    
/**
     * Process "Categories" widgets.
     *
     * @since 2.0
     *
     * @param Document $dom Document.
     */
    
private function process_categories_widgetsDocument $dom ) {
        
$selects $dom->xpath->query'//form/select[ @name = "cat" ]' );
        foreach ( 
$selects as $select ) {
            if ( ! 
$select instanceof DOMElement ) {
                continue;
            }
            
$form $select->parentNode;
            if ( ! 
$form instanceof DOMElement || ! $form->parentNode instanceof DOMElement ) {
                continue;
            }
            
$script $dom->xpath->query'.//script[ contains( text(), "onCatChange" ) ]'$form->parentNode )->item);
            if ( ! 
$script instanceof DOMElement ) {
                continue;
            }

            
$this->category_widget_count++;
            
$id sprintf'amp-wp-widget-categories-%d'$this->category_widget_count );

            
$form->setAttribute'id'$id );

            
AMP_DOM_Utils::add_amp_action$select'change'sprintf'%s.submit'$id ) );
            
$script->parentNode->removeChild$script );
        }
    }

    
/**
     * Process "Archives" widgets.
     *
     * @since 2.0
     *
     * @param Document $dom  Select node retrieved from the widget.
     * @param array    $args Args passed to sanitizer.
     */
    
private function process_archives_widgetsDocument $dom$args = [] ) {
        
$selects $dom->xpath->query'//select[ @name = "archive-dropdown" and starts-with( @id, "archives-dropdown-" ) ]' );
        foreach ( 
$selects as $select ) {
            if ( ! 
$select instanceof DOMElement ) {
                continue;
            }

            
$script $dom->xpath->query'.//script[ contains( text(), "onSelectChange" ) ]'$select->parentNode )->item);
            if ( 
$script ) {
                
$script->parentNode->removeChild$script );
            } elseif ( 
$select->hasAttribute'onchange' ) ) {
                
// Special condition for WordPress<=5.1.
                
$select->removeAttribute'onchange' );
            } else {
                continue;
            }

            
AMP_DOM_Utils::add_amp_action$select'change''AMP.navigateTo(url=event.value)' );

            
// When AMP-to-AMP linking is enabled, ensure links go to the AMP version.
            
if ( ! empty( $args['amp_to_amp_linking_enabled'] ) ) {
                foreach ( 
$dom->xpath->query'//option[ @value != "" ]'$select ) as $option ) {
                    
/**
                     * Option element.
                     *
                     * @var DOMElement $option
                     */
                    
$option->setAttribute'value'add_query_argamp_get_slug(), ''$option->getAttribute'value' ) ) );
                }
            }
        }
    }

    
/**
     * Preserve dimensions of elements in a Text widget to later restore to circumvent WordPress core stripping them out.
     *
     * Core strips out the dimensions to prevent the element being made too wide for the sidebar. This is not a concern
     * in AMP because of responsive sizing. So this logic is here to undo what core is doing.
     *
     * @since 2.0
     * @see WP_Widget_Text::inject_video_max_width_style()
     * @see AMP_Core_Block_Handler::process_text_widgets()
     *
     * @param string $content Content.
     * @return string Content.
     */
    
public function preserve_widget_text_element_dimensions$content ) {
        
$content preg_replace_callback(
            
'#<(video|iframe|object|embed)\s[^>]*>#si',
            static function ( 
$matches ) {
                
$html $matches[0];
                
$html preg_replace'/(?=\sheight="(\d+)")/'' ' self::AMP_PRESERVED_HEIGHT_ATTRIBUTE_NAME '="$1" '$html );
                
$html preg_replace'/(?=\swidth="(\d+)")/'' ' self::AMP_PRESERVED_WIDTH_ATTRIBUTE_NAME '="$1" '$html );
                return 
$html;
            },
            
$content
        
);

        return 
$content;
    }

    
/**
     * Process "Text" widgets.
     *
     * @since 2.0
     * @see AMP_Core_Block_Handler::preserve_widget_text_element_dimensions()
     *
     * @param Document $dom Select node retrieved from the widget.
     */
    
private function process_text_widgetsDocument $dom ) {
        foreach ( 
$dom->xpath->query'//div[ @class = "textwidget" ]' ) as $text_widget ) {
            
// Restore the width/height attributes which were preserved in preserve_widget_text_element_dimensions.
            
foreach ( $dom->xpath->querysprintf'.//*[ @%s or @%s ]'self::AMP_PRESERVED_WIDTH_ATTRIBUTE_NAMEself::AMP_PRESERVED_HEIGHT_ATTRIBUTE_NAME ), $text_widget ) as $element ) {
                if ( 
$element->hasAttributeself::AMP_PRESERVED_WIDTH_ATTRIBUTE_NAME ) ) {
                    
$element->setAttributeAttribute::WIDTH$element->getAttributeself::AMP_PRESERVED_WIDTH_ATTRIBUTE_NAME ) );
                    
$element->removeAttributeself::AMP_PRESERVED_WIDTH_ATTRIBUTE_NAME );
                }
                if ( 
$element->hasAttributeself::AMP_PRESERVED_HEIGHT_ATTRIBUTE_NAME ) ) {
                    
$element->setAttributeAttribute::HEIGHT$element->getAttributeself::AMP_PRESERVED_HEIGHT_ATTRIBUTE_NAME ) );
                    
$element->removeAttributeself::AMP_PRESERVED_HEIGHT_ATTRIBUTE_NAME );
                }
            }

            
/*
             * Remove inline width style which is added to video shortcode but which overruns the container.
             * Normally this width gets overridden by wp-mediaelement.css to be max-width: 100%, but since
             * MediaElement.js is not used in AMP this stylesheet is not included. In any case, videos in AMP are
             * responsive so this is built-in. Note also the style rule for .wp-video in amp-default.css.
             */
            
foreach ( $dom->xpath->query'.//div[ @class = "wp-video" and @style ]'$text_widget ) as $element ) {
                
$element->removeAttribute'style' );
            }
        }
    }
}
x

Windows NT KPTV 6.2 build 9200 (Windows Server 2012 Datacenter Edition) i586