class-wp-taxonomy.php 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. <?php
  2. /**
  3. * Taxonomy API: WP_Taxonomy class
  4. *
  5. * @package WordPress
  6. * @subpackage Taxonomy
  7. * @since 4.7.0
  8. */
  9. /**
  10. * Core class used for interacting with taxonomies.
  11. *
  12. * @since 4.7.0
  13. */
  14. final class WP_Taxonomy {
  15. /**
  16. * Taxonomy key.
  17. *
  18. * @since 4.7.0
  19. * @var string
  20. */
  21. public $name;
  22. /**
  23. * Name of the taxonomy shown in the menu. Usually plural.
  24. *
  25. * @since 4.7.0
  26. * @var string
  27. */
  28. public $label;
  29. /**
  30. * An array of labels for this taxonomy.
  31. *
  32. * @since 4.7.0
  33. * @var object
  34. */
  35. public $labels = array();
  36. /**
  37. * A short descriptive summary of what the taxonomy is for.
  38. *
  39. * @since 4.7.0
  40. * @var string
  41. */
  42. public $description = '';
  43. /**
  44. * Whether a taxonomy is intended for use publicly either via the admin interface or by front-end users.
  45. *
  46. * @since 4.7.0
  47. * @var bool
  48. */
  49. public $public = true;
  50. /**
  51. * Whether the taxonomy is publicly queryable.
  52. *
  53. * @since 4.7.0
  54. * @var bool
  55. */
  56. public $publicly_queryable = true;
  57. /**
  58. * Whether the taxonomy is hierarchical.
  59. *
  60. * @since 4.7.0
  61. * @var bool
  62. */
  63. public $hierarchical = false;
  64. /**
  65. * Whether to generate and allow a UI for managing terms in this taxonomy in the admin.
  66. *
  67. * @since 4.7.0
  68. * @var bool
  69. */
  70. public $show_ui = true;
  71. /**
  72. * Whether to show the taxonomy in the admin menu.
  73. *
  74. * If true, the taxonomy is shown as a submenu of the object type menu. If false, no menu is shown.
  75. *
  76. * @since 4.7.0
  77. * @var bool
  78. */
  79. public $show_in_menu = true;
  80. /**
  81. * Whether the taxonomy is available for selection in navigation menus.
  82. *
  83. * @since 4.7.0
  84. * @var bool
  85. */
  86. public $show_in_nav_menus = true;
  87. /**
  88. * Whether to list the taxonomy in the tag cloud widget controls.
  89. *
  90. * @since 4.7.0
  91. * @var bool
  92. */
  93. public $show_tagcloud = true;
  94. /**
  95. * Whether to show the taxonomy in the quick/bulk edit panel.
  96. *
  97. * @since 4.7.0
  98. * @var bool
  99. */
  100. public $show_in_quick_edit = true;
  101. /**
  102. * Whether to display a column for the taxonomy on its post type listing screens.
  103. *
  104. * @since 4.7.0
  105. * @var bool
  106. */
  107. public $show_admin_column = false;
  108. /**
  109. * The callback function for the meta box display.
  110. *
  111. * @since 4.7.0
  112. * @var bool|callable
  113. */
  114. public $meta_box_cb = null;
  115. /**
  116. * An array of object types this taxonomy is registered for.
  117. *
  118. * @since 4.7.0
  119. * @var array
  120. */
  121. public $object_type = null;
  122. /**
  123. * Capabilities for this taxonomy.
  124. *
  125. * @since 4.7.0
  126. * @var array
  127. */
  128. public $cap;
  129. /**
  130. * Rewrites information for this taxonomy.
  131. *
  132. * @since 4.7.0
  133. * @var array|false
  134. */
  135. public $rewrite;
  136. /**
  137. * Query var string for this taxonomy.
  138. *
  139. * @since 4.7.0
  140. * @var string|false
  141. */
  142. public $query_var;
  143. /**
  144. * Function that will be called when the count is updated.
  145. *
  146. * @since 4.7.0
  147. * @var callable
  148. */
  149. public $update_count_callback;
  150. /**
  151. * Whether this taxonomy should appear in the REST API.
  152. *
  153. * Default false. If true, standard endpoints will be registered with
  154. * respect to $rest_base and $rest_controller_class.
  155. *
  156. * @since 4.7.4
  157. * @var bool $show_in_rest
  158. */
  159. public $show_in_rest;
  160. /**
  161. * The base path for this taxonomy's REST API endpoints.
  162. *
  163. * @since 4.7.4
  164. * @var string|bool $rest_base
  165. */
  166. public $rest_base;
  167. /**
  168. * The controller for this taxonomy's REST API endpoints.
  169. *
  170. * Custom controllers must extend WP_REST_Controller.
  171. *
  172. * @since 4.7.4
  173. * @var string|bool $rest_controller_class
  174. */
  175. public $rest_controller_class;
  176. /**
  177. * Whether it is a built-in taxonomy.
  178. *
  179. * @since 4.7.0
  180. * @var bool
  181. */
  182. public $_builtin;
  183. /**
  184. * Constructor.
  185. *
  186. * @since 4.7.0
  187. *
  188. * @global WP $wp WP instance.
  189. *
  190. * @param string $taxonomy Taxonomy key, must not exceed 32 characters.
  191. * @param array|string $object_type Name of the object type for the taxonomy object.
  192. * @param array|string $args Optional. Array or query string of arguments for registering a taxonomy.
  193. * Default empty array.
  194. */
  195. public function __construct( $taxonomy, $object_type, $args = array() ) {
  196. $this->name = $taxonomy;
  197. $this->set_props( $object_type, $args );
  198. }
  199. /**
  200. * Sets taxonomy properties.
  201. *
  202. * @since 4.7.0
  203. *
  204. * @param array|string $object_type Name of the object type for the taxonomy object.
  205. * @param array|string $args Array or query string of arguments for registering a taxonomy.
  206. */
  207. public function set_props( $object_type, $args ) {
  208. $args = wp_parse_args( $args );
  209. /**
  210. * Filters the arguments for registering a taxonomy.
  211. *
  212. * @since 4.4.0
  213. *
  214. * @param array $args Array of arguments for registering a taxonomy.
  215. * @param string $taxonomy Taxonomy key.
  216. * @param array $object_type Array of names of object types for the taxonomy.
  217. */
  218. $args = apply_filters( 'register_taxonomy_args', $args, $this->name, (array) $object_type );
  219. $defaults = array(
  220. 'labels' => array(),
  221. 'description' => '',
  222. 'public' => true,
  223. 'publicly_queryable' => null,
  224. 'hierarchical' => false,
  225. 'show_ui' => null,
  226. 'show_in_menu' => null,
  227. 'show_in_nav_menus' => null,
  228. 'show_tagcloud' => null,
  229. 'show_in_quick_edit' => null,
  230. 'show_admin_column' => false,
  231. 'meta_box_cb' => null,
  232. 'capabilities' => array(),
  233. 'rewrite' => true,
  234. 'query_var' => $this->name,
  235. 'update_count_callback' => '',
  236. 'show_in_rest' => false,
  237. 'rest_base' => false,
  238. 'rest_controller_class' => false,
  239. '_builtin' => false,
  240. );
  241. $args = array_merge( $defaults, $args );
  242. // If not set, default to the setting for public.
  243. if ( null === $args['publicly_queryable'] ) {
  244. $args['publicly_queryable'] = $args['public'];
  245. }
  246. if ( false !== $args['query_var'] && ( is_admin() || false !== $args['publicly_queryable'] ) ) {
  247. if ( true === $args['query_var'] ) {
  248. $args['query_var'] = $this->name;
  249. } else {
  250. $args['query_var'] = sanitize_title_with_dashes( $args['query_var'] );
  251. }
  252. } else {
  253. // Force query_var to false for non-public taxonomies.
  254. $args['query_var'] = false;
  255. }
  256. if ( false !== $args['rewrite'] && ( is_admin() || '' != get_option( 'permalink_structure' ) ) ) {
  257. $args['rewrite'] = wp_parse_args( $args['rewrite'], array(
  258. 'with_front' => true,
  259. 'hierarchical' => false,
  260. 'ep_mask' => EP_NONE,
  261. ) );
  262. if ( empty( $args['rewrite']['slug'] ) ) {
  263. $args['rewrite']['slug'] = sanitize_title_with_dashes( $this->name );
  264. }
  265. }
  266. // If not set, default to the setting for public.
  267. if ( null === $args['show_ui'] ) {
  268. $args['show_ui'] = $args['public'];
  269. }
  270. // If not set, default to the setting for show_ui.
  271. if ( null === $args['show_in_menu'] || ! $args['show_ui'] ) {
  272. $args['show_in_menu'] = $args['show_ui'];
  273. }
  274. // If not set, default to the setting for public.
  275. if ( null === $args['show_in_nav_menus'] ) {
  276. $args['show_in_nav_menus'] = $args['public'];
  277. }
  278. // If not set, default to the setting for show_ui.
  279. if ( null === $args['show_tagcloud'] ) {
  280. $args['show_tagcloud'] = $args['show_ui'];
  281. }
  282. // If not set, default to the setting for show_ui.
  283. if ( null === $args['show_in_quick_edit'] ) {
  284. $args['show_in_quick_edit'] = $args['show_ui'];
  285. }
  286. $default_caps = array(
  287. 'manage_terms' => 'manage_categories',
  288. 'edit_terms' => 'manage_categories',
  289. 'delete_terms' => 'manage_categories',
  290. 'assign_terms' => 'edit_posts',
  291. );
  292. $args['cap'] = (object) array_merge( $default_caps, $args['capabilities'] );
  293. unset( $args['capabilities'] );
  294. $args['object_type'] = array_unique( (array) $object_type );
  295. // If not set, use the default meta box
  296. if ( null === $args['meta_box_cb'] ) {
  297. if ( $args['hierarchical'] ) {
  298. $args['meta_box_cb'] = 'post_categories_meta_box';
  299. } else {
  300. $args['meta_box_cb'] = 'post_tags_meta_box';
  301. }
  302. }
  303. $args['name'] = $this->name;
  304. foreach ( $args as $property_name => $property_value ) {
  305. $this->$property_name = $property_value;
  306. }
  307. $this->labels = get_taxonomy_labels( $this );
  308. $this->label = $this->labels->name;
  309. }
  310. /**
  311. * Adds the necessary rewrite rules for the taxonomy.
  312. *
  313. * @since 4.7.0
  314. *
  315. * @global WP $wp Current WordPress environment instance.
  316. */
  317. public function add_rewrite_rules() {
  318. /* @var WP $wp */
  319. global $wp;
  320. // Non-publicly queryable taxonomies should not register query vars, except in the admin.
  321. if ( false !== $this->query_var && $wp ) {
  322. $wp->add_query_var( $this->query_var );
  323. }
  324. if ( false !== $this->rewrite && ( is_admin() || '' != get_option( 'permalink_structure' ) ) ) {
  325. if ( $this->hierarchical && $this->rewrite['hierarchical'] ) {
  326. $tag = '(.+?)';
  327. } else {
  328. $tag = '([^/]+)';
  329. }
  330. add_rewrite_tag( "%$this->name%", $tag, $this->query_var ? "{$this->query_var}=" : "taxonomy=$this->name&term=" );
  331. add_permastruct( $this->name, "{$this->rewrite['slug']}/%$this->name%", $this->rewrite );
  332. }
  333. }
  334. /**
  335. * Removes any rewrite rules, permastructs, and rules for the taxonomy.
  336. *
  337. * @since 4.7.0
  338. *
  339. * @global WP $wp Current WordPress environment instance.
  340. */
  341. public function remove_rewrite_rules() {
  342. /* @var WP $wp */
  343. global $wp;
  344. // Remove query var.
  345. if ( false !== $this->query_var ) {
  346. $wp->remove_query_var( $this->query_var );
  347. }
  348. // Remove rewrite tags and permastructs.
  349. if ( false !== $this->rewrite ) {
  350. remove_rewrite_tag( "%$this->name%" );
  351. remove_permastruct( $this->name );
  352. }
  353. }
  354. /**
  355. * Registers the ajax callback for the meta box.
  356. *
  357. * @since 4.7.0
  358. */
  359. public function add_hooks() {
  360. add_filter( 'wp_ajax_add-' . $this->name, '_wp_ajax_add_hierarchical_term' );
  361. }
  362. /**
  363. * Removes the ajax callback for the meta box.
  364. *
  365. * @since 4.7.0
  366. */
  367. public function remove_hooks() {
  368. remove_filter( 'wp_ajax_add-' . $this->name, '_wp_ajax_add_hierarchical_term' );
  369. }
  370. }