acf-field-functions.php 38 KB

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