api-template.php 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427
  1. <?php
  2. /*
  3. * get_field()
  4. *
  5. * This function will return a custom field value for a specific field name/key + post_id.
  6. * There is a 3rd parameter to turn on/off formating. This means that an image field will not use
  7. * its 'return option' to format the value but return only what was saved in the database
  8. *
  9. * @type function
  10. * @since 3.6
  11. * @date 29/01/13
  12. *
  13. * @param $selector (string) the field name or key
  14. * @param $post_id (mixed) the post_id of which the value is saved against
  15. * @param $format_value (boolean) whether or not to format the value as described above
  16. * @return (mixed)
  17. */
  18. function get_field( $selector, $post_id = false, $format_value = true ) {
  19. // filter post_id
  20. $post_id = acf_get_valid_post_id( $post_id );
  21. // get field
  22. $field = acf_maybe_get_field( $selector, $post_id );
  23. // create dummy field
  24. if ( ! $field ) {
  25. $field = acf_get_valid_field(
  26. array(
  27. 'name' => $selector,
  28. 'key' => '',
  29. 'type' => '',
  30. )
  31. );
  32. // prevent formatting
  33. $format_value = false;
  34. }
  35. // get value for field
  36. $value = acf_get_value( $post_id, $field );
  37. // format value
  38. if ( $format_value ) {
  39. // get value for field
  40. $value = acf_format_value( $value, $post_id, $field );
  41. }
  42. // return
  43. return $value;
  44. }
  45. /**
  46. * This function is the same as echo get_field().
  47. *
  48. * @since 1.0.3
  49. * @date 29/01/13
  50. *
  51. * @param string $selector The field name or key.
  52. * @param mixed $post_id The post_id of which the value is saved against.
  53. * @return void
  54. */
  55. function the_field( $selector, $post_id = false, $format_value = true ) {
  56. $value = get_field( $selector, $post_id, $format_value );
  57. if ( is_array( $value ) ) {
  58. $value = implode( ', ', $value );
  59. }
  60. echo $value;
  61. }
  62. /**
  63. * This function will return an array containing all the field data for a given field_name.
  64. *
  65. * @since 3.6
  66. * @date 3/02/13
  67. *
  68. * @param string $selector The field name or key.
  69. * @param mixed $post_id The post_id of which the value is saved against.
  70. * @param bool $format_value Whether to format the field value.
  71. * @param bool $load_value Whether to load the field value.
  72. *
  73. * @return array|false $field
  74. */
  75. function get_field_object( $selector, $post_id = false, $format_value = true, $load_value = true ) {
  76. // Compatibility with ACF ~4.
  77. if ( is_array( $format_value ) && isset( $format_value['format_value'] ) ) {
  78. $format_value = $format_value['format_value'];
  79. }
  80. $post_id = acf_get_valid_post_id( $post_id );
  81. $field = acf_maybe_get_field( $selector, $post_id );
  82. if ( ! $field ) {
  83. return false;
  84. }
  85. if ( $load_value ) {
  86. $field['value'] = acf_get_value( $post_id, $field );
  87. }
  88. if ( $format_value ) {
  89. $field['value'] = acf_format_value( $field['value'], $post_id, $field );
  90. }
  91. return $field;
  92. }
  93. /*
  94. * acf_get_object_field
  95. *
  96. * This function will return a field for the given selector.
  97. * It will also review the field_reference to ensure the correct field is returned which makes it useful for the template API
  98. *
  99. * @type function
  100. * @date 4/08/2015
  101. * @since 5.2.3
  102. *
  103. * @param $selector (mixed) identifyer of field. Can be an ID, key, name or post object
  104. * @param $post_id (mixed) the post_id of which the value is saved against
  105. * @param $strict (boolean) if true, return a field only when a field key is found.
  106. * @return $field (array)
  107. */
  108. function acf_maybe_get_field( $selector, $post_id = false, $strict = true ) {
  109. // init
  110. acf_init();
  111. // Check if field key was given.
  112. if ( acf_is_field_key( $selector ) ) {
  113. return acf_get_field( $selector );
  114. }
  115. // Lookup field via reference.
  116. $post_id = acf_get_valid_post_id( $post_id );
  117. $field = acf_get_meta_field( $selector, $post_id );
  118. if ( $field ) {
  119. return $field;
  120. }
  121. // Lookup field loosely via name.
  122. if ( ! $strict ) {
  123. return acf_get_field( $selector );
  124. }
  125. // Return no result.
  126. return false;
  127. }
  128. /*
  129. * acf_maybe_get_sub_field
  130. *
  131. * This function will attempt to find a sub field
  132. *
  133. * @type function
  134. * @date 3/10/2016
  135. * @since 5.4.0
  136. *
  137. * @param $post_id (int)
  138. * @return $post_id (int)
  139. */
  140. function acf_maybe_get_sub_field( $selectors, $post_id = false, $strict = true ) {
  141. // bail early if not enough selectors
  142. if ( ! is_array( $selectors ) || count( $selectors ) < 3 ) {
  143. return false;
  144. }
  145. // vars
  146. $offset = acf_get_setting( 'row_index_offset' );
  147. $selector = acf_extract_var( $selectors, 0 );
  148. $selectors = array_values( $selectors ); // reset keys
  149. // attempt get field
  150. $field = acf_maybe_get_field( $selector, $post_id, $strict );
  151. // bail early if no field
  152. if ( ! $field ) {
  153. return false;
  154. }
  155. // loop
  156. for ( $j = 0; $j < count( $selectors ); $j += 2 ) {
  157. // vars
  158. $sub_i = $selectors[ $j ];
  159. $sub_s = $selectors[ $j + 1 ];
  160. $field_name = $field['name'];
  161. // find sub field
  162. $field = acf_get_sub_field( $sub_s, $field );
  163. // bail early if no sub field
  164. if ( ! $field ) {
  165. return false;
  166. }
  167. // add to name
  168. $field['name'] = $field_name . '_' . ( $sub_i - $offset ) . '_' . $field['name'];
  169. }
  170. // return
  171. return $field;
  172. }
  173. /*
  174. * get_fields()
  175. *
  176. * This function will return an array containing all the custom field values for a specific post_id.
  177. * The function is not very elegant and wastes a lot of PHP memory / SQL queries if you are not using all the values.
  178. *
  179. * @type function
  180. * @since 3.6
  181. * @date 29/01/13
  182. *
  183. * @param $post_id (mixed) the post_id of which the value is saved against
  184. * @param $format_value (boolean) whether or not to format the field value
  185. * @return (array) associative array where field name => field value
  186. */
  187. function get_fields( $post_id = false, $format_value = true ) {
  188. // vars
  189. $fields = get_field_objects( $post_id, $format_value );
  190. $meta = array();
  191. // bail early
  192. if ( ! $fields ) {
  193. return false;
  194. }
  195. // populate
  196. foreach ( $fields as $k => $field ) {
  197. $meta[ $k ] = $field['value'];
  198. }
  199. // return
  200. return $meta;
  201. }
  202. /*
  203. * get_field_objects()
  204. *
  205. * This function will return an array containing all the custom field objects for a specific post_id.
  206. * The function is not very elegant and wastes a lot of PHP memory / SQL queries if you are not using all the fields / values.
  207. *
  208. * @type function
  209. * @since 3.6
  210. * @date 29/01/13
  211. *
  212. * @param $post_id (mixed) the post_id of which the value is saved against
  213. * @param $format_value (boolean) whether or not to format the field value
  214. * @param $load_value (boolean) whether or not to load the field value
  215. * @return (array) associative array where field name => field
  216. */
  217. function get_field_objects( $post_id = false, $format_value = true, $load_value = true ) {
  218. // init
  219. acf_init();
  220. // validate post_id
  221. $post_id = acf_get_valid_post_id( $post_id );
  222. // get meta
  223. $meta = acf_get_meta( $post_id );
  224. // bail early if no meta
  225. if ( empty( $meta ) ) {
  226. return false;
  227. }
  228. // populate vars
  229. $fields = array();
  230. foreach ( $meta as $key => $value ) {
  231. // bail if reference key does not exist
  232. if ( ! isset( $meta[ "_$key" ] ) || ( ! is_string( $meta[ "_$key" ] ) && ! is_numeric( $meta[ "_$key" ] ) ) ) {
  233. continue;
  234. }
  235. // get field
  236. $field = acf_get_field( $meta[ "_$key" ] );
  237. // bail early if no field, or if the field's name is different to $key
  238. // - solves problem where sub fields (and clone fields) are incorrectly allowed
  239. if ( ! $field || $field['name'] !== $key ) {
  240. continue;
  241. }
  242. // load value
  243. if ( $load_value ) {
  244. $field['value'] = acf_get_value( $post_id, $field );
  245. }
  246. // format value
  247. if ( $format_value ) {
  248. $field['value'] = acf_format_value( $field['value'], $post_id, $field );
  249. }
  250. // append to $value
  251. $fields[ $key ] = $field;
  252. }
  253. // no value
  254. if ( empty( $fields ) ) {
  255. return false;
  256. }
  257. // return
  258. return $fields;
  259. }
  260. /**
  261. * have_rows
  262. *
  263. * Checks if a field (such as Repeater or Flexible Content) has any rows of data to loop over.
  264. * This function is intended to be used in conjunction with the_row() to step through available values.
  265. *
  266. * @date 2/09/13
  267. * @since 4.3.0
  268. *
  269. * @param string $selector The field name or field key.
  270. * @param mixed $post_id The post ID where the value is saved. Defaults to the current post.
  271. * @return bool
  272. */
  273. function have_rows( $selector, $post_id = false ) {
  274. // Validate and backup $post_id.
  275. $_post_id = $post_id;
  276. $post_id = acf_get_valid_post_id( $post_id );
  277. // Vars.
  278. $key = "selector={$selector}/post_id={$post_id}";
  279. $active_loop = acf_get_loop( 'active' );
  280. $prev_loop = acf_get_loop( 'previous' );
  281. $new_loop = false;
  282. $sub_field = false;
  283. // Check if no active loop.
  284. if ( ! $active_loop ) {
  285. $new_loop = 'parent';
  286. // Detect "change" compared to the active loop.
  287. } elseif ( $key !== $active_loop['key'] ) {
  288. // Find sub field and check if a sub value exists.
  289. $sub_field_exists = false;
  290. $sub_field = acf_get_sub_field( $selector, $active_loop['field'] );
  291. if ( $sub_field ) {
  292. $sub_field_exists = isset( $active_loop['value'][ $active_loop['i'] ][ $sub_field['key'] ] );
  293. }
  294. // Detect change in post_id.
  295. if ( $post_id != $active_loop['post_id'] ) {
  296. // Case: Change in $post_id was due to this being a nested loop and not specifying the $post_id.
  297. // Action: Move down one level into a new loop.
  298. if ( empty( $_post_id ) && $sub_field_exists ) {
  299. $new_loop = 'child';
  300. // Case: Change in $post_id was due to a nested loop ending.
  301. // Action: move up one level through the loops.
  302. } elseif ( $prev_loop && $prev_loop['post_id'] == $post_id ) {
  303. acf_remove_loop( 'active' );
  304. $active_loop = $prev_loop;
  305. // Case: Chang in $post_id is the most obvious, used in an WP_Query loop with multiple $post objects.
  306. // Action: leave this current loop alone and create a new parent loop.
  307. } else {
  308. $new_loop = 'parent';
  309. }
  310. // Detect change in selector.
  311. } elseif ( $selector != $active_loop['selector'] ) {
  312. // Case: Change in $field_name was due to this being a nested loop.
  313. // Action: move down one level into a new loop.
  314. if ( $sub_field_exists ) {
  315. $new_loop = 'child';
  316. // Case: Change in $field_name was due to a nested loop ending.
  317. // Action: move up one level through the loops.
  318. } elseif ( $prev_loop && $prev_loop['selector'] == $selector && $prev_loop['post_id'] == $post_id ) {
  319. acf_remove_loop( 'active' );
  320. $active_loop = $prev_loop;
  321. // Case: Change in $field_name is the most obvious, this is a new loop for a different field within the $post.
  322. // Action: leave this current loop alone and create a new parent loop.
  323. } else {
  324. $new_loop = 'parent';
  325. }
  326. }
  327. }
  328. // Add loop if required.
  329. if ( $new_loop ) {
  330. $args = array(
  331. 'key' => $key,
  332. 'selector' => $selector,
  333. 'post_id' => $post_id,
  334. 'name' => null,
  335. 'value' => null,
  336. 'field' => null,
  337. 'i' => -1,
  338. );
  339. // Case: Parent loop.
  340. if ( $new_loop === 'parent' ) {
  341. $field = get_field_object( $selector, $post_id, false );
  342. if ( $field ) {
  343. $args['field'] = $field;
  344. $args['value'] = $field['value'];
  345. $args['name'] = $field['name'];
  346. unset( $args['field']['value'] );
  347. }
  348. // Case: Child loop ($sub_field must exist).
  349. } else {
  350. $args['field'] = $sub_field;
  351. $args['value'] = $active_loop['value'][ $active_loop['i'] ][ $sub_field['key'] ];
  352. $args['name'] = "{$active_loop['name']}_{$active_loop['i']}_{$sub_field['name']}";
  353. $args['post_id'] = $active_loop['post_id'];
  354. }
  355. // Bail early if value is either empty or a non array.
  356. if ( ! $args['value'] || ! is_array( $args['value'] ) ) {
  357. return false;
  358. }
  359. // Allow for non repeatable data for Group and Clone fields.
  360. if ( acf_get_field_type_prop( $args['field']['type'], 'have_rows' ) === 'single' ) {
  361. $args['value'] = array( $args['value'] );
  362. }
  363. // Add loop.
  364. $active_loop = acf_add_loop( $args );
  365. }
  366. // Return true if next row exists.
  367. if ( $active_loop && isset( $active_loop['value'][ $active_loop['i'] + 1 ] ) ) {
  368. return true;
  369. }
  370. // Return false if no next row.
  371. acf_remove_loop( 'active' );
  372. return false;
  373. }
  374. /*
  375. * the_row
  376. *
  377. * This function will progress the global repeater or flexible content value 1 row
  378. *
  379. * @type function
  380. * @date 2/09/13
  381. * @since 4.3.0
  382. *
  383. * @param N/A
  384. * @return (array) the current row data
  385. */
  386. function the_row( $format = false ) {
  387. // vars
  388. $i = acf_get_loop( 'active', 'i' );
  389. // increase
  390. $i++;
  391. // update
  392. acf_update_loop( 'active', 'i', $i );
  393. // return
  394. return get_row( $format );
  395. }
  396. function get_row( $format = false ) {
  397. // vars
  398. $loop = acf_get_loop( 'active' );
  399. // bail early if no loop
  400. if ( ! $loop ) {
  401. return false;
  402. }
  403. // get value
  404. $value = acf_maybe_get( $loop['value'], $loop['i'] );
  405. // bail early if no current value
  406. // possible if get_row_layout() is called before the_row()
  407. if ( ! $value ) {
  408. return false;
  409. }
  410. // format
  411. if ( $format ) {
  412. // vars
  413. $field = $loop['field'];
  414. // single row
  415. if ( acf_get_field_type_prop( $field['type'], 'have_rows' ) === 'single' ) {
  416. // format value
  417. $value = acf_format_value( $value, $loop['post_id'], $field );
  418. // multiple rows
  419. } else {
  420. // format entire value
  421. // - solves problem where cached value is incomplete
  422. // - no performance issues here thanks to cache
  423. $value = acf_format_value( $loop['value'], $loop['post_id'], $field );
  424. $value = acf_maybe_get( $value, $loop['i'] );
  425. }
  426. }
  427. // return
  428. return $value;
  429. }
  430. function get_row_index() {
  431. // vars
  432. $i = acf_get_loop( 'active', 'i' );
  433. $offset = acf_get_setting( 'row_index_offset' );
  434. // return
  435. return $offset + $i;
  436. }
  437. function the_row_index() {
  438. echo get_row_index();
  439. }
  440. /*
  441. * get_row_sub_field
  442. *
  443. * This function is used inside a 'has_sub_field' while loop to return a sub field object
  444. *
  445. * @type function
  446. * @date 16/05/2016
  447. * @since 5.3.8
  448. *
  449. * @param $selector (string)
  450. * @return (array)
  451. */
  452. function get_row_sub_field( $selector ) {
  453. // vars
  454. $row = acf_get_loop( 'active' );
  455. // bail early if no row
  456. if ( ! $row ) {
  457. return false;
  458. }
  459. // attempt to find sub field
  460. $sub_field = acf_get_sub_field( $selector, $row['field'] );
  461. // bail early if no field
  462. if ( ! $sub_field ) {
  463. return false;
  464. }
  465. // update field's name based on row data
  466. $sub_field['name'] = "{$row['name']}_{$row['i']}_{$sub_field['name']}";
  467. // return
  468. return $sub_field;
  469. }
  470. /*
  471. * get_row_sub_value
  472. *
  473. * This function is used inside a 'has_sub_field' while loop to return a sub field value
  474. *
  475. * @type function
  476. * @date 16/05/2016
  477. * @since 5.3.8
  478. *
  479. * @param $selector (string)
  480. * @return (mixed)
  481. */
  482. function get_row_sub_value( $selector ) {
  483. // vars
  484. $row = acf_get_loop( 'active' );
  485. // bail early if no row
  486. if ( ! $row ) {
  487. return null;
  488. }
  489. // return value
  490. if ( isset( $row['value'][ $row['i'] ][ $selector ] ) ) {
  491. return $row['value'][ $row['i'] ][ $selector ];
  492. }
  493. // return
  494. return null;
  495. }
  496. /*
  497. * reset_rows
  498. *
  499. * This function will find the current loop and unset it from the global array.
  500. * To bo used when loop finishes or a break is used
  501. *
  502. * @type function
  503. * @date 26/10/13
  504. * @since 5.0.0
  505. *
  506. * @param $hard_reset (boolean) completely wipe the global variable, or just unset the active row
  507. * @return (boolean)
  508. */
  509. function reset_rows() {
  510. // remove last loop
  511. acf_remove_loop( 'active' );
  512. // return
  513. return true;
  514. }
  515. /*
  516. * has_sub_field()
  517. *
  518. * This function is used inside a while loop to return either true or false (loop again or stop).
  519. * When using a repeater or flexible content field, it will loop through the rows until
  520. * there are none left or a break is detected
  521. *
  522. * @type function
  523. * @since 1.0.3
  524. * @date 29/01/13
  525. *
  526. * @param $field_name (string) the field name
  527. * @param $post_id (mixed) the post_id of which the value is saved against
  528. * @return (boolean)
  529. */
  530. function has_sub_field( $field_name, $post_id = false ) {
  531. // vars
  532. $r = have_rows( $field_name, $post_id );
  533. // if has rows, progress through 1 row for the while loop to work
  534. if ( $r ) {
  535. the_row();
  536. }
  537. // return
  538. return $r;
  539. }
  540. function has_sub_fields( $field_name, $post_id = false ) {
  541. return has_sub_field( $field_name, $post_id );
  542. }
  543. /*
  544. * get_sub_field()
  545. *
  546. * This function is used inside a 'has_sub_field' while loop to return a sub field value
  547. *
  548. * @type function
  549. * @since 1.0.3
  550. * @date 29/01/13
  551. *
  552. * @param $field_name (string) the field name
  553. * @return (mixed)
  554. */
  555. function get_sub_field( $selector = '', $format_value = true ) {
  556. // get sub field
  557. $sub_field = get_sub_field_object( $selector, $format_value );
  558. // bail early if no sub field
  559. if ( ! $sub_field ) {
  560. return false;
  561. }
  562. // return
  563. return $sub_field['value'];
  564. }
  565. /*
  566. * the_sub_field()
  567. *
  568. * This function is the same as echo get_sub_field
  569. *
  570. * @type function
  571. * @since 1.0.3
  572. * @date 29/01/13
  573. *
  574. * @param $field_name (string) the field name
  575. * @return n/a
  576. */
  577. function the_sub_field( $field_name, $format_value = true ) {
  578. $value = get_sub_field( $field_name, $format_value );
  579. if ( is_array( $value ) ) {
  580. $value = implode( ', ', $value );
  581. }
  582. echo $value;
  583. }
  584. /*
  585. * get_sub_field_object()
  586. *
  587. * This function is used inside a 'has_sub_field' while loop to return a sub field object
  588. *
  589. * @type function
  590. * @since 3.5.8.1
  591. * @date 29/01/13
  592. *
  593. * @param $child_name (string) the field name
  594. * @return (array)
  595. */
  596. function get_sub_field_object( $selector, $format_value = true, $load_value = true ) {
  597. // vars
  598. $row = acf_get_loop( 'active' );
  599. // bail early if no row
  600. if ( ! $row ) {
  601. return false;
  602. }
  603. // attempt to find sub field
  604. $sub_field = get_row_sub_field( $selector );
  605. // bail early if no sub field
  606. if ( ! $sub_field ) {
  607. return false;
  608. }
  609. // load value
  610. if ( $load_value ) {
  611. $sub_field['value'] = get_row_sub_value( $sub_field['key'] );
  612. }
  613. // format value
  614. if ( $format_value ) {
  615. // get value for field
  616. $sub_field['value'] = acf_format_value( $sub_field['value'], $row['post_id'], $sub_field );
  617. }
  618. // return
  619. return $sub_field;
  620. }
  621. /*
  622. * get_row_layout()
  623. *
  624. * This function will return a string representation of the current row layout within a 'have_rows' loop
  625. *
  626. * @type function
  627. * @since 3.0.6
  628. * @date 29/01/13
  629. *
  630. * @param n/a
  631. * @return (string)
  632. */
  633. function get_row_layout() {
  634. // vars
  635. $row = get_row();
  636. // return
  637. if ( isset( $row['acf_fc_layout'] ) ) {
  638. return $row['acf_fc_layout'];
  639. }
  640. // return
  641. return false;
  642. }
  643. /**
  644. * This function is used to add basic shortcode support for the ACF plugin
  645. * eg. [acf field="heading" post_id="123" format_value="1"]
  646. *
  647. * @since 1.1.1
  648. * @date 29/01/13
  649. *
  650. * @param array $atts The shortcode attributes.
  651. *
  652. * @return string
  653. */
  654. function acf_shortcode( $atts ) {
  655. // Return if the ACF shortcode is disabled.
  656. if ( ! acf_get_setting( 'enable_shortcode' ) ) {
  657. return;
  658. }
  659. if ( function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() ) {
  660. // Prevent the ACF shortcode in FSE block template parts by default.
  661. if ( ! doing_filter( 'the_content' ) && ! apply_filters( 'acf/shortcode/allow_in_block_themes_outside_content', false ) ) {
  662. return;
  663. }
  664. }
  665. // Limit previews of ACF shortcode data for users without publish_posts permissions.
  666. $preview_capability = apply_filters( 'acf/shortcode/preview_capability', 'publish_posts' );
  667. if ( is_preview() && ! current_user_can( $preview_capability ) ) {
  668. return apply_filters( 'acf/shortcode/preview_capability_message', __( '[ACF shortcode value disabled for preview]', 'acf' ) );
  669. }
  670. // Mitigate issue where some AJAX requests can return ACF field data.
  671. $ajax_capability = apply_filters( 'acf/ajax/shortcode_capability', 'edit_posts' );
  672. if ( wp_doing_ajax() && ( $ajax_capability !== false ) && ! current_user_can( $ajax_capability ) ) {
  673. return;
  674. }
  675. $atts = shortcode_atts(
  676. array(
  677. 'field' => '',
  678. 'post_id' => false,
  679. 'format_value' => true,
  680. ),
  681. $atts,
  682. 'acf'
  683. );
  684. $access_already_prevented = apply_filters( 'acf/prevent_access_to_unknown_fields', false );
  685. $filter_applied = false;
  686. if ( ! $access_already_prevented ) {
  687. $filter_applied = true;
  688. add_filter( 'acf/prevent_access_to_unknown_fields', '__return_true' );
  689. }
  690. // Try to get the field value.
  691. $value = get_field( $atts['field'], $atts['post_id'], $atts['format_value'] );
  692. if ( $filter_applied ) {
  693. remove_filter( 'acf/prevent_access_to_unknown_fields', '__return_true' );
  694. }
  695. if ( is_array( $value ) ) {
  696. $value = implode( ', ', $value );
  697. }
  698. return $value;
  699. }
  700. add_shortcode( 'acf', 'acf_shortcode' );
  701. /*
  702. * update_field()
  703. *
  704. * This function will update a value in the database
  705. *
  706. * @type function
  707. * @since 3.1.9
  708. * @date 29/01/13
  709. *
  710. * @param $selector (string) the field name or key
  711. * @param $value (mixed) the value to save in the database
  712. * @param $post_id (mixed) the post_id of which the value is saved against
  713. * @return (boolean)
  714. */
  715. function update_field( $selector, $value, $post_id = false ) {
  716. // filter post_id
  717. $post_id = acf_get_valid_post_id( $post_id );
  718. // get field
  719. $field = acf_maybe_get_field( $selector, $post_id, false );
  720. // create dummy field
  721. if ( ! $field ) {
  722. $field = acf_get_valid_field(
  723. array(
  724. 'name' => $selector,
  725. 'key' => '',
  726. 'type' => '',
  727. )
  728. );
  729. }
  730. // save
  731. return acf_update_value( $value, $post_id, $field );
  732. }
  733. /*
  734. * update_sub_field
  735. *
  736. * This function will update a value of a sub field in the database
  737. *
  738. * @type function
  739. * @date 2/04/2014
  740. * @since 5.0.0
  741. *
  742. * @param $selector (mixed) the sub field name or key, or an array of ancestors
  743. * @param $value (mixed) the value to save in the database
  744. * @param $post_id (mixed) the post_id of which the value is saved against
  745. * @return (boolean)
  746. */
  747. function update_sub_field( $selector, $value, $post_id = false ) {
  748. // vars
  749. $sub_field = false;
  750. // get sub field
  751. if ( is_array( $selector ) ) {
  752. $post_id = acf_get_valid_post_id( $post_id );
  753. $sub_field = acf_maybe_get_sub_field( $selector, $post_id, false );
  754. } else {
  755. $post_id = acf_get_loop( 'active', 'post_id' );
  756. $sub_field = get_row_sub_field( $selector );
  757. }
  758. // bail early if no sub field
  759. if ( ! $sub_field ) {
  760. return false;
  761. }
  762. // update
  763. return acf_update_value( $value, $post_id, $sub_field );
  764. }
  765. /*
  766. * delete_field()
  767. *
  768. * This function will remove a value from the database
  769. *
  770. * @type function
  771. * @since 3.1.9
  772. * @date 29/01/13
  773. *
  774. * @param $selector (string) the field name or key
  775. * @param $post_id (mixed) the post_id of which the value is saved against
  776. * @return (boolean)
  777. */
  778. function delete_field( $selector, $post_id = false ) {
  779. // filter post_id
  780. $post_id = acf_get_valid_post_id( $post_id );
  781. // get field
  782. $field = acf_maybe_get_field( $selector, $post_id );
  783. // delete
  784. return $field ? acf_delete_value( $post_id, $field ) : false;
  785. }
  786. /*
  787. * delete_sub_field
  788. *
  789. * This function will delete a value of a sub field in the database
  790. *
  791. * @type function
  792. * @date 2/04/2014
  793. * @since 5.0.0
  794. *
  795. * @param $selector (mixed) the sub field name or key, or an array of ancestors
  796. * @param $value (mixed) the value to save in the database
  797. * @param $post_id (mixed) the post_id of which the value is saved against
  798. * @return (boolean)
  799. */
  800. function delete_sub_field( $selector, $post_id = false ) {
  801. return update_sub_field( $selector, null, $post_id );
  802. }
  803. /*
  804. * add_row
  805. *
  806. * This function will add a row of data to a field
  807. *
  808. * @type function
  809. * @date 16/10/2015
  810. * @since 5.2.3
  811. *
  812. * @param $selector (string)
  813. * @param $row (array)
  814. * @param $post_id (mixed)
  815. * @return (boolean)
  816. */
  817. function add_row( $selector, $row = false, $post_id = false ) {
  818. // filter post_id
  819. $post_id = acf_get_valid_post_id( $post_id );
  820. // get field
  821. $field = acf_maybe_get_field( $selector, $post_id, false );
  822. // bail early if no field
  823. if ( ! $field ) {
  824. return false;
  825. }
  826. // get raw value
  827. $value = acf_get_value( $post_id, $field );
  828. // ensure array
  829. $value = acf_get_array( $value );
  830. // append
  831. $value[] = $row;
  832. // Paginated repeaters should be saved normally.
  833. $field['pagination'] = false;
  834. // update value
  835. acf_update_value( $value, $post_id, $field );
  836. // return
  837. return count( $value );
  838. }
  839. /*
  840. * add_sub_row
  841. *
  842. * This function will add a row of data to a field
  843. *
  844. * @type function
  845. * @date 16/10/2015
  846. * @since 5.2.3
  847. *
  848. * @param $selector (string)
  849. * @param $row (array)
  850. * @param $post_id (mixed)
  851. * @return (boolean)
  852. */
  853. function add_sub_row( $selector, $row = false, $post_id = false ) {
  854. // vars
  855. $sub_field = false;
  856. // get sub field
  857. if ( is_array( $selector ) ) {
  858. $post_id = acf_get_valid_post_id( $post_id );
  859. $sub_field = acf_maybe_get_sub_field( $selector, $post_id, false );
  860. } else {
  861. $post_id = acf_get_loop( 'active', 'post_id' );
  862. $sub_field = get_row_sub_field( $selector );
  863. }
  864. // bail early if no sub field
  865. if ( ! $sub_field ) {
  866. return false;
  867. }
  868. // get raw value
  869. $value = acf_get_value( $post_id, $sub_field );
  870. // ensure array
  871. $value = acf_get_array( $value );
  872. // append
  873. $value[] = $row;
  874. // update
  875. acf_update_value( $value, $post_id, $sub_field );
  876. // return
  877. return count( $value );
  878. }
  879. /*
  880. * update_row
  881. *
  882. * This function will update a row of data to a field
  883. *
  884. * @type function
  885. * @date 19/10/2015
  886. * @since 5.2.3
  887. *
  888. * @param $selector (string)
  889. * @param $i (int)
  890. * @param $row (array)
  891. * @param $post_id (mixed)
  892. * @return (boolean)
  893. */
  894. function update_row( $selector, $i = 1, $row = false, $post_id = false ) {
  895. // vars
  896. $offset = acf_get_setting( 'row_index_offset' );
  897. $i = $i - $offset;
  898. // filter post_id
  899. $post_id = acf_get_valid_post_id( $post_id );
  900. // get field
  901. $field = acf_maybe_get_field( $selector, $post_id, false );
  902. // bail early if no field
  903. if ( ! $field ) {
  904. return false;
  905. }
  906. // get raw value
  907. $value = acf_get_value( $post_id, $field );
  908. // ensure array
  909. $value = acf_get_array( $value );
  910. // update
  911. $value[ $i ] = $row;
  912. // update value
  913. acf_update_value( $value, $post_id, $field );
  914. // return
  915. return true;
  916. }
  917. /*
  918. * update_sub_row
  919. *
  920. * This function will add a row of data to a field
  921. *
  922. * @type function
  923. * @date 16/10/2015
  924. * @since 5.2.3
  925. *
  926. * @param $selector (string)
  927. * @param $row (array)
  928. * @param $post_id (mixed)
  929. * @return (boolean)
  930. */
  931. function update_sub_row( $selector, $i = 1, $row = false, $post_id = false ) {
  932. // vars
  933. $sub_field = false;
  934. $offset = acf_get_setting( 'row_index_offset' );
  935. $i = $i - $offset;
  936. // get sub field
  937. if ( is_array( $selector ) ) {
  938. $post_id = acf_get_valid_post_id( $post_id );
  939. $sub_field = acf_maybe_get_sub_field( $selector, $post_id, false );
  940. } else {
  941. $post_id = acf_get_loop( 'active', 'post_id' );
  942. $sub_field = get_row_sub_field( $selector );
  943. }
  944. // bail early if no sub field
  945. if ( ! $sub_field ) {
  946. return false;
  947. }
  948. // get raw value
  949. $value = acf_get_value( $post_id, $sub_field );
  950. // ensure array
  951. $value = acf_get_array( $value );
  952. // append
  953. $value[ $i ] = $row;
  954. // update
  955. acf_update_value( $value, $post_id, $sub_field );
  956. // return
  957. return true;
  958. }
  959. /*
  960. * delete_row
  961. *
  962. * This function will delete a row of data from a field
  963. *
  964. * @type function
  965. * @date 19/10/2015
  966. * @since 5.2.3
  967. *
  968. * @param $selector (string)
  969. * @param $i (int)
  970. * @param $post_id (mixed)
  971. * @return (boolean)
  972. */
  973. function delete_row( $selector, $i = 1, $post_id = false ) {
  974. // vars
  975. $offset = acf_get_setting( 'row_index_offset' );
  976. $i = $i - $offset;
  977. // filter post_id
  978. $post_id = acf_get_valid_post_id( $post_id );
  979. // get field
  980. $field = acf_maybe_get_field( $selector, $post_id );
  981. // bail early if no field
  982. if ( ! $field ) {
  983. return false;
  984. }
  985. // get value
  986. $value = acf_get_value( $post_id, $field );
  987. // ensure array
  988. $value = acf_get_array( $value );
  989. // bail early if index doesn't exist
  990. if ( ! isset( $value[ $i ] ) ) {
  991. return false;
  992. }
  993. // unset
  994. unset( $value[ $i ] );
  995. // update
  996. acf_update_value( $value, $post_id, $field );
  997. // return
  998. return true;
  999. }
  1000. /*
  1001. * delete_sub_row
  1002. *
  1003. * This function will add a row of data to a field
  1004. *
  1005. * @type function
  1006. * @date 16/10/2015
  1007. * @since 5.2.3
  1008. *
  1009. * @param $selector (string)
  1010. * @param $row (array)
  1011. * @param $post_id (mixed)
  1012. * @return (boolean)
  1013. */
  1014. function delete_sub_row( $selector, $i = 1, $post_id = false ) {
  1015. // vars
  1016. $sub_field = false;
  1017. $offset = acf_get_setting( 'row_index_offset' );
  1018. $i = $i - $offset;
  1019. // get sub field
  1020. if ( is_array( $selector ) ) {
  1021. $post_id = acf_get_valid_post_id( $post_id );
  1022. $sub_field = acf_maybe_get_sub_field( $selector, $post_id, false );
  1023. } else {
  1024. $post_id = acf_get_loop( 'active', 'post_id' );
  1025. $sub_field = get_row_sub_field( $selector );
  1026. }
  1027. // bail early if no sub field
  1028. if ( ! $sub_field ) {
  1029. return false;
  1030. }
  1031. // get raw value
  1032. $value = acf_get_value( $post_id, $sub_field );
  1033. // ensure array
  1034. $value = acf_get_array( $value );
  1035. // bail early if index doesn't exist
  1036. if ( ! isset( $value[ $i ] ) ) {
  1037. return false;
  1038. }
  1039. // append
  1040. unset( $value[ $i ] );
  1041. // update
  1042. acf_update_value( $value, $post_id, $sub_field );
  1043. // return
  1044. return true;
  1045. }
  1046. /*
  1047. * Depreceated Functions
  1048. *
  1049. * These functions are outdated
  1050. *
  1051. * @type function
  1052. * @date 4/03/2014
  1053. * @since 1.0.0
  1054. *
  1055. * @param n/a
  1056. * @return n/a
  1057. */
  1058. function create_field( $field ) {
  1059. acf_render_field( $field );
  1060. }
  1061. function render_field( $field ) {
  1062. acf_render_field( $field );
  1063. }
  1064. function reset_the_repeater_field() {
  1065. return reset_rows();
  1066. }
  1067. function the_repeater_field( $field_name, $post_id = false ) {
  1068. return has_sub_field( $field_name, $post_id );
  1069. }
  1070. function the_flexible_field( $field_name, $post_id = false ) {
  1071. return has_sub_field( $field_name, $post_id );
  1072. }
  1073. function acf_filter_post_id( $post_id ) {
  1074. return acf_get_valid_post_id( $post_id );
  1075. }