theme-templates.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. <?php
  2. /**
  3. * Sets a custom slug when creating auto-draft template parts.
  4. *
  5. * This is only needed for auto-drafts created by the regular WP editor.
  6. * If this page is to be removed, this will not be necessary.
  7. *
  8. * @since 5.9.0
  9. *
  10. * @param int $post_id Post ID.
  11. */
  12. function wp_set_unique_slug_on_create_template_part( $post_id ) {
  13. $post = get_post( $post_id );
  14. if ( 'auto-draft' !== $post->post_status ) {
  15. return;
  16. }
  17. if ( ! $post->post_name ) {
  18. wp_update_post(
  19. array(
  20. 'ID' => $post_id,
  21. 'post_name' => 'custom_slug_' . uniqid(),
  22. )
  23. );
  24. }
  25. $terms = get_the_terms( $post_id, 'wp_theme' );
  26. if ( ! is_array( $terms ) || ! count( $terms ) ) {
  27. wp_set_post_terms( $post_id, get_stylesheet(), 'wp_theme' );
  28. }
  29. }
  30. /**
  31. * Generates a unique slug for templates.
  32. *
  33. * @access private
  34. * @since 5.8.0
  35. *
  36. * @param string $override_slug The filtered value of the slug (starts as `null` from apply_filter).
  37. * @param string $slug The original/un-filtered slug (post_name).
  38. * @param int $post_ID Post ID.
  39. * @param string $post_status No uniqueness checks are made if the post is still draft or pending.
  40. * @param string $post_type Post type.
  41. * @return string The original, desired slug.
  42. */
  43. function wp_filter_wp_template_unique_post_slug( $override_slug, $slug, $post_ID, $post_status, $post_type ) {
  44. if ( 'wp_template' !== $post_type && 'wp_template_part' !== $post_type ) {
  45. return $override_slug;
  46. }
  47. if ( ! $override_slug ) {
  48. $override_slug = $slug;
  49. }
  50. /*
  51. * Template slugs must be unique within the same theme.
  52. * TODO - Figure out how to update this to work for a multi-theme environment.
  53. * Unfortunately using `get_the_terms()` for the 'wp-theme' term does not work
  54. * in the case of new entities since is too early in the process to have been saved
  55. * to the entity. So for now we use the currently activated theme for creation.
  56. */
  57. $theme = get_stylesheet();
  58. $terms = get_the_terms( $post_ID, 'wp_theme' );
  59. if ( $terms && ! is_wp_error( $terms ) ) {
  60. $theme = $terms[0]->name;
  61. }
  62. $check_query_args = array(
  63. 'post_name__in' => array( $override_slug ),
  64. 'post_type' => $post_type,
  65. 'posts_per_page' => 1,
  66. 'no_found_rows' => true,
  67. 'post__not_in' => array( $post_ID ),
  68. 'tax_query' => array(
  69. array(
  70. 'taxonomy' => 'wp_theme',
  71. 'field' => 'name',
  72. 'terms' => $theme,
  73. ),
  74. ),
  75. );
  76. $check_query = new WP_Query( $check_query_args );
  77. $posts = $check_query->posts;
  78. if ( count( $posts ) > 0 ) {
  79. $suffix = 2;
  80. do {
  81. $query_args = $check_query_args;
  82. $alt_post_name = _truncate_post_slug( $override_slug, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix";
  83. $query_args['post_name__in'] = array( $alt_post_name );
  84. $query = new WP_Query( $query_args );
  85. $suffix++;
  86. } while ( count( $query->posts ) > 0 );
  87. $override_slug = $alt_post_name;
  88. }
  89. return $override_slug;
  90. }
  91. /**
  92. * Prints the skip-link script & styles.
  93. *
  94. * @access private
  95. * @since 5.8.0
  96. *
  97. * @global string $_wp_current_template_content
  98. */
  99. function the_block_template_skip_link() {
  100. global $_wp_current_template_content;
  101. // Early exit if not a block theme.
  102. if ( ! current_theme_supports( 'block-templates' ) ) {
  103. return;
  104. }
  105. // Early exit if not a block template.
  106. if ( ! $_wp_current_template_content ) {
  107. return;
  108. }
  109. ?>
  110. <?php
  111. /**
  112. * Print the skip-link styles.
  113. */
  114. ?>
  115. <style id="skip-link-styles">
  116. .skip-link.screen-reader-text {
  117. border: 0;
  118. clip: rect(1px,1px,1px,1px);
  119. clip-path: inset(50%);
  120. height: 1px;
  121. margin: -1px;
  122. overflow: hidden;
  123. padding: 0;
  124. position: absolute !important;
  125. width: 1px;
  126. word-wrap: normal !important;
  127. }
  128. .skip-link.screen-reader-text:focus {
  129. background-color: #eee;
  130. clip: auto !important;
  131. clip-path: none;
  132. color: #444;
  133. display: block;
  134. font-size: 1em;
  135. height: auto;
  136. left: 5px;
  137. line-height: normal;
  138. padding: 15px 23px 14px;
  139. text-decoration: none;
  140. top: 5px;
  141. width: auto;
  142. z-index: 100000;
  143. }
  144. </style>
  145. <?php
  146. /**
  147. * Print the skip-link script.
  148. */
  149. ?>
  150. <script>
  151. ( function() {
  152. var skipLinkTarget = document.querySelector( 'main' ),
  153. sibling,
  154. skipLinkTargetID,
  155. skipLink;
  156. // Early exit if a skip-link target can't be located.
  157. if ( ! skipLinkTarget ) {
  158. return;
  159. }
  160. // Get the site wrapper.
  161. // The skip-link will be injected in the beginning of it.
  162. sibling = document.querySelector( '.wp-site-blocks' );
  163. // Early exit if the root element was not found.
  164. if ( ! sibling ) {
  165. return;
  166. }
  167. // Get the skip-link target's ID, and generate one if it doesn't exist.
  168. skipLinkTargetID = skipLinkTarget.id;
  169. if ( ! skipLinkTargetID ) {
  170. skipLinkTargetID = 'wp--skip-link--target';
  171. skipLinkTarget.id = skipLinkTargetID;
  172. }
  173. // Create the skip link.
  174. skipLink = document.createElement( 'a' );
  175. skipLink.classList.add( 'skip-link', 'screen-reader-text' );
  176. skipLink.href = '#' + skipLinkTargetID;
  177. skipLink.innerHTML = '<?php esc_html_e( 'Skip to content' ); ?>';
  178. // Inject the skip link.
  179. sibling.parentElement.insertBefore( skipLink, sibling );
  180. }() );
  181. </script>
  182. <?php
  183. }
  184. /**
  185. * Enables the block templates (editor mode) for themes with theme.json by default.
  186. *
  187. * @access private
  188. * @since 5.8.0
  189. */
  190. function wp_enable_block_templates() {
  191. if ( wp_is_block_theme() || WP_Theme_JSON_Resolver::theme_has_support() ) {
  192. add_theme_support( 'block-templates' );
  193. }
  194. }