acf-value-functions.php 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. <?php
  2. // Register store.
  3. acf_register_store( 'values' )->prop( 'multisite', true );
  4. /**
  5. * acf_get_reference
  6. *
  7. * Retrieves the field key for a given field name and post_id.
  8. *
  9. * @date 26/1/18
  10. * @since 5.6.5
  11. *
  12. * @param string $field_name The name of the field. eg 'sub_heading'.
  13. * @param mixed $post_id The post_id of which the value is saved against.
  14. * @return string The field key.
  15. */
  16. function acf_get_reference( $field_name, $post_id ) {
  17. // Allow filter to short-circuit load_value logic.
  18. $reference = apply_filters( 'acf/pre_load_reference', null, $field_name, $post_id );
  19. if ( $reference !== null ) {
  20. return $reference;
  21. }
  22. // Get hidden meta for this field name.
  23. $reference = acf_get_metadata( $post_id, $field_name, true );
  24. /**
  25. * Filters the reference value.
  26. *
  27. * @date 25/1/19
  28. * @since 5.7.11
  29. *
  30. * @param string $reference The reference value.
  31. * @param string $field_name The field name.
  32. * @param (int|string) $post_id The post ID where meta is stored.
  33. */
  34. return apply_filters( 'acf/load_reference', $reference, $field_name, $post_id );
  35. }
  36. /**
  37. * Retrieves the value for a given field and post_id.
  38. *
  39. * @date 28/09/13
  40. * @since 5.0.0
  41. *
  42. * @param int|string $post_id The post id.
  43. * @param array $field The field array.
  44. * @return mixed
  45. */
  46. function acf_get_value( $post_id, $field ) {
  47. // Allow filter to short-circuit load_value logic.
  48. $value = apply_filters( 'acf/pre_load_value', null, $post_id, $field );
  49. if ( $value !== null ) {
  50. return $value;
  51. }
  52. // Get field name.
  53. $field_name = $field['name'];
  54. // Get field ID & type.
  55. $decoded = acf_decode_post_id( $post_id );
  56. $allow_load = true;
  57. // If we don't have a proper field array, the field doesn't exist currently.
  58. if ( empty( $field['type'] ) && empty( $field['key'] ) ) {
  59. // Check if we should trigger warning about accessing fields too early via action.
  60. do_action( 'acf/get_invalid_field_value', $field, __FUNCTION__ );
  61. if ( apply_filters( 'acf/prevent_access_to_unknown_fields', false ) || ( 'option' === $decoded['type'] && 'options' !== $decoded['id'] ) ) {
  62. $allow_load = false;
  63. }
  64. }
  65. // If we're using a non options_ option key, ensure we have a valid reference key.
  66. if ( 'option' === $decoded['type'] && 'options' !== $decoded['id'] ) {
  67. $meta = acf_get_metadata( $post_id, $field_name, true );
  68. if ( ! $meta ) {
  69. $allow_load = false;
  70. } elseif ( $meta !== $field['key'] ) {
  71. if ( ! isset( $field['__key'] ) || $meta !== $field['__key'] ) {
  72. $allow_load = false;
  73. }
  74. }
  75. }
  76. // Load Store.
  77. $store = acf_get_store( 'values' );
  78. // If we're allowing load, check the store or load value from database.
  79. if ( $allow_load ) {
  80. if ( $store->has( "$post_id:$field_name" ) ) {
  81. return $store->get( "$post_id:$field_name" );
  82. }
  83. $value = acf_get_metadata( $post_id, $field_name );
  84. }
  85. // Use field's default_value if no meta was found.
  86. if ( $value === null && isset( $field['default_value'] ) ) {
  87. $value = $field['default_value'];
  88. }
  89. /**
  90. * Filters the $value after it has been loaded.
  91. *
  92. * @date 28/09/13
  93. * @since 5.0.0
  94. *
  95. * @param mixed $value The value to preview.
  96. * @param string $post_id The post ID for this value.
  97. * @param array $field The field array.
  98. */
  99. $value = apply_filters( 'acf/load_value', $value, $post_id, $field );
  100. // Update store if we allowed the value load.
  101. if ( $allow_load ) {
  102. $store->set( "$post_id:$field_name", $value );
  103. }
  104. // Return value.
  105. return $value;
  106. }
  107. // Register variation.
  108. acf_add_filter_variations( 'acf/load_value', array( 'type', 'name', 'key' ), 2 );
  109. /**
  110. * acf_format_value
  111. *
  112. * Returns a formatted version of the provided value.
  113. *
  114. * @date 28/09/13
  115. * @since 5.0.0
  116. *
  117. * @param mixed $value The field value.
  118. * @param (int|string) $post_id The post id.
  119. * @param array $field The field array.
  120. * @return mixed.
  121. */
  122. function acf_format_value( $value, $post_id, $field ) {
  123. // Allow filter to short-circuit load_value logic.
  124. $check = apply_filters( 'acf/pre_format_value', null, $value, $post_id, $field );
  125. if ( $check !== null ) {
  126. return $check;
  127. }
  128. // Get field name.
  129. $field_name = $field['name'];
  130. // Check store.
  131. $store = acf_get_store( 'values' );
  132. if ( $store->has( "$post_id:$field_name:formatted" ) ) {
  133. return $store->get( "$post_id:$field_name:formatted" );
  134. }
  135. /**
  136. * Filters the $value for use in a template function.
  137. *
  138. * @date 28/09/13
  139. * @since 5.0.0
  140. *
  141. * @param mixed $value The value to preview.
  142. * @param string $post_id The post ID for this value.
  143. * @param array $field The field array.
  144. */
  145. $value = apply_filters( 'acf/format_value', $value, $post_id, $field );
  146. // Update store.
  147. $store->set( "$post_id:$field_name:formatted", $value );
  148. // Return value.
  149. return $value;
  150. }
  151. // Register variation.
  152. acf_add_filter_variations( 'acf/format_value', array( 'type', 'name', 'key' ), 2 );
  153. /**
  154. * acf_update_value
  155. *
  156. * Updates the value for a given field and post_id.
  157. *
  158. * @date 28/09/13
  159. * @since 5.0.0
  160. *
  161. * @param mixed $value The new value.
  162. * @param (int|string) $post_id The post id.
  163. * @param array $field The field array.
  164. * @return bool.
  165. */
  166. function acf_update_value( $value, $post_id, $field ) {
  167. // Allow filter to short-circuit update_value logic.
  168. $check = apply_filters( 'acf/pre_update_value', null, $value, $post_id, $field );
  169. if ( $check !== null ) {
  170. return $check;
  171. }
  172. /**
  173. * Filters the $value before it is updated.
  174. *
  175. * @date 28/09/13
  176. * @since 5.0.0
  177. *
  178. * @param mixed $value The value to update.
  179. * @param string $post_id The post ID for this value.
  180. * @param array $field The field array.
  181. * @param mixed $original The original value before modification.
  182. */
  183. $value = apply_filters( 'acf/update_value', $value, $post_id, $field, $value );
  184. // Allow null to delete value.
  185. if ( $value === null ) {
  186. return acf_delete_value( $post_id, $field );
  187. }
  188. // Update meta.
  189. $return = acf_update_metadata( $post_id, $field['name'], $value );
  190. // Update reference.
  191. acf_update_metadata( $post_id, $field['name'], $field['key'], true );
  192. // Delete stored data.
  193. acf_flush_value_cache( $post_id, $field['name'] );
  194. // Return update status.
  195. return $return;
  196. }
  197. // Register variation.
  198. acf_add_filter_variations( 'acf/update_value', array( 'type', 'name', 'key' ), 2 );
  199. /**
  200. * acf_update_values
  201. *
  202. * Updates an array of values.
  203. *
  204. * @date 26/2/19
  205. * @since 5.7.13
  206. *
  207. * @param array values The array of values.
  208. * @param (int|string) $post_id The post id.
  209. * @return void
  210. */
  211. function acf_update_values( $values, $post_id ) {
  212. // Loop over values.
  213. foreach ( $values as $key => $value ) {
  214. // Get field.
  215. $field = acf_get_field( $key );
  216. // Update value.
  217. if ( $field ) {
  218. acf_update_value( $value, $post_id, $field );
  219. }
  220. }
  221. }
  222. /**
  223. * acf_flush_value_cache
  224. *
  225. * Deletes all cached data for this value.
  226. *
  227. * @date 22/1/19
  228. * @since 5.7.10
  229. *
  230. * @param (int|string) $post_id The post id.
  231. * @param string $field_name The field name.
  232. * @return void
  233. */
  234. function acf_flush_value_cache( $post_id = 0, $field_name = '' ) {
  235. // Delete stored data.
  236. acf_get_store( 'values' )
  237. ->remove( "$post_id:$field_name" )
  238. ->remove( "$post_id:$field_name:formatted" );
  239. }
  240. /**
  241. * acf_delete_value
  242. *
  243. * Deletes the value for a given field and post_id.
  244. *
  245. * @date 28/09/13
  246. * @since 5.0.0
  247. *
  248. * @param (int|string) $post_id The post id.
  249. * @param array $field The field array.
  250. * @return bool.
  251. */
  252. function acf_delete_value( $post_id, $field ) {
  253. /**
  254. * Fires before a value is deleted.
  255. *
  256. * @date 28/09/13
  257. * @since 5.0.0
  258. *
  259. * @param string $post_id The post ID for this value.
  260. * @param mixed $name The meta name.
  261. * @param array $field The field array.
  262. */
  263. do_action( 'acf/delete_value', $post_id, $field['name'], $field );
  264. // Delete meta.
  265. $return = acf_delete_metadata( $post_id, $field['name'] );
  266. // Delete reference.
  267. acf_delete_metadata( $post_id, $field['name'], true );
  268. // Delete stored data.
  269. acf_flush_value_cache( $post_id, $field['name'] );
  270. // Return delete status.
  271. return $return;
  272. }
  273. // Register variation.
  274. acf_add_filter_variations( 'acf/delete_value', array( 'type', 'name', 'key' ), 2 );
  275. /**
  276. * acf_preview_value
  277. *
  278. * Return a human friendly 'preview' for a given field value.
  279. *
  280. * @date 28/09/13
  281. * @since 5.0.0
  282. *
  283. * @param mixed $value The new value.
  284. * @param (int|string) $post_id The post id.
  285. * @param array $field The field array.
  286. * @return bool.
  287. */
  288. function acf_preview_value( $value, $post_id, $field ) {
  289. /**
  290. * Filters the $value before used in HTML.
  291. *
  292. * @date 24/10/16
  293. * @since 5.5.0
  294. *
  295. * @param mixed $value The value to preview.
  296. * @param string $post_id The post ID for this value.
  297. * @param array $field The field array.
  298. */
  299. return apply_filters( 'acf/preview_value', $value, $post_id, $field );
  300. }
  301. // Register variation.
  302. acf_add_filter_variations( 'acf/preview_value', array( 'type', 'name', 'key' ), 2 );
  303. /**
  304. * Potentially log an error if a field doesn't exist when we expect it to.
  305. *
  306. * @param array $field An array representing the field that a value was requested for.
  307. * @param string $function The function that noticed the problem.
  308. *
  309. * @return void
  310. */
  311. function acf_log_invalid_field_notice( $field, $function ) {
  312. // If "init" has fired, ACF probably wasn't initialized early.
  313. if ( did_action( 'init' ) ) {
  314. return;
  315. }
  316. $error_text = sprintf(
  317. __( '<strong>%1$s</strong> - We\'ve detected one or more calls to retrieve ACF field values before ACF has been initialized. This is not supported and can result in malformed or missing data. <a href="%2$s" target="_blank">Learn how to fix this</a>.', 'acf' ),
  318. acf_get_setting( 'name' ),
  319. acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/resources/acf-field-functions/', 'docs', 'early_init_warning' )
  320. );
  321. _doing_it_wrong( $function, $error_text, '5.11.1' );
  322. }
  323. add_action( 'acf/get_invalid_field_value', 'acf_log_invalid_field_notice', 10, 2 );