/php/commands/rewrite.php

https://gitlab.com/Blueprint-Marketing/wp-cli · PHP · 254 lines · 116 code · 32 blank · 106 comment · 31 complexity · f8e95f85f71f3d73814aab27c9873267 MD5 · raw file

  1. <?php
  2. /**
  3. * Manage rewrite rules.
  4. *
  5. * @package wp-cli
  6. */
  7. class Rewrite_Command extends WP_CLI_Command {
  8. /**
  9. * Flush rewrite rules.
  10. *
  11. * ## DESCRIPTION
  12. *
  13. * Resets WordPress' rewrite rules based on registered post types, etc.
  14. *
  15. * To regenerate a .htaccess file with WP-CLI, you'll need to add the mod_rewrite module
  16. * to your wp-cli.yml or config.yml. For example:
  17. *
  18. * apache_modules:
  19. * - mod_rewrite
  20. *
  21. * ## OPTIONS
  22. *
  23. * [--hard]
  24. * : Perform a hard flush - update `.htaccess` rules as well as rewrite rules in database.
  25. */
  26. public function flush( $args, $assoc_args ) {
  27. // make sure we detect mod_rewrite if configured in apache_modules in config
  28. self::apache_modules();
  29. if ( isset( $assoc_args['hard'] ) && ! in_array( 'mod_rewrite', (array) WP_CLI::get_config( 'apache_modules' ) ) ) {
  30. WP_CLI::warning( "Regenerating a .htaccess file requires special configuration. See usage docs." );
  31. }
  32. flush_rewrite_rules( isset( $assoc_args['hard'] ) );
  33. if ( ! get_option( 'rewrite_rules' ) ) {
  34. WP_CLI::warning( "Rewrite rules are empty, possibly because of a missing permalink_structure option. Use 'wp rewrite list' to verify, or 'wp rewrite structure' to update permalink_structure." );
  35. }
  36. }
  37. /**
  38. * Update the permalink structure.
  39. *
  40. * ## DESCRIPTION
  41. *
  42. * Updates the post permalink structure.
  43. *
  44. * To regenerate a .htaccess file with WP-CLI, you'll need to add the mod_rewrite module
  45. * to your wp-cli.yml or config.yml. For example:
  46. *
  47. * apache_modules:
  48. * - mod_rewrite
  49. *
  50. * ## OPTIONS
  51. *
  52. * <permastruct>
  53. * : The new permalink structure to apply.
  54. *
  55. * [--category-base=<base>]
  56. * : Set the base for category permalinks, i.e. '/category/'.
  57. *
  58. * [--tag-base=<base>]
  59. * : Set the base for tag permalinks, i.e. '/tag/'.
  60. *
  61. * [--hard]
  62. * : Perform a hard flush - update `.htaccess` rules as well as rewrite rules in database.
  63. *
  64. * ## EXAMPLES
  65. *
  66. * wp rewrite structure '/%year%/%monthnum%/%postname%'
  67. */
  68. public function structure( $args, $assoc_args ) {
  69. global $wp_rewrite;
  70. // copypasta from /wp-admin/options-permalink.php
  71. $home_path = get_home_path();
  72. $iis7_permalinks = iis7_supports_permalinks();
  73. $prefix = $blog_prefix = '';
  74. if ( ! got_mod_rewrite() && ! $iis7_permalinks )
  75. $prefix = '/index.php';
  76. if ( is_multisite() && !is_subdomain_install() && is_main_site() )
  77. $blog_prefix = '/blog';
  78. $permalink_structure = ( $args[0] == 'default' ) ? '' : $args[0];
  79. if ( ! empty( $permalink_structure ) ) {
  80. $permalink_structure = preg_replace( '#/+#', '/', '/' . str_replace( '#', '', $permalink_structure ) );
  81. if ( $prefix && $blog_prefix )
  82. $permalink_structure = $prefix . preg_replace( '#^/?index\.php#', '', $permalink_structure );
  83. else
  84. $permalink_structure = $blog_prefix . $permalink_structure;
  85. }
  86. $wp_rewrite->set_permalink_structure( $permalink_structure );
  87. // Update category or tag bases
  88. if ( isset( $assoc_args['category-base'] ) ) {
  89. $category_base = $assoc_args['category-base'];
  90. if ( ! empty( $category_base ) )
  91. $category_base = $blog_prefix . preg_replace('#/+#', '/', '/' . str_replace( '#', '', $category_base ) );
  92. $wp_rewrite->set_category_base( $category_base );
  93. }
  94. if ( isset( $assoc_args['tag-base'] ) ) {
  95. $tag_base = $assoc_args['tag-base'];
  96. if ( ! empty( $tag_base ) )
  97. $tag_base = $blog_prefix . preg_replace('#/+#', '/', '/' . str_replace( '#', '', $tag_base ) );
  98. $wp_rewrite->set_tag_base( $tag_base );
  99. }
  100. // make sure we detect mod_rewrite if configured in apache_modules in config
  101. self::apache_modules();
  102. // Launch a new process to flush rewrites because core expects flush
  103. // to happen after rewrites are set
  104. $new_assoc_args = array();
  105. if ( isset( $assoc_args['hard'] ) ) {
  106. $new_assoc_args['hard'] = true;
  107. if ( ! in_array( 'mod_rewrite', (array) WP_CLI::get_config( 'apache_modules' ) ) ) {
  108. WP_CLI::warning( "Regenerating a .htaccess file requires special configuration. See usage docs." );
  109. }
  110. }
  111. \WP_CLI::launch_self( 'rewrite flush', array(), $new_assoc_args );
  112. WP_CLI::success( "Rewrite structure set." );
  113. }
  114. /**
  115. * Print current rewrite rules.
  116. *
  117. * ## OPTIONS
  118. *
  119. * [--match=<url>]
  120. * : Show rewrite rules matching a particular URL.
  121. *
  122. * [--source=<source>]
  123. * : Show rewrite rules from a particular source.
  124. *
  125. * [--format=<format>]
  126. * : Accepted values: table, csv, json, count. Default: table
  127. *
  128. * ## EXAMPLES
  129. *
  130. * wp rewrite list --format=csv
  131. *
  132. * @subcommand list
  133. */
  134. public function list_( $args, $assoc_args ) {
  135. global $wp_rewrite;
  136. $rules = get_option( 'rewrite_rules' );
  137. if ( ! $rules ) {
  138. $rules = array();
  139. WP_CLI::warning( 'No rewrite rules.' );
  140. }
  141. $defaults = array(
  142. 'source' => '',
  143. 'match' => '',
  144. 'format' => 'table'
  145. );
  146. $assoc_args = array_merge( $defaults, $assoc_args );
  147. $rewrite_rules_by_source = array();
  148. $rewrite_rules_by_source['post'] = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->permalink_structure, EP_PERMALINK );
  149. $rewrite_rules_by_source['date'] = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->get_date_permastruct(), EP_DATE );
  150. $rewrite_rules_by_source['root'] = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->root . '/', EP_ROOT );
  151. $rewrite_rules_by_source['comments'] = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->root . $wp_rewrite->comments_base, EP_COMMENTS, true, true, true, false );
  152. $rewrite_rules_by_source['search'] = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->get_search_permastruct(), EP_SEARCH );
  153. $rewrite_rules_by_source['author'] = $wp_rewrite->generate_rewrite_rules($wp_rewrite->get_author_permastruct(), EP_AUTHORS );
  154. $rewrite_rules_by_source['page'] = $wp_rewrite->page_rewrite_rules();
  155. // Extra permastructs including tags, categories, etc.
  156. foreach ( $wp_rewrite->extra_permastructs as $permastructname => $permastruct ) {
  157. if ( is_array( $permastruct ) ) {
  158. $rewrite_rules_by_source[$permastructname] = $wp_rewrite->generate_rewrite_rules( $permastruct['struct'], $permastruct['ep_mask'], $permastruct['paged'], $permastruct['feed'], $permastruct['forcomments'], $permastruct['walk_dirs'], $permastruct['endpoints'] );
  159. } else {
  160. $rewrite_rules_by_source[$permastructname] = $wp_rewrite->generate_rewrite_rules( $permastruct, EP_NONE );
  161. }
  162. }
  163. // Apply the filters used in core just in case
  164. foreach( $rewrite_rules_by_source as $source => $source_rules ) {
  165. $rewrite_rules_by_source[$source] = apply_filters( $source . '_rewrite_rules', $source_rules );
  166. if ( 'post_tag' == $source )
  167. $rewrite_rules_by_source[$source] = apply_filters( 'tag_rewrite_rules', $source_rules );
  168. }
  169. $rule_list = array();
  170. foreach ( $rules as $match => $query ) {
  171. if ( ! empty( $assoc_args['match'] )
  172. && ! preg_match( "!^$match!", trim( $assoc_args['match'], '/' ) ) )
  173. continue;
  174. $source = 'other';
  175. foreach( $rewrite_rules_by_source as $rules_source => $source_rules ) {
  176. if ( array_key_exists( $match, $source_rules ) ) {
  177. $source = $rules_source;
  178. }
  179. }
  180. if ( ! empty( $assoc_args['source'] ) && $source != $assoc_args['source'] )
  181. continue;
  182. $rule_list[] = compact( 'match', 'query', 'source' );
  183. }
  184. WP_CLI\Utils\format_items( $assoc_args['format'], $rule_list, array('match', 'query', 'source' ) );
  185. }
  186. /**
  187. * Expose apache modules if present in config
  188. *
  189. * Implementation Notes: This function exposes a global function
  190. * apache_get_modules and also sets the $is_apache global variable.
  191. *
  192. * This is so that flush_rewrite_rules will actually write out the
  193. * .htaccess file for apache wordpress installations. There is a check
  194. * to see:
  195. *
  196. * 1. if the $is_apache variable is set.
  197. * 2. if the mod_rewrite module is returned from the apche_get_modules
  198. * function.
  199. *
  200. * To get this to work with wp-cli you'll need to add the mod_rewrite module
  201. * to your config.yml. For example
  202. *
  203. * apache_modules:
  204. * - mod_rewrite
  205. *
  206. * If this isn't done then the .htaccess rewrite rules won't be flushed out
  207. * to disk.
  208. */
  209. private static function apache_modules() {
  210. $mods = WP_CLI::get_config('apache_modules');
  211. if ( !empty( $mods ) && !function_exists( 'apache_get_modules' ) ) {
  212. global $is_apache;
  213. $is_apache = true;
  214. // needed for get_home_path() and .htaccess location
  215. $_SERVER['SCRIPT_FILENAME'] = ABSPATH;
  216. function apache_get_modules() {
  217. return WP_CLI::get_config( 'apache_modules' );
  218. }
  219. }
  220. }
  221. }
  222. WP_CLI:: add_command( 'rewrite', 'Rewrite_Command' );