api-term.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. <?php
  2. /*
  3. * acf_get_taxonomies
  4. *
  5. * Returns an array of taxonomy names.
  6. *
  7. * @date 7/10/13
  8. * @since 5.0.0
  9. *
  10. * @param array $args An array of args used in the get_taxonomies() function.
  11. * @return array An array of taxonomy names.
  12. */
  13. function acf_get_taxonomies( $args = array() ) {
  14. // vars
  15. $taxonomies = array();
  16. // get taxonomy objects
  17. $objects = get_taxonomies( $args, 'objects' );
  18. // loop
  19. foreach ( $objects as $i => $object ) {
  20. // bail early if is builtin (WP) private post type
  21. // - nav_menu_item, revision, customize_changeset, etc
  22. if ( $object->_builtin && ! $object->public ) {
  23. continue;
  24. }
  25. // append
  26. $taxonomies[] = $i;
  27. }
  28. // custom post_type arg which does not yet exist in core
  29. if ( isset( $args['post_type'] ) ) {
  30. $taxonomies = acf_get_taxonomies_for_post_type( $args['post_type'] );
  31. }
  32. // filter
  33. $taxonomies = apply_filters( 'acf/get_taxonomies', $taxonomies, $args );
  34. // return
  35. return $taxonomies;
  36. }
  37. /**
  38. * acf_get_taxonomies_for_post_type
  39. *
  40. * Returns an array of taxonomies for a given post type(s)
  41. *
  42. * @date 7/9/18
  43. * @since 5.7.5
  44. *
  45. * @param string|array $post_types The post types to compare against.
  46. * @return array
  47. */
  48. function acf_get_taxonomies_for_post_type( $post_types = 'post' ) {
  49. // vars
  50. $taxonomies = array();
  51. // loop
  52. foreach ( (array) $post_types as $post_type ) {
  53. $object_taxonomies = get_object_taxonomies( $post_type );
  54. foreach ( (array) $object_taxonomies as $taxonomy ) {
  55. $taxonomies[] = $taxonomy;
  56. }
  57. }
  58. // remove duplicates
  59. $taxonomies = array_unique( $taxonomies );
  60. // return
  61. return $taxonomies;
  62. }
  63. /*
  64. * acf_get_taxonomy_labels
  65. *
  66. * Returns an array of taxonomies in the format "name => label" for use in a select field.
  67. *
  68. * @date 3/8/18
  69. * @since 5.7.2
  70. *
  71. * @param array $taxonomies Optional. An array of specific taxonomies to return.
  72. * @return array
  73. */
  74. function acf_get_taxonomy_labels( $taxonomies = array() ) {
  75. // default
  76. if ( empty( $taxonomies ) ) {
  77. $taxonomies = acf_get_taxonomies();
  78. }
  79. // vars
  80. $ref = array();
  81. $data = array();
  82. // loop
  83. foreach ( $taxonomies as $taxonomy ) {
  84. // vars
  85. $object = get_taxonomy( $taxonomy );
  86. $label = $object->labels->singular_name;
  87. // append
  88. $data[ $taxonomy ] = $label;
  89. // increase counter
  90. if ( ! isset( $ref[ $label ] ) ) {
  91. $ref[ $label ] = 0;
  92. }
  93. $ref[ $label ]++;
  94. }
  95. // show taxonomy name next to label for shared labels
  96. foreach ( $data as $taxonomy => $label ) {
  97. if ( $ref[ $label ] > 1 ) {
  98. $data[ $taxonomy ] .= ' (' . $taxonomy . ')';
  99. }
  100. }
  101. // return
  102. return $data;
  103. }
  104. /**
  105. * acf_get_term_title
  106. *
  107. * Returns the title for this term object.
  108. *
  109. * @date 10/9/18
  110. * @since 5.0.0
  111. *
  112. * @param object $term The WP_Term object.
  113. * @return string
  114. */
  115. function acf_get_term_title( $term ) {
  116. $title = $term->name;
  117. // Allow for empty name.
  118. if ( $title === '' ) {
  119. $title = __( '(no title)', 'acf' );
  120. }
  121. // Prepend ancestors indentation.
  122. if ( is_taxonomy_hierarchical( $term->taxonomy ) ) {
  123. $ancestors = get_ancestors( $term->term_id, $term->taxonomy );
  124. $title = str_repeat( '- ', count( $ancestors ) ) . $title;
  125. }
  126. return $title;
  127. }
  128. /**
  129. * acf_get_grouped_terms
  130. *
  131. * Returns an array of terms for the given query $args and groups by taxonomy name.
  132. *
  133. * @date 2/8/18
  134. * @since 5.7.2
  135. *
  136. * @param array $args An array of args used in the get_terms() function.
  137. * @return array
  138. */
  139. function acf_get_grouped_terms( $args ) {
  140. // vars
  141. $data = array();
  142. // defaults
  143. $args = wp_parse_args(
  144. $args,
  145. array(
  146. 'taxonomy' => null,
  147. 'hide_empty' => false,
  148. 'update_term_meta_cache' => false,
  149. )
  150. );
  151. // vars
  152. $taxonomies = acf_get_taxonomy_labels( acf_get_array( $args['taxonomy'] ) );
  153. $is_single = ( count( $taxonomies ) == 1 );
  154. // specify exact taxonomies required for _acf_terms_clauses() to work.
  155. $args['taxonomy'] = array_keys( $taxonomies );
  156. // add filter to group results by taxonomy
  157. if ( ! $is_single ) {
  158. add_filter( 'terms_clauses', '_acf_terms_clauses', 10, 3 );
  159. }
  160. // get terms
  161. $terms = get_terms( $args );
  162. // remove this filter (only once)
  163. if ( ! $is_single ) {
  164. remove_filter( 'terms_clauses', '_acf_terms_clauses', 10, 3 );
  165. }
  166. // loop
  167. foreach ( $taxonomies as $taxonomy => $label ) {
  168. // vars
  169. $this_terms = array();
  170. // populate $this_terms
  171. foreach ( $terms as $term ) {
  172. if ( $term->taxonomy == $taxonomy ) {
  173. $this_terms[] = $term;
  174. }
  175. }
  176. // bail early if no $items
  177. if ( empty( $this_terms ) ) {
  178. continue;
  179. }
  180. // sort into hierachial order
  181. // this will fail if a search has taken place because parents wont exist
  182. if ( is_taxonomy_hierarchical( $taxonomy ) && empty( $args['s'] ) ) {
  183. // get all terms from this taxonomy
  184. $all_terms = get_terms(
  185. array_merge(
  186. $args,
  187. array(
  188. 'number' => 0,
  189. 'offset' => 0,
  190. 'taxonomy' => $taxonomy,
  191. )
  192. )
  193. );
  194. // vars
  195. $length = count( $this_terms );
  196. $offset = 0;
  197. // find starting point (offset)
  198. foreach ( $all_terms as $i => $term ) {
  199. if ( $term->term_id == $this_terms[0]->term_id ) {
  200. $offset = $i;
  201. break;
  202. }
  203. }
  204. // order terms
  205. $parent = acf_maybe_get( $args, 'parent', 0 );
  206. $parent = acf_maybe_get( $args, 'child_of', $parent );
  207. $ordered_terms = _get_term_children( $parent, $all_terms, $taxonomy );
  208. // compare aray lengths
  209. // if $ordered_posts is smaller than $all_posts, WP has lost posts during the get_page_children() function
  210. // this is possible when get_post( $args ) filter out parents (via taxonomy, meta and other search parameters)
  211. if ( count( $ordered_terms ) == count( $all_terms ) ) {
  212. $this_terms = array_slice( $ordered_terms, $offset, $length );
  213. }
  214. }
  215. // populate group
  216. $data[ $label ] = array();
  217. foreach ( $this_terms as $term ) {
  218. $data[ $label ][ $term->term_id ] = $term;
  219. }
  220. }
  221. // return
  222. return $data;
  223. }
  224. /**
  225. * _acf_terms_clauses
  226. *
  227. * Used in the 'terms_clauses' filter to order terms by taxonomy name.
  228. *
  229. * @date 2/8/18
  230. * @since 5.7.2
  231. *
  232. * @param array $pieces Terms query SQL clauses.
  233. * @param array $taxonomies An array of taxonomies.
  234. * @param array $args An array of terms query arguments.
  235. * @return array $pieces
  236. */
  237. function _acf_terms_clauses( $pieces, $taxonomies, $args ) {
  238. // prepend taxonomy to 'orderby' SQL
  239. if ( is_array( $taxonomies ) ) {
  240. $sql = "FIELD(tt.taxonomy,'" . implode( "', '", array_map( 'esc_sql', $taxonomies ) ) . "')";
  241. $pieces['orderby'] = str_replace( 'ORDER BY', "ORDER BY $sql,", $pieces['orderby'] );
  242. }
  243. // return
  244. return $pieces;
  245. }
  246. /**
  247. * acf_get_pretty_taxonomies
  248. *
  249. * Deprecated in favor of acf_get_taxonomy_labels() function.
  250. *
  251. * @date 7/10/13
  252. * @since 5.0.0
  253. * @deprecated 5.7.2
  254. */
  255. function acf_get_pretty_taxonomies( $taxonomies = array() ) {
  256. return acf_get_taxonomy_labels( $taxonomies );
  257. }
  258. /**
  259. * acf_get_term
  260. *
  261. * Similar to get_term() but with some extra functionality.
  262. *
  263. * @date 19/8/18
  264. * @since 5.7.3
  265. *
  266. * @param mixed $term_id The term ID or a string of "taxonomy:slug".
  267. * @param string $taxonomy The taxonomyname.
  268. * @return WP_Term
  269. */
  270. function acf_get_term( $term_id, $taxonomy = '' ) {
  271. // allow $term_id parameter to be a string of "taxonomy:slug" or "taxonomy:id"
  272. if ( is_string( $term_id ) && strpos( $term_id, ':' ) ) {
  273. list( $taxonomy, $term_id ) = explode( ':', $term_id );
  274. $term = get_term_by( 'slug', $term_id, $taxonomy );
  275. if ( $term ) {
  276. return $term;
  277. }
  278. }
  279. // return
  280. return get_term( $term_id, $taxonomy );
  281. }
  282. /**
  283. * acf_encode_term
  284. *
  285. * Returns a "taxonomy:slug" string for a given WP_Term.
  286. *
  287. * @date 27/8/18
  288. * @since 5.7.4
  289. *
  290. * @param WP_Term $term The term object.
  291. * @return string
  292. */
  293. function acf_encode_term( $term ) {
  294. return "{$term->taxonomy}:{$term->slug}";
  295. }
  296. /**
  297. * acf_decode_term
  298. *
  299. * Decodes a "taxonomy:slug" string into an array of taxonomy and slug.
  300. *
  301. * @date 27/8/18
  302. * @since 5.7.4
  303. *
  304. * @param WP_Term $term The term object.
  305. * @return string
  306. */
  307. function acf_decode_term( $string ) {
  308. if ( is_string( $string ) && strpos( $string, ':' ) ) {
  309. list( $taxonomy, $slug ) = explode( ':', $string );
  310. return compact( 'taxonomy', 'slug' );
  311. }
  312. return false;
  313. }
  314. /**
  315. * acf_get_encoded_terms
  316. *
  317. * Returns an array of WP_Term objects from an array of encoded strings
  318. *
  319. * @date 9/9/18
  320. * @since 5.7.5
  321. *
  322. * @param array $values The array of encoded strings.
  323. * @return array
  324. */
  325. function acf_get_encoded_terms( $values ) {
  326. // vars
  327. $terms = array();
  328. // loop over values
  329. foreach ( (array) $values as $value ) {
  330. // find term from string
  331. $term = acf_get_term( $value );
  332. // append
  333. if ( $term instanceof WP_Term ) {
  334. $terms[] = $term;
  335. }
  336. }
  337. // return
  338. return $terms;
  339. }
  340. /**
  341. * acf_get_choices_from_terms
  342. *
  343. * Returns an array of choices from the terms provided.
  344. *
  345. * @date 8/9/18
  346. * @since 5.7.5
  347. *
  348. * @param array $values and array of WP_Terms objects or encoded strings.
  349. * @param string $format The value format (term_id, slug).
  350. * @return array
  351. */
  352. function acf_get_choices_from_terms( $terms, $format = 'term_id' ) {
  353. // vars
  354. $groups = array();
  355. // get taxonomy lables
  356. $labels = acf_get_taxonomy_labels();
  357. // convert array of encoded strings to terms
  358. $term = reset( $terms );
  359. if ( ! $term instanceof WP_Term ) {
  360. $terms = acf_get_encoded_terms( $terms );
  361. }
  362. // loop over terms
  363. foreach ( $terms as $term ) {
  364. $group = $labels[ $term->taxonomy ];
  365. $choice = acf_get_choice_from_term( $term, $format );
  366. $groups[ $group ][ $choice['id'] ] = $choice['text'];
  367. }
  368. // return
  369. return $groups;
  370. }
  371. /**
  372. * acf_get_choices_from_grouped_terms
  373. *
  374. * Returns an array of choices from the grouped terms provided.
  375. *
  376. * @date 8/9/18
  377. * @since 5.7.5
  378. *
  379. * @param array $value A grouped array of WP_Terms objects.
  380. * @param string $format The value format (term_id, slug).
  381. * @return array
  382. */
  383. function acf_get_choices_from_grouped_terms( $value, $format = 'term_id' ) {
  384. // vars
  385. $groups = array();
  386. // loop over values
  387. foreach ( $value as $group => $terms ) {
  388. $groups[ $group ] = array();
  389. foreach ( $terms as $term_id => $term ) {
  390. $choice = acf_get_choice_from_term( $term, $format );
  391. $groups[ $group ][ $choice['id'] ] = $choice['text'];
  392. }
  393. }
  394. // return
  395. return $groups;
  396. }
  397. /**
  398. * acf_get_choice_from_term
  399. *
  400. * Returns an array containing the id and text for this item.
  401. *
  402. * @date 10/9/18
  403. * @since 5.7.6
  404. *
  405. * @param object $item The item object such as WP_Post or WP_Term.
  406. * @param string $format The value format (term_id, slug)
  407. * @return array
  408. */
  409. function acf_get_choice_from_term( $term, $format = 'term_id' ) {
  410. // vars
  411. $id = $term->term_id;
  412. $text = acf_get_term_title( $term );
  413. // return format
  414. if ( $format == 'slug' ) {
  415. $id = acf_encode_term( $term );
  416. }
  417. // return
  418. return array(
  419. 'id' => $id,
  420. 'text' => $text,
  421. );
  422. }
  423. /**
  424. * Returns a valid post_id string for a given term and taxonomy.
  425. * No longer needed since WP introduced the termmeta table in WP 4.4.
  426. *
  427. * @date 6/2/17
  428. * @since 5.5.6
  429. * @deprecated 5.9.2
  430. *
  431. * @param $taxonomy (string) The taxonomy type.
  432. * @param $term_id (int) The term ID.
  433. * @return (string)
  434. */
  435. function acf_get_term_post_id( $taxonomy, $term_id ) {
  436. _deprecated_function( __FUNCTION__, '5.9.2', 'string format term_%d' );
  437. return 'term_' . $term_id;
  438. }