PluginProbe
Advanced Custom Fields (ACF®) / 6.8.1
Advanced Custom Fields (ACF®) v6.8.1
6.8.9 6.8.8 6.8.7 6.8.6 6.8.5 6.8.4 6.8.3 6.8.2 6.8.1 5.8.5 5.8.6 5.8.7 5.8.8 5.8.9 5.9.0 5.9.1 5.9.2 5.9.3 5.9.4 5.9.5 5.9.6 5.9.7 5.9.8 5.9.9 6.0.0 All 230 releases
advanced-custom-fields / includes / assets.php
assets.php
626 lines 16.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package ACF
4 * @author WP Engine
5 *
6 * © 2026 Advanced Custom Fields (ACF®). All rights reserved.
7 * "ACF" is a trademark of WP Engine.
8 * Licensed under the GNU General Public License v2 or later.
9 * https://www.gnu.org/licenses/gpl-2.0.html
10 */
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit; // Exit if accessed directly
14 }
15
16 if ( ! class_exists( 'ACF_Assets' ) ) :
17
18 class ACF_Assets {
19
20 /**
21 * Storage for i18n data.
22 *
23 * @since 5.6.9
24 * @var array
25 */
26 public $text = array();
27
28 /**
29 * Storage for l10n data.
30 *
31 * @since 5.6.9
32 * @var array
33 */
34 public $data = array();
35
36 /**
37 * List of enqueue flags.
38 *
39 * @since 5.9.0
40 * @var boolean
41 */
42 private $enqueue = array();
43
44 /**
45 * Constructor.
46 *
47 * @date 10/4/18
48 * @since 5.6.9
49 *
50 * @param void
51 * @return void
52 */
53 public function __construct() {
54 add_action( 'init', array( $this, 'register_scripts' ) );
55 }
56
57 /**
58 * Magic __call method for backwards compatibility.
59 *
60 * @date 10/4/20
61 * @since 5.9.0
62 *
63 * @param string $name The method name.
64 * @param array $arguments The array of arguments.
65 * @return mixed
66 */
67 public function __call( $name, $arguments ) {
68 switch ( $name ) {
69 case 'admin_enqueue_scripts':
70 case 'admin_print_scripts':
71 case 'admin_head':
72 case 'admin_footer':
73 case 'admin_print_footer_scripts':
74 _doing_it_wrong( __FUNCTION__, 'The ACF_Assets class should not be accessed directly.', '5.9.0' );
75 }
76 }
77
78 /**
79 * Appends an array of i18n data.
80 *
81 * @date 13/4/18
82 * @since 5.6.9
83 *
84 * @param array $text An array of text for i18n.
85 * @return void
86 */
87 public function add_text( $text ) {
88 foreach ( (array) $text as $k => $v ) {
89 $this->text[ $k ] = $v;
90 }
91 }
92
93 /**
94 * Appends an array of l10n data.
95 *
96 * @date 13/4/18
97 * @since 5.6.9
98 *
99 * @param array $data An array of data for l10n.
100 * @return void
101 */
102 public function add_data( $data ) {
103 foreach ( (array) $data as $k => $v ) {
104 $this->data[ $k ] = $v;
105 }
106 }
107
108 /**
109 * Registers the ACF scripts and styles.
110 *
111 * @date 10/4/18
112 * @since 5.6.9
113 *
114 * @param void
115 * @return void
116 */
117 public function register_scripts() {
118 // Extract vars.
119 $suffix = defined( 'ACF_DEVELOPMENT_MODE' ) && ACF_DEVELOPMENT_MODE ? '' : '.min';
120 $version = acf_get_setting( 'version' );
121
122 // Register scripts.
123 wp_register_script( 'acf', acf_get_url( 'assets/build/js/acf' . $suffix . '.js' ), array( 'jquery' ), $version );
124 wp_register_script( 'acf-input', acf_get_url( 'assets/build/js/acf-input' . $suffix . '.js' ), array( 'jquery', 'jquery-ui-sortable', 'jquery-ui-resizable', 'acf', 'wp-a11y' ), $version );
125 wp_register_script( 'acf-field-group', acf_get_url( 'assets/build/js/acf-field-group' . $suffix . '.js' ), array( 'acf-input' ), $version );
126 wp_register_script( 'acf-internal-post-type', acf_get_url( 'assets/build/js/acf-internal-post-type' . $suffix . '.js' ), array( 'acf-input' ), $version );
127 wp_register_script( 'acf-escaped-html-notice', acf_get_url( 'assets/build/js/acf-escaped-html-notice' . $suffix . '.js' ), array( 'jquery' ), $version, true );
128
129 // Register styles.
130 wp_register_style( 'acf-global', acf_get_url( 'assets/build/css/acf-global' . $suffix . '.css' ), array( 'dashicons' ), $version );
131 wp_register_style( 'acf-input', acf_get_url( 'assets/build/css/acf-input' . $suffix . '.css' ), array( 'acf-global' ), $version );
132 wp_register_style( 'acf-field-group', acf_get_url( 'assets/build/css/acf-field-group' . $suffix . '.css' ), array( 'acf-input' ), $version );
133
134 /**
135 * Fires after core scripts and styles have been registered.
136 *
137 * @since 5.6.9
138 *
139 * @param string $version The ACF version.
140 * @param string $suffix The potential ".min" filename suffix.
141 */
142 do_action( 'acf/register_scripts', $version, $suffix );
143 }
144
145 /**
146 * Enqueues a script and sets up actions for priting supplemental scripts.
147 *
148 * @date 27/4/20
149 * @since 5.9.0
150 *
151 * @param string $name The script name.
152 * @return void
153 */
154 public function enqueue_script( $name ) {
155 wp_enqueue_script( $name );
156 $this->add_actions();
157 }
158
159 /**
160 * Enqueues a style.
161 *
162 * @date 27/4/20
163 * @since 5.9.0
164 *
165 * @param string $name The style name.
166 * @return void
167 */
168 public function enqueue_style( $name ) {
169 wp_enqueue_style( $name );
170 }
171
172 /**
173 * Adds the actions needed to print supporting inline scripts.
174 *
175 * @date 27/4/20
176 * @since 5.9.0
177 *
178 * @param void
179 * @return void
180 */
181 private function add_actions() {
182
183 // Only run once.
184 if ( acf_has_done( 'ACF_Assets::add_actions' ) ) {
185 return;
186 }
187
188 // Add actions.
189 $this->add_action( 'admin_enqueue_scripts', 'enqueue_scripts', 20 );
190 $this->add_action( 'admin_print_scripts', 'print_scripts', 20 );
191 $this->add_action( 'admin_print_footer_scripts', 'print_footer_scripts', 20 );
192 }
193
194 /**
195 * Extends the add_action() function with two additional features:
196 * 1. Renames $action depending on the current page (customizer, login, front-end).
197 * 2. Alters the priotiry or calls the method directly if the action has already passed.
198 *
199 * @date 28/4/20
200 * @since 5.9.0
201 *
202 * @param string $action The action name.
203 * @param string $method The method name.
204 * @param integer $priority See add_action().
205 * @param integer $accepted_args See add_action().
206 * @return void
207 */
208 public function add_action( $action, $method, $priority = 10, $accepted_args = 1 ) {
209
210 // Generate an array of action replacements.
211 $replacements = array(
212 'customizer' => array(
213 'admin_enqueue_scripts' => 'admin_enqueue_scripts',
214 'admin_print_scripts' => 'customize_controls_print_scripts',
215 'admin_head' => 'customize_controls_print_scripts',
216 'admin_footer' => 'customize_controls_print_footer_scripts',
217 'admin_print_footer_scripts' => 'customize_controls_print_footer_scripts',
218 ),
219 'login' => array(
220 'admin_enqueue_scripts' => 'login_enqueue_scripts',
221 'admin_print_scripts' => 'login_head',
222 'admin_head' => 'login_head',
223 'admin_footer' => 'login_footer',
224 'admin_print_footer_scripts' => 'login_footer',
225 ),
226 'wp' => array(
227 'admin_enqueue_scripts' => 'wp_enqueue_scripts',
228 'admin_print_scripts' => 'wp_print_scripts',
229 'admin_head' => 'wp_head',
230 'admin_footer' => 'wp_footer',
231 'admin_print_footer_scripts' => 'wp_print_footer_scripts',
232 ),
233 );
234
235 // Determine the current context.
236 if ( did_action( 'customize_controls_init' ) ) {
237 $context = 'customizer';
238 } elseif ( did_action( 'login_form_register' ) ) {
239 $context = 'login';
240 } elseif ( is_admin() ) {
241 $context = 'admin';
242 } else {
243 $context = 'wp';
244 }
245
246 // Replace action if possible.
247 if ( isset( $replacements[ $context ][ $action ] ) ) {
248 $action = $replacements[ $context ][ $action ];
249 }
250
251 // Check if action is currently being or has already been run.
252 if ( did_action( $action ) ) {
253 $doing = acf_doing_action( $action );
254 if ( $doing && $doing < $priority ) {
255 // Allow action to be added as per usual.
256 } else {
257 // Call method directly.
258 return call_user_func( array( $this, $method ) );
259 }
260 }
261
262 // Add action.
263 add_action( $action, array( $this, $method ), $priority, $accepted_args );
264 }
265
266 /**
267 * Generic controller for enqueuing scripts and styles.
268 *
269 * @date 28/4/20
270 * @since 5.9.0
271 *
272 * @param array $args {
273 * @type bool $uploader Whether or not to enqueue uploader scripts.
274 * }
275 * @return void
276 */
277 public function enqueue( $args = array() ) {
278
279 // Apply defaults.
280 $args = wp_parse_args(
281 $args,
282 array(
283 'input' => true,
284 'uploader' => false,
285 )
286 );
287
288 // Set enqueue flags and add actions.
289 if ( $args['input'] ) {
290 $this->enqueue[] = 'input';
291 }
292 if ( $args['uploader'] ) {
293 $this->enqueue[] = 'uploader';
294 }
295 $this->add_actions();
296 }
297
298 /**
299 * Enqueues the scripts and styles needed for the WP media uploader.
300 *
301 * @date 27/10/2014
302 * @since 5.0.9
303 *
304 * @param void
305 * @return void
306 */
307 public function enqueue_uploader() {
308
309 // Only run once.
310 if ( acf_has_done( 'ACF_Assets::enqueue_uploader' ) ) {
311 return;
312 }
313
314 // Enqueue media assets.
315 if ( current_user_can( 'upload_files' ) ) {
316 wp_enqueue_media();
317 }
318
319 // Add actions.
320 $this->add_action( 'admin_footer', 'print_uploader_scripts', 1 );
321
322 /**
323 * Fires when enqueuing the uploader.
324 *
325 * @since 5.6.9
326 *
327 * @param void
328 */
329 do_action( 'acf/enqueue_uploader' );
330 }
331
332 /**
333 * Enqueues and localizes scripts.
334 *
335 * @since 5.9.0
336 *
337 * @return void
338 */
339 public function enqueue_scripts() {
340 // Enqueue input scripts.
341 if ( in_array( 'input', $this->enqueue, true ) ) {
342 wp_enqueue_script( 'acf-input' );
343 wp_enqueue_style( 'acf-input' );
344 }
345
346 // Enqueue media scripts.
347 if ( in_array( 'uploader', $this->enqueue, true ) ) {
348 $this->enqueue_uploader();
349 }
350
351 // Localize text.
352 acf_localize_text(
353 array(
354 // Tooltip
355 'Are you sure?' => esc_html__( 'Are you sure?', 'acf' ),
356 'Yes' => esc_html__( 'Yes', 'acf' ),
357 'No' => esc_html__( 'No', 'acf' ),
358 'Remove' => esc_html__( 'Remove', 'acf' ),
359 'Cancel' => esc_html__( 'Cancel', 'acf' ),
360 'Close modal' => esc_html__( 'Close modal', 'acf' ),
361 )
362 );
363
364 // Localize "input" text.
365 if ( wp_script_is( 'acf-input' ) ) {
366 acf_localize_text(
367 array(
368 // Unload
369 'The changes you made will be lost if you navigate away from this page' => esc_html__( 'The changes you made will be lost if you navigate away from this page', 'acf' ),
370
371 // Metaboxes
372 'Toggle panel' => __( 'Toggle panel', 'acf' ),
373
374 // Validation
375 'Validation successful' => esc_html__( 'Validation successful', 'acf' ),
376 'Validation failed' => esc_html__( 'Validation failed', 'acf' ),
377 '1 field requires attention' => esc_html__( '1 field requires attention', 'acf' ),
378 /* translators: %d is the number of fields that require attention */
379 '%d fields require attention' => esc_html__( '%d fields require attention', 'acf' ),
380
381 // Block Validation
382 'An ACF Block on this page requires attention before you can save.' => esc_html__( 'An ACF Block on this page requires attention before you can save.', 'acf' ),
383
384 // Other
385 'Edit field group' => esc_html__( 'Edit field group', 'acf' ),
386 )
387 );
388
389 /**
390 * Fires during "admin_enqueue_scripts" when ACF scripts are enqueued.
391 *
392 * @since 5.6.9
393 */
394 do_action( 'acf/input/admin_enqueue_scripts' );
395 }
396
397 /**
398 * Fires during "admin_enqueue_scripts" when ACF scripts are enqueued.
399 *
400 * @since 5.6.9
401 */
402 do_action( 'acf/admin_enqueue_scripts' );
403 do_action( 'acf/enqueue_scripts' );
404
405 // Filter i18n translations that differ from English and localize script.
406 $text = array();
407 foreach ( $this->text as $k => $v ) {
408 if ( str_replace( '.verb', '', $k ) !== $v ) {
409 $text[ $k ] = $v;
410 }
411 }
412
413 if ( $text ) {
414 wp_localize_script( 'acf', 'acfL10n', $text );
415 }
416 }
417
418 /**
419 * Prints scripts in head.
420 *
421 * @date 27/4/20
422 * @since 5.9.0
423 *
424 * @param void
425 * @return void
426 */
427 public function print_scripts() {
428 if ( wp_script_is( 'acf-input' ) ) {
429
430 /**
431 * Fires during "admin_head" when ACF scripts are enqueued.
432 *
433 * @since 5.6.9
434 *
435 * @param void
436 */
437 do_action( 'acf/input/admin_head' );
438 do_action( 'acf/input/admin_print_scripts' );
439 }
440
441 /**
442 * Fires during "admin_head" when ACF scripts are enqueued.
443 *
444 * @since 5.6.9
445 *
446 * @param void
447 */
448 do_action( 'acf/admin_head' );
449 do_action( 'acf/admin_print_scripts' );
450 }
451
452 /**
453 * Prints scripts in footer.
454 *
455 * @date 27/4/20
456 * @since 5.9.0
457 *
458 * @param void
459 * @return void
460 */
461 public function print_footer_scripts() {
462 global $wp_version;
463
464 // Bail early if 'acf' script was never enqueued (fixes Elementor enqueue reset conflict).
465 if ( ! wp_script_is( 'acf' ) ) {
466 return;
467 }
468
469 // Localize data.
470 $data_to_localize = array(
471 'admin_url' => admin_url(),
472 'ajaxurl' => admin_url( 'admin-ajax.php' ),
473 'nonce' => wp_create_nonce( 'acf_nonce' ),
474 'acf_version' => acf_get_setting( 'version' ),
475 'wp_version' => $wp_version,
476 'browser' => acf_get_browser(),
477 'locale' => acf_get_locale(),
478 'rtl' => is_rtl(),
479 'screen' => acf_get_form_data( 'screen' ),
480 'post_id' => acf_get_form_data( 'post_id' ),
481 'validation' => acf_get_form_data( 'validation' ),
482 'editor' => acf_is_block_editor() ? 'block' : 'classic',
483 'is_pro' => acf_is_pro(),
484 'debug' => acf_is_beta() || ( defined( 'ACF_DEVELOPMENT_MODE' ) && ACF_DEVELOPMENT_MODE ),
485 'StrictMode' => defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG && version_compare( $wp_version, '6.6', '>=' ),
486 );
487
488 acf_localize_data( $data_to_localize );
489
490 // Print inline script.
491 wp_print_inline_script_tag( 'acf.data = ' . wp_json_encode( $this->data ) . ';' );
492
493 if ( wp_script_is( 'acf-input' ) ) {
494
495 /**
496 * Filters an empty array for compat l10n data.
497 *
498 * @since 5.0.0
499 *
500 * @param array $data An array of data to append to.
501 */
502 $compat_l10n = apply_filters( 'acf/input/admin_l10n', array() );
503 if ( $compat_l10n ) {
504 wp_print_inline_script_tag( 'acf.l10n = ' . wp_json_encode( $compat_l10n ) . ';' );
505 }
506
507 /**
508 * Fires during "admin_footer" when ACF scripts are enqueued.
509 *
510 * @since 5.6.9
511 */
512 do_action( 'acf/input/admin_footer' );
513 do_action( 'acf/input/admin_print_footer_scripts' );
514 }
515
516 /**
517 * Fires during "admin_footer" when ACF scripts are enqueued.
518 *
519 * @since 5.6.9
520 *
521 * @param void
522 */
523 do_action( 'acf/admin_footer' );
524 do_action( 'acf/admin_print_footer_scripts' );
525
526 // Once all data is localized, trigger acf.prepare() to execute functionality before DOM ready.
527 wp_print_inline_script_tag( "acf.doAction( 'prepare' );" );
528 }
529
530 /**
531 * Prints uploader scripts in footer.
532 *
533 * @date 11/06/2020
534 * @since 5.9.0
535 *
536 * @param void
537 * @return void
538 */
539 public function print_uploader_scripts() {
540 // Todo: investigate output-buffer to hide HTML.
541 ?>
542 <div id="acf-hidden-wp-editor" style="display: none;">
543 <?php wp_editor( '', 'acf_content' ); ?>
544 </div>
545 <?php
546
547 /**
548 * Fires when printing uploader scripts.
549 *
550 * @since 5.6.9
551 *
552 * @param void
553 */
554 do_action( 'acf/admin_print_uploader_scripts' );
555 }
556 }
557
558 // instantiate
559 acf_new_instance( 'ACF_Assets' );
560 endif; // class_exists check
561
562 /**
563 * Appends an array of i18n data for localization.
564 *
565 * @date 13/4/18
566 * @since 5.6.9
567 *
568 * @param array $text An array of text for i18n.
569 * @return void
570 */
571 function acf_localize_text( $text ) {
572 return acf_get_instance( 'ACF_Assets' )->add_text( $text );
573 }
574
575 /**
576 * Appends an array of l10n data for localization.
577 *
578 * @date 13/4/18
579 * @since 5.6.9
580 *
581 * @param array $data An array of data for l10n.
582 * @return void
583 */
584 function acf_localize_data( $data ) {
585 return acf_get_instance( 'ACF_Assets' )->add_data( $data );
586 }
587
588 /**
589 * Enqueues a script with support for supplemental inline scripts.
590 *
591 * @date 27/4/20
592 * @since 5.9.0
593 *
594 * @param string $name The script name.
595 * @return void
596 */
597 function acf_enqueue_script( $name ) {
598 return acf_get_instance( 'ACF_Assets' )->enqueue_script( $name );
599 }
600
601 /**
602 * Enqueues the input scripts required for fields.
603 *
604 * @date 13/4/18
605 * @since 5.6.9
606 *
607 * @param array $args See ACF_Assets::enqueue_scripts() for a list of args.
608 * @return void
609 */
610 function acf_enqueue_scripts( $args = array() ) {
611 return acf_get_instance( 'ACF_Assets' )->enqueue( $args );
612 }
613
614 /**
615 * Enqueues the WP media uploader scripts and styles.
616 *
617 * @date 27/10/2014
618 * @since 5.0.9
619 *
620 * @param void
621 * @return void
622 */
623 function acf_enqueue_uploader() {
624 return acf_get_instance( 'ACF_Assets' )->enqueue_uploader();
625 }
626