Nenhuma Descrição

class-wp-taxonomy.php 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  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. * Labels object for this taxonomy.
  31. *
  32. * If not set, tag labels are inherited for non-hierarchical types
  33. * and category labels for hierarchical ones.
  34. *
  35. * @see get_taxonomy_labels()
  36. *
  37. * @since 4.7.0
  38. * @var stdClass
  39. */
  40. public $labels;
  41. /**
  42. * A short descriptive summary of what the taxonomy is for.
  43. *
  44. * @since 4.7.0
  45. * @var string
  46. */
  47. public $description = '';
  48. /**
  49. * Whether a taxonomy is intended for use publicly either via the admin interface or by front-end users.
  50. *
  51. * @since 4.7.0
  52. * @var bool
  53. */
  54. public $public = true;
  55. /**
  56. * Whether the taxonomy is publicly queryable.
  57. *
  58. * @since 4.7.0
  59. * @var bool
  60. */
  61. public $publicly_queryable = true;
  62. /**
  63. * Whether the taxonomy is hierarchical.
  64. *
  65. * @since 4.7.0
  66. * @var bool
  67. */
  68. public $hierarchical = false;
  69. /**
  70. * Whether to generate and allow a UI for managing terms in this taxonomy in the admin.
  71. *
  72. * @since 4.7.0
  73. * @var bool
  74. */
  75. public $show_ui = true;
  76. /**
  77. * Whether to show the taxonomy in the admin menu.
  78. *
  79. * If true, the taxonomy is shown as a submenu of the object type menu. If false, no menu is shown.
  80. *
  81. * @since 4.7.0
  82. * @var bool
  83. */
  84. public $show_in_menu = true;
  85. /**
  86. * Whether the taxonomy is available for selection in navigation menus.
  87. *
  88. * @since 4.7.0
  89. * @var bool
  90. */
  91. public $show_in_nav_menus = true;
  92. /**
  93. * Whether to list the taxonomy in the tag cloud widget controls.
  94. *
  95. * @since 4.7.0
  96. * @var bool
  97. */
  98. public $show_tagcloud = true;
  99. /**
  100. * Whether to show the taxonomy in the quick/bulk edit panel.
  101. *
  102. * @since 4.7.0
  103. * @var bool
  104. */
  105. public $show_in_quick_edit = true;
  106. /**
  107. * Whether to display a column for the taxonomy on its post type listing screens.
  108. *
  109. * @since 4.7.0
  110. * @var bool
  111. */
  112. public $show_admin_column = false;
  113. /**
  114. * The callback function for the meta box display.
  115. *
  116. * @since 4.7.0
  117. * @var bool|callable
  118. */
  119. public $meta_box_cb = null;
  120. /**
  121. * The callback function for sanitizing taxonomy data saved from a meta box.
  122. *
  123. * @since 5.1.0
  124. * @var callable
  125. */
  126. public $meta_box_sanitize_cb = null;
  127. /**
  128. * An array of object types this taxonomy is registered for.
  129. *
  130. * @since 4.7.0
  131. * @var array
  132. */
  133. public $object_type = null;
  134. /**
  135. * Capabilities for this taxonomy.
  136. *
  137. * @since 4.7.0
  138. * @var stdClass
  139. */
  140. public $cap;
  141. /**
  142. * Rewrites information for this taxonomy.
  143. *
  144. * @since 4.7.0
  145. * @var array|false
  146. */
  147. public $rewrite;
  148. /**
  149. * Query var string for this taxonomy.
  150. *
  151. * @since 4.7.0
  152. * @var string|false
  153. */
  154. public $query_var;
  155. /**
  156. * Function that will be called when the count is updated.
  157. *
  158. * @since 4.7.0
  159. * @var callable
  160. */
  161. public $update_count_callback;
  162. /**
  163. * Whether this taxonomy should appear in the REST API.
  164. *
  165. * Default false. If true, standard endpoints will be registered with
  166. * respect to $rest_base and $rest_controller_class.
  167. *
  168. * @since 4.7.4
  169. * @var bool $show_in_rest
  170. */
  171. public $show_in_rest;
  172. /**
  173. * The base path for this taxonomy's REST API endpoints.
  174. *
  175. * @since 4.7.4
  176. * @var string|bool $rest_base
  177. */
  178. public $rest_base;
  179. /**
  180. * The controller for this taxonomy's REST API endpoints.
  181. *
  182. * Custom controllers must extend WP_REST_Controller.
  183. *
  184. * @since 4.7.4
  185. * @var string|bool $rest_controller_class
  186. */
  187. public $rest_controller_class;
  188. /**
  189. * The controller instance for this taxonomy's REST API endpoints.
  190. *
  191. * Lazily computed. Should be accessed using {@see WP_Taxonomy::get_rest_controller()}.
  192. *
  193. * @since 5.5.0
  194. * @var WP_REST_Controller $rest_controller
  195. */
  196. public $rest_controller;
  197. /**
  198. * The default term name for this taxonomy. If you pass an array you have
  199. * to set 'name' and optionally 'slug' and 'description'.
  200. *
  201. * @since 5.5.0
  202. * @var array|string
  203. */
  204. public $default_term;
  205. /**
  206. * Whether terms in this taxonomy should be sorted in the order they are provided to `wp_set_object_terms()`.
  207. *
  208. * Use this in combination with `'orderby' => 'term_order'` when fetching terms.
  209. *
  210. * @since 2.5.0
  211. * @var bool|null
  212. */
  213. public $sort = null;
  214. /**
  215. * Array of arguments to automatically use inside `wp_get_object_terms()` for this taxonomy.
  216. *
  217. * @since 2.6.0
  218. * @var array|null
  219. */
  220. public $args = null;
  221. /**
  222. * Whether it is a built-in taxonomy.
  223. *
  224. * @since 4.7.0
  225. * @var bool
  226. */
  227. public $_builtin;
  228. /**
  229. * Constructor.
  230. *
  231. * See the register_taxonomy() function for accepted arguments for `$args`.
  232. *
  233. * @since 4.7.0
  234. *
  235. * @global WP $wp Current WordPress environment instance.
  236. *
  237. * @param string $taxonomy Taxonomy key, must not exceed 32 characters.
  238. * @param array|string $object_type Name of the object type for the taxonomy object.
  239. * @param array|string $args Optional. Array or query string of arguments for registering a taxonomy.
  240. * Default empty array.
  241. */
  242. public function __construct( $taxonomy, $object_type, $args = array() ) {
  243. $this->name = $taxonomy;
  244. $this->set_props( $object_type, $args );
  245. }
  246. /**
  247. * Sets taxonomy properties.
  248. *
  249. * See the register_taxonomy() function for accepted arguments for `$args`.
  250. *
  251. * @since 4.7.0
  252. *
  253. * @param array|string $object_type Name of the object type for the taxonomy object.
  254. * @param array|string $args Array or query string of arguments for registering a taxonomy.
  255. */
  256. public function set_props( $object_type, $args ) {
  257. $args = wp_parse_args( $args );
  258. /**
  259. * Filters the arguments for registering a taxonomy.
  260. *
  261. * @since 4.4.0
  262. *
  263. * @param array $args Array of arguments for registering a taxonomy.
  264. * See the register_taxonomy() function for accepted arguments.
  265. * @param string $taxonomy Taxonomy key.
  266. * @param string[] $object_type Array of names of object types for the taxonomy.
  267. */
  268. $args = apply_filters( 'register_taxonomy_args', $args, $this->name, (array) $object_type );
  269. $defaults = array(
  270. 'labels' => array(),
  271. 'description' => '',
  272. 'public' => true,
  273. 'publicly_queryable' => null,
  274. 'hierarchical' => false,
  275. 'show_ui' => null,
  276. 'show_in_menu' => null,
  277. 'show_in_nav_menus' => null,
  278. 'show_tagcloud' => null,
  279. 'show_in_quick_edit' => null,
  280. 'show_admin_column' => false,
  281. 'meta_box_cb' => null,
  282. 'meta_box_sanitize_cb' => null,
  283. 'capabilities' => array(),
  284. 'rewrite' => true,
  285. 'query_var' => $this->name,
  286. 'update_count_callback' => '',
  287. 'show_in_rest' => false,
  288. 'rest_base' => false,
  289. 'rest_controller_class' => false,
  290. 'default_term' => null,
  291. 'sort' => null,
  292. 'args' => null,
  293. '_builtin' => false,
  294. );
  295. $args = array_merge( $defaults, $args );
  296. // If not set, default to the setting for 'public'.
  297. if ( null === $args['publicly_queryable'] ) {
  298. $args['publicly_queryable'] = $args['public'];
  299. }
  300. if ( false !== $args['query_var'] && ( is_admin() || false !== $args['publicly_queryable'] ) ) {
  301. if ( true === $args['query_var'] ) {
  302. $args['query_var'] = $this->name;
  303. } else {
  304. $args['query_var'] = sanitize_title_with_dashes( $args['query_var'] );
  305. }
  306. } else {
  307. // Force 'query_var' to false for non-public taxonomies.
  308. $args['query_var'] = false;
  309. }
  310. if ( false !== $args['rewrite'] && ( is_admin() || get_option( 'permalink_structure' ) ) ) {
  311. $args['rewrite'] = wp_parse_args(
  312. $args['rewrite'],
  313. array(
  314. 'with_front' => true,
  315. 'hierarchical' => false,
  316. 'ep_mask' => EP_NONE,
  317. )
  318. );
  319. if ( empty( $args['rewrite']['slug'] ) ) {
  320. $args['rewrite']['slug'] = sanitize_title_with_dashes( $this->name );
  321. }
  322. }
  323. // If not set, default to the setting for 'public'.
  324. if ( null === $args['show_ui'] ) {
  325. $args['show_ui'] = $args['public'];
  326. }
  327. // If not set, default to the setting for 'show_ui'.
  328. if ( null === $args['show_in_menu'] || ! $args['show_ui'] ) {
  329. $args['show_in_menu'] = $args['show_ui'];
  330. }
  331. // If not set, default to the setting for 'public'.
  332. if ( null === $args['show_in_nav_menus'] ) {
  333. $args['show_in_nav_menus'] = $args['public'];
  334. }
  335. // If not set, default to the setting for 'show_ui'.
  336. if ( null === $args['show_tagcloud'] ) {
  337. $args['show_tagcloud'] = $args['show_ui'];
  338. }
  339. // If not set, default to the setting for 'show_ui'.
  340. if ( null === $args['show_in_quick_edit'] ) {
  341. $args['show_in_quick_edit'] = $args['show_ui'];
  342. }
  343. $default_caps = array(
  344. 'manage_terms' => 'manage_categories',
  345. 'edit_terms' => 'manage_categories',
  346. 'delete_terms' => 'manage_categories',
  347. 'assign_terms' => 'edit_posts',
  348. );
  349. $args['cap'] = (object) array_merge( $default_caps, $args['capabilities'] );
  350. unset( $args['capabilities'] );
  351. $args['object_type'] = array_unique( (array) $object_type );
  352. // If not set, use the default meta box.
  353. if ( null === $args['meta_box_cb'] ) {
  354. if ( $args['hierarchical'] ) {
  355. $args['meta_box_cb'] = 'post_categories_meta_box';
  356. } else {
  357. $args['meta_box_cb'] = 'post_tags_meta_box';
  358. }
  359. }
  360. $args['name'] = $this->name;
  361. // Default meta box sanitization callback depends on the value of 'meta_box_cb'.
  362. if ( null === $args['meta_box_sanitize_cb'] ) {
  363. switch ( $args['meta_box_cb'] ) {
  364. case 'post_categories_meta_box':
  365. $args['meta_box_sanitize_cb'] = 'taxonomy_meta_box_sanitize_cb_checkboxes';
  366. break;
  367. case 'post_tags_meta_box':
  368. default:
  369. $args['meta_box_sanitize_cb'] = 'taxonomy_meta_box_sanitize_cb_input';
  370. break;
  371. }
  372. }
  373. // Default taxonomy term.
  374. if ( ! empty( $args['default_term'] ) ) {
  375. if ( ! is_array( $args['default_term'] ) ) {
  376. $args['default_term'] = array( 'name' => $args['default_term'] );
  377. }
  378. $args['default_term'] = wp_parse_args(
  379. $args['default_term'],
  380. array(
  381. 'name' => '',
  382. 'slug' => '',
  383. 'description' => '',
  384. )
  385. );
  386. }
  387. foreach ( $args as $property_name => $property_value ) {
  388. $this->$property_name = $property_value;
  389. }
  390. $this->labels = get_taxonomy_labels( $this );
  391. $this->label = $this->labels->name;
  392. }
  393. /**
  394. * Adds the necessary rewrite rules for the taxonomy.
  395. *
  396. * @since 4.7.0
  397. *
  398. * @global WP $wp Current WordPress environment instance.
  399. */
  400. public function add_rewrite_rules() {
  401. /* @var WP $wp */
  402. global $wp;
  403. // Non-publicly queryable taxonomies should not register query vars, except in the admin.
  404. if ( false !== $this->query_var && $wp ) {
  405. $wp->add_query_var( $this->query_var );
  406. }
  407. if ( false !== $this->rewrite && ( is_admin() || get_option( 'permalink_structure' ) ) ) {
  408. if ( $this->hierarchical && $this->rewrite['hierarchical'] ) {
  409. $tag = '(.+?)';
  410. } else {
  411. $tag = '([^/]+)';
  412. }
  413. add_rewrite_tag( "%$this->name%", $tag, $this->query_var ? "{$this->query_var}=" : "taxonomy=$this->name&term=" );
  414. add_permastruct( $this->name, "{$this->rewrite['slug']}/%$this->name%", $this->rewrite );
  415. }
  416. }
  417. /**
  418. * Removes any rewrite rules, permastructs, and rules for the taxonomy.
  419. *
  420. * @since 4.7.0
  421. *
  422. * @global WP $wp Current WordPress environment instance.
  423. */
  424. public function remove_rewrite_rules() {
  425. /* @var WP $wp */
  426. global $wp;
  427. // Remove query var.
  428. if ( false !== $this->query_var ) {
  429. $wp->remove_query_var( $this->query_var );
  430. }
  431. // Remove rewrite tags and permastructs.
  432. if ( false !== $this->rewrite ) {
  433. remove_rewrite_tag( "%$this->name%" );
  434. remove_permastruct( $this->name );
  435. }
  436. }
  437. /**
  438. * Registers the ajax callback for the meta box.
  439. *
  440. * @since 4.7.0
  441. */
  442. public function add_hooks() {
  443. add_filter( 'wp_ajax_add-' . $this->name, '_wp_ajax_add_hierarchical_term' );
  444. }
  445. /**
  446. * Removes the ajax callback for the meta box.
  447. *
  448. * @since 4.7.0
  449. */
  450. public function remove_hooks() {
  451. remove_filter( 'wp_ajax_add-' . $this->name, '_wp_ajax_add_hierarchical_term' );
  452. }
  453. /**
  454. * Gets the REST API controller for this taxonomy.
  455. *
  456. * Will only instantiate the controller class once per request.
  457. *
  458. * @since 5.5.0
  459. *
  460. * @return WP_REST_Controller|null The controller instance, or null if the taxonomy
  461. * is set not to show in rest.
  462. */
  463. public function get_rest_controller() {
  464. if ( ! $this->show_in_rest ) {
  465. return null;
  466. }
  467. $class = $this->rest_controller_class ? $this->rest_controller_class : WP_REST_Terms_Controller::class;
  468. if ( ! class_exists( $class ) ) {
  469. return null;
  470. }
  471. if ( ! is_subclass_of( $class, WP_REST_Controller::class ) ) {
  472. return null;
  473. }
  474. if ( ! $this->rest_controller ) {
  475. $this->rest_controller = new $class( $this->name );
  476. }
  477. if ( ! ( $this->rest_controller instanceof $class ) ) {
  478. return null;
  479. }
  480. return $this->rest_controller;
  481. }
  482. }