/htdocs/wp-includes/post.php

https://gitlab.com/VTTE/sitios-vtte · PHP · 1368 lines · 742 code · 112 blank · 514 comment · 82 complexity · 3f0c3e17a15f8c178d9d1cb139de1975 MD5 · raw file

  1. <?php
  2. /**
  3. * Core Post API
  4. *
  5. * @package WordPress
  6. * @subpackage Post
  7. */
  8. //
  9. // Post Type registration.
  10. //
  11. /**
  12. * Creates the initial post types when 'init' action is fired.
  13. *
  14. * See {@see 'init'}.
  15. *
  16. * @since 2.9.0
  17. */
  18. function create_initial_post_types() {
  19. register_post_type(
  20. 'post',
  21. array(
  22. 'labels' => array(
  23. 'name_admin_bar' => _x( 'Post', 'add new from admin bar' ),
  24. ),
  25. 'public' => true,
  26. '_builtin' => true, /* internal use only. don't use this when registering your own post type. */
  27. '_edit_link' => 'post.php?post=%d', /* internal use only. don't use this when registering your own post type. */
  28. 'capability_type' => 'post',
  29. 'map_meta_cap' => true,
  30. 'menu_position' => 5,
  31. 'menu_icon' => 'dashicons-admin-post',
  32. 'hierarchical' => false,
  33. 'rewrite' => false,
  34. 'query_var' => false,
  35. 'delete_with_user' => true,
  36. 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'trackbacks', 'custom-fields', 'comments', 'revisions', 'post-formats' ),
  37. 'show_in_rest' => true,
  38. 'rest_base' => 'posts',
  39. 'rest_controller_class' => 'WP_REST_Posts_Controller',
  40. )
  41. );
  42. register_post_type(
  43. 'page',
  44. array(
  45. 'labels' => array(
  46. 'name_admin_bar' => _x( 'Page', 'add new from admin bar' ),
  47. ),
  48. 'public' => true,
  49. 'publicly_queryable' => false,
  50. '_builtin' => true, /* internal use only. don't use this when registering your own post type. */
  51. '_edit_link' => 'post.php?post=%d', /* internal use only. don't use this when registering your own post type. */
  52. 'capability_type' => 'page',
  53. 'map_meta_cap' => true,
  54. 'menu_position' => 20,
  55. 'menu_icon' => 'dashicons-admin-page',
  56. 'hierarchical' => true,
  57. 'rewrite' => false,
  58. 'query_var' => false,
  59. 'delete_with_user' => true,
  60. 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'page-attributes', 'custom-fields', 'comments', 'revisions' ),
  61. 'show_in_rest' => true,
  62. 'rest_base' => 'pages',
  63. 'rest_controller_class' => 'WP_REST_Posts_Controller',
  64. )
  65. );
  66. register_post_type(
  67. 'attachment',
  68. array(
  69. 'labels' => array(
  70. 'name' => _x( 'Media', 'post type general name' ),
  71. 'name_admin_bar' => _x( 'Media', 'add new from admin bar' ),
  72. 'add_new' => _x( 'Add New', 'add new media' ),
  73. 'edit_item' => __( 'Edit Media' ),
  74. 'view_item' => __( 'View Attachment Page' ),
  75. 'attributes' => __( 'Attachment Attributes' ),
  76. ),
  77. 'public' => true,
  78. 'show_ui' => true,
  79. '_builtin' => true, /* internal use only. don't use this when registering your own post type. */
  80. '_edit_link' => 'post.php?post=%d', /* internal use only. don't use this when registering your own post type. */
  81. 'capability_type' => 'post',
  82. 'capabilities' => array(
  83. 'create_posts' => 'upload_files',
  84. ),
  85. 'map_meta_cap' => true,
  86. 'menu_icon' => 'dashicons-admin-media',
  87. 'hierarchical' => false,
  88. 'rewrite' => false,
  89. 'query_var' => false,
  90. 'show_in_nav_menus' => false,
  91. 'delete_with_user' => true,
  92. 'supports' => array( 'title', 'author', 'comments' ),
  93. 'show_in_rest' => true,
  94. 'rest_base' => 'media',
  95. 'rest_controller_class' => 'WP_REST_Attachments_Controller',
  96. )
  97. );
  98. add_post_type_support( 'attachment:audio', 'thumbnail' );
  99. add_post_type_support( 'attachment:video', 'thumbnail' );
  100. register_post_type(
  101. 'revision',
  102. array(
  103. 'labels' => array(
  104. 'name' => __( 'Revisions' ),
  105. 'singular_name' => __( 'Revision' ),
  106. ),
  107. 'public' => false,
  108. '_builtin' => true, /* internal use only. don't use this when registering your own post type. */
  109. '_edit_link' => 'revision.php?revision=%d', /* internal use only. don't use this when registering your own post type. */
  110. 'capability_type' => 'post',
  111. 'map_meta_cap' => true,
  112. 'hierarchical' => false,
  113. 'rewrite' => false,
  114. 'query_var' => false,
  115. 'can_export' => false,
  116. 'delete_with_user' => true,
  117. 'supports' => array( 'author' ),
  118. )
  119. );
  120. register_post_type(
  121. 'nav_menu_item',
  122. array(
  123. 'labels' => array(
  124. 'name' => __( 'Navigation Menu Items' ),
  125. 'singular_name' => __( 'Navigation Menu Item' ),
  126. ),
  127. 'public' => false,
  128. '_builtin' => true, /* internal use only. don't use this when registering your own post type. */
  129. 'hierarchical' => false,
  130. 'rewrite' => false,
  131. 'delete_with_user' => false,
  132. 'query_var' => false,
  133. )
  134. );
  135. register_post_type(
  136. 'custom_css',
  137. array(
  138. 'labels' => array(
  139. 'name' => __( 'Custom CSS' ),
  140. 'singular_name' => __( 'Custom CSS' ),
  141. ),
  142. 'public' => false,
  143. 'hierarchical' => false,
  144. 'rewrite' => false,
  145. 'query_var' => false,
  146. 'delete_with_user' => false,
  147. 'can_export' => true,
  148. '_builtin' => true, /* internal use only. don't use this when registering your own post type. */
  149. 'supports' => array( 'title', 'revisions' ),
  150. 'capabilities' => array(
  151. 'delete_posts' => 'edit_theme_options',
  152. 'delete_post' => 'edit_theme_options',
  153. 'delete_published_posts' => 'edit_theme_options',
  154. 'delete_private_posts' => 'edit_theme_options',
  155. 'delete_others_posts' => 'edit_theme_options',
  156. 'edit_post' => 'edit_css',
  157. 'edit_posts' => 'edit_css',
  158. 'edit_others_posts' => 'edit_css',
  159. 'edit_published_posts' => 'edit_css',
  160. 'read_post' => 'read',
  161. 'read_private_posts' => 'read',
  162. 'publish_posts' => 'edit_theme_options',
  163. ),
  164. )
  165. );
  166. register_post_type(
  167. 'customize_changeset',
  168. array(
  169. 'labels' => array(
  170. 'name' => _x( 'Changesets', 'post type general name' ),
  171. 'singular_name' => _x( 'Changeset', 'post type singular name' ),
  172. 'menu_name' => _x( 'Changesets', 'admin menu' ),
  173. 'name_admin_bar' => _x( 'Changeset', 'add new on admin bar' ),
  174. 'add_new' => _x( 'Add New', 'Customize Changeset' ),
  175. 'add_new_item' => __( 'Add New Changeset' ),
  176. 'new_item' => __( 'New Changeset' ),
  177. 'edit_item' => __( 'Edit Changeset' ),
  178. 'view_item' => __( 'View Changeset' ),
  179. 'all_items' => __( 'All Changesets' ),
  180. 'search_items' => __( 'Search Changesets' ),
  181. 'not_found' => __( 'No changesets found.' ),
  182. 'not_found_in_trash' => __( 'No changesets found in Trash.' ),
  183. ),
  184. 'public' => false,
  185. '_builtin' => true, /* internal use only. don't use this when registering your own post type. */
  186. 'map_meta_cap' => true,
  187. 'hierarchical' => false,
  188. 'rewrite' => false,
  189. 'query_var' => false,
  190. 'can_export' => false,
  191. 'delete_with_user' => false,
  192. 'supports' => array( 'title', 'author' ),
  193. 'capability_type' => 'customize_changeset',
  194. 'capabilities' => array(
  195. 'create_posts' => 'customize',
  196. 'delete_others_posts' => 'customize',
  197. 'delete_post' => 'customize',
  198. 'delete_posts' => 'customize',
  199. 'delete_private_posts' => 'customize',
  200. 'delete_published_posts' => 'customize',
  201. 'edit_others_posts' => 'customize',
  202. 'edit_post' => 'customize',
  203. 'edit_posts' => 'customize',
  204. 'edit_private_posts' => 'customize',
  205. 'edit_published_posts' => 'do_not_allow',
  206. 'publish_posts' => 'customize',
  207. 'read' => 'read',
  208. 'read_post' => 'customize',
  209. 'read_private_posts' => 'customize',
  210. ),
  211. )
  212. );
  213. register_post_type(
  214. 'oembed_cache',
  215. array(
  216. 'labels' => array(
  217. 'name' => __( 'oEmbed Responses' ),
  218. 'singular_name' => __( 'oEmbed Response' ),
  219. ),
  220. 'public' => false,
  221. 'hierarchical' => false,
  222. 'rewrite' => false,
  223. 'query_var' => false,
  224. 'delete_with_user' => false,
  225. 'can_export' => false,
  226. '_builtin' => true, /* internal use only. don't use this when registering your own post type. */
  227. 'supports' => array(),
  228. )
  229. );
  230. register_post_type(
  231. 'user_request',
  232. array(
  233. 'labels' => array(
  234. 'name' => __( 'User Requests' ),
  235. 'singular_name' => __( 'User Request' ),
  236. ),
  237. 'public' => false,
  238. '_builtin' => true, /* internal use only. don't use this when registering your own post type. */
  239. 'hierarchical' => false,
  240. 'rewrite' => false,
  241. 'query_var' => false,
  242. 'can_export' => false,
  243. 'delete_with_user' => false,
  244. 'supports' => array(),
  245. )
  246. );
  247. register_post_type(
  248. 'wp_block',
  249. array(
  250. 'labels' => array(
  251. 'name' => _x( 'Blocks', 'post type general name' ),
  252. 'singular_name' => _x( 'Block', 'post type singular name' ),
  253. 'menu_name' => _x( 'Blocks', 'admin menu' ),
  254. 'name_admin_bar' => _x( 'Block', 'add new on admin bar' ),
  255. 'add_new' => _x( 'Add New', 'Block' ),
  256. 'add_new_item' => __( 'Add New Block' ),
  257. 'new_item' => __( 'New Block' ),
  258. 'edit_item' => __( 'Edit Block' ),
  259. 'view_item' => __( 'View Block' ),
  260. 'all_items' => __( 'All Blocks' ),
  261. 'search_items' => __( 'Search Blocks' ),
  262. 'not_found' => __( 'No blocks found.' ),
  263. 'not_found_in_trash' => __( 'No blocks found in Trash.' ),
  264. 'filter_items_list' => __( 'Filter blocks list' ),
  265. 'items_list_navigation' => __( 'Blocks list navigation' ),
  266. 'items_list' => __( 'Blocks list' ),
  267. 'item_published' => __( 'Block published.' ),
  268. 'item_published_privately' => __( 'Block published privately.' ),
  269. 'item_reverted_to_draft' => __( 'Block reverted to draft.' ),
  270. 'item_scheduled' => __( 'Block scheduled.' ),
  271. 'item_updated' => __( 'Block updated.' ),
  272. ),
  273. 'public' => false,
  274. '_builtin' => true, /* internal use only. don't use this when registering your own post type. */
  275. 'show_ui' => true,
  276. 'show_in_menu' => false,
  277. 'rewrite' => false,
  278. 'show_in_rest' => true,
  279. 'rest_base' => 'blocks',
  280. 'rest_controller_class' => 'WP_REST_Blocks_Controller',
  281. 'capability_type' => 'block',
  282. 'capabilities' => array(
  283. // You need to be able to edit posts, in order to read blocks in their raw form.
  284. 'read' => 'edit_posts',
  285. // You need to be able to publish posts, in order to create blocks.
  286. 'create_posts' => 'publish_posts',
  287. 'edit_posts' => 'edit_posts',
  288. 'edit_published_posts' => 'edit_published_posts',
  289. 'delete_published_posts' => 'delete_published_posts',
  290. 'edit_others_posts' => 'edit_others_posts',
  291. 'delete_others_posts' => 'delete_others_posts',
  292. ),
  293. 'map_meta_cap' => true,
  294. 'supports' => array(
  295. 'title',
  296. 'editor',
  297. ),
  298. )
  299. );
  300. register_post_status(
  301. 'publish',
  302. array(
  303. 'label' => _x( 'Published', 'post status' ),
  304. 'public' => true,
  305. '_builtin' => true, /* internal use only. */
  306. /* translators: %s: Number of published posts. */
  307. 'label_count' => _n_noop(
  308. 'Published <span class="count">(%s)</span>',
  309. 'Published <span class="count">(%s)</span>'
  310. ),
  311. )
  312. );
  313. register_post_status(
  314. 'future',
  315. array(
  316. 'label' => _x( 'Scheduled', 'post status' ),
  317. 'protected' => true,
  318. '_builtin' => true, /* internal use only. */
  319. /* translators: %s: Number of scheduled posts. */
  320. 'label_count' => _n_noop(
  321. 'Scheduled <span class="count">(%s)</span>',
  322. 'Scheduled <span class="count">(%s)</span>'
  323. ),
  324. )
  325. );
  326. register_post_status(
  327. 'draft',
  328. array(
  329. 'label' => _x( 'Draft', 'post status' ),
  330. 'protected' => true,
  331. '_builtin' => true, /* internal use only. */
  332. /* translators: %s: Number of draft posts. */
  333. 'label_count' => _n_noop(
  334. 'Draft <span class="count">(%s)</span>',
  335. 'Drafts <span class="count">(%s)</span>'
  336. ),
  337. 'date_floating' => true,
  338. )
  339. );
  340. register_post_status(
  341. 'pending',
  342. array(
  343. 'label' => _x( 'Pending', 'post status' ),
  344. 'protected' => true,
  345. '_builtin' => true, /* internal use only. */
  346. /* translators: %s: Number of pending posts. */
  347. 'label_count' => _n_noop(
  348. 'Pending <span class="count">(%s)</span>',
  349. 'Pending <span class="count">(%s)</span>'
  350. ),
  351. 'date_floating' => true,
  352. )
  353. );
  354. register_post_status(
  355. 'private',
  356. array(
  357. 'label' => _x( 'Private', 'post status' ),
  358. 'private' => true,
  359. '_builtin' => true, /* internal use only. */
  360. /* translators: %s: Number of private posts. */
  361. 'label_count' => _n_noop(
  362. 'Private <span class="count">(%s)</span>',
  363. 'Private <span class="count">(%s)</span>'
  364. ),
  365. )
  366. );
  367. register_post_status(
  368. 'trash',
  369. array(
  370. 'label' => _x( 'Trash', 'post status' ),
  371. 'internal' => true,
  372. '_builtin' => true, /* internal use only. */
  373. /* translators: %s: Number of trashed posts. */
  374. 'label_count' => _n_noop(
  375. 'Trash <span class="count">(%s)</span>',
  376. 'Trash <span class="count">(%s)</span>'
  377. ),
  378. 'show_in_admin_status_list' => true,
  379. )
  380. );
  381. register_post_status(
  382. 'auto-draft',
  383. array(
  384. 'label' => 'auto-draft',
  385. 'internal' => true,
  386. '_builtin' => true, /* internal use only. */
  387. 'date_floating' => true,
  388. )
  389. );
  390. register_post_status(
  391. 'inherit',
  392. array(
  393. 'label' => 'inherit',
  394. 'internal' => true,
  395. '_builtin' => true, /* internal use only. */
  396. 'exclude_from_search' => false,
  397. )
  398. );
  399. register_post_status(
  400. 'request-pending',
  401. array(
  402. 'label' => _x( 'Pending', 'request status' ),
  403. 'internal' => true,
  404. '_builtin' => true, /* internal use only. */
  405. /* translators: %s: Number of pending requests. */
  406. 'label_count' => _n_noop(
  407. 'Pending <span class="count">(%s)</span>',
  408. 'Pending <span class="count">(%s)</span>'
  409. ),
  410. 'exclude_from_search' => false,
  411. )
  412. );
  413. register_post_status(
  414. 'request-confirmed',
  415. array(
  416. 'label' => _x( 'Confirmed', 'request status' ),
  417. 'internal' => true,
  418. '_builtin' => true, /* internal use only. */
  419. /* translators: %s: Number of confirmed requests. */
  420. 'label_count' => _n_noop(
  421. 'Confirmed <span class="count">(%s)</span>',
  422. 'Confirmed <span class="count">(%s)</span>'
  423. ),
  424. 'exclude_from_search' => false,
  425. )
  426. );
  427. register_post_status(
  428. 'request-failed',
  429. array(
  430. 'label' => _x( 'Failed', 'request status' ),
  431. 'internal' => true,
  432. '_builtin' => true, /* internal use only. */
  433. /* translators: %s: Number of failed requests. */
  434. 'label_count' => _n_noop(
  435. 'Failed <span class="count">(%s)</span>',
  436. 'Failed <span class="count">(%s)</span>'
  437. ),
  438. 'exclude_from_search' => false,
  439. )
  440. );
  441. register_post_status(
  442. 'request-completed',
  443. array(
  444. 'label' => _x( 'Completed', 'request status' ),
  445. 'internal' => true,
  446. '_builtin' => true, /* internal use only. */
  447. /* translators: %s: Number of completed requests. */
  448. 'label_count' => _n_noop(
  449. 'Completed <span class="count">(%s)</span>',
  450. 'Completed <span class="count">(%s)</span>'
  451. ),
  452. 'exclude_from_search' => false,
  453. )
  454. );
  455. }
  456. /**
  457. * Retrieve attached file path based on attachment ID.
  458. *
  459. * By default the path will go through the 'get_attached_file' filter, but
  460. * passing a true to the $unfiltered argument of get_attached_file() will
  461. * return the file path unfiltered.
  462. *
  463. * The function works by getting the single post meta name, named
  464. * '_wp_attached_file' and returning it. This is a convenience function to
  465. * prevent looking up the meta name and provide a mechanism for sending the
  466. * attached filename through a filter.
  467. *
  468. * @since 2.0.0
  469. *
  470. * @param int $attachment_id Attachment ID.
  471. * @param bool $unfiltered Optional. Whether to apply filters. Default false.
  472. * @return string|false The file path to where the attached file should be, false otherwise.
  473. */
  474. function get_attached_file( $attachment_id, $unfiltered = false ) {
  475. $file = get_post_meta( $attachment_id, '_wp_attached_file', true );
  476. // If the file is relative, prepend upload dir.
  477. if ( $file && 0 !== strpos( $file, '/' ) && ! preg_match( '|^.:\\\|', $file ) ) {
  478. $uploads = wp_get_upload_dir();
  479. if ( false === $uploads['error'] ) {
  480. $file = $uploads['basedir'] . "/$file";
  481. }
  482. }
  483. if ( $unfiltered ) {
  484. return $file;
  485. }
  486. /**
  487. * Filters the attached file based on the given ID.
  488. *
  489. * @since 2.1.0
  490. *
  491. * @param string $file Path to attached file.
  492. * @param int $attachment_id Attachment ID.
  493. */
  494. return apply_filters( 'get_attached_file', $file, $attachment_id );
  495. }
  496. /**
  497. * Update attachment file path based on attachment ID.
  498. *
  499. * Used to update the file path of the attachment, which uses post meta name
  500. * '_wp_attached_file' to store the path of the attachment.
  501. *
  502. * @since 2.1.0
  503. *
  504. * @param int $attachment_id Attachment ID.
  505. * @param string $file File path for the attachment.
  506. * @return bool True on success, false on failure.
  507. */
  508. function update_attached_file( $attachment_id, $file ) {
  509. if ( ! get_post( $attachment_id ) ) {
  510. return false;
  511. }
  512. /**
  513. * Filters the path to the attached file to update.
  514. *
  515. * @since 2.1.0
  516. *
  517. * @param string $file Path to the attached file to update.
  518. * @param int $attachment_id Attachment ID.
  519. */
  520. $file = apply_filters( 'update_attached_file', $file, $attachment_id );
  521. $file = _wp_relative_upload_path( $file );
  522. if ( $file ) {
  523. return update_post_meta( $attachment_id, '_wp_attached_file', $file );
  524. } else {
  525. return delete_post_meta( $attachment_id, '_wp_attached_file' );
  526. }
  527. }
  528. /**
  529. * Return relative path to an uploaded file.
  530. *
  531. * The path is relative to the current upload dir.
  532. *
  533. * @since 2.9.0
  534. * @access private
  535. *
  536. * @param string $path Full path to the file.
  537. * @return string Relative path on success, unchanged path on failure.
  538. */
  539. function _wp_relative_upload_path( $path ) {
  540. $new_path = $path;
  541. $uploads = wp_get_upload_dir();
  542. if ( 0 === strpos( $new_path, $uploads['basedir'] ) ) {
  543. $new_path = str_replace( $uploads['basedir'], '', $new_path );
  544. $new_path = ltrim( $new_path, '/' );
  545. }
  546. /**
  547. * Filters the relative path to an uploaded file.
  548. *
  549. * @since 2.9.0
  550. *
  551. * @param string $new_path Relative path to the file.
  552. * @param string $path Full path to the file.
  553. */
  554. return apply_filters( '_wp_relative_upload_path', $new_path, $path );
  555. }
  556. /**
  557. * Retrieve all children of the post parent ID.
  558. *
  559. * Normally, without any enhancements, the children would apply to pages. In the
  560. * context of the inner workings of WordPress, pages, posts, and attachments
  561. * share the same table, so therefore the functionality could apply to any one
  562. * of them. It is then noted that while this function does not work on posts, it
  563. * does not mean that it won't work on posts. It is recommended that you know
  564. * what context you wish to retrieve the children of.
  565. *
  566. * Attachments may also be made the child of a post, so if that is an accurate
  567. * statement (which needs to be verified), it would then be possible to get
  568. * all of the attachments for a post. Attachments have since changed since
  569. * version 2.5, so this is most likely inaccurate, but serves generally as an
  570. * example of what is possible.
  571. *
  572. * The arguments listed as defaults are for this function and also of the
  573. * get_posts() function. The arguments are combined with the get_children defaults
  574. * and are then passed to the get_posts() function, which accepts additional arguments.
  575. * You can replace the defaults in this function, listed below and the additional
  576. * arguments listed in the get_posts() function.
  577. *
  578. * The 'post_parent' is the most important argument and important attention
  579. * needs to be paid to the $args parameter. If you pass either an object or an
  580. * integer (number), then just the 'post_parent' is grabbed and everything else
  581. * is lost. If you don't specify any arguments, then it is assumed that you are
  582. * in The Loop and the post parent will be grabbed for from the current post.
  583. *
  584. * The 'post_parent' argument is the ID to get the children. The 'numberposts'
  585. * is the amount of posts to retrieve that has a default of '-1', which is
  586. * used to get all of the posts. Giving a number higher than 0 will only
  587. * retrieve that amount of posts.
  588. *
  589. * The 'post_type' and 'post_status' arguments can be used to choose what
  590. * criteria of posts to retrieve. The 'post_type' can be anything, but WordPress
  591. * post types are 'post', 'pages', and 'attachments'. The 'post_status'
  592. * argument will accept any post status within the write administration panels.
  593. *
  594. * @since 2.0.0
  595. *
  596. * @see get_posts()
  597. * @todo Check validity of description.
  598. *
  599. * @global WP_Post $post Global post object.
  600. *
  601. * @param mixed $args Optional. User defined arguments for replacing the defaults. Default empty.
  602. * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to
  603. * a WP_Post object, an associative array, or a numeric array, respectively. Default OBJECT.
  604. * @return WP_Post[]|int[] Array of post objects or post IDs.
  605. */
  606. function get_children( $args = '', $output = OBJECT ) {
  607. $kids = array();
  608. if ( empty( $args ) ) {
  609. if ( isset( $GLOBALS['post'] ) ) {
  610. $args = array( 'post_parent' => (int) $GLOBALS['post']->post_parent );
  611. } else {
  612. return $kids;
  613. }
  614. } elseif ( is_object( $args ) ) {
  615. $args = array( 'post_parent' => (int) $args->post_parent );
  616. } elseif ( is_numeric( $args ) ) {
  617. $args = array( 'post_parent' => (int) $args );
  618. }
  619. $defaults = array(
  620. 'numberposts' => -1,
  621. 'post_type' => 'any',
  622. 'post_status' => 'any',
  623. 'post_parent' => 0,
  624. );
  625. $parsed_args = wp_parse_args( $args, $defaults );
  626. $children = get_posts( $parsed_args );
  627. if ( ! $children ) {
  628. return $kids;
  629. }
  630. if ( ! empty( $parsed_args['fields'] ) ) {
  631. return $children;
  632. }
  633. update_post_cache( $children );
  634. foreach ( $children as $key => $child ) {
  635. $kids[ $child->ID ] = $children[ $key ];
  636. }
  637. if ( OBJECT == $output ) {
  638. return $kids;
  639. } elseif ( ARRAY_A == $output ) {
  640. $weeuns = array();
  641. foreach ( (array) $kids as $kid ) {
  642. $weeuns[ $kid->ID ] = get_object_vars( $kids[ $kid->ID ] );
  643. }
  644. return $weeuns;
  645. } elseif ( ARRAY_N == $output ) {
  646. $babes = array();
  647. foreach ( (array) $kids as $kid ) {
  648. $babes[ $kid->ID ] = array_values( get_object_vars( $kids[ $kid->ID ] ) );
  649. }
  650. return $babes;
  651. } else {
  652. return $kids;
  653. }
  654. }
  655. /**
  656. * Get extended entry info (<!--more-->).
  657. *
  658. * There should not be any space after the second dash and before the word
  659. * 'more'. There can be text or space(s) after the word 'more', but won't be
  660. * referenced.
  661. *
  662. * The returned array has 'main', 'extended', and 'more_text' keys. Main has the text before
  663. * the `<!--more-->`. The 'extended' key has the content after the
  664. * `<!--more-->` comment. The 'more_text' key has the custom "Read More" text.
  665. *
  666. * @since 1.0.0
  667. *
  668. * @param string $post Post content.
  669. * @return string[] {
  670. * Extended entry info.
  671. *
  672. * @type string $main Content before the more tag.
  673. * @type string $extended Content after the more tag.
  674. * @type string $more_text Custom read more text, or empty string.
  675. * }
  676. */
  677. function get_extended( $post ) {
  678. // Match the new style more links.
  679. if ( preg_match( '/<!--more(.*?)?-->/', $post, $matches ) ) {
  680. list($main, $extended) = explode( $matches[0], $post, 2 );
  681. $more_text = $matches[1];
  682. } else {
  683. $main = $post;
  684. $extended = '';
  685. $more_text = '';
  686. }
  687. // Leading and trailing whitespace.
  688. $main = preg_replace( '/^[\s]*(.*)[\s]*$/', '\\1', $main );
  689. $extended = preg_replace( '/^[\s]*(.*)[\s]*$/', '\\1', $extended );
  690. $more_text = preg_replace( '/^[\s]*(.*)[\s]*$/', '\\1', $more_text );
  691. return array(
  692. 'main' => $main,
  693. 'extended' => $extended,
  694. 'more_text' => $more_text,
  695. );
  696. }
  697. /**
  698. * Retrieves post data given a post ID or post object.
  699. *
  700. * See sanitize_post() for optional $filter values. Also, the parameter
  701. * `$post`, must be given as a variable, since it is passed by reference.
  702. *
  703. * @since 1.5.1
  704. *
  705. * @global WP_Post $post Global post object.
  706. *
  707. * @param int|WP_Post|null $post Optional. Post ID or post object. Defaults to global $post.
  708. * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to
  709. * a WP_Post object, an associative array, or a numeric array, respectively. Default OBJECT.
  710. * @param string $filter Optional. Type of filter to apply. Accepts 'raw', 'edit', 'db',
  711. * or 'display'. Default 'raw'.
  712. * @return WP_Post|array|null Type corresponding to $output on success or null on failure.
  713. * When $output is OBJECT, a `WP_Post` instance is returned.
  714. */
  715. function get_post( $post = null, $output = OBJECT, $filter = 'raw' ) {
  716. if ( empty( $post ) && isset( $GLOBALS['post'] ) ) {
  717. $post = $GLOBALS['post'];
  718. }
  719. if ( $post instanceof WP_Post ) {
  720. $_post = $post;
  721. } elseif ( is_object( $post ) ) {
  722. if ( empty( $post->filter ) ) {
  723. $_post = sanitize_post( $post, 'raw' );
  724. $_post = new WP_Post( $_post );
  725. } elseif ( 'raw' == $post->filter ) {
  726. $_post = new WP_Post( $post );
  727. } else {
  728. $_post = WP_Post::get_instance( $post->ID );
  729. }
  730. } else {
  731. $_post = WP_Post::get_instance( $post );
  732. }
  733. if ( ! $_post ) {
  734. return null;
  735. }
  736. $_post = $_post->filter( $filter );
  737. if ( ARRAY_A == $output ) {
  738. return $_post->to_array();
  739. } elseif ( ARRAY_N == $output ) {
  740. return array_values( $_post->to_array() );
  741. }
  742. return $_post;
  743. }
  744. /**
  745. * Retrieve ancestors of a post.
  746. *
  747. * @since 2.5.0
  748. *
  749. * @param int|WP_Post $post Post ID or post object.
  750. * @return int[] Ancestor IDs or empty array if none are found.
  751. */
  752. function get_post_ancestors( $post ) {
  753. $post = get_post( $post );
  754. if ( ! $post || empty( $post->post_parent ) || $post->post_parent == $post->ID ) {
  755. return array();
  756. }
  757. $ancestors = array();
  758. $id = $post->post_parent;
  759. $ancestors[] = $id;
  760. while ( $ancestor = get_post( $id ) ) {
  761. // Loop detection: If the ancestor has been seen before, break.
  762. if ( empty( $ancestor->post_parent ) || ( $ancestor->post_parent == $post->ID ) || in_array( $ancestor->post_parent, $ancestors ) ) {
  763. break;
  764. }
  765. $id = $ancestor->post_parent;
  766. $ancestors[] = $id;
  767. }
  768. return $ancestors;
  769. }
  770. /**
  771. * Retrieve data from a post field based on Post ID.
  772. *
  773. * Examples of the post field will be, 'post_type', 'post_status', 'post_content',
  774. * etc and based off of the post object property or key names.
  775. *
  776. * The context values are based off of the taxonomy filter functions and
  777. * supported values are found within those functions.
  778. *
  779. * @since 2.3.0
  780. * @since 4.5.0 The `$post` parameter was made optional.
  781. *
  782. * @see sanitize_post_field()
  783. *
  784. * @param string $field Post field name.
  785. * @param int|WP_Post $post Optional. Post ID or post object. Defaults to global $post.
  786. * @param string $context Optional. How to filter the field. Accepts 'raw', 'edit', 'db',
  787. * or 'display'. Default 'display'.
  788. * @return string The value of the post field on success, empty string on failure.
  789. */
  790. function get_post_field( $field, $post = null, $context = 'display' ) {
  791. $post = get_post( $post );
  792. if ( ! $post ) {
  793. return '';
  794. }
  795. if ( ! isset( $post->$field ) ) {
  796. return '';
  797. }
  798. return sanitize_post_field( $field, $post->$field, $post->ID, $context );
  799. }
  800. /**
  801. * Retrieve the mime type of an attachment based on the ID.
  802. *
  803. * This function can be used with any post type, but it makes more sense with
  804. * attachments.
  805. *
  806. * @since 2.0.0
  807. *
  808. * @param int|WP_Post $post Optional. Post ID or post object. Defaults to global $post.
  809. * @return string|false The mime type on success, false on failure.
  810. */
  811. function get_post_mime_type( $post = null ) {
  812. $post = get_post( $post );
  813. if ( is_object( $post ) ) {
  814. return $post->post_mime_type;
  815. }
  816. return false;
  817. }
  818. /**
  819. * Retrieve the post status based on the post ID.
  820. *
  821. * If the post ID is of an attachment, then the parent post status will be given
  822. * instead.
  823. *
  824. * @since 2.0.0
  825. *
  826. * @param int|WP_Post $post Optional. Post ID or post object. Defaults to global $post..
  827. * @return string|false Post status on success, false on failure.
  828. */
  829. function get_post_status( $post = null ) {
  830. $post = get_post( $post );
  831. if ( ! is_object( $post ) ) {
  832. return false;
  833. }
  834. if ( 'attachment' == $post->post_type ) {
  835. if ( 'private' == $post->post_status ) {
  836. return 'private';
  837. }
  838. // Unattached attachments are assumed to be published.
  839. if ( ( 'inherit' == $post->post_status ) && ( 0 == $post->post_parent ) ) {
  840. return 'publish';
  841. }
  842. // Inherit status from the parent.
  843. if ( $post->post_parent && ( $post->ID != $post->post_parent ) ) {
  844. $parent_post_status = get_post_status( $post->post_parent );
  845. if ( 'trash' == $parent_post_status ) {
  846. return get_post_meta( $post->post_parent, '_wp_trash_meta_status', true );
  847. } else {
  848. return $parent_post_status;
  849. }
  850. }
  851. }
  852. /**
  853. * Filters the post status.
  854. *
  855. * @since 4.4.0
  856. *
  857. * @param string $post_status The post status.
  858. * @param WP_Post $post The post object.
  859. */
  860. return apply_filters( 'get_post_status', $post->post_status, $post );
  861. }
  862. /**
  863. * Retrieve all of the WordPress supported post statuses.
  864. *
  865. * Posts have a limited set of valid status values, this provides the
  866. * post_status values and descriptions.
  867. *
  868. * @since 2.5.0
  869. *
  870. * @return string[] Array of post status labels keyed by their status.
  871. */
  872. function get_post_statuses() {
  873. $status = array(
  874. 'draft' => __( 'Draft' ),
  875. 'pending' => __( 'Pending Review' ),
  876. 'private' => __( 'Private' ),
  877. 'publish' => __( 'Published' ),
  878. );
  879. return $status;
  880. }
  881. /**
  882. * Retrieve all of the WordPress support page statuses.
  883. *
  884. * Pages have a limited set of valid status values, this provides the
  885. * post_status values and descriptions.
  886. *
  887. * @since 2.5.0
  888. *
  889. * @return string[] Array of page status labels keyed by their status.
  890. */
  891. function get_page_statuses() {
  892. $status = array(
  893. 'draft' => __( 'Draft' ),
  894. 'private' => __( 'Private' ),
  895. 'publish' => __( 'Published' ),
  896. );
  897. return $status;
  898. }
  899. /**
  900. * Return statuses for privacy requests.
  901. *
  902. * @since 4.9.6
  903. * @access private
  904. *
  905. * @return array
  906. */
  907. function _wp_privacy_statuses() {
  908. return array(
  909. 'request-pending' => __( 'Pending' ), // Pending confirmation from user.
  910. 'request-confirmed' => __( 'Confirmed' ), // User has confirmed the action.
  911. 'request-failed' => __( 'Failed' ), // User failed to confirm the action.
  912. 'request-completed' => __( 'Completed' ), // Admin has handled the request.
  913. );
  914. }
  915. /**
  916. * Register a post status. Do not use before init.
  917. *
  918. * A simple function for creating or modifying a post status based on the
  919. * parameters given. The function will accept an array (second optional
  920. * parameter), along with a string for the post status name.
  921. *
  922. * Arguments prefixed with an _underscore shouldn't be used by plugins and themes.
  923. *
  924. * @since 3.0.0
  925. * @global array $wp_post_statuses Inserts new post status object into the list
  926. *
  927. * @param string $post_status Name of the post status.
  928. * @param array|string $args {
  929. * Optional. Array or string of post status arguments.
  930. *
  931. * @type bool|string $label A descriptive name for the post status marked
  932. * for translation. Defaults to value of $post_status.
  933. * @type bool|array $label_count Descriptive text to use for nooped plurals.
  934. * Default array of $label, twice.
  935. * @type bool $exclude_from_search Whether to exclude posts with this post status
  936. * from search results. Default is value of $internal.
  937. * @type bool $_builtin Whether the status is built-in. Core-use only.
  938. * Default false.
  939. * @type bool $public Whether posts of this status should be shown
  940. * in the front end of the site. Default false.
  941. * @type bool $internal Whether the status is for internal use only.
  942. * Default false.
  943. * @type bool $protected Whether posts with this status should be protected.
  944. * Default false.
  945. * @type bool $private Whether posts with this status should be private.
  946. * Default false.
  947. * @type bool $publicly_queryable Whether posts with this status should be publicly-
  948. * queryable. Default is value of $public.
  949. * @type bool $show_in_admin_all_list Whether to include posts in the edit listing for
  950. * their post type. Default is the opposite value
  951. * of $internal.
  952. * @type bool $show_in_admin_status_list Show in the list of statuses with post counts at
  953. * the top of the edit listings,
  954. * e.g. All (12) | Published (9) | My Custom Status (2)
  955. * Default is the opposite value of $internal.
  956. * @type bool $date_floating Whether the post has a floating creation date.
  957. * Default to false.
  958. * }
  959. * @return object
  960. */
  961. function register_post_status( $post_status, $args = array() ) {
  962. global $wp_post_statuses;
  963. if ( ! is_array( $wp_post_statuses ) ) {
  964. $wp_post_statuses = array();
  965. }
  966. // Args prefixed with an underscore are reserved for internal use.
  967. $defaults = array(
  968. 'label' => false,
  969. 'label_count' => false,
  970. 'exclude_from_search' => null,
  971. '_builtin' => false,
  972. 'public' => null,
  973. 'internal' => null,
  974. 'protected' => null,
  975. 'private' => null,
  976. 'publicly_queryable' => null,
  977. 'show_in_admin_status_list' => null,
  978. 'show_in_admin_all_list' => null,
  979. 'date_floating' => null,
  980. );
  981. $args = wp_parse_args( $args, $defaults );
  982. $args = (object) $args;
  983. $post_status = sanitize_key( $post_status );
  984. $args->name = $post_status;
  985. // Set various defaults.
  986. if ( null === $args->public && null === $args->internal && null === $args->protected && null === $args->private ) {
  987. $args->internal = true;
  988. }
  989. if ( null === $args->public ) {
  990. $args->public = false;
  991. }
  992. if ( null === $args->private ) {
  993. $args->private = false;
  994. }
  995. if ( null === $args->protected ) {
  996. $args->protected = false;
  997. }
  998. if ( null === $args->internal ) {
  999. $args->internal = false;
  1000. }
  1001. if ( null === $args->publicly_queryable ) {
  1002. $args->publicly_queryable = $args->public;
  1003. }
  1004. if ( null === $args->exclude_from_search ) {
  1005. $args->exclude_from_search = $args->internal;
  1006. }
  1007. if ( null === $args->show_in_admin_all_list ) {
  1008. $args->show_in_admin_all_list = ! $args->internal;
  1009. }
  1010. if ( null === $args->show_in_admin_status_list ) {
  1011. $args->show_in_admin_status_list = ! $args->internal;
  1012. }
  1013. if ( null === $args->date_floating ) {
  1014. $args->date_floating = false;
  1015. }
  1016. if ( false === $args->label ) {
  1017. $args->label = $post_status;
  1018. }
  1019. if ( false === $args->label_count ) {
  1020. // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralSingle,WordPress.WP.I18n.NonSingularStringLiteralPlural
  1021. $args->label_count = _n_noop( $args->label, $args->label );
  1022. }
  1023. $wp_post_statuses[ $post_status ] = $args;
  1024. return $args;
  1025. }
  1026. /**
  1027. * Retrieve a post status object by name.
  1028. *
  1029. * @since 3.0.0
  1030. *
  1031. * @global array $wp_post_statuses List of post statuses.
  1032. *
  1033. * @see register_post_status()
  1034. *
  1035. * @param string $post_status The name of a registered post status.
  1036. * @return object|null A post status object.
  1037. */
  1038. function get_post_status_object( $post_status ) {
  1039. global $wp_post_statuses;
  1040. if ( empty( $wp_post_statuses[ $post_status ] ) ) {
  1041. return null;
  1042. }
  1043. return $wp_post_statuses[ $post_status ];
  1044. }
  1045. /**
  1046. * Get a list of post statuses.
  1047. *
  1048. * @since 3.0.0
  1049. *
  1050. * @global array $wp_post_statuses List of post statuses.
  1051. *
  1052. * @see register_post_status()
  1053. *
  1054. * @param array|string $args Optional. Array or string of post status arguments to compare against
  1055. * properties of the global `$wp_post_statuses objects`. Default empty array.
  1056. * @param string $output Optional. The type of output to return, either 'names' or 'objects'. Default 'names'.
  1057. * @param string $operator Optional. The logical operation to perform. 'or' means only one element
  1058. * from the array needs to match; 'and' means all elements must match.
  1059. * Default 'and'.
  1060. * @return array A list of post status names or objects.
  1061. */
  1062. function get_post_stati( $args = array(), $output = 'names', $operator = 'and' ) {
  1063. global $wp_post_statuses;
  1064. $field = ( 'names' == $output ) ? 'name' : false;
  1065. return wp_filter_object_list( $wp_post_statuses, $args, $operator, $field );
  1066. }
  1067. /**
  1068. * Whether the post type is hierarchical.
  1069. *
  1070. * A false return value might also mean that the post type does not exist.
  1071. *
  1072. * @since 3.0.0
  1073. *
  1074. * @see get_post_type_object()
  1075. *
  1076. * @param string $post_type Post type name
  1077. * @return bool Whether post type is hierarchical.
  1078. */
  1079. function is_post_type_hierarchical( $post_type ) {
  1080. if ( ! post_type_exists( $post_type ) ) {
  1081. return false;
  1082. }
  1083. $post_type = get_post_type_object( $post_type );
  1084. return $post_type->hierarchical;
  1085. }
  1086. /**
  1087. * Determines whether a post type is registered.
  1088. *
  1089. * For more information on this and similar theme functions, check out
  1090. * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
  1091. * Conditional Tags} article in the Theme Developer Handbook.
  1092. *
  1093. * @since 3.0.0
  1094. *
  1095. * @see get_post_type_object()
  1096. *
  1097. * @param string $post_type Post type name.
  1098. * @return bool Whether post type is registered.
  1099. */
  1100. function post_type_exists( $post_type ) {
  1101. return (bool) get_post_type_object( $post_type );
  1102. }
  1103. /**
  1104. * Retrieves the post type of the current post or of a given post.
  1105. *
  1106. * @since 2.1.0
  1107. *
  1108. * @param int|WP_Post|null $post Optional. Post ID or post object. Default is global $post.
  1109. * @return string|false Post type on success, false on failure.
  1110. */
  1111. function get_post_type( $post = null ) {
  1112. $post = get_post( $post );
  1113. if ( $post ) {
  1114. return $post->post_type;
  1115. }
  1116. return false;
  1117. }
  1118. /**
  1119. * Retrieves a post type object by name.
  1120. *
  1121. * @since 3.0.0
  1122. * @since 4.6.0 Object returned is now an instance of `WP_Post_Type`.
  1123. *
  1124. * @global array $wp_post_types List of post types.
  1125. *
  1126. * @see register_post_type()
  1127. *
  1128. * @param string $post_type The name of a registered post type.
  1129. * @return WP_Post_Type|null WP_Post_Type object if it exists, null otherwise.
  1130. */
  1131. function get_post_type_object( $post_type ) {
  1132. global $wp_post_types;
  1133. if ( ! is_scalar( $post_type ) || empty( $wp_post_types[ $post_type ] ) ) {
  1134. return null;
  1135. }
  1136. return $wp_post_types[ $post_type ];
  1137. }
  1138. /**
  1139. * Get a list of all registered post type objects.
  1140. *
  1141. * @since 2.9.0
  1142. *
  1143. * @global array $wp_post_types List of post types.
  1144. *
  1145. * @see register_post_type() for accepted arguments.
  1146. *
  1147. * @param array|string $args Optional. An array of key => value arguments to match against
  1148. * the post type objects. Default empty array.
  1149. * @param string $output Optional. The type of output to return. Accepts post type 'names'
  1150. * or 'objects'. Default 'names'.
  1151. * @param string $operator Optional. The logical operation to perform. 'or' means only one
  1152. * element from the array needs to match; 'and' means all elements
  1153. * must match; 'not' means no elements may match. Default 'and'.
  1154. * @return string[]|WP_Post_Type[] An array of post type names or objects.
  1155. */
  1156. function get_post_types( $args = array(), $output = 'names', $operator = 'and' ) {
  1157. global $wp_post_types;
  1158. $field = ( 'names' == $output ) ? 'name' : false;
  1159. return wp_filter_object_list( $wp_post_types, $args, $operator, $field );
  1160. }
  1161. /**
  1162. * Registers a post type.
  1163. *
  1164. * Note: Post type registrations should not be hooked before the
  1165. * {@see 'init'} action. Also, any taxonomy connections should be
  1166. * registered via the `$taxonomies` argument to ensure consistency
  1167. * when hooks such as {@see 'parse_query'} or {@see 'pre_get_posts'}
  1168. * are used.
  1169. *
  1170. * Post types can support any number of built-in core features such
  1171. * as meta boxes, custom fields, post thumbnails, post statuses,
  1172. * comments, and more. See the `$supports` argument for a complete
  1173. * list of supported features.
  1174. *
  1175. * @since 2.9.0
  1176. * @since 3.0.0 The `show_ui` argument is now enforced on the new post screen.
  1177. * @since 4.4.0 The `show_ui` argument is now enforced on the post type listing
  1178. * screen and post editing screen.
  1179. * @since 4.6.0 Post type object returned is now an instance of `WP_Post_Type`.
  1180. * @since 4.7.0 Introduced `show_in_rest`, `rest_base` and `rest_controller_class`
  1181. * arguments to register the post type in REST API.
  1182. * @since 5.3.0 The `supports` argument will now accept an array of arguments for a feature.
  1183. * .
  1184. * @global array $wp_post_types List of post types.
  1185. *
  1186. * @param string $post_type Post type key. Must not exceed 20 characters and may
  1187. * only contain lowercase alphanumeric characters, dashes,
  1188. * and underscores. See sanitize_key().
  1189. * @param array|string $args {
  1190. * Array or string of arguments for registering a post type.
  1191. *
  1192. * @type string $label Name of the post type shown in the menu. Usually plural.
  1193. * Default is value of $labels['name'].
  1194. * @type array $labels An array of labels for this post type. If not set, post
  1195. * labels are inherited for non-hierarchical types and page
  1196. * labels for hierarchical ones. See get_post_type_labels() for a full
  1197. * list of supported labels.
  1198. * @type string $description A short descriptive summary of what the post type is.
  1199. * Default empty.
  1200. * @type bool $public Whether a post type is intended for use publicly either via
  1201. * the admin interface or by front-end users. While the default
  1202. * settings of $exclude_from_search, $publicly_queryable, $show_ui,
  1203. * and $show_in_nav_menus are inherited from public, each does not
  1204. * rely on this relationship and controls a very specific intention.
  1205. * Default false.
  1206. * @type bool $hierarchical Whether the post type is hierarchical (e.g. page). Default false.
  1207. * @type bool $exclude_from_search Whether to exclude posts with this post type from front end search
  1208. * results. Default is the opposite value of $public.
  1209. * @type bool $publicly_queryable Whether queries can be performed on the front end for the post type
  1210. * as part of parse_request(). Endpoints would include:
  1211. * * ?post_type={post_type_key}
  1212. * * ?{post_type_key}={single_post_slug}
  1213. * * ?{post_type_query_var}={single_post_slug}
  1214. * If not set, the default is inherited from $public.
  1215. * @type bool $show_ui Whether to generate and allow a UI for managing this post type in the
  1216. * admin. Default is value of $public.
  1217. * @type bool|string $show_in_menu Where to show the post type in the admin menu. To work, $show_ui
  1218. * must be true. If true, the post type is shown in its own top level
  1219. * menu. If false, no menu is shown. If a string of an existing top
  1220. * level menu (eg. 'tools.php' or 'edit.php?post_type=page'), the post
  1221. * type will be placed as a sub-menu of that.
  1222. * Default is value of $show_ui.
  1223. * @type bool $show_in_nav_menus Makes this post type available for selection in navigation menus.
  1224. * Default is value of $public.
  1225. * @type bool $show_in_admin_bar Makes this post type available via the admin bar. Default is value
  1226. * of $show_in_menu.
  1227. * @type bool $show_in_rest Whether to include the post type in the REST API. Set this to true
  1228. * for the post type to be available in the block editor.
  1229. * @type string $rest_base To change the base url of REST API route. Default is $post_type.
  1230. * @type string $rest_controller_class REST API Controller class name. Default is 'WP_REST_Posts_Controller'.
  1231. * @type int $menu_position The position in the menu order the post type should appear. To work,
  1232. * $show_in_menu must be true. Default null (at the bottom).
  1233. * @type string $menu_icon The url to the icon to be used for this menu. Pass a base64-encoded
  1234. * SVG using a data URI, which will be colored to match the color scheme
  1235. * -- this should begin with 'data:image/svg+xml;base64,'. Pass the name
  1236. * of a Dashicons helper class to use a font icon, e.g.
  1237. * 'dashicons-chart-pie'. Pass 'none' to leave div.wp-menu-image empty
  1238. * so an icon can be added via CSS. Defaults to use the posts icon.
  1239. * @type string $capability_type The string to use to build the read, edit, and delete capabilities.
  1240. * May be passed as an array to allow for alternative plurals when using
  1241. * this argument as a base to construct the capabilities, e.g.
  1242. * array('story', 'stories'). Default 'post'.
  1243. * @type array $capabilities Array of capabilities for this post type. $capability_type is used
  1244. * as a base to construct capabilities by default.
  1245. * See get_post_type_capabilities().
  1246. * @type bool $map_meta_cap Whether to use the internal default meta capability handling.
  1247. * Default false.
  1248. * @type array $supports Core feature(s) the post type supports. Serves as an alias for calling
  1249. * add_post_type_support() directly. Core features include 'title',
  1250. * 'editor', 'comments', 'revisions', 'trackbacks', 'author', 'excerpt',
  1251. * 'page-attributes', 'thumbnail', 'custom-fields', and 'post-formats'.
  1252. * Additionally, the 'revisions' feature dictates whether the post type
  1253. * will store revisions, and the 'comments' feature dictates whether the
  1254. * comments count will show on the edit screen. A feature can also be
  1255. * specified as an array of arguments to provide additional information
  1256. * about supporting that feature. Example: `array( 'my_featu