/core/fields/_functions.php

  1. <?php 
  2.  
  3. /** 
  4. * Field Functions 
  5. * 
  6. * @description: The API for all fields 
  7. * @since: 3.6 
  8. * @created: 23/01/13 
  9. */ 
  10.  
  11. class acf_field_functions 
  12.  
  13. /** 
  14. * __construct 
  15. * 
  16. * @description:  
  17. * @since 3.1.8 
  18. * @created: 23/06/12 
  19. */ 
  20.  
  21. function __construct() 
  22. //value 
  23. add_filter('acf/load_value', array($this, 'load_value'), 5, 3); 
  24. add_action('acf/update_value', array($this, 'update_value'), 5, 3); 
  25. add_action('acf/delete_value', array($this, 'delete_value'), 5, 2); 
  26. add_action('acf/format_value', array($this, 'format_value'), 5, 3); 
  27. add_action('acf/format_value_for_api', array($this, 'format_value_for_api'), 5, 3); 
  28.  
  29.  
  30. // field 
  31. add_filter('acf/load_field', array($this, 'load_field'), 5, 3); 
  32. add_action('acf/update_field', array($this, 'update_field'), 5, 2); 
  33. add_action('acf/delete_field', array($this, 'delete_field'), 5, 2); 
  34. add_action('acf/create_field', array($this, 'create_field'), 5, 1); 
  35. add_action('acf/create_field_options', array($this, 'create_field_options'), 5, 1); 
  36.  
  37.  
  38. // extra 
  39. add_filter('acf/load_field_defaults', array($this, 'load_field_defaults'), 5, 1); 
  40.  
  41.  
  42. /** 
  43. * load_value 
  44. * 
  45. * @description: loads basic value from the db 
  46. * @since: 3.6 
  47. * @created: 23/01/13 
  48. */ 
  49.  
  50. function load_value($value, $post_id, $field) 
  51. $found = false; 
  52. $cache = wp_cache_get( 'load_value/post_id=' . $post_id . '/name=' . $field['name'], 'acf', false, $found ); 
  53.  
  54. if( $found ) 
  55. return $cache; 
  56.  
  57.  
  58. // set default value 
  59. $value = false; 
  60.  
  61.  
  62. // if $post_id is a string, then it is used in the everything fields and can be found in the options table 
  63. if( is_numeric($post_id) ) 
  64. $v = get_post_meta( $post_id, $field['name'], false ); 
  65.  
  66. // value is an array 
  67. if( isset($v[0]) ) 
  68. $value = $v[0]; 
  69.  
  70. elseif( strpos($post_id, 'user_') !== false ) 
  71. $post_id = str_replace('user_', '', $post_id); 
  72.  
  73. $v = get_user_meta( $post_id, $field['name'], false ); 
  74.  
  75. // value is an array 
  76. if( isset($v[0]) ) 
  77. $value = $v[0]; 
  78.  
  79. else 
  80. $v = get_option( $post_id . '_' . $field['name'], false ); 
  81.  
  82. if( !is_null($value) ) 
  83. $value = $v; 
  84.  
  85.  
  86. // no value? 
  87. if( $value === false ) 
  88. if( isset($field['default_value']) && $field['default_value'] !== "" ) 
  89. $value = $field['default_value']; 
  90.  
  91.  
  92. // if value was duplicated, it may now be a serialized string! 
  93. $value = maybe_unserialize($value); 
  94.  
  95.  
  96. // apply filters 
  97. foreach( array('type', 'name', 'key') as $key ) 
  98. // run filters 
  99. $value = apply_filters('acf/load_value/' . $key . '=' . $field[ $key ], $value, $post_id, $field); // new filter 
  100.  
  101.  
  102. //update cache 
  103. wp_cache_set( 'load_value/post_id=' . $post_id . '/name=' . $field['name'], $value, 'acf' ); 
  104.  
  105.  
  106. return $value; 
  107.  
  108.  
  109. /** 
  110. * format_value 
  111. * 
  112. * @description: uses the basic value and allows the field type to format it 
  113. * @since: 3.6 
  114. * @created: 26/01/13 
  115. */ 
  116.  
  117. function format_value( $value, $post_id, $field ) 
  118. $value = apply_filters('acf/format_value/type=' . $field['type'], $value, $post_id, $field); 
  119.  
  120. return $value; 
  121.  
  122.  
  123. /** 
  124. * format_value_for_api 
  125. * 
  126. * @description: uses the basic value and allows the field type to format it or the api functions 
  127. * @since: 3.6 
  128. * @created: 26/01/13 
  129. */ 
  130.  
  131. function format_value_for_api( $value, $post_id, $field ) 
  132. $value = apply_filters('acf/format_value_for_api/type=' . $field['type'], $value, $post_id, $field); 
  133.  
  134. return $value; 
  135.  
  136.  
  137. /** 
  138. * update_value 
  139. * 
  140. * updates a value into the db 
  141. * 
  142. * @type action 
  143. * @date 23/01/13 
  144. * 
  145. * @param {mixed} $value the value to be saved 
  146. * @param {int} $post_id the post ID to save the value to 
  147. * @param {array} $field the field array 
  148. * @param {boolean} $exact allows the update_value filter to be skipped 
  149. * @return N/A 
  150. */ 
  151.  
  152. function update_value( $value, $post_id, $field ) 
  153.  
  154. // strip slashes 
  155. // - not needed? http://support.advancedcustomfields.com/discussion/3168/backslashes-stripped-in-wysiwyg-filed 
  156. //if( get_magic_quotes_gpc() ) 
  157. //{ 
  158. $value = stripslashes_deep($value); 
  159. //} 
  160.  
  161.  
  162. // apply filters  
  163. foreach( array('key', 'name', 'type') as $key ) 
  164. // run filters 
  165. $value = apply_filters('acf/update_value/' . $key . '=' . $field[ $key ], $value, $post_id, $field); // new filter 
  166.  
  167.  
  168. // if $post_id is a string, then it is used in the everything fields and can be found in the options table 
  169. if( is_numeric($post_id) ) 
  170. // allow ACF to save to revision! 
  171. update_metadata('post', $post_id, $field['name'], $value ); 
  172. update_metadata('post', $post_id, '_' . $field['name'], $field['key']); 
  173. elseif( strpos($post_id, 'user_') !== false ) 
  174. $user_id = str_replace('user_', '', $post_id); 
  175. update_metadata('user', $user_id, $field['name'], $value); 
  176. update_metadata('user', $user_id, '_' . $field['name'], $field['key']); 
  177. else 
  178. // for some reason, update_option does not use stripslashes_deep. 
  179. // update_metadata -> http://core.trac.wordpress.org/browser/tags/3.4.2/wp-includes/meta.php#L82: line 101 (does use stripslashes_deep) 
  180. // update_option -> http://core.trac.wordpress.org/browser/tags/3.5.1/wp-includes/option.php#L0: line 215 (does not use stripslashes_deep) 
  181. $value = stripslashes_deep($value); 
  182.  
  183. $this->update_option( $post_id . '_' . $field['name'], $value ); 
  184. $this->update_option( '_' . $post_id . '_' . $field['name'], $field['key'] ); 
  185.  
  186.  
  187. // update the cache 
  188. wp_cache_set( 'load_value/post_id=' . $post_id . '/name=' . $field['name'], $value, 'acf' ); 
  189.  
  190.  
  191.  
  192. /** 
  193. * update_option 
  194. * 
  195. * This function is a wrapper for the WP update_option but provides logic for a 'no' autoload 
  196. * 
  197. * @type function 
  198. * @date 4/01/2014 
  199. * @since 5.0.0 
  200. * 
  201. * @param $option (string) 
  202. * @param $value (mixed) 
  203. * @return (boolean) 
  204. */ 
  205.  
  206. function update_option( $option = '', $value = false, $autoload = 'no' ) { 
  207.  
  208. // vars 
  209. $deprecated = ''; 
  210. $return = false; 
  211.  
  212.  
  213. if( get_option($option) !== false ) 
  214. $return = update_option( $option, $value ); 
  215. else 
  216. $return = add_option( $option, $value, $deprecated, $autoload ); 
  217.  
  218.  
  219. // return 
  220. return $return; 
  221.  
  222.  
  223.  
  224. /** 
  225. * delete_value 
  226. * 
  227. * @description: deletes a value from the database 
  228. * @since: 3.6 
  229. * @created: 23/01/13 
  230. */ 
  231.  
  232. function delete_value( $post_id, $key ) 
  233. // if $post_id is a string, then it is used in the everything fields and can be found in the options table 
  234. if( is_numeric($post_id) ) 
  235. delete_post_meta( $post_id, $key ); 
  236. delete_post_meta( $post_id, '_' . $key ); 
  237. elseif( strpos($post_id, 'user_') !== false ) 
  238. $post_id = str_replace('user_', '', $post_id); 
  239. delete_user_meta( $post_id, $key ); 
  240. delete_user_meta( $post_id, '_' . $key ); 
  241. else 
  242. delete_option( $post_id . '_' . $key ); 
  243. delete_option( '_' . $post_id . '_' . $key ); 
  244.  
  245. wp_cache_delete( 'load_value/post_id=' . $post_id . '/name=' . $key, 'acf' ); 
  246.  
  247.  
  248. /** 
  249. * load_field 
  250. * 
  251. * @description: loads a field from the database 
  252. * @since 3.5.1 
  253. * @created: 14/10/12 
  254. */ 
  255.  
  256. function load_field( $field, $field_key, $post_id = false ) 
  257. // load cache 
  258. if( !$field ) 
  259. $field = wp_cache_get( 'load_field/key=' . $field_key, 'acf' ); 
  260.  
  261.  
  262. // load from DB 
  263. if( !$field ) 
  264. // vars 
  265. global $wpdb; 
  266.  
  267.  
  268. // get field from postmeta 
  269. $sql = $wpdb->prepare("SELECT post_id, meta_value FROM $wpdb->postmeta WHERE meta_key = %s", $field_key); 
  270.  
  271. if( $post_id ) 
  272. $sql .= $wpdb->prepare("AND post_id = %d", $post_id); 
  273.  
  274. $rows = $wpdb->get_results( $sql, ARRAY_A ); 
  275.  
  276.  
  277.  
  278. // nothing found? 
  279. if( !empty($rows) ) 
  280. $row = $rows[0]; 
  281.  
  282.  
  283. /** 
  284. * WPML compatibility 
  285. * 
  286. * If WPML is active, and the $post_id (Field group ID) was not defined,  
  287. * it is assumed that the load_field functio has been called from the API (front end). 
  288. * In this case, the field group ID is never known and we can check for the correct translated field group 
  289. */ 
  290.  
  291. if( defined('ICL_LANGUAGE_CODE') && !$post_id ) 
  292. $wpml_post_id = icl_object_id($row['post_id'], 'acf', true, ICL_LANGUAGE_CODE); 
  293.  
  294. foreach( $rows as $r ) 
  295. if( $r['post_id'] == $wpml_post_id ) 
  296. // this row is a field from the translated field group 
  297. $row = $r; 
  298.  
  299.  
  300. // return field if it is not in a trashed field group 
  301. if( get_post_status( $row['post_id'] ) != "trash" ) 
  302. $field = $row['meta_value']; 
  303. $field = maybe_unserialize( $field ); 
  304. $field = maybe_unserialize( $field ); // run again for WPML 
  305.  
  306.  
  307. // add field_group ID 
  308. $field['field_group'] = $row['post_id']; 
  309.  
  310.  
  311.  
  312. // apply filters 
  313. $field = apply_filters('acf/load_field_defaults', $field); 
  314.  
  315.  
  316. // apply filters 
  317. foreach( array('type', 'name', 'key') as $key ) 
  318. // run filters 
  319. $field = apply_filters('acf/load_field/' . $key . '=' . $field[ $key ], $field); // new filter 
  320.  
  321.  
  322. // set cache 
  323. wp_cache_set( 'load_field/key=' . $field_key, $field, 'acf' ); 
  324.  
  325. return $field; 
  326.  
  327.  
  328. /** 
  329. * load_field_defaults 
  330. * 
  331. * @description: applies default values to the field after it has been loaded 
  332. * @since 3.5.1 
  333. * @created: 14/10/12 
  334. */ 
  335.  
  336. function load_field_defaults( $field ) 
  337. // validate $field 
  338. if( !is_array($field) ) 
  339. $field = array(); 
  340.  
  341.  
  342. // defaults 
  343. $defaults = array( 
  344. 'key' => '',  
  345. 'label' => '',  
  346. 'name' => '',  
  347. '_name' => '',  
  348. 'type' => 'text',  
  349. 'order_no' => 1,  
  350. 'instructions' => '',  
  351. 'required' => 0,  
  352. 'id' => '',  
  353. 'class' => '',  
  354. 'conditional_logic' => array( 
  355. 'status' => 0,  
  356. 'allorany' => 'all',  
  357. 'rules' => 0 
  358. ),  
  359. ); 
  360. $field = array_merge($defaults, $field); 
  361.  
  362.  
  363. // Parse Values 
  364. $field = apply_filters( 'acf/parse_types', $field ); 
  365.  
  366.  
  367. // field specific defaults 
  368. $field = apply_filters('acf/load_field_defaults/type=' . $field['type'] , $field); 
  369.  
  370.  
  371. // class 
  372. if( !$field['class'] ) 
  373. $field['class'] = $field['type']; 
  374.  
  375.  
  376. // id 
  377. if( !$field['id'] ) 
  378. $id = $field['name']; 
  379. $id = str_replace('][', '_', $id); 
  380. $id = str_replace('fields[', '', $id); 
  381. $id = str_replace('[', '-', $id); // location rules (select) does'nt have "fields[" in it 
  382. $id = str_replace(']', '', $id); 
  383.  
  384. $field['id'] = 'acf-field-' . $id; 
  385.  
  386.  
  387. // _name 
  388. if( !$field['_name'] ) 
  389. $field['_name'] = $field['name']; 
  390.  
  391.  
  392. // clean up conditional logic keys 
  393. if( !empty($field['conditional_logic']['rules']) ) 
  394. $field['conditional_logic']['rules'] = array_values($field['conditional_logic']['rules']); 
  395.  
  396.  
  397. // return 
  398. return $field; 
  399.  
  400.  
  401. /** 
  402. * update_field 
  403. * 
  404. * @description: updates a field in the database 
  405. * @since: 3.6 
  406. * @created: 24/01/13 
  407. */ 
  408.  
  409. function update_field( $field, $post_id ) 
  410. // sanitize field name 
  411. // - http://support.advancedcustomfields.com/discussion/5262/sanitize_title-on-field-name 
  412. // - issue with camel case! Replaced with JS 
  413. //$field['name'] = sanitize_title( $field['name'] ); 
  414.  
  415.  
  416. // filters 
  417. $field = apply_filters('acf/update_field/type=' . $field['type'], $field, $post_id ); // new filter 
  418.  
  419.  
  420. // clear cache 
  421. wp_cache_delete( 'load_field/key=' . $field['key'], 'acf' ); 
  422.  
  423.  
  424. // save 
  425. update_post_meta( $post_id, $field['key'], $field ); 
  426.  
  427.  
  428. /** 
  429. * delete_field 
  430. * 
  431. * @description: deletes a field in the database 
  432. * @since: 3.6 
  433. * @created: 24/01/13 
  434. */ 
  435.  
  436. function delete_field( $post_id, $field_key ) 
  437. // clear cache 
  438. wp_cache_delete( 'load_field/key=' . $field_key, 'acf' ); 
  439.  
  440.  
  441. // delete 
  442. delete_post_meta($post_id, $field_key); 
  443.  
  444.  
  445. /** 
  446. * create_field 
  447. * 
  448. * @description: renders a field into a HTML interface 
  449. * @since: 3.6 
  450. * @created: 23/01/13 
  451. */ 
  452.  
  453. function create_field( $field ) 
  454. // load defaults 
  455. // if field was loaded from db, these default will already be appield 
  456. // if field was written by hand, it may be missing keys 
  457. $field = apply_filters('acf/load_field_defaults', $field); 
  458.  
  459.  
  460. // create field specific html 
  461. do_action('acf/create_field/type=' . $field['type'], $field); 
  462.  
  463.  
  464. // conditional logic 
  465. if( $field['conditional_logic']['status'] ) 
  466. $field['conditional_logic']['field'] = $field['key']; 
  467.  
  468. ?> 
  469. <script type="text/javascript"> 
  470. (function($) { 
  471.  
  472. if( typeof acf !== 'undefined' ) 
  473. acf.conditional_logic.items.push(<?php echo json_encode($field['conditional_logic']); ?>); 
  474.  
  475. })(jQuery);  
  476. </script> 
  477. <?php 
  478.  
  479.  
  480.  
  481. /** 
  482. * create_field_options 
  483. * 
  484. * @description: renders a field into a HTML interface 
  485. * @since: 3.6 
  486. * @created: 23/01/13 
  487. */ 
  488.  
  489. function create_field_options($field) 
  490. // load standard + field specific defaults 
  491. $field = apply_filters('acf/load_field_defaults', $field); 
  492.  
  493. // render HTML 
  494. do_action('acf/create_field_options/type=' . $field['type'], $field); 
  495.  
  496.  
  497.  
  498.  
  499. new acf_field_functions(); 
  500.  
  501. ?> 
.