PluginProbe ʕ •ᴥ•ʔ
Advanced Custom Fields (ACF®) / 6.8.8
Advanced Custom Fields (ACF®) v6.8.8
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 6.0.1 6.0.2 6.0.3 6.0.4 6.0.5 6.0.6 6.0.7 6.1.0 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.1.6 6.1.7 6.1.8 6.2.0 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.2.6 6.2.6.1 6.2.7 6.2.8 6.2.9 6.3.0 6.3.1 6.3.10.2 6.3.11 6.3.12 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.6.1 6.4.0 6.4.0.1 6.4.1 6.4.2 6.4.3 6.5.0 6.5.1 6.6.0 6.6.1 6.6.2 6.7.0 6.7.1 6.7.2 6.8.0 trunk 1.0.0 1.0.2 1.0.3 1.0.5 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.1.1 2.1.3 2.1.4 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.6 3.0.7 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.4.0 3.4.1 3.4.2 3.4.3 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.5.6 3.5.7 3.5.8 4.0.0 4.0.1 4.0.2 4.0.3 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.8 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.3.8 4.3.9 4.4.0 4.4.1 4.4.10 4.4.11 4.4.12 4.4.2 4.4.3 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 5.10 5.10.1 5.10.2 5.11 5.11.1 5.11.2 5.11.3 5.11.4 5.12 5.12.1 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.6.10 5.6.2 5.6.3 5.6.4 5.6.5 5.6.6 5.6.7 5.6.8 5.6.9 5.7.0 5.7.1 5.7.10 5.7.12 5.7.13 5.7.2 5.7.3 5.7.4 5.7.5 5.7.6 5.7.7 5.7.8 5.7.9 5.8.0 5.8.1 5.8.10 5.8.11 5.8.12 5.8.13 5.8.14 5.8.2 5.8.3 5.8.4
advanced-custom-fields / includes / forms / form-post.php
advanced-custom-fields / includes / forms Last commit date
form-attachment.php 5 months ago form-comment.php 4 weeks ago form-customizer.php 5 months ago form-front.php 2 months ago form-gutenberg.php 5 months ago form-nav-menu.php 5 months ago form-post.php 3 months ago form-taxonomy.php 2 months ago form-user.php 4 weeks ago form-widget.php 5 months ago index.php 2 years ago
form-post.php
361 lines
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_Form_Post' ) ) :
17
18 class ACF_Form_Post {
19
20 /** @var string The first field groups style CSS. */
21 var $style = '';
22
23 /**
24 * __construct
25 *
26 * Sets up the class functionality.
27 *
28 * @date 5/03/2014
29 * @since 5.0.0
30 *
31 * @param void
32 * @return void
33 */
34 function __construct() {
35
36 // initialize on post edit screens
37 add_action( 'load-post.php', array( $this, 'initialize' ) );
38 add_action( 'load-post-new.php', array( $this, 'initialize' ) );
39
40 // save
41 add_filter( 'wp_insert_post_empty_content', array( $this, 'wp_insert_post_empty_content' ), 10, 2 );
42 add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );
43 }
44
45
46 /**
47 * initialize
48 *
49 * Sets up Form functionality.
50 *
51 * @date 19/9/18
52 * @since 5.7.6
53 *
54 * @param void
55 * @return void
56 */
57 function initialize() {
58
59 // globals
60 global $typenow;
61
62 $acf_post_types = acf_get_internal_post_types();
63
64 foreach ( $acf_post_types as $post_type ) {
65 remove_meta_box( 'submitdiv', $post_type, 'side' );
66 }
67
68 // restrict specific post types
69 $restricted = array_merge( $acf_post_types, array( 'acf-taxonomy', 'attachment' ) );
70 if ( in_array( $typenow, $restricted ) ) {
71 return;
72 }
73
74 // enqueue scripts
75 acf_enqueue_scripts(
76 array(
77 'uploader' => true,
78 )
79 );
80
81 // actions
82 add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 10, 2 );
83 }
84
85 /**
86 * add_meta_boxes
87 *
88 * Adds ACF metaboxes for the given $post_type and $post.
89 *
90 * @date 19/9/18
91 * @since 5.7.6
92 *
93 * @param string $post_type The post type.
94 * @param WP_Post $post The post being edited.
95 * @return void
96 */
97 function add_meta_boxes( $post_type, $post ) {
98
99 // Storage for localized postboxes.
100 $postboxes = array();
101
102 // Get field groups for this screen.
103 $field_groups = acf_get_field_groups(
104 array(
105 'post_id' => $post->ID,
106 'post_type' => $post_type,
107 )
108 );
109
110 // Loop over field groups.
111 if ( $field_groups ) {
112 foreach ( $field_groups as $field_group ) {
113 $id = esc_attr( "acf-{$field_group['key']}" );
114 $context = esc_attr( $field_group['position'] );
115 $priority = 'high';
116
117 // Reduce priority for sidebar metaboxes for best position.
118 if ( $context === 'side' ) {
119 $priority = 'core';
120 }
121
122 /**
123 * Filters the metabox priority.
124 *
125 * @date 23/06/12
126 * @since 3.1.8
127 *
128 * @param string $priority The metabox priority (high, core, default, low).
129 * @param array $field_group The field group array.
130 */
131 $priority = apply_filters( 'acf/input/meta_box_priority', $priority, $field_group );
132
133 // Localize data
134 $postboxes[] = array(
135 'id' => $id,
136 'key' => esc_attr( $field_group['key'] ),
137 'style' => esc_attr( $field_group['style'] ),
138 'label' => esc_attr( $field_group['label_placement'] ),
139 'edit' => esc_url( acf_get_field_group_edit_link( $field_group['ID'] ) ),
140 );
141
142 // Add the meta box.
143 add_meta_box(
144 $id,
145 acf_esc_html( acf_get_field_group_title( $field_group ) ),
146 array( $this, 'render_meta_box' ),
147 $post_type,
148 $context,
149 $priority,
150 array( 'field_group' => $field_group )
151 );
152 }
153
154 // Set style from first field group.
155 $this->style = acf_get_field_group_style( $field_groups[0] );
156
157 // Localize postboxes.
158 acf_localize_data(
159 array(
160 'postboxes' => $postboxes,
161 )
162 );
163 }
164
165 // remove postcustom metabox (removes expensive SQL query)
166 if ( acf_get_setting( 'remove_wp_meta_box' ) ) {
167 remove_meta_box( 'postcustom', false, 'normal' );
168 }
169
170 // Add hidden input fields.
171 add_action( 'edit_form_after_title', array( $this, 'edit_form_after_title' ) );
172
173 /**
174 * Fires after metaboxes have been added.
175 *
176 * @date 13/12/18
177 * @since 5.8.0
178 *
179 * @param string $post_type The post type.
180 * @param WP_Post $post The post being edited.
181 * @param array $field_groups The field groups added.
182 */
183 do_action( 'acf/add_meta_boxes', $post_type, $post, $field_groups );
184 }
185
186 /**
187 * Called after the title and before the content editor to render the after title metaboxes.
188 * Also renders the CSS required to hide the "hide-on-screen" elements on the page based on the field group settings.
189 *
190 * @since 5.7.6
191 */
192 public function edit_form_after_title() {
193
194 // globals
195 global $post, $wp_meta_boxes;
196
197 // render post data
198 acf_form_data(
199 array(
200 'screen' => 'post',
201 'post_id' => $post->ID,
202 )
203 );
204
205 // render 'acf_after_title' metaboxes
206 do_meta_boxes( get_current_screen(), 'acf_after_title', $post );
207
208 $style = '';
209 if ( is_string( $this->style ) ) {
210 $style = $this->style;
211 }
212
213 // Render dynamic field group style, using wp_strip_all_tags as this is filterable, but should only contain valid styles and no html.
214 echo '<style type="text/css" id="acf-style">' . wp_strip_all_tags( $style ) . '</style>'; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- CSS only, escaped by wp_strip_all_tags.
215 }
216
217 /**
218 * render_meta_box
219 *
220 * Renders the ACF metabox HTML.
221 *
222 * @date 19/9/18
223 * @since 5.7.6
224 *
225 * @param WP_Post $post The post being edited.
226 * @param array metabox The add_meta_box() args.
227 * @return void
228 */
229 function render_meta_box( $post, $metabox ) {
230
231 // vars
232 $id = $metabox['id'];
233 $field_group = $metabox['args']['field_group'];
234
235 // Render fields.
236 $fields = acf_get_fields( $field_group );
237 acf_render_fields( $fields, $post->ID, 'div', $field_group['instruction_placement'] );
238 }
239
240 /**
241 * wp_insert_post_empty_content
242 *
243 * Allows WP to insert a new post without title or post_content if ACF data exists.
244 *
245 * @date 16/07/2014
246 * @since 5.0.1
247 *
248 * @param boolean $maybe_empty Whether the post should be considered "empty".
249 * @param array $postarr Array of post data.
250 * @return boolean
251 */
252 function wp_insert_post_empty_content( $maybe_empty, $postarr ) {
253
254 // return false and allow insert if '_acf_changed' exists
255 if ( $maybe_empty && acf_maybe_get_POST( '_acf_changed' ) ) {
256 return false;
257 }
258
259 // return
260 return $maybe_empty;
261 }
262
263 /**
264 * Checks if the $post is allowed to be saved.
265 * Used to avoid triggering "acf/save_post" on dynamically created posts during save.
266 *
267 * @type function
268 * @date 26/06/2016
269 * @since 5.3.8
270 *
271 * @param WP_Post $post The post to check.
272 * @return boolean
273 */
274 function allow_save_post( $post ) {
275
276 // vars
277 $allow = true;
278
279 // restrict post types
280 $restrict = array( 'auto-draft', 'revision', 'acf-field', 'acf-field-group' );
281 if ( in_array( $post->post_type, $restrict ) ) {
282 $allow = false;
283 }
284
285 // disallow if the $_POST ID value does not match the $post->ID
286 $form_post_id = (int) acf_maybe_get_POST( 'post_ID' );
287 if ( $form_post_id && $form_post_id !== $post->ID ) {
288 $allow = false;
289 }
290
291 // revision (preview)
292 if ( $post->post_type == 'revision' ) {
293
294 // allow if doing preview and this $post is a child of the $_POST ID
295 if ( acf_maybe_get_POST( 'wp-preview' ) == 'dopreview' && $form_post_id === $post->post_parent ) {
296 $allow = true;
297 }
298 }
299
300 // return
301 return $allow;
302 }
303
304 /**
305 * Triggers during the 'save_post' action to save the $_POST data.
306 *
307 * @since 1.0.0
308 *
309 * @param integer $post_id The post ID.
310 * @param WP_Post $post The post object.
311 * @return integer
312 */
313 public function save_post( $post_id, $post ) {
314 // Bail early if not allowed to save this post type.
315 if ( ! $this->allow_save_post( $post ) ) {
316 return $post_id;
317 }
318
319 /**
320 * Filters whether ACF_Form_Post::save_post() should bail without
321 * verifying the nonce or running acf_save_post(). Allows extensions
322 * to short-circuit the save when another handler is responsible for
323 * persisting field values for the current request.
324 *
325 * @since 6.8.1
326 *
327 * @param boolean $skip Whether to skip the save.
328 * @param integer $post_id The post ID being saved.
329 * @param WP_Post $post The post being saved.
330 */
331 if ( apply_filters( 'acf/form-post/skip_save', false, $post_id, $post ) ) {
332 return $post_id;
333 }
334
335 // Verify nonce.
336 if ( ! acf_verify_nonce( 'post' ) ) {
337 return $post_id;
338 }
339
340 // Validate for published post (allow draft to save without validation).
341 if ( $post->post_status === 'publish' ) {
342 // Bail early if validation fails.
343 if ( ! acf_validate_save_post() ) {
344 return;
345 }
346 }
347
348 acf_save_post( $post_id );
349
350 // We handle revisions differently on WP 6.4+.
351 if ( version_compare( get_bloginfo( 'version' ), '6.4', '<' ) && post_type_supports( $post->post_type, 'revisions' ) ) {
352 acf_save_post_revision( $post_id );
353 }
354
355 return $post_id;
356 }
357 }
358
359 acf_new_instance( 'ACF_Form_Post' );
360 endif;
361