Sin descripción

acf-field-functions.php 36KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596
  1. <?php
  2. // Register store.
  3. acf_register_store( 'fields' )->prop( 'multisite', true );
  4. /**
  5. * acf_get_field
  6. *
  7. * Retrieves a field for the given identifier.
  8. *
  9. * @date 17/1/19
  10. * @since 5.7.10
  11. *
  12. * @param (int|string) $id The field ID, key or name.
  13. * @return (array|false) The field array.
  14. */
  15. function acf_get_field( $id = 0 ) {
  16. // Allow WP_Post to be passed.
  17. if ( is_object( $id ) ) {
  18. $id = $id->ID;
  19. }
  20. // Check store.
  21. $store = acf_get_store( 'fields' );
  22. if ( $store->has( $id ) ) {
  23. return $store->get( $id );
  24. }
  25. // Check local fields first.
  26. if ( acf_is_local_field( $id ) ) {
  27. $field = acf_get_local_field( $id );
  28. // Then check database.
  29. } else {
  30. $field = acf_get_raw_field( $id );
  31. }
  32. // Bail early if no field.
  33. if ( ! $field ) {
  34. return false;
  35. }
  36. // Validate field.
  37. $field = acf_validate_field( $field );
  38. // Set input prefix.
  39. $field['prefix'] = 'acf';
  40. /**
  41. * Filters the $field array after it has been loaded.
  42. *
  43. * @date 12/02/2014
  44. * @since 5.0.0
  45. *
  46. * @param array The field array.
  47. */
  48. $field = apply_filters( 'acf/load_field', $field );
  49. // Store field using aliasses to also find via key, ID and name.
  50. $store->set( $field['key'], $field );
  51. $store->alias( $field['key'], $field['ID'], $field['name'] );
  52. // Return.
  53. return $field;
  54. }
  55. // Register variation.
  56. acf_add_filter_variations( 'acf/load_field', array( 'type', 'name', 'key' ), 0 );
  57. /**
  58. * acf_get_raw_field
  59. *
  60. * Retrieves raw field data for the given identifier.
  61. *
  62. * @date 18/1/19
  63. * @since 5.7.10
  64. *
  65. * @param (int|string) $id The field ID, key or name.
  66. * @return (array|false) The field array.
  67. */
  68. function acf_get_raw_field( $id = 0 ) {
  69. // Get raw field from database.
  70. $post = acf_get_field_post( $id );
  71. if ( ! $post ) {
  72. return false;
  73. }
  74. // Bail early if incorrect post type.
  75. if ( $post->post_type !== 'acf-field' ) {
  76. return false;
  77. }
  78. // Unserialize post_content.
  79. $field = (array) maybe_unserialize( $post->post_content );
  80. // update attributes
  81. $field['ID'] = $post->ID;
  82. $field['key'] = $post->post_name;
  83. $field['label'] = $post->post_title;
  84. $field['name'] = $post->post_excerpt;
  85. $field['menu_order'] = $post->menu_order;
  86. $field['parent'] = $post->post_parent;
  87. // Return field.
  88. return $field;
  89. }
  90. /**
  91. * acf_get_field_post
  92. *
  93. * Retrieves the field's WP_Post object.
  94. *
  95. * @date 18/1/19
  96. * @since 5.7.10
  97. *
  98. * @param (int|string) $id The field ID, key or name.
  99. * @return (array|false) The field array.
  100. */
  101. function acf_get_field_post( $id = 0 ) {
  102. // Get post if numeric.
  103. if ( is_numeric( $id ) ) {
  104. return get_post( $id );
  105. // Search posts if is string.
  106. } elseif ( is_string( $id ) ) {
  107. // Determine id type.
  108. $type = acf_is_field_key( $id ) ? 'key' : 'name';
  109. // Try cache.
  110. $cache_key = acf_cache_key( "acf_get_field_post:$type:$id" );
  111. $post_id = wp_cache_get( $cache_key, 'acf' );
  112. if ( $post_id === false ) {
  113. // Query posts.
  114. $posts = get_posts(
  115. array(
  116. 'posts_per_page' => 1,
  117. 'post_type' => 'acf-field',
  118. 'orderby' => 'menu_order title',
  119. 'order' => 'ASC',
  120. 'suppress_filters' => false,
  121. 'cache_results' => true,
  122. 'update_post_meta_cache' => false,
  123. 'update_post_term_cache' => false,
  124. "acf_field_$type" => $id,
  125. )
  126. );
  127. // Update $post_id with a non false value.
  128. $post_id = $posts ? $posts[0]->ID : 0;
  129. // Update cache.
  130. wp_cache_set( $cache_key, $post_id, 'acf' );
  131. }
  132. // Check $post_id and return the post when possible.
  133. if ( $post_id ) {
  134. return get_post( $post_id );
  135. }
  136. }
  137. // Return false by default.
  138. return false;
  139. }
  140. /**
  141. * acf_is_field_key
  142. *
  143. * Returns true if the given identifier is a field key.
  144. *
  145. * @date 6/12/2013
  146. * @since 5.0.0
  147. *
  148. * @param string $id The identifier.
  149. * @return bool
  150. */
  151. function acf_is_field_key( $id = '' ) {
  152. // Check if $id is a string starting with "field_".
  153. if ( is_string( $id ) && substr( $id, 0, 6 ) === 'field_' ) {
  154. return true;
  155. }
  156. /**
  157. * Filters whether the $id is a field key.
  158. *
  159. * @date 23/1/19
  160. * @since 5.7.10
  161. *
  162. * @param bool $bool The result.
  163. * @param string $id The identifier.
  164. */
  165. return apply_filters( 'acf/is_field_key', false, $id );
  166. }
  167. /**
  168. * acf_validate_field
  169. *
  170. * Ensures the given field valid.
  171. *
  172. * @date 18/1/19
  173. * @since 5.7.10
  174. *
  175. * @param array $field The field array.
  176. * @return array
  177. */
  178. function acf_validate_field( $field = array() ) {
  179. // Bail early if already valid.
  180. if ( is_array( $field ) && ! empty( $field['_valid'] ) ) {
  181. return $field;
  182. }
  183. // Apply defaults.
  184. $field = wp_parse_args(
  185. $field,
  186. array(
  187. 'ID' => 0,
  188. 'key' => '',
  189. 'label' => '',
  190. 'name' => '',
  191. 'prefix' => '',
  192. 'type' => 'text',
  193. 'value' => null,
  194. 'menu_order' => 0,
  195. 'instructions' => '',
  196. 'required' => false,
  197. 'id' => '',
  198. 'class' => '',
  199. 'conditional_logic' => false,
  200. 'parent' => 0,
  201. 'wrapper' => array(),
  202. // 'attributes' => array()
  203. )
  204. );
  205. // Convert types.
  206. $field['ID'] = (int) $field['ID'];
  207. $field['menu_order'] = (int) $field['menu_order'];
  208. // Add backwards compatibility for wrapper attributes.
  209. // Todo: Remove need for this.
  210. $field['wrapper'] = wp_parse_args(
  211. $field['wrapper'],
  212. array(
  213. 'width' => '',
  214. 'class' => '',
  215. 'id' => '',
  216. )
  217. );
  218. // Store backups.
  219. $field['_name'] = $field['name'];
  220. $field['_valid'] = 1;
  221. /**
  222. * Filters the $field array to validate settings.
  223. *
  224. * @date 12/02/2014
  225. * @since 5.0.0
  226. *
  227. * @param array $field The field array.
  228. */
  229. $field = apply_filters( 'acf/validate_field', $field );
  230. // return
  231. return $field;
  232. }
  233. // Register variation.
  234. acf_add_filter_variations( 'acf/validate_field', array( 'type' ), 0 );
  235. /**
  236. * acf_get_valid_field
  237. *
  238. * Ensures the given field valid.
  239. *
  240. * @date 28/09/13
  241. * @since 5.0.0
  242. *
  243. * @param array $field The field array.
  244. * @return array
  245. */
  246. function acf_get_valid_field( $field = false ) {
  247. return acf_validate_field( $field );
  248. }
  249. /**
  250. * acf_translate_field
  251. *
  252. * Translates a field's settings.
  253. *
  254. * @date 8/03/2016
  255. * @since 5.3.2
  256. *
  257. * @param array $field The field array.
  258. * @return array
  259. */
  260. function acf_translate_field( $field = array() ) {
  261. // Get settings.
  262. $l10n = acf_get_setting( 'l10n' );
  263. $l10n_textdomain = acf_get_setting( 'l10n_textdomain' );
  264. // Translate field settings if textdomain is set.
  265. if ( $l10n && $l10n_textdomain ) {
  266. $field['label'] = acf_translate( $field['label'] );
  267. $field['instructions'] = acf_translate( $field['instructions'] );
  268. /**
  269. * Filters the $field array to translate strings.
  270. *
  271. * @date 12/02/2014
  272. * @since 5.0.0
  273. *
  274. * @param array $field The field array.
  275. */
  276. $field = apply_filters( 'acf/translate_field', $field );
  277. }
  278. // Return field.
  279. return $field;
  280. }
  281. // Register variation.
  282. acf_add_filter_variations( 'acf/translate_field', array( 'type' ), 0 );
  283. // Translate fields passing through validation.
  284. add_action( 'acf/validate_field', 'acf_translate_field' );
  285. /**
  286. * acf_get_fields
  287. *
  288. * Returns and array of fields for the given $parent.
  289. *
  290. * @date 30/09/13
  291. * @since 5.0.0
  292. *
  293. * @param (int|string|array) $parent The field group or field settings. Also accepts the field group ID or key.
  294. * @return array
  295. */
  296. function acf_get_fields( $parent ) {
  297. // Allow field group selector as $parent.
  298. if ( ! is_array( $parent ) ) {
  299. $parent = acf_get_field_group( $parent );
  300. if ( ! $parent ) {
  301. return array();
  302. }
  303. }
  304. // Vars.
  305. $fields = array();
  306. // Check local fields first.
  307. if ( acf_have_local_fields( $parent['key'] ) ) {
  308. $raw_fields = acf_get_local_fields( $parent['key'] );
  309. foreach ( $raw_fields as $raw_field ) {
  310. $fields[] = acf_get_field( $raw_field['key'] );
  311. }
  312. // Then check database.
  313. } else {
  314. $raw_fields = acf_get_raw_fields( $parent['ID'] );
  315. foreach ( $raw_fields as $raw_field ) {
  316. $fields[] = acf_get_field( $raw_field['ID'] );
  317. }
  318. }
  319. /**
  320. * Filters the $fields array.
  321. *
  322. * @date 12/02/2014
  323. * @since 5.0.0
  324. *
  325. * @param array $fields The array of fields.
  326. */
  327. $fields = apply_filters( 'acf/load_fields', $fields, $parent );
  328. // Return fields
  329. return $fields;
  330. }
  331. /**
  332. * acf_get_raw_fields
  333. *
  334. * Returns and array of raw field data for the given parent id.
  335. *
  336. * @date 18/1/19
  337. * @since 5.7.10
  338. *
  339. * @param int $id The field group or field id.
  340. * @return array
  341. */
  342. function acf_get_raw_fields( $id = 0 ) {
  343. // Try cache.
  344. $cache_key = acf_cache_key( "acf_get_field_posts:$id" );
  345. $post_ids = wp_cache_get( $cache_key, 'acf' );
  346. if ( $post_ids === false ) {
  347. // Query posts.
  348. $posts = get_posts(
  349. array(
  350. 'posts_per_page' => -1,
  351. 'post_type' => 'acf-field',
  352. 'orderby' => 'menu_order',
  353. 'order' => 'ASC',
  354. 'suppress_filters' => true, // DO NOT allow WPML to modify the query
  355. 'cache_results' => true,
  356. 'update_post_meta_cache' => false,
  357. 'update_post_term_cache' => false,
  358. 'post_parent' => $id,
  359. 'post_status' => array( 'publish', 'trash' ),
  360. )
  361. );
  362. // Update $post_ids with a non false value.
  363. $post_ids = array();
  364. foreach ( $posts as $post ) {
  365. $post_ids[] = $post->ID;
  366. }
  367. // Update cache.
  368. wp_cache_set( $cache_key, $post_ids, 'acf' );
  369. }
  370. // Loop over ids and populate array of fields.
  371. $fields = array();
  372. foreach ( $post_ids as $post_id ) {
  373. $fields[] = acf_get_raw_field( $post_id );
  374. }
  375. // Return fields.
  376. return $fields;
  377. }
  378. /**
  379. * acf_get_field_count
  380. *
  381. * Return the number of fields for the given field group.
  382. *
  383. * @date 17/10/13
  384. * @since 5.0.0
  385. *
  386. * @param array $parent The field group or field array.
  387. * @return int
  388. */
  389. function acf_get_field_count( $parent ) {
  390. // Check local fields first.
  391. if ( acf_have_local_fields( $parent['key'] ) ) {
  392. $raw_fields = acf_get_local_fields( $parent['key'] );
  393. // Then check database.
  394. } else {
  395. $raw_fields = acf_get_raw_fields( $parent['ID'] );
  396. }
  397. /**
  398. * Filters the counted number of fields.
  399. *
  400. * @date 12/02/2014
  401. * @since 5.0.0
  402. *
  403. * @param int $count The number of fields.
  404. * @param array $parent The field group or field array.
  405. */
  406. return apply_filters( 'acf/get_field_count', count( $raw_fields ), $parent );
  407. }
  408. /**
  409. * acf_clone_field
  410. *
  411. * Allows customization to a field when it is cloned. Used by the clone field.
  412. *
  413. * @date 8/03/2016
  414. * @since 5.3.2
  415. *
  416. * @param array $field The field being cloned.
  417. * @param array $clone_field The clone field.
  418. * @return array
  419. */
  420. function acf_clone_field( $field, $clone_field ) {
  421. // Add reference to the clone field.
  422. $field['_clone'] = $clone_field['key'];
  423. /**
  424. * Filters the $field array when it is being cloned.
  425. *
  426. * @date 12/02/2014
  427. * @since 5.0.0
  428. *
  429. * @param array $field The field array.
  430. * @param array $clone_field The clone field array.
  431. */
  432. $field = apply_filters( 'acf/clone_field', $field, $clone_field );
  433. // Return field.
  434. return $field;
  435. }
  436. // Register variation.
  437. acf_add_filter_variations( 'acf/clone_field', array( 'type' ), 0 );
  438. /**
  439. * acf_prepare_field
  440. *
  441. * Prepare a field for input.
  442. *
  443. * @date 20/1/19
  444. * @since 5.7.10
  445. *
  446. * @param array $field The field array.
  447. * @return array
  448. */
  449. function acf_prepare_field( $field ) {
  450. // Bail early if already prepared.
  451. if ( ! empty( $field['_prepare'] ) ) {
  452. return $field;
  453. }
  454. // Use field key to override input name.
  455. if ( $field['key'] ) {
  456. $field['name'] = $field['key'];
  457. }
  458. // Use field prefix to modify input name.
  459. if ( ! empty( $field['prefix'] ) ) {
  460. $field['name'] = "{$field['prefix']}[{$field['name']}]";
  461. }
  462. // Generate id attribute from name.
  463. $field['id'] = acf_idify( $field['name'] );
  464. // Add state to field.
  465. $field['_prepare'] = true;
  466. /**
  467. * Filters the $field array.
  468. *
  469. * Allows developers to modify field settings or return false to remove field.
  470. *
  471. * @date 12/02/2014
  472. * @since 5.0.0
  473. *
  474. * @param array $field The field array.
  475. */
  476. $field = apply_filters( 'acf/prepare_field', $field );
  477. // return
  478. return $field;
  479. }
  480. // Register variation.
  481. acf_add_filter_variations( 'acf/prepare_field', array( 'type', 'name', 'key' ), 0 );
  482. /**
  483. * acf_render_fields
  484. *
  485. * Renders an array of fields. Also loads the field's value.
  486. *
  487. * @date 8/10/13
  488. * @since 5.0.0
  489. * @since 5.6.9 Changed parameter order.
  490. *
  491. * @param array $fields An array of fields.
  492. * @param (int|string) $post_id The post ID to load values from.
  493. * @param string $element The wrapping element type.
  494. * @param string $instruction The instruction render position (label|field).
  495. * @return void
  496. */
  497. function acf_render_fields( $fields, $post_id = 0, $el = 'div', $instruction = 'label' ) {
  498. // Parameter order changed in ACF 5.6.9.
  499. if ( is_array( $post_id ) ) {
  500. $args = func_get_args();
  501. $fields = $args[1];
  502. $post_id = $args[0];
  503. }
  504. /**
  505. * Filters the $fields array before they are rendered.
  506. *
  507. * @date 12/02/2014
  508. * @since 5.0.0
  509. *
  510. * @param array $fields An array of fields.
  511. * @param (int|string) $post_id The post ID to load values from.
  512. */
  513. $fields = apply_filters( 'acf/pre_render_fields', $fields, $post_id );
  514. // Filter our false results.
  515. $fields = array_filter( $fields );
  516. // Loop over and render fields.
  517. if ( $fields ) {
  518. foreach ( $fields as $field ) {
  519. // Load value if not already loaded.
  520. if ( $field['value'] === null ) {
  521. $field['value'] = acf_get_value( $post_id, $field );
  522. }
  523. // Render wrap.
  524. acf_render_field_wrap( $field, $el, $instruction );
  525. }
  526. }
  527. /**
  528. * Fires after fields have been rendered.
  529. *
  530. * @date 12/02/2014
  531. * @since 5.0.0
  532. *
  533. * @param array $fields An array of fields.
  534. * @param (int|string) $post_id The post ID to load values from.
  535. */
  536. do_action( 'acf/render_fields', $fields, $post_id );
  537. }
  538. /**
  539. * acf_render_field_wrap
  540. *
  541. * Render the wrapping element for a given field.
  542. *
  543. * @date 28/09/13
  544. * @since 5.0.0
  545. *
  546. * @param array $field The field array.
  547. * @param string $element The wrapping element type.
  548. * @param string $instruction The instruction render position (label|field).
  549. * @return void
  550. */
  551. function acf_render_field_wrap( $field, $element = 'div', $instruction = 'label' ) {
  552. // Ensure field is complete (adds all settings).
  553. $field = acf_validate_field( $field );
  554. // Prepare field for input (modifies settings).
  555. $field = acf_prepare_field( $field );
  556. // Allow filters to cancel render.
  557. if ( ! $field ) {
  558. return;
  559. }
  560. // Determine wrapping element.
  561. $elements = array(
  562. 'div' => 'div',
  563. 'tr' => 'td',
  564. 'td' => 'div',
  565. 'ul' => 'li',
  566. 'ol' => 'li',
  567. 'dl' => 'dt',
  568. );
  569. if ( isset( $elements[ $element ] ) ) {
  570. $inner_element = $elements[ $element ];
  571. } else {
  572. $element = $inner_element = 'div';
  573. }
  574. // Generate wrapper attributes.
  575. $wrapper = array(
  576. 'id' => '',
  577. 'class' => 'acf-field',
  578. 'width' => '',
  579. 'style' => '',
  580. 'data-name' => $field['_name'],
  581. 'data-type' => $field['type'],
  582. 'data-key' => $field['key'],
  583. );
  584. // Add field type attributes.
  585. $wrapper['class'] .= " acf-field-{$field['type']}";
  586. // add field key attributes
  587. if ( $field['key'] ) {
  588. $wrapper['class'] .= " acf-field-{$field['key']}";
  589. }
  590. // Add required attributes.
  591. // Todo: Remove data-required
  592. if ( $field['required'] ) {
  593. $wrapper['class'] .= ' is-required';
  594. $wrapper['data-required'] = 1;
  595. }
  596. // Clean up class attribute.
  597. $wrapper['class'] = str_replace( '_', '-', $wrapper['class'] );
  598. $wrapper['class'] = str_replace( 'field-field-', 'field-', $wrapper['class'] );
  599. // Merge in field 'wrapper' setting without destroying class and style.
  600. if ( $field['wrapper'] ) {
  601. $wrapper = acf_merge_attributes( $wrapper, $field['wrapper'] );
  602. }
  603. // Extract wrapper width and generate style.
  604. // Todo: Move from $wrapper out into $field.
  605. $width = acf_extract_var( $wrapper, 'width' );
  606. if ( $width ) {
  607. $width = acf_numval( $width );
  608. if ( $element !== 'tr' && $element !== 'td' ) {
  609. $wrapper['data-width'] = $width;
  610. $wrapper['style'] .= " width:{$width}%;";
  611. }
  612. }
  613. // Clean up all attributes.
  614. $wrapper = array_map( 'trim', $wrapper );
  615. $wrapper = array_filter( $wrapper );
  616. /**
  617. * Filters the $wrapper array before rendering.
  618. *
  619. * @date 21/1/19
  620. * @since 5.7.10
  621. *
  622. * @param array $wrapper The wrapper attributes array.
  623. * @param array $field The field array.
  624. */
  625. $wrapper = apply_filters( 'acf/field_wrapper_attributes', $wrapper, $field );
  626. // Append conditional logic attributes.
  627. if ( ! empty( $field['conditional_logic'] ) ) {
  628. $wrapper['data-conditions'] = $field['conditional_logic'];
  629. }
  630. if ( ! empty( $field['conditions'] ) ) {
  631. $wrapper['data-conditions'] = $field['conditions'];
  632. }
  633. // Vars for render.
  634. $attributes_html = acf_esc_attr( $wrapper );
  635. // Render HTML
  636. echo "<$element $attributes_html>" . "\n";
  637. if ( $element !== 'td' ) {
  638. echo "<$inner_element class=\"acf-label\">" . "\n";
  639. acf_render_field_label( $field );
  640. if ( $instruction == 'label' ) {
  641. acf_render_field_instructions( $field );
  642. }
  643. echo "</$inner_element>" . "\n";
  644. }
  645. echo "<$inner_element class=\"acf-input\">" . "\n";
  646. acf_render_field( $field );
  647. if ( $instruction == 'field' ) {
  648. acf_render_field_instructions( $field );
  649. }
  650. echo "</$inner_element>" . "\n";
  651. echo "</$element>" . "\n";
  652. }
  653. /**
  654. * acf_render_field
  655. *
  656. * Render the input element for a given field.
  657. *
  658. * @date 21/1/19
  659. * @since 5.7.10
  660. *
  661. * @param array $field The field array.
  662. * @return void
  663. */
  664. function acf_render_field( $field ) {
  665. // Ensure field is complete (adds all settings).
  666. $field = acf_validate_field( $field );
  667. // Prepare field for input (modifies settings).
  668. $field = acf_prepare_field( $field );
  669. // Allow filters to cancel render.
  670. if ( ! $field ) {
  671. return;
  672. }
  673. /**
  674. * Fires when rendering a field.
  675. *
  676. * @date 12/02/2014
  677. * @since 5.0.0
  678. *
  679. * @param array $field The field array.
  680. */
  681. do_action( 'acf/render_field', $field );
  682. }
  683. // Register variation.
  684. acf_add_action_variations( 'acf/render_field', array( 'type', 'name', 'key' ), 0 );
  685. /**
  686. * acf_render_field_label
  687. *
  688. * Renders the field's label.
  689. *
  690. * @date 19/9/17
  691. * @since 5.6.3
  692. *
  693. * @param array $field The field array.
  694. * @return void
  695. */
  696. function acf_render_field_label( $field ) {
  697. // Get label.
  698. $label = acf_get_field_label( $field );
  699. // Output label.
  700. if ( $label ) {
  701. echo '<label' . ( $field['id'] ? ' for="' . esc_attr( $field['id'] ) . '"' : '' ) . '>' . acf_esc_html( $label ) . '</label>';
  702. }
  703. }
  704. /**
  705. * acf_get_field_label
  706. *
  707. * Returns the field's label with appropriate required label.
  708. *
  709. * @date 4/11/2013
  710. * @since 5.0.0
  711. *
  712. * @param array $field The field array.
  713. * @param string $context The output context (admin).
  714. * @return void
  715. */
  716. function acf_get_field_label( $field, $context = '' ) {
  717. // Get label.
  718. $label = $field['label'];
  719. // Display empty text when editing field.
  720. if ( $context == 'admin' && $label === '' ) {
  721. $label = __( '(no label)', 'acf' );
  722. }
  723. // Add required HTML.
  724. if ( $field['required'] ) {
  725. $label .= ' <span class="acf-required">*</span>';
  726. }
  727. /**
  728. * Filters the field's label HTML.
  729. *
  730. * @date 21/1/19
  731. * @since 5.7.10
  732. *
  733. * @param string The label HTML.
  734. * @param array $field The field array.
  735. * @param string $context The output context (admin).
  736. */
  737. $label = apply_filters( 'acf/get_field_label', $label, $field, $context );
  738. // Return label.
  739. return $label;
  740. }
  741. /**
  742. * acf_render_field_instructions
  743. *
  744. * Renders the field's instructions.
  745. *
  746. * @date 19/9/17
  747. * @since 5.6.3
  748. *
  749. * @param array $field The field array.
  750. * @return void
  751. */
  752. function acf_render_field_instructions( $field ) {
  753. // Output instructions.
  754. if ( $field['instructions'] ) {
  755. echo '<p class="description">' . acf_esc_html( $field['instructions'] ) . '</p>';
  756. }
  757. }
  758. /**
  759. * acf_render_field_setting
  760. *
  761. * Renders a field setting used in the admin edit screen.
  762. *
  763. * @date 21/1/19
  764. * @since 5.7.10
  765. *
  766. * @param array $field The field array.
  767. * @param array $setting The settings field array.
  768. * @param bool $global Whether this setting is a global or field type specific one.
  769. * @return void
  770. */
  771. function acf_render_field_setting( $field, $setting, $global = false ) {
  772. // Validate field.
  773. $setting = acf_validate_field( $setting );
  774. // Add custom attributes to setting wrapper.
  775. $setting['wrapper']['data-key'] = $setting['name'];
  776. $setting['wrapper']['class'] .= ' acf-field-setting-' . $setting['name'];
  777. if ( ! $global ) {
  778. $setting['wrapper']['data-setting'] = $field['type'];
  779. }
  780. // Copy across prefix.
  781. $setting['prefix'] = $field['prefix'];
  782. // Find setting value from field.
  783. if ( $setting['value'] === null ) {
  784. // Name.
  785. if ( isset( $field[ $setting['name'] ] ) ) {
  786. $setting['value'] = $field[ $setting['name'] ];
  787. // Default value.
  788. } elseif ( isset( $setting['default_value'] ) ) {
  789. $setting['value'] = $setting['default_value'];
  790. }
  791. }
  792. // Add append attribute used by JS to join settings.
  793. if ( isset( $setting['_append'] ) ) {
  794. $setting['wrapper']['data-append'] = $setting['_append'];
  795. }
  796. // Render setting.
  797. acf_render_field_wrap( $setting, 'tr', 'label' );
  798. }
  799. /**
  800. * acf_update_field
  801. *
  802. * Updates a field in the database.
  803. *
  804. * @date 21/1/19
  805. * @since 5.7.10
  806. *
  807. * @param array $field The field array.
  808. * @param array $specific An array of specific field attributes to update.
  809. * @return void
  810. */
  811. function acf_update_field( $field, $specific = array() ) {
  812. // Validate field.
  813. $field = acf_validate_field( $field );
  814. // May have been posted. Remove slashes.
  815. $field = wp_unslash( $field );
  816. // Parse types (converts string '0' to int 0).
  817. $field = acf_parse_types( $field );
  818. // Clean up conditional logic keys.
  819. if ( $field['conditional_logic'] ) {
  820. // Remove empty values and convert to associated array.
  821. $field['conditional_logic'] = array_filter( $field['conditional_logic'] );
  822. $field['conditional_logic'] = array_values( $field['conditional_logic'] );
  823. $field['conditional_logic'] = array_map( 'array_filter', $field['conditional_logic'] );
  824. $field['conditional_logic'] = array_map( 'array_values', $field['conditional_logic'] );
  825. }
  826. // Parent may be provided as a field key.
  827. if ( $field['parent'] && ! is_numeric( $field['parent'] ) ) {
  828. $parent = acf_get_field_post( $field['parent'] );
  829. $field['parent'] = $parent ? $parent->ID : 0;
  830. }
  831. /**
  832. * Filters the $field array before it is updated.
  833. *
  834. * @date 12/02/2014
  835. * @since 5.0.0
  836. *
  837. * @param array $field The field array.
  838. */
  839. $field = apply_filters( 'acf/update_field', $field );
  840. // Make a backup of field data and remove some args.
  841. $_field = $field;
  842. acf_extract_vars( $_field, array( 'ID', 'key', 'label', 'name', 'prefix', 'value', 'menu_order', 'id', 'class', 'parent', '_name', '_prepare', '_valid' ) );
  843. // Create array of data to save.
  844. $save = array(
  845. 'ID' => $field['ID'],
  846. 'post_status' => 'publish',
  847. 'post_type' => 'acf-field',
  848. 'post_title' => $field['label'],
  849. 'post_name' => $field['key'],
  850. 'post_excerpt' => $field['name'],
  851. 'post_content' => maybe_serialize( $_field ),
  852. 'post_parent' => $field['parent'],
  853. 'menu_order' => $field['menu_order'],
  854. );
  855. // Reduce save data if specific key list is provided.
  856. if ( $specific ) {
  857. $specific[] = 'ID';
  858. $save = acf_get_sub_array( $save, $specific );
  859. }
  860. // Unhook wp_targeted_link_rel() filter from WP 5.1 corrupting serialized data.
  861. remove_filter( 'content_save_pre', 'wp_targeted_link_rel' );
  862. // Slash data.
  863. // WP expects all data to be slashed and will unslash it (fixes '\' character issues).
  864. $save = wp_slash( $save );
  865. // Update or Insert.
  866. if ( $field['ID'] ) {
  867. wp_update_post( $save );
  868. } else {
  869. $field['ID'] = wp_insert_post( $save );
  870. }
  871. // Flush field cache.
  872. acf_flush_field_cache( $field );
  873. /**
  874. * Fires after a field has been updated, and the field cache has been cleaned.
  875. *
  876. * @date 24/1/19
  877. * @since 5.7.10
  878. *
  879. * @param array $field The field array.
  880. */
  881. do_action( 'acf/updated_field', $field );
  882. // Return field.
  883. return $field;
  884. }
  885. // Register variation.
  886. acf_add_filter_variations( 'acf/update_field', array( 'type', 'name', 'key' ), 0 );
  887. /**
  888. * _acf_apply_unique_field_slug
  889. *
  890. * Allows full control over 'acf-field' slugs.
  891. *
  892. * @date 21/1/19
  893. * @since 5.7.10
  894. *
  895. * @param string $slug The post slug.
  896. * @param int $post_ID Post ID.
  897. * @param string $post_status The post status.
  898. * @param string $post_type Post type.
  899. * @param int $post_parent Post parent ID
  900. * @param string $original_slug The original post slug.
  901. */
  902. function _acf_apply_unique_field_slug( $slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug ) {
  903. // Check post type and reset to original value.
  904. if ( $post_type === 'acf-field' ) {
  905. return $original_slug;
  906. }
  907. // Return slug.
  908. return $slug;
  909. }
  910. // Hook into filter.
  911. add_filter( 'wp_unique_post_slug', '_acf_apply_unique_field_slug', 999, 6 );
  912. /**
  913. * acf_flush_field_cache
  914. *
  915. * Deletes all caches for this field.
  916. *
  917. * @date 22/1/19
  918. * @since 5.7.10
  919. *
  920. * @param array $field The field array.
  921. * @return void
  922. */
  923. function acf_flush_field_cache( $field ) {
  924. // Delete stored data.
  925. acf_get_store( 'fields' )->remove( $field['key'] );
  926. // Flush cached post_id for this field's name and key.
  927. wp_cache_delete( acf_cache_key( "acf_get_field_post:name:{$field['name']}" ), 'acf' );
  928. wp_cache_delete( acf_cache_key( "acf_get_field_post:key:{$field['key']}" ), 'acf' );
  929. // Flush cached array of post_ids for this field's parent.
  930. wp_cache_delete( acf_cache_key( "acf_get_field_posts:{$field['parent']}" ), 'acf' );
  931. }
  932. /**
  933. * acf_delete_field
  934. *
  935. * Deletes a field from the database.
  936. *
  937. * @date 21/1/19
  938. * @since 5.7.10
  939. *
  940. * @param (int|string) $id The field ID, key or name.
  941. * @return bool True if field was deleted.
  942. */
  943. function acf_delete_field( $id = 0 ) {
  944. // Get the field.
  945. $field = acf_get_field( $id );
  946. // Bail early if field was not found.
  947. if ( ! $field || ! $field['ID'] ) {
  948. return false;
  949. }
  950. // Delete post.
  951. wp_delete_post( $field['ID'], true );
  952. // Flush field cache.
  953. acf_flush_field_cache( $field );
  954. /**
  955. * Fires immediately after a field has been deleted.
  956. *
  957. * @date 12/02/2014
  958. * @since 5.0.0
  959. *
  960. * @param array $field The field array.
  961. */
  962. do_action( 'acf/delete_field', $field );
  963. // Return true.
  964. return true;
  965. }
  966. // Register variation.
  967. acf_add_action_variations( 'acf/delete_field', array( 'type', 'name', 'key' ), 0 );
  968. /**
  969. * acf_trash_field
  970. *
  971. * Trashes a field from the database.
  972. *
  973. * @date 2/10/13
  974. * @since 5.0.0
  975. *
  976. * @param (int|string) $id The field ID, key or name.
  977. * @return bool True if field was trashed.
  978. */
  979. function acf_trash_field( $id = 0 ) {
  980. // Get the field.
  981. $field = acf_get_field( $id );
  982. // Bail early if field was not found.
  983. if ( ! $field || ! $field['ID'] ) {
  984. return false;
  985. }
  986. // Trash post.
  987. wp_trash_post( $field['ID'], true );
  988. /**
  989. * Fires immediately after a field has been trashed.
  990. *
  991. * @date 12/02/2014
  992. * @since 5.0.0
  993. *
  994. * @param array $field The field array.
  995. */
  996. do_action( 'acf/trash_field', $field );
  997. // Return true.
  998. return true;
  999. }
  1000. /**
  1001. * acf_untrash_field
  1002. *
  1003. * Restores a field from the trash.
  1004. *
  1005. * @date 2/10/13
  1006. * @since 5.0.0
  1007. *
  1008. * @param (int|string) $id The field ID, key or name.
  1009. * @return bool True if field was trashed.
  1010. */
  1011. function acf_untrash_field( $id = 0 ) {
  1012. // Get the field.
  1013. $field = acf_get_field( $id );
  1014. // Bail early if field was not found.
  1015. if ( ! $field || ! $field['ID'] ) {
  1016. return false;
  1017. }
  1018. // Untrash post.
  1019. wp_untrash_post( $field['ID'], true );
  1020. // Flush field cache.
  1021. acf_flush_field_cache( $field );
  1022. /**
  1023. * Fires immediately after a field has been trashed.
  1024. *
  1025. * @date 12/02/2014
  1026. * @since 5.0.0
  1027. *
  1028. * @param array $field The field array.
  1029. */
  1030. do_action( 'acf/untrash_field', $field );
  1031. // Return true.
  1032. return true;
  1033. }
  1034. /**
  1035. * Filter callback which returns the previous post_status instead of "draft" for the "acf-field" post type.
  1036. *
  1037. * Prior to WordPress 5.6.0, this filter was not needed as restored posts were always assigned their original status.
  1038. *
  1039. * @since 5.9.5
  1040. *
  1041. * @param string $new_status The new status of the post being restored.
  1042. * @param int $post_id The ID of the post being restored.
  1043. * @param string $previous_status The status of the post at the point where it was trashed.
  1044. * @return string.
  1045. */
  1046. function _acf_untrash_field_post_status( $new_status, $post_id, $previous_status ) {
  1047. return ( get_post_type( $post_id ) === 'acf-field' ) ? $previous_status : $new_status;
  1048. }
  1049. add_action( 'wp_untrash_post_status', '_acf_untrash_field_post_status', 10, 3 );
  1050. /**
  1051. * acf_prefix_fields
  1052. *
  1053. * Changes the prefix for an array of fields by reference.
  1054. *
  1055. * @date 5/9/17
  1056. * @since 5.6.0
  1057. *
  1058. * @param array $fields An array of fields.
  1059. * @param string $prefix The new prefix.
  1060. * @return void
  1061. */
  1062. function acf_prefix_fields( &$fields, $prefix = 'acf' ) {
  1063. // Loopover fields.
  1064. foreach ( $fields as &$field ) {
  1065. // Replace 'acf' with $prefix.
  1066. $field['prefix'] = $prefix . substr( $field['prefix'], 3 );
  1067. }
  1068. }
  1069. /**
  1070. * acf_get_sub_field
  1071. *
  1072. * Searches a field for sub fields matching the given selector.
  1073. *
  1074. * @date 21/1/19
  1075. * @since 5.7.10
  1076. *
  1077. * @param (int|string) $id The field ID, key or name.
  1078. * @param array $field The parent field array.
  1079. * @return (array|false)
  1080. */
  1081. function acf_get_sub_field( $id, $field ) {
  1082. // Vars.
  1083. $sub_field = false;
  1084. // Search sub fields.
  1085. if ( isset( $field['sub_fields'] ) ) {
  1086. $sub_field = acf_search_fields( $id, $field['sub_fields'] );
  1087. }
  1088. /**
  1089. * Filters the $sub_field found.
  1090. *
  1091. * @date 12/02/2014
  1092. * @since 5.0.0
  1093. *
  1094. * @param array $sub_field The found sub field array.
  1095. * @param string $selector The selector used to search.
  1096. * @param array $field The parent field array.
  1097. */
  1098. $sub_field = apply_filters( 'acf/get_sub_field', $sub_field, $id, $field );
  1099. // return
  1100. return $sub_field;
  1101. }
  1102. // Register variation.
  1103. acf_add_filter_variations( 'acf/get_sub_field', array( 'type' ), 2 );
  1104. /**
  1105. * acf_search_fields
  1106. *
  1107. * Searches an array of fields for one that matches the given identifier.
  1108. *
  1109. * @date 12/2/19
  1110. * @since 5.7.11
  1111. *
  1112. * @param (int|string) $id The field ID, key or name.
  1113. * @param array $haystack The array of fields.
  1114. * @return (int|false)
  1115. */
  1116. function acf_search_fields( $id, $fields ) {
  1117. // Loop over searchable keys in order of priority.
  1118. // Important to search "name" on all fields before "_name" backup.
  1119. foreach ( array( 'key', 'name', '_name', '__name' ) as $key ) {
  1120. // Loop over fields and compare.
  1121. foreach ( $fields as $field ) {
  1122. if ( isset( $field[ $key ] ) && $field[ $key ] === $id ) {
  1123. return $field;
  1124. }
  1125. }
  1126. }
  1127. // Return not found.
  1128. return false;
  1129. }
  1130. /**
  1131. * acf_is_field
  1132. *
  1133. * Returns true if the given params match a field.
  1134. *
  1135. * @date 21/1/19
  1136. * @since 5.7.10
  1137. *
  1138. * @param array $field The field array.
  1139. * @param mixed $id An optional identifier to search for.
  1140. * @return bool
  1141. */
  1142. function acf_is_field( $field = false, $id = '' ) {
  1143. return (
  1144. is_array( $field )
  1145. && isset( $field['key'] )
  1146. && isset( $field['name'] )
  1147. );
  1148. }
  1149. /**
  1150. * acf_get_field_ancestors
  1151. *
  1152. * Returns an array of ancestor field ID's or keys.
  1153. *
  1154. * @date 22/06/2016
  1155. * @since 5.3.8
  1156. *
  1157. * @param array $field The field array.
  1158. * @return array
  1159. */
  1160. function acf_get_field_ancestors( $field ) {
  1161. // Vars.
  1162. $ancestors = array();
  1163. // Loop over parents.
  1164. while ( $field['parent'] && $field = acf_get_field( $field['parent'] ) ) {
  1165. $ancestors[] = $field['ID'] ? $field['ID'] : $field['key'];
  1166. }
  1167. // return
  1168. return $ancestors;
  1169. }
  1170. /**
  1171. * acf_duplicate_fields
  1172. *
  1173. * Duplicate an array of fields.
  1174. *
  1175. * @date 16/06/2014
  1176. * @since 5.0.0
  1177. *
  1178. * @param array $fields An array of fields.
  1179. * @param int $parent_id The new parent ID.
  1180. * @return array
  1181. */
  1182. function acf_duplicate_fields( $fields = array(), $parent_id = 0 ) {
  1183. // Generate keys for all new fields
  1184. // - Needed to alter conditional logic rules
  1185. // - Use usleep() to ensure unique keys.
  1186. $keys = array();
  1187. foreach ( $fields as $field ) {
  1188. usleep( 1 );
  1189. $keys[ $field['key'] ] = uniqid( 'field_' );
  1190. }
  1191. acf_append_data( 'generated_keys', $keys );
  1192. // Duplicate fields.
  1193. foreach ( $fields as $field ) {
  1194. $field_id = $field['ID'] ? $field['ID'] : $field['key'];
  1195. $duplicates[] = acf_duplicate_field( $field_id, $parent_id );
  1196. }
  1197. // Return.
  1198. return $duplicates;
  1199. }
  1200. /**
  1201. * acf_duplicate_field
  1202. *
  1203. * Duplicates a field.
  1204. *
  1205. * @date 16/06/2014
  1206. * @since 5.0.0
  1207. *
  1208. * @param (int|string) $id The field ID, key or name.
  1209. * @param int $parent_id The new parent ID.
  1210. * @return bool True if field was duplicated.
  1211. */
  1212. function acf_duplicate_field( $id = 0, $parent_id = 0 ) {
  1213. // Get the field.
  1214. $field = acf_get_field( $id );
  1215. // Bail early if field was not found.
  1216. if ( ! $field ) {
  1217. return false;
  1218. }
  1219. // Remove ID to avoid update.
  1220. $field['ID'] = 0;
  1221. // Generate key.
  1222. $keys = acf_get_data( 'generated_keys' );
  1223. if ( isset( $keys[ $field['key'] ] ) ) {
  1224. $field['key'] = $keys[ $field['key'] ];
  1225. } else {
  1226. $field['key'] = uniqid( 'field_' );
  1227. }
  1228. // Set parent.
  1229. if ( $parent_id ) {
  1230. $field['parent'] = $parent_id;
  1231. }
  1232. // Update conditional logic references because field keys have changed.
  1233. if ( $field['conditional_logic'] ) {
  1234. // Loop over groups
  1235. foreach ( $field['conditional_logic'] as $group_i => $group ) {
  1236. // Loop over rules
  1237. foreach ( $group as $rule_i => $rule ) {
  1238. $field['conditional_logic'][ $group_i ][ $rule_i ]['field'] = isset( $keys[ $rule['field'] ] ) ? $keys[ $rule['field'] ] : $rule['field'];
  1239. }
  1240. }
  1241. }
  1242. /**
  1243. * Filters the $field array after it has been duplicated.
  1244. *
  1245. * @date 12/02/2014
  1246. * @since 5.0.0
  1247. *
  1248. * @param array $field The field array.
  1249. */
  1250. $field = apply_filters( 'acf/duplicate_field', $field );
  1251. // Update and return.
  1252. return acf_update_field( $field );
  1253. }
  1254. // Register variation.
  1255. acf_add_filter_variations( 'acf/duplicate_field', array( 'type' ), 0 );
  1256. /**
  1257. * acf_prepare_fields_for_export
  1258. *
  1259. * Returns a modified array of fields ready for export.
  1260. *
  1261. * @date 11/03/2014
  1262. * @since 5.0.0
  1263. *
  1264. * @param array $fields An array of fields.
  1265. * @return array
  1266. */
  1267. function acf_prepare_fields_for_export( $fields = array() ) {
  1268. // Map function and return.
  1269. return array_map( 'acf_prepare_field_for_export', $fields );
  1270. }
  1271. /**
  1272. * acf_prepare_field_for_export
  1273. *
  1274. * Returns a modified field ready for export.
  1275. *
  1276. * @date 11/03/2014
  1277. * @since 5.0.0
  1278. *
  1279. * @param array $field The field array.
  1280. * @return array
  1281. */
  1282. function acf_prepare_field_for_export( $field ) {
  1283. // Remove args.
  1284. acf_extract_vars( $field, array( 'ID', 'prefix', 'value', 'menu_order', 'id', 'class', 'parent', '_name', '_prepare', '_valid' ) );
  1285. /**
  1286. * Filters the $field array before being returned to the export tool.
  1287. *
  1288. * @date 12/02/2014
  1289. * @since 5.0.0
  1290. *
  1291. * @param array $field The field array.
  1292. */
  1293. return apply_filters( 'acf/prepare_field_for_export', $field );
  1294. }
  1295. // Register variation.
  1296. acf_add_filter_variations( 'acf/prepare_field_for_export', array( 'type' ), 0 );
  1297. /**
  1298. * acf_prepare_field_for_import
  1299. *
  1300. * Returns a modified array of fields ready for import.
  1301. *
  1302. * @date 11/03/2014
  1303. * @since 5.0.0
  1304. *
  1305. * @param array $fields An array of fields.
  1306. * @return array
  1307. */
  1308. function acf_prepare_fields_for_import( $fields = array() ) {
  1309. // Ensure array is sequential.
  1310. $fields = array_values( $fields );
  1311. // Prepare each field for import making sure to detect additional sub fields.
  1312. $i = 0;
  1313. while ( $i < count( $fields ) ) {
  1314. // Prepare field.
  1315. $field = acf_prepare_field_for_import( $fields[ $i ] );
  1316. // Update single field.
  1317. if ( isset( $field['key'] ) ) {
  1318. $fields[ $i ] = $field;
  1319. // Insert multiple fields.
  1320. } else {
  1321. array_splice( $fields, $i, 1, $field );
  1322. }
  1323. // Iterate.
  1324. $i++;
  1325. }
  1326. /**
  1327. * Filters the $fields array before being returned to the import tool.
  1328. *
  1329. * @date 12/02/2014
  1330. * @since 5.0.0
  1331. *
  1332. * @param array $fields The array of fields.
  1333. */
  1334. return apply_filters( 'acf/prepare_fields_for_import', $fields );
  1335. }
  1336. /**
  1337. * acf_prepare_field_for_import
  1338. *
  1339. * Returns a modified field ready for import.
  1340. * Allows parent fields to modify themselves and also return sub fields.
  1341. *
  1342. * @date 11/03/2014
  1343. * @since 5.0.0
  1344. *
  1345. * @param array $field The field array.
  1346. * @return array
  1347. */
  1348. function acf_prepare_field_for_import( $field ) {
  1349. /**
  1350. * Filters the $field array before being returned to the import tool.
  1351. *
  1352. * @date 12/02/2014
  1353. * @since 5.0.0
  1354. *
  1355. * @param array $field The field array.
  1356. */
  1357. return apply_filters( 'acf/prepare_field_for_import', $field );
  1358. }
  1359. // Register variation.
  1360. acf_add_filter_variations( 'acf/prepare_field_for_import', array( 'type' ), 0 );