PluginProbe ʕ •ᴥ•ʔ
Advanced Custom Fields (ACF®) / 6.8.2
Advanced Custom Fields (ACF®) v6.8.2
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 / upgrades.php
advanced-custom-fields / includes Last commit date
admin 2 months ago ajax 3 weeks ago api 3 weeks ago fields 2 months ago forms 1 week ago legacy 3 months ago locations 3 months ago post-types 2 months ago rest-api 2 months ago walkers 3 months ago acf-bidirectional-functions.php 3 months ago acf-field-functions.php 2 months ago acf-field-group-functions.php 3 months ago acf-form-functions.php 3 months ago acf-helper-functions.php 3 months ago acf-hook-functions.php 3 months ago acf-input-functions.php 3 months ago acf-internal-post-type-functions.php 3 months ago acf-meta-functions.php 3 months ago acf-post-functions.php 3 months ago acf-post-type-functions.php 3 months ago acf-taxonomy-functions.php 3 months ago acf-user-functions.php 3 months ago acf-utility-functions.php 3 months ago acf-value-functions.php 3 months ago acf-wp-functions.php 3 months ago assets.php 2 months ago class-acf-data.php 3 months ago class-acf-internal-post-type.php 3 months ago compatibility.php 3 months ago deprecated.php 3 months ago fields.php 3 months ago index.php 1 year ago l10n.php 3 months ago local-fields.php 3 months ago local-json.php 3 weeks ago local-meta.php 3 months ago locations.php 3 months ago loop.php 3 months ago media.php 3 months ago rest-api.php 3 months ago revisions.php 3 weeks ago third-party.php 3 months ago upgrades.php 3 months ago validation.php 3 months ago wpml.php 3 months ago
upgrades.php
549 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 /**
13 * acf_has_upgrade
14 *
15 * Returns true if this site has an upgrade avaialble.
16 *
17 * @date 24/8/18
18 * @since 5.7.4
19 *
20 * @param void
21 * @return boolean
22 */
23 function acf_has_upgrade() {
24 $db_version = acf_get_db_version();
25
26 if ( $db_version && acf_version_compare( $db_version, '<', ACF_UPGRADE_VERSION ) ) {
27 return true;
28 }
29
30 if ( $db_version !== ACF_VERSION ) {
31 acf_update_db_version( ACF_VERSION );
32 }
33
34 return false;
35 }
36
37 /**
38 * Runs upgrade routines if this site has an upgrade available.
39 *
40 * @date 24/8/18
41 * @since 5.7.4
42 */
43 function acf_upgrade_all() {
44 // Increase time limit if possible.
45 if ( function_exists( 'set_time_limit' ) ) {
46 set_time_limit( 600 );
47 }
48
49 // start timer
50 timer_start();
51
52 // log
53 acf_dev_log( 'ACF Upgrade Begin.' );
54
55 // vars
56 $db_version = acf_get_db_version();
57
58 // 5.0.0
59 if ( acf_version_compare( $db_version, '<', '5.0.0' ) ) {
60 acf_upgrade_500();
61 }
62
63 // 5.5.0
64 if ( acf_version_compare( $db_version, '<', '5.5.0' ) ) {
65 acf_upgrade_550();
66 }
67
68 /**
69 * When adding new upgrade routines here, increment the ACF_UPGRADE_VERSION
70 * constant in `acf.php` to the new highest upgrade version.
71 */
72
73 // upgrade DB version once all updates are complete
74 acf_update_db_version( ACF_VERSION );
75
76 if ( is_multisite() ) {
77 // Clears the network upgrade notification banner after site upgrades.
78 delete_site_transient( 'acf_network_upgrade_needed_' . ACF_UPGRADE_VERSION );
79 }
80
81 // log
82 global $wpdb;
83 acf_dev_log( 'ACF Upgrade Complete.', $wpdb->num_queries, timer_stop( 0 ) );
84 }
85
86 /**
87 * acf_get_db_version
88 *
89 * Returns the ACF DB version.
90 *
91 * @date 10/09/2016
92 * @since 5.4.0
93 *
94 * @param void
95 * @return string
96 */
97 function acf_get_db_version() {
98 return get_option( 'acf_version' );
99 }
100
101 /**
102 * Updates the ACF DB version.
103 *
104 * @date 10/09/2016
105 * @since 5.4.0
106 *
107 * @param string $version The new version.
108 * @return void
109 */
110 function acf_update_db_version( $version = '' ) {
111 update_option( 'acf_version', $version );
112 }
113
114 /**
115 * acf_upgrade_500
116 *
117 * Version 5 introduces new post types for field groups and fields.
118 *
119 * @date 23/8/18
120 * @since 5.7.4
121 *
122 * @param void
123 * @return void
124 */
125 function acf_upgrade_500() {
126
127 // log
128 acf_dev_log( 'ACF Upgrade 5.0.0.' );
129
130 // action
131 do_action( 'acf/upgrade_500' );
132
133 // do tasks
134 acf_upgrade_500_field_groups();
135
136 // update version
137 acf_update_db_version( '5.0.0' );
138 }
139
140 /**
141 * acf_upgrade_500_field_groups
142 *
143 * Upgrades all ACF4 field groups to ACF5
144 *
145 * @date 23/8/18
146 * @since 5.7.4
147 *
148 * @param void
149 * @return void
150 */
151 function acf_upgrade_500_field_groups() {
152
153 // log
154 acf_dev_log( 'ACF Upgrade 5.0.0 Field Groups.' );
155
156 // get old field groups
157 $ofgs = get_posts(
158 array(
159 'numberposts' => -1,
160 'post_type' => 'acf',
161 'orderby' => 'menu_order title',
162 'order' => 'asc',
163 'suppress_filters' => true,
164 )
165 );
166
167 // loop
168 if ( $ofgs ) {
169 foreach ( $ofgs as $ofg ) {
170 acf_upgrade_500_field_group( $ofg );
171 }
172 }
173 }
174
175 /**
176 * acf_upgrade_500_field_group
177 *
178 * Upgrades a ACF4 field group to ACF5
179 *
180 * @date 23/8/18
181 * @since 5.7.4
182 *
183 * @param object $ofg The old field group post object.
184 * @return array $nfg The new field group array.
185 */
186 function acf_upgrade_500_field_group( $ofg ) {
187
188 // log
189 acf_dev_log( 'ACF Upgrade 5.0.0 Field Group.', $ofg );
190
191 // vars
192 $nfg = array(
193 'ID' => 0,
194 'title' => $ofg->post_title,
195 'menu_order' => $ofg->menu_order,
196 );
197
198 // construct the location rules
199 $rules = get_post_meta( $ofg->ID, 'rule', false );
200 $anyorall = get_post_meta( $ofg->ID, 'allorany', true );
201 if ( is_array( $rules ) ) {
202
203 // if field group was duplicated, rules may be a serialized string!
204 $rules = array_map( 'acf_maybe_unserialize', $rules );
205
206 // convert rules to groups
207 $nfg['location'] = acf_convert_rules_to_groups( $rules, $anyorall );
208 }
209
210 // settings
211 if ( $position = get_post_meta( $ofg->ID, 'position', true ) ) {
212 $nfg['position'] = $position;
213 }
214
215 if ( $layout = get_post_meta( $ofg->ID, 'layout', true ) ) {
216 $nfg['layout'] = $layout;
217 }
218
219 if ( $hide_on_screen = get_post_meta( $ofg->ID, 'hide_on_screen', true ) ) {
220 $nfg['hide_on_screen'] = acf_maybe_unserialize( $hide_on_screen );
221 }
222
223 // save field group
224 // acf_upgrade_field_group will call the acf_get_valid_field_group function and apply 'compatibility' changes
225 $nfg = acf_update_field_group( $nfg );
226
227 // log
228 acf_dev_log( '> Complete.', $nfg );
229
230 // action for 3rd party
231 do_action( 'acf/upgrade_500_field_group', $nfg, $ofg );
232
233 // upgrade fields
234 acf_upgrade_500_fields( $ofg, $nfg );
235
236 // trash?
237 if ( $ofg->post_status == 'trash' ) {
238 acf_trash_field_group( $nfg['ID'] );
239 }
240
241 // return
242 return $nfg;
243 }
244
245 /**
246 * acf_upgrade_500_fields
247 *
248 * Upgrades all ACF4 fields to ACF5 from a specific field group
249 *
250 * @date 23/8/18
251 * @since 5.7.4
252 *
253 * @param object $ofg The old field group post object.
254 * @param array $nfg The new field group array.
255 * @return void
256 */
257 function acf_upgrade_500_fields( $ofg, $nfg ) {
258
259 // log
260 acf_dev_log( 'ACF Upgrade 5.0.0 Fields.' );
261
262 // global
263 global $wpdb;
264
265 // get field from postmeta
266 $rows = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->postmeta WHERE post_id = %d AND meta_key LIKE %s", $ofg->ID, 'field_%' ), ARRAY_A );
267
268 // check
269 if ( $rows ) {
270
271 // vars
272 $checked = array();
273
274 // loop
275 foreach ( $rows as $row ) {
276
277 // vars
278 $field = $row['meta_value'];
279 $field = acf_maybe_unserialize( $field );
280 $field = acf_maybe_unserialize( $field ); // run again for WPML
281
282 // bail early if key already migrated (potential duplicates in DB)
283 if ( isset( $checked[ $field['key'] ] ) ) {
284 continue;
285 }
286 $checked[ $field['key'] ] = 1;
287
288 // add parent
289 $field['parent'] = $nfg['ID'];
290
291 // migrate field
292 $field = acf_upgrade_500_field( $field );
293 }
294 }
295 }
296
297 /**
298 * acf_upgrade_500_field
299 *
300 * Upgrades a ACF4 field to ACF5
301 *
302 * @date 23/8/18
303 * @since 5.7.4
304 *
305 * @param array $field The old field.
306 * @return array $field The new field.
307 */
308 function acf_upgrade_500_field( $field ) {
309
310 // log
311 acf_dev_log( 'ACF Upgrade 5.0.0 Field.', $field );
312
313 // order_no is now menu_order
314 $field['menu_order'] = acf_extract_var( $field, 'order_no', 0 );
315
316 // correct very old field keys (field2 => field_2)
317 if ( substr( $field['key'], 0, 6 ) !== 'field_' ) {
318 $field['key'] = 'field_' . str_replace( 'field', '', $field['key'] );
319 }
320
321 // extract sub fields
322 $sub_fields = array();
323 if ( $field['type'] == 'repeater' ) {
324
325 // loop over sub fields
326 if ( ! empty( $field['sub_fields'] ) ) {
327 foreach ( $field['sub_fields'] as $sub_field ) {
328 $sub_fields[] = $sub_field;
329 }
330 }
331
332 // remove sub fields from field
333 unset( $field['sub_fields'] );
334 } elseif ( $field['type'] == 'flexible_content' ) {
335
336 // loop over layouts
337 if ( is_array( $field['layouts'] ) ) {
338 foreach ( $field['layouts'] as $i => $layout ) {
339
340 // generate key
341 $layout['key'] = uniqid( 'layout_' );
342
343 // loop over sub fields
344 if ( ! empty( $layout['sub_fields'] ) ) {
345 foreach ( $layout['sub_fields'] as $sub_field ) {
346 $sub_field['parent_layout'] = $layout['key'];
347 $sub_fields[] = $sub_field;
348 }
349 }
350
351 // remove sub fields from layout
352 unset( $layout['sub_fields'] );
353
354 // update
355 $field['layouts'][ $i ] = $layout;
356 }
357 }
358 }
359
360 // save field
361 $field = acf_update_field( $field );
362
363 // log
364 acf_dev_log( '> Complete.', $field );
365
366 // sub fields
367 if ( $sub_fields ) {
368 foreach ( $sub_fields as $sub_field ) {
369 $sub_field['parent'] = $field['ID'];
370 acf_upgrade_500_field( $sub_field );
371 }
372 }
373
374 // action for 3rd party
375 do_action( 'acf/update_500_field', $field );
376
377 // return
378 return $field;
379 }
380
381 /**
382 * acf_upgrade_550
383 *
384 * Version 5.5 adds support for the wp_termmeta table added in WP 4.4.
385 *
386 * @date 23/8/18
387 * @since 5.7.4
388 *
389 * @param void
390 * @return void
391 */
392 function acf_upgrade_550() {
393
394 // log
395 acf_dev_log( 'ACF Upgrade 5.5.0.' );
396
397 // action
398 do_action( 'acf/upgrade_550' );
399
400 // do tasks
401 acf_upgrade_550_termmeta();
402
403 // update version
404 acf_update_db_version( '5.5.0' );
405 }
406
407 /**
408 * acf_upgrade_550_termmeta
409 *
410 * Upgrades all ACF4 termmeta saved in wp_options to the wp_termmeta table.
411 *
412 * @date 23/8/18
413 * @since 5.7.4
414 *
415 * @param void
416 * @return void
417 */
418 function acf_upgrade_550_termmeta() {
419
420 // log
421 acf_dev_log( 'ACF Upgrade 5.5.0 Termmeta.' );
422
423 // bail early if no wp_termmeta table
424 if ( get_option( 'db_version' ) < 34370 ) {
425 return;
426 }
427
428 // get all taxonomies
429 $taxonomies = get_taxonomies( false, 'objects' );
430
431 // loop
432 if ( $taxonomies ) {
433 foreach ( $taxonomies as $taxonomy ) {
434 acf_upgrade_550_taxonomy( $taxonomy->name );
435 }
436 }
437
438 // action for 3rd party
439 do_action( 'acf/upgrade_550_termmeta' );
440 }
441
442 /**
443 * When the database is updated to support term meta, migrate ACF term meta data across.
444 *
445 * @date 23/8/18
446 * @since 5.7.4
447 *
448 * @param string $wp_db_version The new $wp_db_version.
449 * @param string $wp_current_db_version The old (current) $wp_db_version.
450 * @return void
451 */
452 function acf_wp_upgrade_550_termmeta( $wp_db_version, $wp_current_db_version ) {
453 if ( $wp_db_version >= 34370 && $wp_current_db_version < 34370 ) {
454 if ( acf_version_compare( acf_get_db_version(), '>', '5.5.0' ) ) {
455 acf_upgrade_550_termmeta();
456 }
457 }
458 }
459 add_action( 'wp_upgrade', 'acf_wp_upgrade_550_termmeta', 10, 2 );
460
461 /**
462 * acf_upgrade_550_taxonomy
463 *
464 * Upgrades all ACF4 termmeta for a specific taxonomy.
465 *
466 * @date 24/8/18
467 * @since 5.7.4
468 *
469 * @param string $taxonomy The taxonomy name.
470 * @return void
471 */
472 function acf_upgrade_550_taxonomy( $taxonomy ) {
473
474 // log
475 acf_dev_log( 'ACF Upgrade 5.5.0 Taxonomy.', $taxonomy );
476
477 // global
478 global $wpdb;
479
480 // vars
481 $search = $taxonomy . '_%';
482 $_search = '_' . $search;
483
484 // escape '_'
485 // http://stackoverflow.com/questions/2300285/how-do-i-escape-in-sql-server
486 $search = str_replace( '_', '\_', $search );
487 $_search = str_replace( '_', '\_', $_search );
488
489 // search
490 // results show faster query times using 2 LIKE vs 2 wildcards
491 $rows = $wpdb->get_results(
492 $wpdb->prepare(
493 "SELECT *
494 FROM $wpdb->options
495 WHERE option_name LIKE %s
496 OR option_name LIKE %s",
497 $search,
498 $_search
499 ),
500 ARRAY_A
501 );
502
503 // loop
504 if ( $rows ) {
505 foreach ( $rows as $row ) {
506
507 /**
508 * Use regex to find "(_)taxonomy_(term_id)_(field_name)" and populate $matches:
509 * Array
510 * (
511 * [0] => _category_3_color
512 * [1] => _
513 * [2] => 3
514 * [3] => color
515 * )
516 */
517 if ( ! preg_match( "/^(_?){$taxonomy}_(\d+)_(.+)/", is_null( $row['option_name'] ) ? '' : $row['option_name'], $matches ) ) {
518 continue;
519 }
520
521 // vars
522 $term_id = $matches[2];
523 $meta_key = $matches[1] . $matches[3];
524 $meta_value = $row['option_value'];
525
526 // update
527 // memory usage reduced by 50% by using a manual insert vs update_metadata() function.
528 // update_metadata( 'term', $term_id, $meta_name, $meta_value );
529 $wpdb->insert(
530 $wpdb->termmeta,
531 array(
532 'term_id' => $term_id,
533 'meta_key' => $meta_key,
534 'meta_value' => $meta_value,
535 )
536 );
537
538 // log
539 acf_dev_log( 'ACF Upgrade 5.5.0 Term.', $term_id, $meta_key );
540
541 // action
542 do_action( 'acf/upgrade_550_taxonomy_term', $term_id );
543 }
544 }
545
546 // action for 3rd party
547 do_action( 'acf/upgrade_550_taxonomy', $taxonomy );
548 }
549