/core/api.php

  1. <?php 
  2.  
  3. /** 
  4. * get_field_reference() 
  5. * 
  6. * This function will find the $field_key that is related to the $field_name. 
  7. * This is know as the field value reference 
  8. * 
  9. * @type function 
  10. * @since 3.6 
  11. * @date 29/01/13 
  12. * 
  13. * @param mixed $field_name: the name of the field - 'sub_heading' 
  14. * @param int $post_id: the post_id of which the value is saved against 
  15. * 
  16. * @return string $return: a string containing the field_key 
  17. */ 
  18.  
  19. function get_field_reference( $field_name, $post_id ) { 
  20.  
  21. // cache 
  22. $found = false; 
  23. $cache = wp_cache_get( 'field_reference/post_id=' . $post_id . '/name=' . $field_name, 'acf', false, $found ); 
  24.  
  25. if( $found ) 
  26. return $cache; 
  27.  
  28.  
  29. // vars 
  30. $return = ''; 
  31.  
  32.  
  33. // get field key 
  34. if( is_numeric($post_id) ) 
  35. $return = get_post_meta($post_id, '_' . $field_name, true);  
  36. elseif( strpos($post_id, 'user_') !== false ) 
  37. $temp_post_id = str_replace('user_', '', $post_id); 
  38. $return = get_user_meta($temp_post_id, '_' . $field_name, true);  
  39. else 
  40. $return = get_option('_' . $post_id . '_' . $field_name);  
  41.  
  42.  
  43. // set cache 
  44. wp_cache_set( 'field_reference/post_id=' . $post_id . '/name=' . $field_name, $return, 'acf' ); 
  45.  
  46.  
  47. // return  
  48. return $return; 
  49.  
  50.  
  51. /** 
  52. * get_field_objects() 
  53. * 
  54. * This function will return an array containing all the custom field objects for a specific post_id. 
  55. * The function is not very elegant and wastes a lot of PHP memory / SQL queries if you are not using all the fields / values. 
  56. * 
  57. * @type function 
  58. * @since 3.6 
  59. * @date 29/01/13 
  60. * 
  61. * @param mixed $post_id: the post_id of which the value is saved against 
  62. * 
  63. * @return array $return: an array containin the field groups 
  64. */ 
  65.  
  66. function get_field_objects( $post_id = false, $options = array() ) { 
  67.  
  68. // global 
  69. global $wpdb; 
  70.  
  71.  
  72. // filter post_id 
  73. $post_id = apply_filters('acf/get_post_id', $post_id ); 
  74.  
  75.  
  76. // vars 
  77. $field_key = ''; 
  78. $value = array(); 
  79.  
  80.  
  81. // get field_names 
  82. if( is_numeric($post_id) ) 
  83. $keys = $wpdb->get_col($wpdb->prepare( 
  84. "SELECT meta_value FROM $wpdb->postmeta WHERE post_id = %d and meta_key LIKE %s AND meta_value LIKE %s",  
  85. $post_id,  
  86. '_%',  
  87. 'field_%' 
  88. )); 
  89. elseif( strpos($post_id, 'user_') !== false ) 
  90. $user_id = str_replace('user_', '', $post_id); 
  91.  
  92. $keys = $wpdb->get_col($wpdb->prepare( 
  93. "SELECT meta_value FROM $wpdb->usermeta WHERE user_id = %d and meta_key LIKE %s AND meta_value LIKE %s",  
  94. $user_id,  
  95. '_%',  
  96. 'field_%' 
  97. )); 
  98. else 
  99. $keys = $wpdb->get_col($wpdb->prepare( 
  100. "SELECT option_value FROM $wpdb->options WHERE option_name LIKE %s",  
  101. '_' . $post_id . '_%'  
  102. )); 
  103.  
  104.  
  105. if( is_array($keys) ) 
  106. foreach( $keys as $key ) 
  107. $field = get_field_object( $key, $post_id, $options ); 
  108.  
  109. if( !is_array($field) ) 
  110. continue; 
  111.  
  112. $value[ $field['name'] ] = $field; 
  113.  
  114.  
  115. // no value 
  116. if( empty($value) ) 
  117. return false; 
  118.  
  119.  
  120. // return 
  121. return $value; 
  122.  
  123.  
  124. /** 
  125. * get_fields() 
  126. * 
  127. * This function will return an array containing all the custom field values for a specific post_id. 
  128. * The function is not very elegant and wastes a lot of PHP memory / SQL queries if you are not using all the values. 
  129. * 
  130. * @type function 
  131. * @since 3.6 
  132. * @date 29/01/13 
  133. * 
  134. * @param mixed $post_id: the post_id of which the value is saved against 
  135. * 
  136. * @return array $return: an array containin the field values 
  137. */ 
  138.  
  139. function get_fields( $post_id = false, $format_value = true ) { 
  140.  
  141. // vars 
  142. $options = array( 
  143. 'load_value' => true,  
  144. 'format_value' => $format_value 
  145. ); 
  146.  
  147.  
  148. $fields = get_field_objects( $post_id, $options ); 
  149.  
  150. if( is_array($fields) ) 
  151. foreach( $fields as $k => $field ) 
  152. $fields[ $k ] = $field['value']; 
  153.  
  154. return $fields;  
  155.  
  156.  
  157. /** 
  158. * get_field() 
  159. * 
  160. * This function will return a custom field value for a specific field name/key + post_id. 
  161. * There is a 3rd parameter to turn on/off formating. This means that an Image field will not use  
  162. * its 'return option' to format the value but return only what was saved in the database 
  163. * 
  164. * @type function 
  165. * @since 3.6 
  166. * @date 29/01/13 
  167. * 
  168. * @param string $field_key: string containing the name of teh field name / key ('sub_field' / 'field_1') 
  169. * @param mixed $post_id: the post_id of which the value is saved against 
  170. * @param boolean $format_value: whether or not to format the value as described above 
  171. * 
  172. * @return mixed $value: the value found 
  173. */ 
  174.  
  175. function get_field( $field_key, $post_id = false, $format_value = true ) { 
  176.  
  177. // vars 
  178. $return = false; 
  179. $options = array( 
  180. 'load_value' => true,  
  181. 'format_value' => $format_value 
  182. ); 
  183.  
  184.  
  185. $field = get_field_object( $field_key, $post_id, $options); 
  186.  
  187.  
  188. if( is_array($field) ) 
  189. $return = $field['value']; 
  190.  
  191.  
  192. return $return; 
  193.  
  194.  
  195.  
  196. /** 
  197. * get_field_object() 
  198. * 
  199. * This function will return an array containing all the field data for a given field_name 
  200. * 
  201. * @type function 
  202. * @since 3.6 
  203. * @date 3/02/13 
  204. * 
  205. * @param string $field_key: string containing the name of teh field name / key ('sub_field' / 'field_1') 
  206. * @param mixed $post_id: the post_id of which the value is saved against 
  207. * @param array $options: an array containing options 
  208. * boolean + load_value: load the field value or not. Defaults to true 
  209. * boolean + format_value: format the field value or not. Defaults to true 
  210. * 
  211. * @return array $return: an array containin the field groups 
  212. */ 
  213.  
  214. function get_field_object( $field_key, $post_id = false, $options = array() ) { 
  215.  
  216. // make sure add-ons are included 
  217. acf()->include_3rd_party(); 
  218.  
  219.  
  220. // filter post_id 
  221. $post_id = apply_filters('acf/get_post_id', $post_id ); 
  222. $field = false; 
  223. $orig_field_key = $field_key; 
  224.  
  225.  
  226. // defaults for options 
  227. $defaults = array( 
  228. 'load_value' => true,  
  229. 'format_value' => true,  
  230. ); 
  231.  
  232. $options = array_merge($defaults, $options); 
  233.  
  234.  
  235. // is $field_name a name? pre 3.4.0 
  236. if( substr($field_key, 0, 6) !== 'field_' ) 
  237. // get field key 
  238. $field_key = get_field_reference( $field_key, $post_id ); 
  239.  
  240.  
  241. // get field 
  242. if( substr($field_key, 0, 6) === 'field_' ) 
  243. $field = apply_filters('acf/load_field', false, $field_key ); 
  244.  
  245.  
  246. // validate field 
  247. if( !$field ) 
  248. // treat as text field 
  249. $field = array( 
  250. 'type' => 'text',  
  251. 'name' => $orig_field_key,  
  252. 'key' => 'field_' . $orig_field_key,  
  253. ); 
  254. $field = apply_filters('acf/load_field', $field, $field['key'] ); 
  255.  
  256.  
  257. // load value 
  258. if( $options['load_value'] ) 
  259. $field['value'] = apply_filters('acf/load_value', false, $post_id, $field); 
  260.  
  261.  
  262. // format value 
  263. if( $options['format_value'] ) 
  264. $field['value'] = apply_filters('acf/format_value_for_api', $field['value'], $post_id, $field); 
  265.  
  266.  
  267. return $field; 
  268.  
  269.  
  270.  
  271. /** 
  272. * the_field() 
  273. * 
  274. * This function is the same as echo get_field(). 
  275. * 
  276. * @type function 
  277. * @since 1.0.3 
  278. * @date 29/01/13 
  279. * 
  280. * @param string $field_name: the name of the field - 'sub_heading' 
  281. * @param mixed $post_id: the post_id of which the value is saved against 
  282. * 
  283. * @return string $value 
  284. */ 
  285.  
  286. function the_field( $field_name, $post_id = false ) { 
  287.  
  288. $value = get_field($field_name, $post_id); 
  289.  
  290. if( is_array($value) ) 
  291. $value = @implode(', ', $value); 
  292.  
  293. echo $value; 
  294.  
  295.  
  296. /** 
  297. * have_rows 
  298. * 
  299. * This function will instantiate a global variable containing the rows of a repeater or flexible content field,  
  300. * afterwhich, it will determine if another row exists to loop through 
  301. * 
  302. * @type function 
  303. * @date 2/09/13 
  304. * @since 4.3.0 
  305. * 
  306. * @param $field_name (string) the name of the field - 'images' 
  307. * @return $post_id (mixed) the post_id of which the value is saved against 
  308. */ 
  309.  
  310. function have_rows( $field_name, $post_id = false ) { 
  311.  
  312. // vars 
  313. $depth = 0; 
  314. $row = array(); 
  315. $new_parent_loop = false; 
  316. $new_child_loop = false; 
  317.  
  318.  
  319. // reference 
  320. $_post_id = $post_id; 
  321.  
  322.  
  323. // filter post_id 
  324. $post_id = apply_filters('acf/get_post_id', $post_id ); 
  325.  
  326.  
  327. // empty? 
  328. if( empty($GLOBALS['acf_field']) ) 
  329. // reset 
  330. reset_rows( true ); 
  331.  
  332.  
  333. // create a new loop 
  334. $new_parent_loop = true; 
  335. else 
  336. // vars 
  337. $row = end( $GLOBALS['acf_field'] ); 
  338. $prev = prev( $GLOBALS['acf_field'] ); 
  339.  
  340.  
  341. // If post_id has changed, this is most likely an archive loop 
  342. if( $post_id != $row['post_id'] ) 
  343. if( $prev && $prev['post_id'] == $post_id ) 
  344. // case: Change in $post_id was due to a nested loop ending 
  345. // action: move up one level through the loops 
  346. reset_rows(); 
  347. elseif( empty($_post_id) && isset($row['value'][ $row['i'] ][ $field_name ]) ) 
  348. // case: Change in $post_id was due to this being a nested loop and not specifying the $post_id 
  349. // action: move down one level into a new loop 
  350. $new_child_loop = true; 
  351. else 
  352. // case: Chang in $post_id is the most obvious, used in an WP_Query loop with multiple $post objects 
  353. // action: leave this current loop alone and create a new parent loop 
  354. $new_parent_loop = true; 
  355. elseif( $field_name != $row['name'] ) 
  356. if( $prev && $prev['name'] == $field_name && $prev['post_id'] == $post_id ) 
  357. // case: Change in $field_name was due to a nested loop ending 
  358. // action: move up one level through the loops 
  359. reset_rows(); 
  360. elseif( isset($row['value'][ $row['i'] ][ $field_name ]) ) 
  361. // case: Change in $field_name was due to this being a nested loop 
  362. // action: move down one level into a new loop 
  363. $new_child_loop = true; 
  364.  
  365. else 
  366. // case: Chang in $field_name is the most obvious, this is a new loop for a different field within the $post 
  367. // action: leave this current loop alone and create a new parent loop 
  368. $new_parent_loop = true; 
  369.  
  370.  
  371.  
  372.  
  373. if( $new_parent_loop ) 
  374. // vars 
  375. $f = get_field_object( $field_name, $post_id ); 
  376. $v = $f['value']; 
  377. unset( $f['value'] ); 
  378.  
  379.  
  380. // add row 
  381. $GLOBALS['acf_field'][] = array( 
  382. 'name' => $field_name,  
  383. 'value' => $v,  
  384. 'field' => $f,  
  385. 'i' => -1,  
  386. 'post_id' => $post_id,  
  387. ); 
  388.  
  389. elseif( $new_child_loop ) 
  390. // vars 
  391. $f = acf_get_child_field_from_parent_field( $field_name, $row['field'] ); 
  392. $v = $row['value'][ $row['i'] ][ $field_name ]; 
  393.  
  394. $GLOBALS['acf_field'][] = array( 
  395. 'name' => $field_name,  
  396. 'value' => $v,  
  397. 'field' => $f,  
  398. 'i' => -1,  
  399. 'post_id' => $post_id,  
  400. ); 
  401.  
  402. }  
  403.  
  404.  
  405. // update vars 
  406. $row = end( $GLOBALS['acf_field'] ); 
  407.  
  408.  
  409. if( is_array($row['value']) && array_key_exists( $row['i']+1, $row['value'] ) ) 
  410. // next row exists 
  411. return true; 
  412.  
  413.  
  414. // no next row! 
  415. reset_rows(); 
  416.  
  417.  
  418. // return 
  419. return false; 
  420.  
  421.  
  422.  
  423. /** 
  424. * the_row 
  425. * 
  426. * This function will progress the global repeater or flexible content value 1 row 
  427. * 
  428. * @type function 
  429. * @date 2/09/13 
  430. * @since 4.3.0 
  431. * 
  432. * @param N/A 
  433. * @return N/A 
  434. */ 
  435.  
  436. function the_row() { 
  437.  
  438. // vars 
  439. $depth = count( $GLOBALS['acf_field'] ) - 1; 
  440.  
  441.  
  442.  
  443. // increase row 
  444. $GLOBALS['acf_field'][ $depth ]['i']++; 
  445.  
  446.  
  447. // get row 
  448. $value = $GLOBALS['acf_field'][ $depth ]['value']; 
  449. $i = $GLOBALS['acf_field'][ $depth ]['i']; 
  450.  
  451.  
  452. // return 
  453. return $value[ $i ]; 
  454.  
  455.  
  456. /** 
  457. * reset_rows 
  458. * 
  459. * This function will find the current loop and unset it from the global array. 
  460. * To bo used when loop finishes or a break is used 
  461. * 
  462. * @type function 
  463. * @date 26/10/13 
  464. * @since 5.0.0 
  465. * 
  466. * @param $post_id (int) 
  467. * @return $post_id (int) 
  468. */ 
  469.  
  470. function reset_rows( $hard_reset = false ) { 
  471.  
  472. // completely destroy? 
  473. if( $hard_reset ) 
  474. $GLOBALS['acf_field'] = array(); 
  475. else 
  476. // vars 
  477. $depth = count( $GLOBALS['acf_field'] ) - 1; 
  478.  
  479.  
  480. // remove 
  481. unset( $GLOBALS['acf_field'][$depth] ); 
  482.  
  483.  
  484. // refresh index 
  485. $GLOBALS['acf_field'] = array_values($GLOBALS['acf_field']); 
  486.  
  487.  
  488. // return 
  489. return true; 
  490.  
  491.  
  492.  
  493.  
  494. /** 
  495. * has_sub_field() 
  496. * 
  497. * This function is used inside a while loop to return either true or false (loop again or stop). 
  498. * When using a repeater or flexible content field, it will loop through the rows until  
  499. * there are none left or a break is detected 
  500. * 
  501. * @type function 
  502. * @since 1.0.3 
  503. * @date 29/01/13 
  504. * 
  505. * @param string $field_name: the name of the field - 'sub_heading' 
  506. * @param mixed $post_id: the post_id of which the value is saved against 
  507. * 
  508. * @return bool 
  509. */ 
  510.  
  511. function has_sub_field( $field_name, $post_id = false ) { 
  512.  
  513. // vars 
  514. $r = have_rows( $field_name, $post_id ); 
  515.  
  516.  
  517. // if has rows, progress through 1 row for the while loop to work 
  518. if( $r ) 
  519. the_row(); 
  520.  
  521.  
  522. // return 
  523. return $r; 
  524.  
  525.  
  526. /** 
  527. * has_sub_fields() 
  528. * 
  529. * This function is a replica of 'has_sub_field' 
  530. * 
  531. * @type function 
  532. * @since 4.0.0 
  533. * @date 29/01/13 
  534. * 
  535. * @param string $field_name: the name of the field - 'sub_heading' 
  536. * @param mixed $post_id: the post_id of which the value is saved against 
  537. * 
  538. * @return bool 
  539. */ 
  540.  
  541. function has_sub_fields( $field_name, $post_id = false ) 
  542. return has_sub_field( $field_name, $post_id ); 
  543.  
  544.  
  545. /** 
  546. * get_sub_field() 
  547. * 
  548. * This function is used inside a 'has_sub_field' while loop to return a sub field value 
  549. * 
  550. * @type function 
  551. * @since 1.0.3 
  552. * @date 29/01/13 
  553. * 
  554. * @param string $field_name: the name of the field - 'sub_heading' 
  555. * 
  556. * @return mixed $value 
  557. */ 
  558.  
  559. function get_sub_field( $field_name ) { 
  560.  
  561. // no field? 
  562. if( empty($GLOBALS['acf_field']) ) 
  563. return false; 
  564.  
  565.  
  566. // vars 
  567. $row = end( $GLOBALS['acf_field'] ); 
  568.  
  569.  
  570. // return value 
  571. if( isset($row['value'][ $row['i'] ][ $field_name ]) ) 
  572. return $row['value'][ $row['i'] ][ $field_name ]; 
  573.  
  574.  
  575. // return false 
  576. return false; 
  577.  
  578.  
  579. /** 
  580. * get_sub_field() 
  581. * 
  582. * This function is the same as echo get_sub_field 
  583. * 
  584. * @type function 
  585. * @since 1.0.3 
  586. * @date 29/01/13 
  587. * 
  588. * @param string $field_name: the name of the field - 'sub_heading' 
  589. * 
  590. * @return string $value 
  591. */ 
  592.  
  593. function the_sub_field($field_name) 
  594. $value = get_sub_field($field_name); 
  595.  
  596. if(is_array($value)) 
  597. $value = implode(', ', $value); 
  598.  
  599. echo $value; 
  600.  
  601.  
  602. /** 
  603. * get_sub_field_object() 
  604. * 
  605. * This function is used inside a 'has_sub_field' while loop to return a sub field object 
  606. * 
  607. * @type function 
  608. * @since 3.5.8.1 
  609. * @date 29/01/13 
  610. * 
  611. * @param string $field_name: the name of the field - 'sub_heading' 
  612. * 
  613. * @return array $sub_field  
  614. */ 
  615.  
  616. function get_sub_field_object( $child_name ) 
  617. // no field? 
  618. if( empty($GLOBALS['acf_field']) ) 
  619. return false; 
  620.  
  621.  
  622. // vars 
  623. $depth = count( $GLOBALS['acf_field'] ) - 1; 
  624. $parent = $GLOBALS['acf_field'][$depth]['field']; 
  625.  
  626.  
  627. // return 
  628. return acf_get_child_field_from_parent_field( $child_name, $parent ); 
  629.  
  630.  
  631.  
  632. /** 
  633. * acf_get_sub_field_from_parent_field() 
  634. * 
  635. * This function is used by the get_sub_field_object to find a sub field within a parent field 
  636. * 
  637. * @type function 
  638. * @since 3.5.8.1 
  639. * @date 29/01/13 
  640. * 
  641. * @param string $child_name: the name of the field - 'sub_heading' 
  642. * @param array $parent: the parent field object 
  643. * 
  644. * @return array $sub_field  
  645. */ 
  646.  
  647. function acf_get_child_field_from_parent_field( $child_name, $parent ) 
  648. // vars 
  649. $return = false; 
  650.  
  651.  
  652. // find child 
  653. if( isset($parent['sub_fields']) && is_array($parent['sub_fields']) ) 
  654. foreach( $parent['sub_fields'] as $child ) 
  655. if( $child['name'] == $child_name || $child['key'] == $child_name ) 
  656. $return = $child; 
  657. break; 
  658.  
  659. // perhaps child has grand children? 
  660. $grand_child = acf_get_child_field_from_parent_field( $child_name, $child ); 
  661. if( $grand_child ) 
  662. $return = $grand_child; 
  663. break; 
  664. elseif( isset($parent['layouts']) && is_array($parent['layouts']) ) 
  665. foreach( $parent['layouts'] as $layout ) 
  666. $child = acf_get_child_field_from_parent_field( $child_name, $layout ); 
  667. if( $child ) 
  668. $return = $child; 
  669. break; 
  670.  
  671.  
  672. // return 
  673. return $return; 
  674.  
  675.  
  676.  
  677. /** 
  678. * register_field_group() 
  679. * 
  680. * This function is used to register a field group via code. It acceps 1 array containing 
  681. * all the field group data. This data can be obtained by using teh export tool within ACF 
  682. * 
  683. * @type function 
  684. * @since 3.0.6 
  685. * @date 29/01/13 
  686. * 
  687. * @param array $array: an array holding all the field group data 
  688. * 
  689. * @return 
  690. */ 
  691.  
  692. $GLOBALS['acf_register_field_group'] = array(); 
  693.  
  694. function register_field_group( $array ) 
  695. // add id 
  696. if( !isset($array['id']) ) 
  697. $array['id'] = uniqid(); 
  698.  
  699.  
  700. // 3.2.5 - changed show_on_page option 
  701. if( !isset($array['options']['hide_on_screen']) && isset($array['options']['show_on_page']) ) 
  702. $show_all = array('the_content', 'discussion', 'custom_fields', 'comments', 'slug', 'author'); 
  703. $array['options']['hide_on_screen'] = array_diff($show_all, $array['options']['show_on_page']); 
  704. unset( $array['options']['show_on_page'] ); 
  705.  
  706.  
  707. // 4.0.4 - changed location rules architecture 
  708. if( isset($array['location']['rules']) ) 
  709. // vars 
  710. $groups = array(); 
  711. $group_no = 0; 
  712.  
  713.  
  714. if( is_array($array['location']['rules']) ) 
  715. foreach( $array['location']['rules'] as $rule ) 
  716. $rule['group_no'] = $group_no; 
  717.  
  718. // sperate groups? 
  719. if( $array['location']['allorany'] == 'any' ) 
  720. $group_no++; 
  721.  
  722.  
  723. // add to group 
  724. $groups[ $rule['group_no'] ][ $rule['order_no'] ] = $rule; 
  725.  
  726.  
  727. // sort rules 
  728. ksort( $groups[ $rule['group_no'] ] ); 
  729.  
  730.  
  731. // sort groups 
  732. ksort( $groups ); 
  733.  
  734. $array['location'] = $groups; 
  735.  
  736.  
  737. $GLOBALS['acf_register_field_group'][] = $array; 
  738.  
  739.  
  740. add_filter('acf/get_field_groups', 'api_acf_get_field_groups', 2, 1); 
  741. function api_acf_get_field_groups( $return ) 
  742. // validate 
  743. if( empty($GLOBALS['acf_register_field_group']) ) 
  744. return $return; 
  745.  
  746.  
  747. foreach( $GLOBALS['acf_register_field_group'] as $acf ) 
  748. $return[] = array( 
  749. 'id' => $acf['id'],  
  750. 'title' => $acf['title'],  
  751. 'menu_order' => $acf['menu_order'],  
  752. ); 
  753.  
  754.  
  755. // order field groups based on menu_order, title 
  756. // Obtain a list of columns 
  757. foreach( $return as $key => $row ) 
  758. $menu_order[ $key ] = $row['menu_order']; 
  759. $title[ $key ] = $row['title']; 
  760.  
  761. // Sort the array with menu_order ascending 
  762. // Add $array as the last parameter, to sort by the common key 
  763. if(isset($menu_order)) 
  764. array_multisort($menu_order, SORT_ASC, $title, SORT_ASC, $return); 
  765.  
  766. return $return; 
  767.  
  768.  
  769. add_filter('acf/field_group/get_fields', 'api_acf_field_group_get_fields', 1, 2); 
  770. function api_acf_field_group_get_fields( $fields, $post_id ) 
  771. // validate 
  772. if( !empty($GLOBALS['acf_register_field_group']) ) 
  773. foreach( $GLOBALS['acf_register_field_group'] as $acf ) 
  774. if( $acf['id'] == $post_id ) 
  775. foreach( $acf['fields'] as $f ) 
  776. $fields[] = apply_filters('acf/load_field', $f, $f['key']); 
  777.  
  778. break; 
  779.  
  780. return $fields; 
  781.  
  782.  
  783.  
  784. add_filter('acf/load_field', 'api_acf_load_field', 1, 2); 
  785. function api_acf_load_field( $field, $field_key ) 
  786. // validate 
  787. if( !empty($GLOBALS['acf_register_field_group']) ) 
  788. foreach( $GLOBALS['acf_register_field_group'] as $acf ) 
  789. if( !empty($acf['fields']) ) 
  790. foreach( $acf['fields'] as $f ) 
  791. if( $f['key'] == $field_key ) 
  792. $field = $f; 
  793. break; 
  794.  
  795. return $field; 
  796.  
  797.  
  798. add_filter('acf/field_group/get_location', 'api_acf_field_group_get_location', 1, 2); 
  799. function api_acf_field_group_get_location( $location, $post_id ) 
  800. // validate 
  801. if( !empty($GLOBALS['acf_register_field_group']) ) 
  802. foreach( $GLOBALS['acf_register_field_group'] as $acf ) 
  803. if( $acf['id'] == $post_id ) 
  804. $location = $acf['location']; 
  805. break; 
  806.  
  807. return $location; 
  808.  
  809.  
  810.  
  811. add_filter('acf/field_group/get_options', 'api_acf_field_group_get_options', 1, 2); 
  812. function api_acf_field_group_get_options( $options, $post_id ) 
  813. // validate 
  814. if( !empty($GLOBALS['acf_register_field_group']) ) 
  815. foreach( $GLOBALS['acf_register_field_group'] as $acf ) 
  816. if( $acf['id'] == $post_id ) 
  817. $options = $acf['options']; 
  818. break; 
  819.  
  820. return $options; 
  821.  
  822.  
  823. /** 
  824. * get_row_layout() 
  825. * 
  826. * This function will return a string representation of the current row layout within a 'has_sub_field' loop 
  827. * 
  828. * @type function 
  829. * @since 3.0.6 
  830. * @date 29/01/13 
  831. * 
  832. * @return $value - string containing the layout 
  833. */ 
  834.  
  835. function get_row_layout() 
  836. // vars 
  837. $value = get_sub_field('acf_fc_layout'); 
  838.  
  839.  
  840. return $value; 
  841.  
  842.  
  843. /** 
  844. * acf_shortcode() 
  845. * 
  846. * This function is used to add basic shortcode support for the ACF plugin 
  847. * 
  848. * @type function 
  849. * @since 1.1.1 
  850. * @date 29/01/13 
  851. * 
  852. * @param array $atts: an array holding the shortcode options 
  853. * string + field: the field name 
  854. * mixed + post_id: the post_id to load from 
  855. * 
  856. * @return string $value: the value found by get_field 
  857. */ 
  858.  
  859. function acf_shortcode( $atts ) 
  860. // extract attributs 
  861. extract( shortcode_atts( array( 
  862. 'field' => "",  
  863. 'post_id' => false,  
  864. ), $atts ) ); 
  865.  
  866.  
  867. // $field is requird 
  868. if( !$field || $field == "" ) 
  869. return ""; 
  870.  
  871.  
  872. // get value and return it 
  873. $value = get_field( $field, $post_id ); 
  874.  
  875.  
  876. if( is_array($value) ) 
  877. $value = @implode( ', ', $value ); 
  878.  
  879. return $value; 
  880. add_shortcode( 'acf', 'acf_shortcode' ); 
  881.  
  882.  
  883. /** 
  884. * acf_form_head() 
  885. * 
  886. * This function is placed at the very top of a template (before any HTML is rendered) and saves the $_POST data sent by acf_form. 
  887. * 
  888. * @type function 
  889. * @since 1.1.4 
  890. * @date 29/01/13 
  891. * 
  892. * @param N/A 
  893. * 
  894. * @return N/A 
  895. */ 
  896.  
  897. function acf_form_head() 
  898. // global vars 
  899. global $post_id; 
  900.  
  901.  
  902. // verify nonce 
  903. if( isset($_POST['acf_nonce']) && wp_verify_nonce($_POST['acf_nonce'], 'input') ) 
  904. // $post_id to save against 
  905. $post_id = $_POST['post_id']; 
  906.  
  907.  
  908. // allow for custom save 
  909. $post_id = apply_filters('acf/pre_save_post', $post_id); 
  910.  
  911.  
  912. // save the data 
  913. do_action('acf/save_post', $post_id);  
  914.  
  915.  
  916. // redirect 
  917. if(isset($_POST['return'])) 
  918. wp_redirect($_POST['return']); 
  919. exit; 
  920.  
  921.  
  922. // need wp styling 
  923. wp_enqueue_style(array( 
  924. 'colors-fresh' 
  925. )); 
  926.  
  927.  
  928. // actions 
  929. do_action('acf/input/admin_enqueue_scripts'); 
  930.  
  931. add_action('wp_head', 'acf_form_wp_head'); 
  932.  
  933.  
  934. function acf_form_wp_head() 
  935. do_action('acf/input/admin_head'); 
  936.  
  937.  
  938. /** 
  939. * acf_form() 
  940. * 
  941. * This function is used to create an ACF form. 
  942. * 
  943. * @type function 
  944. * @since 1.1.4 
  945. * @date 29/01/13 
  946. * 
  947. * @param array $options: an array containing many options to customize the form 
  948. * string + post_id: post id to get field groups from and save data to. Default is false 
  949. * array + field_groups: an array containing field group ID's. If this option is set,  
  950. * the post_id will not be used to dynamically find the field groups 
  951. * boolean + form: display the form tag or not. Defaults to true 
  952. * array + form_attributes: an array containg attributes which will be added into the form tag 
  953. * string + return: the return URL 
  954. * string + html_before_fields: html inside form before fields 
  955. * string + html_after_fields: html inside form after fields 
  956. * string + submit_value: value of submit button 
  957. * string + updated_message: default updated message. Can be false  
  958. * 
  959. * @return N/A 
  960. */ 
  961.  
  962. function acf_form( $options = array() ) 
  963. global $post; 
  964.  
  965.  
  966. // defaults 
  967. $defaults = array( 
  968. 'post_id' => false,  
  969. 'field_groups' => array(),  
  970. 'form' => true,  
  971. 'form_attributes' => array( 
  972. 'id' => 'post',  
  973. 'class' => '',  
  974. 'action' => '',  
  975. 'method' => 'post',  
  976. ),  
  977. 'return' => add_query_arg( 'updated', 'true', get_permalink() ),  
  978. 'html_before_fields' => '',  
  979. 'html_after_fields' => '',  
  980. 'submit_value' => __("Update", 'acf'),  
  981. 'updated_message' => __("Post updated", 'acf'),  
  982. ); 
  983.  
  984.  
  985. // merge defaults with options 
  986. $options = array_merge($defaults, $options); 
  987.  
  988.  
  989. // merge sub arrays 
  990. foreach( $options as $k => $v ) 
  991. if( is_array($v) ) 
  992. $options[ $k ] = array_merge($defaults[ $k ], $options[ $k ]); 
  993.  
  994.  
  995. // filter post_id 
  996. $options['post_id'] = apply_filters('acf/get_post_id', $options['post_id'] ); 
  997.  
  998.  
  999. // attributes 
  1000. $options['form_attributes']['class'] .= 'acf-form'; 
  1001.  
  1002.  
  1003.  
  1004. // register post box 
  1005. if( empty($options['field_groups']) ) 
  1006. // get field groups 
  1007. $filter = array( 
  1008. 'post_id' => $options['post_id'] 
  1009. ); 
  1010.  
  1011.  
  1012. if( strpos($options['post_id'], 'user_') !== false ) 
  1013. $user_id = str_replace('user_', '', $options['post_id']); 
  1014. $filter = array( 
  1015. 'ef_user' => $user_id 
  1016. ); 
  1017. elseif( strpos($options['post_id'], 'taxonomy_') !== false ) 
  1018. $taxonomy_id = str_replace('taxonomy_', '', $options['post_id']); 
  1019. $filter = array( 
  1020. 'ef_taxonomy' => $taxonomy_id 
  1021. ); 
  1022.  
  1023.  
  1024. $options['field_groups'] = array(); 
  1025. $options['field_groups'] = apply_filters( 'acf/location/match_field_groups', $options['field_groups'], $filter ); 
  1026.  
  1027.  
  1028. // updated message 
  1029. if(isset($_GET['updated']) && $_GET['updated'] == 'true' && $options['updated_message']) 
  1030. echo '<div id="message" class="updated"><p>' . $options['updated_message'] . '</p></div>'; 
  1031.  
  1032.  
  1033. // display form 
  1034. if( $options['form'] ): ?> 
  1035. <form <?php if($options['form_attributes']) {foreach($options['form_attributes'] as $k => $v) {echo $k . '="' . $v .'" '; }} ?>> 
  1036. <?php endif; ?> 
  1037.  
  1038. <div style="display:none"> 
  1039. <script type="text/javascript"> 
  1040. acf.o.post_id = <?php echo is_numeric($options['post_id']) ? $options['post_id'] : '"' . $options['post_id'] . '"'; ?>; 
  1041. </script> 
  1042. <input type="hidden" name="acf_nonce" value="<?php echo wp_create_nonce( 'input' ); ?>" /> 
  1043. <input type="hidden" name="post_id" value="<?php echo $options['post_id']; ?>" /> 
  1044. <input type="hidden" name="return" value="<?php echo $options['return']; ?>" /> 
  1045. <?php wp_editor('', 'acf_settings'); ?> 
  1046. </div> 
  1047.  
  1048. <div id="poststuff"> 
  1049. <?php 
  1050.  
  1051. // html before fields 
  1052. echo $options['html_before_fields']; 
  1053.  
  1054.  
  1055. $acfs = apply_filters('acf/get_field_groups', array()); 
  1056.  
  1057. if( is_array($acfs) ) { foreach( $acfs as $acf ) { 
  1058.  
  1059. // only add the chosen field groups 
  1060. if( !in_array( $acf['id'], $options['field_groups'] ) ) 
  1061. continue; 
  1062.  
  1063.  
  1064. // load options 
  1065. $acf['options'] = apply_filters('acf/field_group/get_options', array(), $acf['id']); 
  1066.  
  1067.  
  1068. // load fields 
  1069. $fields = apply_filters('acf/field_group/get_fields', array(), $acf['id']); 
  1070.  
  1071.  
  1072. echo '<div id="acf_' . $acf['id'] . '" class="postbox acf_postbox ' . $acf['options']['layout'] . '">'; 
  1073. echo '<h3 class="hndle"><span>' . $acf['title'] . '</span></h3>'; 
  1074. echo '<div class="inside">'; 
  1075.  
  1076. do_action('acf/create_fields', $fields, $options['post_id']); 
  1077.  
  1078. echo '</div></div>'; 
  1079.  
  1080. }} 
  1081.  
  1082.  
  1083. // html after fields 
  1084. echo $options['html_after_fields']; 
  1085.  
  1086. ?> 
  1087.  
  1088. <?php if( $options['form'] ): ?> 
  1089. <!-- Submit --> 
  1090. <div class="field"> 
  1091. <input type="submit" value="<?php echo $options['submit_value']; ?>" /> 
  1092. </div> 
  1093. <!-- / Submit --> 
  1094. <?php endif; ?> 
  1095.  
  1096. </div><!-- <div id="poststuff"> --> 
  1097.  
  1098. <?php if( $options['form'] ): ?> 
  1099. </form> 
  1100. <?php endif; 
  1101.  
  1102.  
  1103. /** 
  1104. * update_field() 
  1105. * 
  1106. * This function will update a value in the database 
  1107. * 
  1108. * @type function 
  1109. * @since 3.1.9 
  1110. * @date 29/01/13 
  1111. * 
  1112. * @param mixed $field_name: the name of the field - 'sub_heading' 
  1113. * @param mixed $value: the value to save in the database. The variable type is dependant on the field type 
  1114. * @param mixed $post_id: the post_id of which the value is saved against 
  1115. * 
  1116. * @return N/A 
  1117. */ 
  1118.  
  1119. function update_field( $field_key, $value, $post_id = false ) 
  1120. // filter post_id 
  1121. $post_id = apply_filters('acf/get_post_id', $post_id ); 
  1122.  
  1123.  
  1124. // vars 
  1125. $options = array( 
  1126. 'load_value' => false,  
  1127. 'format_value' => false 
  1128. ); 
  1129.  
  1130. $field = get_field_object( $field_key, $post_id, $options); 
  1131.  
  1132.  
  1133. // sub fields? They need formatted data 
  1134. if( $field['type'] == 'repeater' ) 
  1135. $value = acf_convert_field_names_to_keys( $value, $field ); 
  1136. elseif( $field['type'] == 'flexible_content' ) 
  1137. if( $field['layouts'] ) 
  1138. foreach( $field['layouts'] as $layout ) 
  1139. $value = acf_convert_field_names_to_keys( $value, $layout ); 
  1140.  
  1141.  
  1142. // save 
  1143. do_action('acf/update_value', $value, $post_id, $field ); 
  1144.  
  1145.  
  1146. return true; 
  1147.  
  1148.  
  1149.  
  1150. /** 
  1151. * delete_field() 
  1152. * 
  1153. * This function will remove a value from the database 
  1154. * 
  1155. * @type function 
  1156. * @since 3.1.9 
  1157. * @date 29/01/13 
  1158. * 
  1159. * @param mixed $field_name: the name of the field - 'sub_heading' 
  1160. * @param mixed $post_id: the post_id of which the value is saved against 
  1161. * 
  1162. * @return N/A 
  1163. */ 
  1164.  
  1165. function delete_field( $field_name, $post_id ) 
  1166. do_action('acf/delete_value', $post_id, $field_name ); 
  1167.  
  1168.  
  1169. /** 
  1170. * create_field() 
  1171. * 
  1172. * This function will creat the HTML for a field 
  1173. * 
  1174. * @type function 
  1175. * @since 4.0.0 
  1176. * @date 17/03/13 
  1177. * 
  1178. * @param array $field - an array containing all the field attributes 
  1179. * 
  1180. * @return N/A 
  1181. */ 
  1182.  
  1183. function create_field( $field ) 
  1184. do_action('acf/create_field', $field ); 
  1185.  
  1186.  
  1187. /** 
  1188. * acf_convert_field_names_to_keys() 
  1189. * 
  1190. * Helper for the update_field function 
  1191. * 
  1192. * @type function 
  1193. * @since 4.0.0 
  1194. * @date 17/03/13 
  1195. * 
  1196. * @param array $value: the value returned via get_field 
  1197. * @param array $field: the field or layout to find sub fields from 
  1198. * 
  1199. * @return N/A 
  1200. */ 
  1201.  
  1202. function acf_convert_field_names_to_keys( $value, $field ) 
  1203. // only if $field has sub fields 
  1204. if( !isset($field['sub_fields']) ) 
  1205. return $value; 
  1206.  
  1207.  
  1208. // define sub field keys 
  1209. $sub_fields = array(); 
  1210. if( $field['sub_fields'] ) 
  1211. foreach( $field['sub_fields'] as $sub_field ) 
  1212. $sub_fields[ $sub_field['name'] ] = $sub_field; 
  1213.  
  1214.  
  1215. // loop through the values and format the array to use sub field keys 
  1216. if( is_array($value) ) 
  1217. foreach( $value as $row_i => $row) 
  1218. if( $row ) 
  1219. foreach( $row as $sub_field_name => $sub_field_value ) 
  1220. // sub field must exist! 
  1221. if( !isset($sub_fields[ $sub_field_name ]) ) 
  1222. continue; 
  1223.  
  1224.  
  1225. // vars 
  1226. $sub_field = $sub_fields[ $sub_field_name ]; 
  1227. $sub_field_value = acf_convert_field_names_to_keys( $sub_field_value, $sub_field ); 
  1228.  
  1229.  
  1230. // set new value 
  1231. $value[$row_i][ $sub_field['key'] ] = $sub_field_value; 
  1232.  
  1233.  
  1234. // unset old value 
  1235. unset( $value[$row_i][$sub_field_name] ); 
  1236.  
  1237.  
  1238. // foreach( $row as $sub_field_name => $sub_field_value ) 
  1239. // if( $row ) 
  1240. // foreach( $value as $row_i => $row) 
  1241. // if( $value ) 
  1242.  
  1243.  
  1244. return $value; 
  1245.  
  1246.  
  1247.  
  1248. /** 
  1249. * acf_force_type_array 
  1250. * 
  1251. * This function will force a variable to become an array 
  1252. * 
  1253. * @type function 
  1254. * @date 4/02/2014 
  1255. * @since 5.0.0 
  1256. * 
  1257. * @param $var (mixed) 
  1258. * @return (array) 
  1259. */ 
  1260.  
  1261. function acf_force_type_array( $var ) { 
  1262.  
  1263. // is array? 
  1264. if( is_array($var) ) { 
  1265.  
  1266. return $var; 
  1267.  
  1268.  
  1269.  
  1270. // bail early if empty 
  1271. if( empty($var) && !is_numeric($var) ) { 
  1272.  
  1273. return array(); 
  1274.  
  1275.  
  1276.  
  1277. // string  
  1278. if( is_string($var) ) { 
  1279.  
  1280. return explode(', ', $var); 
  1281.  
  1282.  
  1283.  
  1284. // place in array 
  1285. return array( $var ); 
  1286. }  
  1287.  
  1288.  
  1289. /** 
  1290. * acf_get_valid_terms 
  1291. * 
  1292. * This function will replace old terms with new split term ids 
  1293. * 
  1294. * @type function 
  1295. * @date 27/02/2015 
  1296. * @since 5.1.5 
  1297. * 
  1298. * @param $terms (int|array) 
  1299. * @param $taxonomy (string) 
  1300. * @return $terms 
  1301. */ 
  1302.  
  1303. function acf_get_valid_terms( $terms = false, $taxonomy = 'category' ) { 
  1304.  
  1305. // bail early if function does not yet exist or 
  1306. if( !function_exists('wp_get_split_term') || empty($terms) ) { 
  1307.  
  1308. return $terms; 
  1309.  
  1310.  
  1311.  
  1312. // vars 
  1313. $is_array = is_array($terms); 
  1314.  
  1315.  
  1316. // force into array 
  1317. $terms = acf_force_type_array( $terms ); 
  1318.  
  1319.  
  1320. // force ints 
  1321. $terms = array_map('intval', $terms); 
  1322.  
  1323.  
  1324. // attempt to find new terms 
  1325. foreach( $terms as $i => $term_id ) { 
  1326.  
  1327. $new_term_id = wp_get_split_term($term_id, $taxonomy); 
  1328.  
  1329. if( $new_term_id ) { 
  1330.  
  1331. $terms[ $i ] = $new_term_id; 
  1332.  
  1333.  
  1334.  
  1335.  
  1336. // revert array if needed 
  1337. if( !$is_array ) { 
  1338.  
  1339. $terms = $terms[0]; 
  1340.  
  1341.  
  1342.  
  1343. // return 
  1344. return $terms; 
  1345.  
  1346.  
  1347.  
  1348. /** 
  1349. * Depreceated Functions 
  1350. * 
  1351. * @description:  
  1352. * @created: 23/07/12 
  1353. */ 
  1354.  
  1355.  
  1356. /**-------------------------------------------------------------------------------------- 
  1357. * 
  1358. * reset_the_repeater_field 
  1359. * 
  1360. * @author Elliot Condon 
  1361. * @depreciated: 3.3.4 - now use has_sub_field 
  1362. * @since 1.0.3 
  1363. *  
  1364. *-------------------------------------------------------------------------------------*/ 
  1365.  
  1366. function reset_the_repeater_field() 
  1367. // do nothing 
  1368.  
  1369.  
  1370. /**-------------------------------------------------------------------------------------- 
  1371. * 
  1372. * the_repeater_field 
  1373. * 
  1374. * @author Elliot Condon 
  1375. * @depreciated: 3.3.4 - now use has_sub_field 
  1376. * @since 1.0.3 
  1377. *  
  1378. *-------------------------------------------------------------------------------------*/ 
  1379.  
  1380. function the_repeater_field($field_name, $post_id = false) 
  1381. return has_sub_field($field_name, $post_id); 
  1382.  
  1383.  
  1384. /**-------------------------------------------------------------------------------------- 
  1385. * 
  1386. * the_flexible_field 
  1387. * 
  1388. * @author Elliot Condon 
  1389. * @depreciated: 3.3.4 - now use has_sub_field 
  1390. * @since 3.?.? 
  1391. *  
  1392. *-------------------------------------------------------------------------------------*/ 
  1393.  
  1394. function the_flexible_field($field_name, $post_id = false) 
  1395. return has_sub_field($field_name, $post_id); 
  1396.  
  1397. /** 
  1398. * acf_filter_post_id() 
  1399. * 
  1400. * This is a deprecated function which is now run through a filter 
  1401. * 
  1402. * @type function 
  1403. * @since 3.6 
  1404. * @date 29/01/13 
  1405. * 
  1406. * @param mixed $post_id 
  1407. * 
  1408. * @return mixed $post_id 
  1409. */ 
  1410.  
  1411. function acf_filter_post_id( $post_id ) 
  1412. return apply_filters('acf/get_post_id', $post_id ); 
  1413.  
  1414. ?> 
.