WordPress.org

Make WordPress Core

Ticket #42804: class.wp-scripts.php

File class.wp-scripts.php, 13.7 KB (added by sasiddiqui, 3 years ago)

Fixed the type issue with enqueue and inline script tags

Line 
1<?php
2/**
3 * Dependencies API: WP_Scripts class
4 *
5 * @since 2.6.0
6 *
7 * @package WordPress
8 * @subpackage Dependencies
9 */
10
11/**
12 * Core class used to register scripts.
13 *
14 * @since 2.1.0
15 *
16 * @see WP_Dependencies
17 */
18class WP_Scripts extends WP_Dependencies {
19        /**
20         * Base URL for scripts.
21         *
22         * Full URL with trailing slash.
23         *
24         * @since 2.6.0
25         * @var string
26         */
27        public $base_url;
28
29        /**
30         * URL of the content directory.
31         *
32         * @since 2.8.0
33         * @var string
34         */
35        public $content_url;
36
37        /**
38         * Default version string for stylesheets.
39         *
40         * @since 2.6.0
41         * @var string
42         */
43        public $default_version;
44
45        /**
46         * Holds handles of scripts which are enqueued in footer.
47         *
48         * @since 2.8.0
49         * @var array
50         */
51        public $in_footer = array();
52
53        /**
54         * Holds a list of script handles which will be concatenated.
55         *
56         * @since 2.8.0
57         * @var string
58         */
59        public $concat = '';
60
61        /**
62         * Holds a string which contains script handles and their version.
63         *
64         * @since 2.8.0
65         * @deprecated 3.4.0
66         * @var string
67         */
68        public $concat_version = '';
69
70        /**
71         * Whether to perform concatenation.
72         *
73         * @since 2.8.0
74         * @var bool
75         */
76        public $do_concat = false;
77
78        /**
79         * Holds HTML markup of scripts and additional data if concatenation
80         * is enabled.
81         *
82         * @since 2.8.0
83         * @var string
84         */
85        public $print_html = '';
86
87        /**
88         * Holds inline code if concatenation is enabled.
89         *
90         * @since 2.8.0
91         * @var string
92         */
93        public $print_code = '';
94
95        /**
96         * Holds a list of script handles which are not in the default directory
97         * if concatenation is enabled.
98         *
99         * Unused in core.
100         *
101         * @since 2.8.0
102         * @var string
103         */
104        public $ext_handles = '';
105
106        /**
107         * Holds a string which contains handles and versions of scripts which
108         * are not in the default directory if concatenation is enabled.
109         *
110         * Unused in core.
111         *
112         * @since 2.8.0
113         * @var string
114         */
115        public $ext_version = '';
116
117        /**
118         * List of default directories.
119         *
120         * @since 2.8.0
121         * @var array
122         */
123        public $default_dirs;
124
125        /**
126         * Constructor.
127         *
128         * @since 2.6.0
129         */
130        public function __construct() {
131                $this->init();
132                add_action( 'init', array( $this, 'init' ), 0 );
133        }
134
135        /**
136         * Initialize the class.
137         *
138         * @since 3.4.0
139         */
140        public function init() {
141                /**
142                 * Fires when the WP_Scripts instance is initialized.
143                 *
144                 * @since 2.6.0
145                 *
146                 * @param WP_Scripts $this WP_Scripts instance (passed by reference).
147                 */
148                do_action_ref_array( 'wp_default_scripts', array(&$this) );
149        }
150
151        /**
152         * Prints scripts.
153         *
154         * Prints the scripts passed to it or the print queue. Also prints all necessary dependencies.
155         *
156         * @since 2.1.0
157         * @since 2.8.0 Added the `$group` parameter.
158         *
159         * @param mixed $handles Optional. Scripts to be printed. (void) prints queue, (string) prints
160         *                       that script, (array of strings) prints those scripts. Default false.
161         * @param int   $group   Optional. If scripts were queued in groups prints this group number.
162         *                       Default false.
163         * @return array Scripts that have been printed.
164         */
165        public function print_scripts( $handles = false, $group = false ) {
166                return $this->do_items( $handles, $group );
167        }
168
169        /**
170         * Prints extra scripts of a registered script.
171         *
172         * @since 2.1.0
173         * @since 2.8.0 Added the `$echo` parameter.
174         * @deprecated 3.3.0
175         *
176         * @see print_extra_script()
177         *
178         * @param string $handle The script's registered handle.
179         * @param bool   $echo   Optional. Whether to echo the extra script instead of just returning it.
180         *                       Default true.
181         * @return bool|string|void Void if no data exists, extra scripts if `$echo` is true, true otherwise.
182         */
183        public function print_scripts_l10n( $handle, $echo = true ) {
184                _deprecated_function( __FUNCTION__, '3.3.0', 'WP_Scripts::print_extra_script()' );
185                return $this->print_extra_script( $handle, $echo );
186        }
187
188        /**
189         * Prints extra scripts of a registered script.
190         *
191         * @since 3.3.0
192         *
193         * @param string $handle The script's registered handle.
194         * @param bool   $echo   Optional. Whether to echo the extra script instead of just returning it.
195         *                       Default true.
196         * @return bool|string|void Void if no data exists, extra scripts if `$echo` is true, true otherwise.
197         */
198        public function print_extra_script( $handle, $echo = true ) {
199                if ( !$output = $this->get_data( $handle, 'data' ) )
200                        return;
201
202                if ( !$echo )
203                        return $output;
204
205                echo "<script>\n"; // CDATA and type='text/javascript' is not needed for HTML 5
206                echo "/* <![CDATA[ */\n";
207                echo "$output\n";
208                echo "/* ]]> */\n";
209                echo "</script>\n";
210
211                return true;
212        }
213
214        /**
215         * Processes a script dependency.
216         *
217         * @since 2.6.0
218         * @since 2.8.0 Added the `$group` parameter.
219         *
220         * @see WP_Dependencies::do_item()
221         *
222         * @param string $handle    The script's registered handle.
223         * @param int|false $group  Optional. Group level: (int) level, (false) no groups. Default false.
224         * @return bool True on success, false on failure.
225         */
226        public function do_item( $handle, $group = false ) {
227                if ( !parent::do_item($handle) )
228                        return false;
229
230                if ( 0 === $group && $this->groups[$handle] > 0 ) {
231                        $this->in_footer[] = $handle;
232                        return false;
233                }
234
235                if ( false === $group && in_array($handle, $this->in_footer, true) )
236                        $this->in_footer = array_diff( $this->in_footer, (array) $handle );
237
238                $obj = $this->registered[$handle];
239
240                if ( null === $obj->ver ) {
241                        $ver = '';
242                } else {
243                        $ver = $obj->ver ? $obj->ver : $this->default_version;
244                }
245
246                if ( isset($this->args[$handle]) )
247                        $ver = $ver ? $ver . '&amp;' . $this->args[$handle] : $this->args[$handle];
248
249                $src = $obj->src;
250                $cond_before = $cond_after = '';
251                $conditional = isset( $obj->extra['conditional'] ) ? $obj->extra['conditional'] : '';
252
253                if ( $conditional ) {
254                        $cond_before = "<!--[if {$conditional}]>\n";
255                        $cond_after = "<![endif]-->\n";
256                }
257
258                $before_handle = $this->print_inline_script( $handle, 'before', false );
259                $after_handle = $this->print_inline_script( $handle, 'after', false );
260
261                if ( $before_handle ) {
262                        $before_handle = sprintf( "<script>\n%s\n</script>\n", $before_handle );
263                }
264
265                if ( $after_handle ) {
266                        $after_handle = sprintf( "<script>\n%s\n</script>\n", $after_handle );
267                }
268
269                if ( $this->do_concat ) {
270                        /**
271                         * Filters the script loader source.
272                         *
273                         * @since 2.2.0
274                         *
275                         * @param string $src    Script loader source path.
276                         * @param string $handle Script handle.
277                         */
278                        $srce = apply_filters( 'script_loader_src', $src, $handle );
279
280                        if ( $this->in_default_dir( $srce ) && ( $before_handle || $after_handle ) ) {
281                                $this->do_concat = false;
282
283                                // Have to print the so-far concatenated scripts right away to maintain the right order.
284                                _print_scripts();
285                                $this->reset();
286                        } elseif ( $this->in_default_dir( $srce ) && ! $conditional ) {
287                                $this->print_code .= $this->print_extra_script( $handle, false );
288                                $this->concat .= "$handle,";
289                                $this->concat_version .= "$handle$ver";
290                                return true;
291                        } else {
292                                $this->ext_handles .= "$handle,";
293                                $this->ext_version .= "$handle$ver";
294                        }
295                }
296
297                $has_conditional_data = $conditional && $this->get_data( $handle, 'data' );
298
299                if ( $has_conditional_data ) {
300                        echo $cond_before;
301                }
302
303                $this->print_extra_script( $handle );
304
305                if ( $has_conditional_data ) {
306                        echo $cond_after;
307                }
308
309                // A single item may alias a set of items, by having dependencies, but no source.
310                if ( ! $obj->src ) {
311                        return true;
312                }
313
314                if ( ! preg_match( '|^(https?:)?//|', $src ) && ! ( $this->content_url && 0 === strpos( $src, $this->content_url ) ) ) {
315                        $src = $this->base_url . $src;
316                }
317
318                if ( ! empty( $ver ) )
319                        $src = add_query_arg( 'ver', $ver, $src );
320
321                /** This filter is documented in wp-includes/class.wp-scripts.php */
322                $src = esc_url( apply_filters( 'script_loader_src', $src, $handle ) );
323
324                if ( ! $src )
325                        return true;
326
327                $tag = "{$cond_before}{$before_handle}<script src='$src'></script>\n{$after_handle}{$cond_after}";
328
329                /**
330                 * Filters the HTML script tag of an enqueued script.
331                 *
332                 * @since 4.1.0
333                 *
334                 * @param string $tag    The `<script>` tag for the enqueued script.
335                 * @param string $handle The script's registered handle.
336                 * @param string $src    The script's source URL.
337                 */
338                $tag = apply_filters( 'script_loader_tag', $tag, $handle, $src );
339
340                if ( $this->do_concat ) {
341                        $this->print_html .= $tag;
342                } else {
343                        echo $tag;
344                }
345
346                return true;
347        }
348
349        /**
350         * Adds extra code to a registered script.
351         *
352         * @since 4.5.0
353         *
354         * @param string $handle   Name of the script to add the inline script to. Must be lowercase.
355         * @param string $data     String containing the javascript to be added.
356         * @param string $position Optional. Whether to add the inline script before the handle
357         *                         or after. Default 'after'.
358         * @return bool True on success, false on failure.
359         */
360        public function add_inline_script( $handle, $data, $position = 'after' ) {
361                if ( ! $data ) {
362                        return false;
363                }
364
365                if ( 'after' !== $position ) {
366                        $position = 'before';
367                }
368
369                $script   = (array) $this->get_data( $handle, $position );
370                $script[] = $data;
371
372                return $this->add_data( $handle, $position, $script );
373        }
374
375        /**
376         * Prints inline scripts registered for a specific handle.
377         *
378         * @since 4.5.0
379         *
380         * @param string $handle   Name of the script to add the inline script to. Must be lowercase.
381         * @param string $position Optional. Whether to add the inline script before the handle
382         *                         or after. Default 'after'.
383         * @param bool $echo       Optional. Whether to echo the script instead of just returning it.
384         *                         Default true.
385         * @return string|false Script on success, false otherwise.
386         */
387        public function print_inline_script( $handle, $position = 'after', $echo = true ) {
388                $output = $this->get_data( $handle, $position );
389
390                if ( empty( $output ) ) {
391                        return false;
392                }
393
394                $output = trim( implode( "\n", $output ), "\n" );
395
396                if ( $echo ) {
397                        printf( "<script>\n%s\n</script>\n", $output );
398                }
399
400                return $output;
401        }
402
403        /**
404         * Localizes a script, only if the script has already been added.
405         *
406         * @since 2.1.0
407         *
408         * @param string $handle
409         * @param string $object_name
410         * @param array $l10n
411         * @return bool
412         */
413        public function localize( $handle, $object_name, $l10n ) {
414                if ( $handle === 'jquery' )
415                        $handle = 'jquery-core';
416
417                if ( is_array($l10n) && isset($l10n['l10n_print_after']) ) { // back compat, preserve the code in 'l10n_print_after' if present
418                        $after = $l10n['l10n_print_after'];
419                        unset($l10n['l10n_print_after']);
420                }
421
422                foreach ( (array) $l10n as $key => $value ) {
423                        if ( !is_scalar($value) )
424                                continue;
425
426                        $l10n[$key] = html_entity_decode( (string) $value, ENT_QUOTES, 'UTF-8');
427                }
428
429                $script = "var $object_name = " . wp_json_encode( $l10n ) . ';';
430
431                if ( !empty($after) )
432                        $script .= "\n$after;";
433
434                $data = $this->get_data( $handle, 'data' );
435
436                if ( !empty( $data ) )
437                        $script = "$data\n$script";
438
439                return $this->add_data( $handle, 'data', $script );
440        }
441
442        /**
443         * Sets handle group.
444         *
445         * @since 2.8.0
446         *
447         * @see WP_Dependencies::set_group()
448         *
449         * @param string    $handle    Name of the item. Should be unique.
450         * @param bool      $recursion Internal flag that calling function was called recursively.
451         * @param int|false $group     Optional. Group level: (int) level, (false) no groups. Default false.
452         * @return bool Not already in the group or a lower group
453         */
454        public function set_group( $handle, $recursion, $group = false ) {
455                if ( isset( $this->registered[$handle]->args ) && $this->registered[$handle]->args === 1 )
456                        $grp = 1;
457                else
458                        $grp = (int) $this->get_data( $handle, 'group' );
459
460                if ( false !== $group && $grp > $group )
461                        $grp = $group;
462
463                return parent::set_group( $handle, $recursion, $grp );
464        }
465
466        /**
467         * Determines script dependencies.
468     *
469         * @since 2.1.0
470         *
471         * @see WP_Dependencies::all_deps()
472         *
473         * @param mixed     $handles   Item handle and argument (string) or item handles and arguments (array of strings).
474         * @param bool      $recursion Internal flag that function is calling itself.
475         * @param int|false $group     Optional. Group level: (int) level, (false) no groups. Default false.
476         * @return bool True on success, false on failure.
477         */
478        public function all_deps( $handles, $recursion = false, $group = false ) {
479                $r = parent::all_deps( $handles, $recursion, $group );
480                if ( ! $recursion ) {
481                        /**
482                         * Filters the list of script dependencies left to print.
483                         *
484                         * @since 2.3.0
485                         *
486                         * @param array $to_do An array of script dependencies.
487                         */
488                        $this->to_do = apply_filters( 'print_scripts_array', $this->to_do );
489                }
490                return $r;
491        }
492
493        /**
494         * Processes items and dependencies for the head group.
495         *
496         * @since 2.8.0
497         *
498         * @see WP_Dependencies::do_items()
499         *
500         * @return array Handles of items that have been processed.
501         */
502        public function do_head_items() {
503                $this->do_items(false, 0);
504                return $this->done;
505        }
506
507        /**
508         * Processes items and dependencies for the footer group.
509         *
510         * @since 2.8.0
511         *
512         * @see WP_Dependencies::do_items()
513         *
514         * @return array Handles of items that have been processed.
515         */
516        public function do_footer_items() {
517                $this->do_items(false, 1);
518                return $this->done;
519        }
520
521        /**
522         * Whether a handle's source is in a default directory.
523         *
524         * @since 2.8.0
525         *
526         * @param string $src The source of the enqueued script.
527         * @return bool True if found, false if not.
528         */
529        public function in_default_dir( $src ) {
530                if ( ! $this->default_dirs ) {
531                        return true;
532                }
533
534                if ( 0 === strpos( $src, '/' . WPINC . '/js/l10n' ) ) {
535                        return false;
536                }
537
538                foreach ( (array) $this->default_dirs as $test ) {
539                        if ( 0 === strpos( $src, $test ) ) {
540                                return true;
541                        }
542                }
543                return false;
544        }
545
546        /**
547         * Resets class properties.
548         *
549         * @since 2.8.0
550         */
551        public function reset() {
552                $this->do_concat = false;
553                $this->print_code = '';
554                $this->concat = '';
555                $this->concat_version = '';
556                $this->print_html = '';
557                $this->ext_version = '';
558                $this->ext_handles = '';
559        }
560}