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 / validation.php
validation.php
374 lines 8.1 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_validation' ) ) :
17 class acf_validation {
18
19 /**
20 * An array of validation errors.
21 * @var array
22 */
23 public $errors = array();
24
25 /**
26 * This function will setup the class functionality
27 *
28 * @type function
29 * @date 5/03/2014
30 * @since 5.0.0
31 *
32 * @param n/a
33 * @return n/a
34 */
35 function __construct() {
36
37 // ajax
38 add_action( 'wp_ajax_acf/validate_save_post', array( $this, 'ajax_validate_save_post' ) );
39 add_action( 'wp_ajax_nopriv_acf/validate_save_post', array( $this, 'ajax_validate_save_post' ) );
40 add_action( 'acf/validate_save_post', array( $this, 'acf_validate_save_post' ), 5 );
41 }
42
43
44 /**
45 * This function will add an error message for a field
46 *
47 * @type function
48 * @date 25/11/2013
49 * @since 5.0.0
50 *
51 * @param $input (string) name attribute of DOM elmenet
52 * @param $message (string) error message
53 * @return $post_id (int)
54 */
55 function add_error( $input, $message ) {
56
57 // add to array
58 $this->errors[] = array(
59 'input' => $input,
60 'message' => $message,
61 );
62 }
63
64
65 /**
66 * This function will return an error for a given input
67 *
68 * @type function
69 * @date 5/03/2016
70 * @since 5.3.2
71 *
72 * @param $input (string) name attribute of DOM elmenet
73 * @return (mixed)
74 */
75 function get_error( $input ) {
76
77 // bail early if no errors
78 if ( empty( $this->errors ) ) {
79 return false;
80 }
81
82 // loop
83 foreach ( $this->errors as $error ) {
84 if ( $error['input'] === $input ) {
85 return $error;
86 }
87 }
88
89 // return
90 return false;
91 }
92
93
94 /**
95 * This function will return validation errors
96 *
97 * @type function
98 * @date 25/11/2013
99 * @since 5.0.0
100 *
101 * @param n/a
102 * @return (array|boolean)
103 */
104 function get_errors() {
105
106 // bail early if no errors
107 if ( empty( $this->errors ) ) {
108 return false;
109 }
110
111 // return
112 return $this->errors;
113 }
114
115
116 /**
117 * This function will remove all errors
118 *
119 * @type function
120 * @date 4/03/2016
121 * @since 5.3.2
122 *
123 * @param n/a
124 * @return n/a
125 */
126 function reset_errors() {
127
128 $this->errors = array();
129 }
130
131 /**
132 * Validates $_POST data via AJAX prior to save.
133 *
134 * @since 5.0.9
135 *
136 * @return void
137 */
138 public function ajax_validate_save_post() {
139 if ( ! acf_verify_ajax() ) {
140 if ( empty( $_REQUEST['nonce'] ) ) {
141 $nonce_error = __( 'ACF was unable to perform validation because no nonce was received by the server.', 'acf' );
142 } else {
143 $nonce_error = __( 'ACF was unable to perform validation because the provided nonce failed verification.', 'acf' );
144 }
145
146 wp_send_json_success(
147 array(
148 'valid' => 0,
149 'errors' => array(
150 array(
151 'input' => false,
152 'message' => $nonce_error,
153 'action' => array(
154 'label' => __( 'Learn more', 'acf' ),
155 'url' => acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/resources/validation-nonce-errors/', 'docs', 'validation-nonce' ),
156 ),
157 ),
158 ),
159 )
160 );
161 }
162
163 $json = array(
164 'valid' => 1,
165 'errors' => 0,
166 );
167
168 if ( acf_validate_save_post() ) {
169 wp_send_json_success( $json );
170 }
171
172 $json['valid'] = 0;
173 $json['errors'] = acf_get_validation_errors();
174
175 wp_send_json_success( $json );
176 }
177
178 /**
179 * Loops over $_POST data and validates ACF values.
180 *
181 * @since 5.4.0
182 */
183 public function acf_validate_save_post() {
184 // phpcs:disable WordPress.Security.NonceVerification.Missing -- Verified elsewhere.
185 $post_type = acf_request_arg( 'post_type', false );
186 $screen = acf_request_arg( '_acf_screen', false );
187
188 if ( in_array( $screen, array( 'post_type', 'taxonomy', 'ui_options_page' ), true ) && in_array( $post_type, array( 'acf-post-type', 'acf-taxonomy', 'acf-ui-options-page' ), true ) ) {
189 acf_validate_internal_post_type_values( $post_type );
190 } elseif ( acf_request_arg( 'acf_ui_options_page' ) ) {
191 acf_validate_internal_post_type_values( 'acf-ui-options-page' );
192 } else {
193 // Bail early if no matching $_POST.
194 if ( empty( $_POST['acf'] ) ) {
195 return;
196 }
197
198 acf_validate_values( $_POST['acf'], 'acf' ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
199 }
200 // phpcs:enable WordPress.Security.NonceVerification.Missing
201 }
202 }
203
204 // initialize
205 acf()->validation = new acf_validation();
206 endif; // class_exists check
207
208
209 /**
210 * Public functions
211 *
212 * alias of acf()->validation->function()
213 *
214 * @type function
215 * @date 6/10/13
216 * @since 5.0.0
217 *
218 * @param n/a
219 * @return n/a
220 */
221 function acf_add_validation_error( $input, $message = '' ) {
222
223 return acf()->validation->add_error( $input, $message );
224 }
225
226 function acf_get_validation_errors() {
227
228 return acf()->validation->get_errors();
229 }
230
231 function acf_get_validation_error() {
232
233 return acf()->validation->get_error( $input );
234 }
235
236 function acf_reset_validation_errors() {
237
238 return acf()->validation->reset_errors();
239 }
240
241
242 /**
243 * This function will validate $_POST data and add errors
244 *
245 * @type function
246 * @date 25/11/2013
247 * @since 5.0.0
248 *
249 * @param $show_errors (boolean) if true, errors will be shown via a wp_die screen
250 * @return (boolean)
251 */
252 function acf_validate_save_post( $show_errors = false ) {
253
254 // action
255 do_action( 'acf/validate_save_post' );
256
257 // vars
258 $errors = acf_get_validation_errors();
259
260 // bail early if no errors
261 if ( ! $errors ) {
262 return true;
263 }
264
265 // show errors
266 if ( $show_errors ) {
267 $message = '<h2>' . __( 'Validation failed', 'acf' ) . '</h2>';
268 $message .= '<ul>';
269 foreach ( $errors as $error ) {
270 $message .= '<li>' . $error['message'] . '</li>';
271 }
272 $message .= '</ul>';
273
274 // die
275 wp_die( acf_esc_html( $message ), esc_html__( 'Validation failed', 'acf' ) );
276 }
277
278 // return
279 return false;
280 }
281
282
283 /**
284 * This function will validate an array of field values
285 *
286 * @type function
287 * @date 6/10/13
288 * @since 5.0.0
289 *
290 * @param values (array)
291 * @param $input_prefix (string)
292 * @return n/a
293 */
294 function acf_validate_values( $values, $input_prefix = '' ) {
295
296 // bail early if empty
297 if ( empty( $values ) ) {
298 return;
299 }
300
301 // loop
302 foreach ( $values as $key => $value ) {
303
304 // vars
305 $field = acf_get_field( $key );
306 $input = $input_prefix . '[' . $key . ']';
307
308 // bail early if not found
309 if ( ! $field ) {
310 continue;
311 }
312
313 // validate
314 acf_validate_value( $value, $field, $input );
315 }
316 }
317
318
319 /**
320 * This function will validate a field's value
321 *
322 * @type function
323 * @date 6/10/13
324 * @since 5.0.0
325 *
326 * @param n/a
327 * @return n/a
328 */
329 function acf_validate_value( $value, $field, $input ) {
330
331 // vars
332 $valid = true;
333 $message = sprintf( __( '%s value is required', 'acf' ), $field['label'] );
334
335 // valid
336 if ( $field['required'] ) {
337
338 // valid is set to false if the value is empty, but allow 0 as a valid value
339 if ( empty( $value ) && ! is_numeric( $value ) ) {
340 $valid = false;
341 }
342 }
343
344 /**
345 * Filters whether the value is valid.
346 *
347 * @date 28/09/13
348 * @since 5.0.0
349 *
350 * @param bool $valid The valid status. Return a string to display a custom error message.
351 * @param mixed $value The value.
352 * @param array $field The field array.
353 * @param string $input The input element's name attribute.
354 */
355 $valid = apply_filters( "acf/validate_value/type={$field['type']}", $valid, $value, $field, $input );
356 $valid = apply_filters( "acf/validate_value/name={$field['_name']}", $valid, $value, $field, $input );
357 $valid = apply_filters( "acf/validate_value/key={$field['key']}", $valid, $value, $field, $input );
358 $valid = apply_filters( 'acf/validate_value', $valid, $value, $field, $input );
359
360 // allow $valid to be a custom error message
361 if ( ! empty( $valid ) && is_string( $valid ) ) {
362 $message = $valid;
363 $valid = false;
364 }
365
366 if ( ! $valid ) {
367 acf_add_validation_error( $input, $message );
368 return false;
369 }
370
371 // return
372 return true;
373 }
374