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 / admin / admin.php
admin.php
438 lines 14.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_Admin' ) ) :
17
18 class ACF_Admin {
19
20 /**
21 * Constructor.
22 *
23 * @since 5.0.0
24 */
25 public function __construct() {
26 add_action( 'admin_menu', array( $this, 'admin_menu' ) );
27 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
28 add_action( 'admin_body_class', array( $this, 'admin_body_class' ) );
29 add_action( 'current_screen', array( $this, 'current_screen' ) );
30 add_action( 'admin_notices', array( $this, 'maybe_show_escaped_html_notice' ) );
31 add_action( 'admin_notices', array( $this, 'maybe_show_select2_v3_deprecation_notice' ) );
32 add_action( 'admin_init', array( $this, 'dismiss_escaped_html_notice' ) );
33 add_action( 'admin_init', array( $this, 'clear_escaped_html_log' ) );
34 add_filter( 'parent_file', array( $this, 'ensure_menu_selection' ) );
35 add_filter( 'submenu_file', array( $this, 'ensure_submenu_selection' ) );
36 }
37
38 /**
39 * Adds the ACF menu item.
40 *
41 * @date 28/09/13
42 * @since 5.0.0
43 */
44 public function admin_menu() {
45
46 // Bail early if ACF is hidden.
47 if ( ! acf_get_setting( 'show_admin' ) ) {
48 return;
49 }
50
51 // Vars.
52 $cap = acf_get_setting( 'capability' );
53 $parent_slug = 'edit.php?post_type=acf-field-group';
54
55 // Add menu items.
56 add_menu_page( __( 'ACF', 'acf' ), __( 'ACF', 'acf' ), $cap, $parent_slug, false, 'dashicons-welcome-widgets-menus', 80 );
57 }
58
59 /**
60 * Enqueues global admin styling.
61 *
62 * @since 5.0.0
63 */
64 public function admin_enqueue_scripts() {
65 wp_enqueue_style( 'acf-global' );
66 wp_enqueue_script( 'acf-escaped-html-notice' );
67
68 wp_localize_script(
69 'acf-escaped-html-notice',
70 'acf_escaped_html_notice',
71 array(
72 'show_details' => __( 'Show&nbsp;details', 'acf' ),
73 'hide_details' => __( 'Hide&nbsp;details', 'acf' ),
74 )
75 );
76 }
77
78 /**
79 * Appends custom admin body classes.
80 *
81 * @date 5/11/19
82 * @since 5.8.7
83 *
84 * @param string $classes Space-separated list of CSS classes.
85 * @return string
86 */
87 public function admin_body_class( $classes ) {
88 global $wp_version;
89
90 // Add body class.
91 $classes .= ' acf-admin-5-3';
92
93 // Add browser for specific CSS.
94 $classes .= ' acf-browser-' . esc_attr( acf_get_browser() );
95
96 // Return classes.
97 return $classes;
98 }
99
100 /**
101 * Adds custom functionality to "ACF" admin pages.
102 *
103 * @date 7/4/20
104 * @since 5.9.0
105 *
106 * @param void
107 * @return void
108 */
109 public function current_screen( $screen ) {
110 // Determine if the current page being viewed is "ACF" related.
111 if ( isset( $screen->post_type ) && in_array( $screen->post_type, acf_get_internal_post_types(), true ) ) {
112 add_action( 'in_admin_header', array( $this, 'in_admin_header' ) );
113 add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ) );
114 add_filter( 'update_footer', array( $this, 'admin_footer_version_text' ) );
115 $this->setup_help_tab();
116 $this->maybe_show_import_from_cptui_notice();
117 }
118 }
119
120 /**
121 * Sets up the admin help tab.
122 *
123 * @date 20/4/20
124 * @since 5.9.0
125 *
126 * @param void
127 * @return void
128 */
129 public function setup_help_tab() {
130 $screen = get_current_screen();
131
132 // Overview tab.
133 $screen->add_help_tab(
134 array(
135 'id' => 'overview',
136 'title' => __( 'Overview', 'acf' ),
137 'content' =>
138 '<p><strong>' . __( 'Overview', 'acf' ) . '</strong></p>' .
139 '<p>' . __( 'The Advanced Custom Fields plugin provides a visual form builder to customize WordPress edit screens with extra fields, and an intuitive API to display custom field values in any theme template file.', 'acf' ) . '</p>' .
140 '<p>' . sprintf(
141 __( 'Before creating your first Field Group, we recommend first reading our <a href="%s" target="_blank">Getting started</a> guide to familiarize yourself with the plugin\'s philosophy and best practises.', 'acf' ),
142 acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/resources/getting-started-with-acf/', 'docs', 'help-tab' )
143 ) . '</p>' .
144 '<p>' . __( 'Please use the Help & Support tab to get in touch should you find yourself requiring assistance.', 'acf' ) . '</p>' .
145 '',
146 )
147 );
148
149 // Help tab.
150 $screen->add_help_tab(
151 array(
152 'id' => 'help',
153 'title' => __( 'Help & Support', 'acf' ),
154 'content' =>
155 '<p><strong>' . __( 'Help & Support', 'acf' ) . '</strong></p>' .
156 '<p>' . __( 'We are fanatical about support, and want you to get the best out of your website with ACF. If you run into any difficulties, there are several places you can find help:', 'acf' ) . '</p>' .
157 '<ul>' .
158 '<li>' . sprintf(
159 __( '<a href="%s" target="_blank">Documentation</a>. Our extensive documentation contains references and guides for most situations you may encounter.', 'acf' ),
160 acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/resources/', 'docs', 'help-tab' )
161 ) . '</li>' .
162 '<li>' . sprintf(
163 __( '<a href="%s" target="_blank">Discussions</a>. We have an active and friendly community on our Community Forums who may be able to help you figure out the \'how-tos\' of the ACF world.', 'acf' ),
164 acf_add_url_utm_tags( 'https://support.advancedcustomfields.com/', 'docs', 'help-tab' )
165 ) . '</li>' .
166 '<li>' . sprintf(
167 __( '<a href="%s" target="_blank">Help Desk</a>. The support professionals on our Help Desk will assist with your more in depth, technical challenges.', 'acf' ),
168 acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/support/', 'docs', 'help-tab' )
169 ) . '</li>' .
170 '</ul>',
171 )
172 );
173
174 // Sidebar.
175 $screen->set_help_sidebar(
176 '<p><strong>' . __( 'Information', 'acf' ) . '</strong></p>' .
177 '<p><span class="dashicons dashicons-admin-plugins"></span> ' . sprintf( __( 'Version %s', 'acf' ), ACF_VERSION ) . '</p>' .
178 '<p><span class="dashicons dashicons-wordpress"></span> <a href="https://wordpress.org/plugins/advanced-custom-fields/" target="_blank">' . __( 'View details', 'acf' ) . '</a></p>' .
179 '<p><span class="dashicons dashicons-admin-home"></span> <a href="' . acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/', 'docs', 'help-tab' ) . '" target="_blank" target="_blank">' . __( 'Visit website', 'acf' ) . '</a></p>' .
180 ''
181 );
182 }
183
184 /**
185 * Shows a notice to import post types and taxonomies from CPTUI if that plugin is active.
186 *
187 * @since 6.1
188 */
189 public function maybe_show_import_from_cptui_notice() {
190 global $plugin_page;
191
192 // Only show if CPTUI is active and post types are enabled.
193 if ( ! acf_get_setting( 'enable_post_types' ) || ! is_plugin_active( 'custom-post-type-ui/custom-post-type-ui.php' ) ) {
194 return;
195 }
196
197 // No need to show on the tools page.
198 if ( 'acf-tools' === $plugin_page ) {
199 return;
200 }
201
202 $text = sprintf(
203 /* translators: %s - URL to ACF tools page. */
204 __( 'Import Post Types and Taxonomies registered with Custom Post Type UI and manage them with ACF. <a href="%s">Get Started</a>.', 'acf' ),
205 acf_get_admin_tools_url()
206 );
207
208 acf_add_admin_notice( $text, 'success', true, true );
209 }
210
211 /**
212 * Notifies the user that fields rendered via shortcode or the_field() have
213 * had HTML removed/altered due to unsafe HTML being escaped.
214 *
215 * @since 6.2.5
216 */
217 public function maybe_show_escaped_html_notice() {
218 // Only show to editors and above.
219 if ( ! current_user_can( 'edit_others_posts' ) ) {
220 return;
221 }
222
223 // Allow opting-out of the notice.
224 if ( apply_filters( 'acf/admin/prevent_escaped_html_notice', true ) ) {
225 return;
226 }
227
228 if ( get_option( 'acf_escaped_html_notice_dismissed' ) ) {
229 return;
230 }
231
232 $escaped = _acf_get_escaped_html_log();
233
234 // Notice for when HTML has already been escaped.
235 if ( ! empty( $escaped ) ) {
236 acf_get_view( 'escaped-html-notice', array( 'acf_escaped' => $escaped ) );
237 }
238 }
239
240 /**
241 * Dismisses the escaped unsafe HTML notice.
242 *
243 * @since 6.2.5
244 */
245 public function dismiss_escaped_html_notice() {
246 if ( empty( $_GET['acf-dismiss-esc-html-notice'] ) ) {
247 return;
248 }
249
250 $nonce = sanitize_text_field( wp_unslash( $_GET['acf-dismiss-esc-html-notice'] ) );
251
252 if (
253 ! wp_verify_nonce( $nonce, 'acf/dismiss_escaped_html_notice' ) ||
254 ! current_user_can( acf_get_setting( 'capability' ) )
255 ) {
256 return;
257 }
258
259 update_option( 'acf_escaped_html_notice_dismissed', true );
260
261 _acf_delete_escaped_html_log();
262
263 wp_safe_redirect( remove_query_arg( 'acf-dismiss-esc-html-notice' ) );
264 exit;
265 }
266
267 /**
268 * Clear the escaped unsafe HTML log.
269 *
270 * @since 6.2.5
271 */
272 public function clear_escaped_html_log() {
273 if ( empty( $_GET['acf-clear-esc-html-log'] ) ) {
274 return;
275 }
276
277 $nonce = sanitize_text_field( wp_unslash( $_GET['acf-clear-esc-html-log'] ) );
278
279 if (
280 ! wp_verify_nonce( $nonce, 'acf/clear_escaped_html_log' ) ||
281 ! current_user_can( acf_get_setting( 'capability' ) )
282 ) {
283 return;
284 }
285
286 _acf_delete_escaped_html_log();
287
288 wp_safe_redirect( remove_query_arg( 'acf-clear-esc-html-log' ) );
289 exit;
290 }
291
292 /**
293 * Notifies the user that Select2 v3 has been deprecated and will be removed.
294 *
295 * @since 6.4.3
296 *
297 * @return void
298 */
299 public function maybe_show_select2_v3_deprecation_notice() {
300 // Only show to editors and above.
301 if ( ! current_user_can( 'edit_others_posts' ) ) {
302 return;
303 }
304
305 if ( 3 === acf_get_setting( 'select2_version' ) ) {
306 $acf_plugin_name = acf_is_pro() ? 'ACF PRO' : 'ACF';
307 $acf_plugin_name = '<strong>' . $acf_plugin_name . ' &mdash;</strong>';
308
309 $text = sprintf(
310 /* translators: %1$s - Plugin name, %2$s URL to documentation */
311 __( '%1$s We have detected that this website is configured to use v3 of the Select2 jQuery library, which has been deprecated in favor of v4 and will be removed in a future version of ACF. <a href="%2$s" target="_blank">Learn more</a>.', 'acf' ),
312 $acf_plugin_name,
313 acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/resources/select2-v3-deprecation/', 'docs', 'select2-deprecation-notice' ),
314 );
315
316 acf_add_admin_notice( $text, 'warning', false );
317 }
318 }
319
320 /**
321 * Renders the admin navigation element.
322 *
323 * @date 27/3/20
324 * @since 5.9.0
325 *
326 * @param void
327 * @return void
328 */
329 function in_admin_header() {
330 acf_get_view( 'global/navigation' );
331
332 $screen = get_current_screen();
333
334 if ( isset( $screen->base ) && 'post' === $screen->base ) {
335 acf_get_view( 'global/form-top' );
336 }
337
338 do_action( 'acf/in_admin_header' );
339 }
340
341 /**
342 * Modifies the admin footer text.
343 *
344 * @date 7/4/20
345 * @since 5.9.0
346 *
347 * @param string $text The current admin footer text.
348 * @return string
349 */
350 public function admin_footer_text( $text ) {
351 $wp_engine_link = acf_add_url_utm_tags( 'https://wpengine.com/', 'bx_prod_referral', acf_is_pro() ? 'acf_pro_plugin_footer_text' : 'acf_free_plugin_footer_text', false, 'acf_plugin', 'referral' );
352 $acf_link = acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/', 'footer', 'footer' );
353
354 if ( acf_is_pro() ) {
355 return sprintf(
356 /* translators: This text is prepended by a link to ACF's website, and appended by a link to WP Engine's website. */
357 '<a href="%1$s" target="_blank">ACF&#174;</a> and <a href="%1$s" target="_blank">ACF&#174; PRO</a> ' . __( 'are developed and maintained by', 'acf' ) . ' <a href="%2$s" target="_blank">WP Engine</a>.',
358 $acf_link,
359 $wp_engine_link
360 );
361 }
362
363 return sprintf(
364 /* translators: This text is prepended by a link to ACF's website, and appended by a link to WP Engine's website. */
365 '<a href="%1$s" target="_blank">ACF&#174;</a> ' . __( 'is developed and maintained by', 'acf' ) . ' <a href="%2$s" target="_blank">WP Engine</a>.',
366 $acf_link,
367 $wp_engine_link
368 );
369 }
370
371 /**
372 * Modifies the admin footer version text.
373 *
374 * @since 6.2
375 *
376 * @param string $text The current admin footer version text.
377 * @return string
378 */
379 public function admin_footer_version_text( $text ) {
380 $documentation_link = acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/resources/', 'footer', 'footer' );
381 $support_link = acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/support/', 'footer', 'footer' );
382 $feedback_link = acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/feedback/', 'footer', 'footer' );
383 $version_link = acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/changelog/', 'footer', 'footer' );
384
385 return sprintf(
386 '<a href="%s" target="_blank">%s</a> &#8729; <a href="%s" target="_blank">%s</a> &#8729; <a href="%s" target="_blank">%s</a> &#8729; <a href="%s" target="_blank">%s %s</a>',
387 $documentation_link,
388 __( 'Documentation', 'acf' ),
389 $support_link,
390 __( 'Support', 'acf' ),
391 $feedback_link,
392 __( 'Feedback', 'acf' ),
393 $version_link,
394 acf_is_pro() ? __( 'ACF PRO', 'acf' ) : __( 'ACF', 'acf' ),
395 ACF_VERSION
396 );
397 }
398
399 /**
400 * Ensure the ACF parent menu is selected for add-new.php
401 *
402 * @since 6.1
403 * @param string $parent_file The parent file checked against menu activation.
404 * @return string The modified parent file
405 */
406 public function ensure_menu_selection( $parent_file ) {
407 if ( ! is_string( $parent_file ) ) {
408 return $parent_file;
409 }
410 if ( strpos( $parent_file, 'edit.php?post_type=acf-' ) === 0 ) {
411 return 'edit.php?post_type=acf-field-group';
412 }
413 return $parent_file;
414 }
415
416
417 /**
418 * Ensure the correct ACF submenu item is selected when in post-new versions of edit pages
419 *
420 * @since 6.1
421 * @param string $submenu_file The submenu filename.
422 * @return string The modified submenu filename
423 */
424 public function ensure_submenu_selection( $submenu_file ) {
425 if ( ! is_string( $submenu_file ) ) {
426 return $submenu_file;
427 }
428 if ( strpos( $submenu_file, 'post-new.php?post_type=acf-' ) === 0 ) {
429 return str_replace( 'post-new', 'edit', $submenu_file );
430 }
431 return $submenu_file;
432 }
433 }
434
435 // Instantiate.
436 acf_new_instance( 'ACF_Admin' );
437 endif; // class_exists check
438