C:\xampp\htdocs\landing\wp-content\plugins\amp\includes\sanitizers\class-amp-link-sanitizer.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
<?php
/**
 * Class AMP_Links_Sanitizer.
 *
 * @package AMP
 */

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

/**
 * Class AMP_Link_Sanitizer.
 *
 * Adapts links for AMP-to-AMP navigation:
 *  - In paired AMP (Transitional and Reader modes), internal links get '?amp' added to them.
 *  - Internal links on AMP pages get rel=amphtml added to them.
 *  - Forms with internal actions get a hidden 'amp' input added to them.
 *  - AMP pages get meta[amp-to-amp-navigation] added to them.
 *  - Any elements in the admin bar are excluded.
 *
 * Adapted from https://gist.github.com/westonruter/f9ee9ea717d52471bae092879e3d52b0
 *
 * @link https://github.com/ampproject/amphtml/issues/12496
 * @since 1.4.0
 * @internal
 */
class AMP_Link_Sanitizer extends AMP_Base_Sanitizer {

    
/**
     * Default meta tag content.
     *
     * @var string
     */
    
const DEFAULT_META_CONTENT 'AMP-Redirect-To; AMP.navigateTo';

    
/**
     * Placeholder for default arguments, to be set in child classes.
     *
     * @var array
     */
    
protected $DEFAULT_ARGS = [ // phpcs:ignore WordPress.NamingConventions.ValidVariableName.PropertyNotSnakeCase
        
'paired'        => false// Only set to true when in a paired mode (will be false when amp_is_canonical()). Controls whether query var is added.
        
'meta_content'  => self::DEFAULT_META_CONTENT,
        
'excluded_urls' => [], // URLs in this won't have AMP-to-AMP links in a paired mode.
    
];

    
/**
     * Home host.
     *
     * @var string
     */
    
protected $home_host;

    
/**
     * Content path.
     *
     * @var string
     */
    
protected $content_path;

    
/**
     * Admin path.
     *
     * @var string
     */
    
protected $admin_path;

    
/**
     * Sanitizer constructor.
     *
     * @param Document $dom  Document.
     * @param array    $args Args.
     */
    
public function __construct$dom, array $args = [] ) {
        if ( ! isset( 
$args['meta_content'] ) ) {
            
$args['meta_content'] = self::DEFAULT_META_CONTENT;
        }

        
parent::__construct$dom$args );

        
$this->home_host    wp_parse_urlhome_url(), PHP_URL_HOST );
        
$this->content_path wp_parse_urlcontent_url'/' ), PHP_URL_PATH );
        
$this->admin_path   wp_parse_urladmin_url(), PHP_URL_PATH );
    }

    
/**
     * Sanitize.
     */
    
public function sanitize() {
        if ( ! empty( 
$this->args['meta_content'] ) ) {
            
$this->add_meta_tag$this->args['meta_content'] );
        }

        
$this->process_links();
    }

    
/**
     * Add the amp-to-amp-navigation meta tag.
     *
     * @param string $content The content for the meta tag, for example 'AMP-Redirect-To; AMP.navigateTo'.
     * @return DOMElement|null The added meta element if successful.
     */
    
public function add_meta_tag$content self::DEFAULT_META_CONTENT ) {
        if ( ! 
$content ) {
            return 
null;
        }
        
$meta $this->dom->createElement'meta' );
        
$meta->setAttribute'name''amp-to-amp-navigation' );
        
$meta->setAttribute'content'$content );
        
$this->dom->head->appendChild$meta );
        return 
$meta;
    }

    
/**
     * Process links by adding adding AMP query var to links in paired mode and adding rel=amphtml.
     */
    
public function process_links() {
        
// Remove admin bar from DOM to prevent mutating it.
        
$admin_bar_container   $this->dom->getElementById'wpadminbar' );
        
$admin_bar_placeholder null;
        if ( 
$admin_bar_container ) {
            
$admin_bar_placeholder $this->dom->createComment'wpadminbar' );
            
$admin_bar_container->parentNode->replaceChild$admin_bar_placeholder$admin_bar_container );
        }

        
$link_query $this->dom->xpath->query'//*[ local-name() = "a" or local-name() = "area" ][ @href ]' );
        foreach ( 
$link_query as $link ) {
            
$this->process_element$linkAttribute::HREF );
        }

        
$form_query $this->dom->xpath->query'//form[ @action and translate( @method, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz") = "get" ]' );
        foreach ( 
$form_query as $form ) {
            
$this->process_element$formAttribute::ACTION );
        }

        
// Replace the admin bar after mutations are done.
        
if ( $admin_bar_container && $admin_bar_placeholder ) {
            
$admin_bar_placeholder->parentNode->replaceChild$admin_bar_container$admin_bar_placeholder );
        }
    }

    
/**
     * Check if element is descendant of a template element.
     *
     * @param DOMElement $node Node.
     * @return bool Descendant of template.
     */
    
private function is_descendant_of_template_elementDOMElement $node ) {
        while ( 
$node instanceof DOMElement ) {
            
$parent $node->parentNode;
            if ( 
$parent instanceof DOMElement && Tag::TEMPLATE === $parent->tagName ) {
                return 
true;
            }
            
$node $parent;
        }
        return 
false;
    }

    
/**
     * Process element.
     *
     * @param DOMElement $element        Element to process.
     * @param string     $attribute_name Attribute name that contains the URL.
     */
    
private function process_elementDOMElement $element$attribute_name ) {
        
$url $element->getAttribute$attribute_name );

        
// Skip page anchor links or non-frontend links.
        
if ( empty( $url ) || '#' === substr$url0) || ! $this->is_frontend_url$url ) ) {
            return;
        }

        
// Skip links with template variables.
        
if ( preg_match'/{{[^}]+?}}/'$url ) && $this->is_descendant_of_template_element$element ) ) {
            return;
        }

        
// Gather the rel values that were attributed to the element.
        // Note that links and forms may both have this attribute.
        // See <https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel>.
        
if ( $element->hasAttributeAttribute::REL ) ) {
            
$rel array_filterpreg_split'/\s+/'trim$element->getAttributeAttribute::REL ) ) ) );
        } else {
            
$rel = [];
        }

        
$excluded = (
            
in_arrayAttribute::REL_NOAMPHTML$reltrue )
            ||
            
in_arraystrtok$url'#' ), $this->args['excluded_urls'], true )
        );

        
/**
         * Filters whether AMP-to-AMP is excluded for an element.
         *
         * The element may be either a link (`a` or `area`) or a `form`.
         *
         * @param bool       $excluded Excluded. Default value is whether element already has a `noamphtml` link relation or the URL is among `excluded_urls`.
         * @param string     $url      URL considered for exclusion.
         * @param string[]   $rel      Link relations.
         * @param DOMElement $element  The element considered for excluding from AMP-to-AMP linking. May be instance of `a`, `area`, or `form`.
         */
        
$excluded = (bool) apply_filters'amp_to_amp_linking_element_excluded'$excluded$url$rel$element );

        
$query_vars = [];

        if ( ! 
$excluded ) {
            
$rel[] = Attribute::REL_AMPHTML;
            
$rel   array_diff(
                
$rel,
                [ 
Attribute::REL_NOAMPHTML ]
            );

            
$element->setAttributeAttribute::RELimplode' '$rel ) );

            
// Only add the AMP query var when requested (in Transitional or Reader mode).
            
if ( ! empty( $this->args['paired'] ) ) {
                
$query_varsamp_get_slug() ] = '';
            }
        }

        
/**
         * Filters the query vars that are added to the link/form which is considered for AMP-to-AMP linking.
         *
         * @internal
         *
         * @param string[]   $query_vars Query vars.
         * @param bool       $excluded   Whether the element was excluded.
         * @param string     $url        URL considered for exclusion.
         * @param string[]   $rel        Link relations.
         * @param DOMElement $element    Element.
         */
        
$query_vars apply_filters'amp_to_amp_linking_element_query_vars'$query_vars$excluded$url$element$rel );

        if ( 
$query_vars ) {
            if ( 
Tag::FORM === $element->nodeName ) {
                foreach ( 
$query_vars as $name => $value ) {
                    
$input $this->dom->createElementTag::INPUT );
                    
$input->setAttributeAttribute::NAME$name );
                    
$input->setAttributeAttribute::VALUE$value );
                    
$input->setAttributeAttribute::TYPE'hidden' );
                    
$element->appendChild$input );
                }
            } else {
                
$url add_query_arg$query_vars$url );
                
$element->setAttribute$attribute_name$url );
            }
        }
    }

    
/**
     * Determine whether a URL is for the frontend.
     *
     * @param string $url URL.
     * @return bool Whether it is a frontend URL.
     */
    
public function is_frontend_url$url ) {
        
$parsed_url wp_parse_url$url );

        if ( ! empty( 
$parsed_url['scheme'] ) && ! in_arraystrtolower$parsed_url['scheme'] ), [ 'http''https' ], true ) ) {
            return 
false;
        }

        
// Skip adding query var to links on other URLs.
        
if ( ! empty( $parsed_url['host'] ) && $this->home_host !== $parsed_url['host'] ) {
            return 
false;
        }

        
// Skip adding query var to PHP files (e.g. wp-login.php).
        
if ( ! empty( $parsed_url['path'] ) && preg_match'/\.php$/'$parsed_url['path'] ) ) {
            return 
false;
        }

        
// Skip adding query var to feed URLs.
        
if ( ! empty( $parsed_url['path'] ) && preg_match':/feed/(\w+/)?$:'$parsed_url['path'] ) ) {
            return 
false;
        }

        
// Skip adding query var to the admin.
        
if ( ! empty( $parsed_url['path'] ) && false !== strpos$parsed_url['path'], $this->admin_path ) ) {
            return 
false;
        }

        
// Skip adding query var to content links (e.g. images).
        
if ( ! empty( $parsed_url['path'] ) && false !== strpos$parsed_url['path'], $this->content_path ) ) {
            return 
false;
        }

        return 
true;
    }
}
x

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