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