diff --git a/composer.json b/composer.json
index d643595421..532366ed31 100644
--- a/composer.json
+++ b/composer.json
@@ -52,6 +52,7 @@
"wp-cli/entity-command": "^1.0",
"wp-cli/extension-command": "^1.0",
"wp-cli/config-command": "^1.0",
+ "wp-cli/rewrite-command": "^1.0",
"wp-cli/super-admin-command": "^1.0",
"wp-cli/scaffold-command": "^1.0"
},
diff --git a/composer.lock b/composer.lock
index 38c49b2e81..4924ac0cc4 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "content-hash": "b9a5b88ef89f4decd2780cc46806a12c",
+ "content-hash": "faa9802c94d954d24b8615c54361362a",
"packages": [
{
"name": "composer/ca-bundle",
@@ -1937,6 +1937,58 @@
],
"time": "2017-02-15T12:17:55+00:00"
},
+ {
+ "name": "wp-cli/rewrite-command",
+ "version": "v1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/wp-cli/rewrite-command.git",
+ "reference": "9b09d552c1c77cf406edecda20d93880d2bf1579"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/wp-cli/rewrite-command/zipball/9b09d552c1c77cf406edecda20d93880d2bf1579",
+ "reference": "9b09d552c1c77cf406edecda20d93880d2bf1579",
+ "shasum": ""
+ },
+ "require-dev": {
+ "behat/behat": "~2.5",
+ "wp-cli/wp-cli": "*"
+ },
+ "type": "wp-cli-package",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.x-dev"
+ },
+ "commands": [
+ "rewrite flush",
+ "rewrite list",
+ "rewrite structure"
+ ]
+ },
+ "autoload": {
+ "psr-4": {
+ "": "src/"
+ },
+ "files": [
+ "rewrite-command.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Daniel Bachhuber",
+ "email": "daniel@runcommand.io",
+ "homepage": "https://runcommand.io"
+ }
+ ],
+ "description": "Manage rewrite rules.",
+ "homepage": "https://github.com/wp-cli/rewrite-command",
+ "time": "2017-04-12T12:56:12+00:00"
+ },
{
"name": "wp-cli/scaffold-command",
"version": "v1.0.0",
diff --git a/features/rewrite.feature b/features/rewrite.feature
deleted file mode 100644
index 3443d191ad..0000000000
--- a/features/rewrite.feature
+++ /dev/null
@@ -1,137 +0,0 @@
-Feature: Manage WordPress rewrites
-
- Scenario: Change site permastructs
- Given a WP install
-
- When I run `wp rewrite structure /blog/%year%/%monthnum%/%day%/%postname%/ --category-base=section --tag-base=topic`
- And I run `wp option get permalink_structure`
- Then STDOUT should contain:
- """
- /blog/%year%/%monthnum%/%day%/%postname%/
- """
-
- When I run `wp option get category_base`
- Then STDOUT should contain:
- """
- section
- """
-
- When I run `wp option get tag_base`
- Then STDOUT should contain:
- """
- topic
- """
-
- When I run `wp rewrite list --format=csv`
- Then STDOUT should be CSV containing:
- | match | query | source |
- | blog/[0-9]{4}/[0-9]{1,2}/[0-9]{1,2}/[^/]+/attachment/([^/]+)/trackback/?$ | index.php?attachment=$matches[1]&tb=1 | post |
- | topic/([^/]+)/?$ | index.php?tag=$matches[1] | post_tag |
- | section/(.+?)/?$ | index.php?category_name=$matches[1] | category |
-
- When I run `wp rewrite list --match=/topic/apple/ --format=csv --fields=match,query`
- Then STDOUT should be CSV containing:
- | match | query |
- | topic/([^/]+)/?$ | index.php?tag=$matches[1] |
- And STDOUT should not contain:
- """
- source
- """
-
- Scenario: Missing permalink_structure
- Given a WP install
-
- When I run `wp option delete permalink_structure`
- And I try `wp option get permalink_structure`
- Then STDOUT should be empty
-
- When I try `wp rewrite flush`
- Then STDERR should contain:
- """
- Warning: Rewrite rules are empty, possibly because of a missing permalink_structure option.
- """
- And STDOUT should be empty
-
- When I run `wp rewrite structure /%year%/%monthnum%/%day%/%postname%/`
- Then I run `wp rewrite flush`
- Then STDOUT should be:
- """
- Success: Rewrite rules flushed.
- """
-
- Scenario: Generate .htaccess on hard flush with a project config
- Given a WP install
- And a wp-cli.yml file:
- """
- apache_modules: [mod_rewrite]
- """
-
- When I run `wp rewrite structure /%year%/%monthnum%/%day%/%postname%/ --hard`
- Then the .htaccess file should exist
- And the return code should be 0
- And STDERR should be empty
-
- Scenario: Generate .htaccess on hard flush with a global config
- Given a WP install
- And a config.yml file:
- """
- apache_modules: [mod_rewrite]
- """
-
- When I run `WP_CLI_CONFIG_PATH=config.yml wp rewrite structure /%year%/%monthnum%/%day%/%postname%/ --hard`
- Then the .htaccess file should exist
- And the return code should be 0
- And STDERR should be empty
-
- Scenario: Error when trying to generate .htaccess on a multisite install
- Given a WP multisite install
- And a wp-cli.yml file:
- """
- apache_modules: [mod_rewrite]
- """
-
- When I try `wp rewrite flush --hard`
- Then STDERR should be:
- """
- Warning: WordPress can't generate .htaccess file for a multisite install.
- """
- And STDOUT should be:
- """
- Success: Rewrite rules flushed.
- """
- And the return code should be 0
-
- When I try `wp rewrite structure /%year%/%monthnum%/%day%/%postname%/ --hard`
- Then STDERR should contain:
- """
- Warning: WordPress can't generate .htaccess file for a multisite install.
- """
- And STDOUT should be:
- """
- Success: Rewrite rules flushed.
- Success: Rewrite structure set.
- """
- And the return code should be 0
-
- Scenario: Warn the user when --skip-plugins or --skip-themes is used
- Given a WP install
-
- When I run `wp --skip-plugins rewrite flush`
- Then STDERR should contain:
- """
- Warning: Some rewrite rules may be missing because plugins weren't loaded.
- """
- And the return code should be 0
-
- When I run `wp --skip-plugins --skip-themes rewrite flush`
- Then STDERR should contain:
- """
- Warning: Some rewrite rules may be missing because plugins and themes weren't loaded.
- """
- And the return code should be 0
-
- When I run `wp rewrite flush`
- Then STDERR should not contain:
- """
- Warning: Some rewrite rules may be missing
- """
diff --git a/php/commands/rewrite.php b/php/commands/rewrite.php
deleted file mode 100644
index 381bd22c89..0000000000
--- a/php/commands/rewrite.php
+++ /dev/null
@@ -1,337 +0,0 @@
-
- * : The new permalink structure to apply.
- *
- * [--category-base=]
- * : Set the base for category permalinks, i.e. '/category/'.
- *
- * [--tag-base=]
- * : Set the base for tag permalinks, i.e. '/tag/'.
- *
- * [--hard]
- * : Perform a hard flush - update `.htaccess` rules as well as rewrite rules in database.
- *
- * ## EXAMPLES
- *
- * $ wp rewrite structure '/%year%/%monthnum%/%postname%'
- * Success: Rewrite structure set.
- */
- public function structure( $args, $assoc_args ) {
- global $wp_rewrite;
-
- // copypasta from /wp-admin/options-permalink.php
-
- $prefix = $blog_prefix = '';
- if ( is_multisite() && !is_subdomain_install() && is_main_site() )
- $blog_prefix = '/blog';
-
- $permalink_structure = ( $args[0] == 'default' ) ? '' : $args[0];
-
- if ( ! empty( $permalink_structure ) ) {
- $permalink_structure = preg_replace( '#/+#', '/', '/' . str_replace( '#', '', $permalink_structure ) );
- if ( $prefix && $blog_prefix )
- $permalink_structure = $prefix . preg_replace( '#^/?index\.php#', '', $permalink_structure );
- else
- $permalink_structure = $blog_prefix . $permalink_structure;
- }
- $wp_rewrite->set_permalink_structure( $permalink_structure );
-
- // Update category or tag bases
- if ( isset( $assoc_args['category-base'] ) ) {
-
- $category_base = $assoc_args['category-base'];
- if ( ! empty( $category_base ) )
- $category_base = $blog_prefix . preg_replace('#/+#', '/', '/' . str_replace( '#', '', $category_base ) );
- $wp_rewrite->set_category_base( $category_base );
- }
-
- if ( isset( $assoc_args['tag-base'] ) ) {
-
- $tag_base = $assoc_args['tag-base'];
- if ( ! empty( $tag_base ) )
- $tag_base = $blog_prefix . preg_replace('#/+#', '/', '/' . str_replace( '#', '', $tag_base ) );
- $wp_rewrite->set_tag_base( $tag_base );
- }
-
- // make sure we detect mod_rewrite if configured in apache_modules in config
- self::apache_modules();
-
- // Launch a new process to flush rewrites because core expects flush
- // to happen after rewrites are set
- $new_assoc_args = array();
- $cmd = 'rewrite flush';
- if ( \WP_CLI\Utils\get_flag_value( $assoc_args, 'hard' ) ) {
- $cmd .= ' --hard';
- $new_assoc_args['hard'] = true;
- if ( ! in_array( 'mod_rewrite', (array) WP_CLI::get_config( 'apache_modules' ) ) ) {
- WP_CLI::warning( "Regenerating a .htaccess file requires special configuration. See usage docs." );
- }
- }
-
- $process_run = WP_CLI::runcommand( $cmd );
- if ( ! empty( $process_run->stderr ) ) {
- // Strip "Warning: "
- WP_CLI::warning( substr( $process_run->stderr, 9 ) );
- }
-
- WP_CLI::success( "Rewrite structure set." );
- }
-
- /**
- * Get a list of the current rewrite rules.
- *
- * ## OPTIONS
- *
- * [--match=]
- * : Show rewrite rules matching a particular URL.
- *
- * [--source=]
- * : Show rewrite rules from a particular source.
- *
- * [--fields=]
- * : Limit the output to specific fields. Defaults to match,query,source.
- *
- * [--format=]
- * : Render output in a particular format.
- * ---
- * default: table
- * options:
- * - table
- * - csv
- * - json
- * - count
- * - yaml
- * ---
- *
- * ## EXAMPLES
- *
- * $ wp rewrite list --format=csv
- * match,query,source
- * ^wp-json/?$,index.php?rest_route=/,other
- * ^wp-json/(.*)?,index.php?rest_route=/$matches[1],other
- * category/(.+?)/feed/(feed|rdf|rss|rss2|atom)/?$,index.php?category_name=$matches[1]&feed=$matches[2],category
- * category/(.+?)/(feed|rdf|rss|rss2|atom)/?$,index.php?category_name=$matches[1]&feed=$matches[2],category
- * category/(.+?)/embed/?$,index.php?category_name=$matches[1]&embed=true,category
- *
- * @subcommand list
- */
- public function list_( $args, $assoc_args ) {
- global $wp_rewrite;
-
- $rules = get_option( 'rewrite_rules' );
- if ( ! $rules ) {
- $rules = array();
- WP_CLI::warning( 'No rewrite rules.' );
- }
-
- self::check_skip_plugins_themes();
-
- $defaults = array(
- 'source' => '',
- 'match' => '',
- 'format' => 'table',
- 'fields' => 'match,query,source',
- );
- $assoc_args = array_merge( $defaults, $assoc_args );
-
- $rewrite_rules_by_source = array();
- $rewrite_rules_by_source['post'] = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->permalink_structure, EP_PERMALINK );
- $rewrite_rules_by_source['date'] = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->get_date_permastruct(), EP_DATE );
- $rewrite_rules_by_source['root'] = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->root . '/', EP_ROOT );
- $rewrite_rules_by_source['comments'] = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->root . $wp_rewrite->comments_base, EP_COMMENTS, true, true, true, false );
- $rewrite_rules_by_source['search'] = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->get_search_permastruct(), EP_SEARCH );
- $rewrite_rules_by_source['author'] = $wp_rewrite->generate_rewrite_rules($wp_rewrite->get_author_permastruct(), EP_AUTHORS );
- $rewrite_rules_by_source['page'] = $wp_rewrite->page_rewrite_rules();
-
- // Extra permastructs including tags, categories, etc.
- foreach ( $wp_rewrite->extra_permastructs as $permastructname => $permastruct ) {
- if ( is_array( $permastruct ) ) {
- $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'] );
- } else {
- $rewrite_rules_by_source[$permastructname] = $wp_rewrite->generate_rewrite_rules( $permastruct, EP_NONE );
- }
- }
-
- // Apply the filters used in core just in case
- foreach( $rewrite_rules_by_source as $source => $source_rules ) {
- $rewrite_rules_by_source[$source] = apply_filters( $source . '_rewrite_rules', $source_rules );
- if ( 'post_tag' == $source )
- $rewrite_rules_by_source[$source] = apply_filters( 'tag_rewrite_rules', $source_rules );
- }
-
- $rule_list = array();
- foreach ( $rules as $match => $query ) {
-
- if ( ! empty( $assoc_args['match'] )
- && ! preg_match( "!^$match!", trim( $assoc_args['match'], '/' ) ) )
- continue;
-
- $source = 'other';
- foreach( $rewrite_rules_by_source as $rules_source => $source_rules ) {
- if ( array_key_exists( $match, $source_rules ) ) {
- $source = $rules_source;
- }
- }
-
- if ( ! empty( $assoc_args['source'] ) && $source != $assoc_args['source'] )
- continue;
-
- $rule_list[] = compact( 'match', 'query', 'source' );
- }
-
- WP_CLI\Utils\format_items( $assoc_args['format'], $rule_list, explode( ',', $assoc_args['fields'] ) );
- }
-
- /**
- * Expose apache modules if present in config
- *
- * Implementation Notes: This function exposes a global function
- * apache_get_modules and also sets the $is_apache global variable.
- *
- * This is so that flush_rewrite_rules will actually write out the
- * .htaccess file for apache wordpress installations. There is a check
- * to see:
- *
- * 1. if the $is_apache variable is set.
- * 2. if the mod_rewrite module is returned from the apache_get_modules
- * function.
- *
- * To get this to work with wp-cli you'll need to add the mod_rewrite module
- * to your config.yml. For example
- *
- * ```
- * apache_modules:
- * - mod_rewrite
- * ```
- *
- * If this isn't done then the .htaccess rewrite rules won't be flushed out
- * to disk.
- */
- private static function apache_modules() {
- $mods = WP_CLI::get_config('apache_modules');
- if ( !empty( $mods ) && !function_exists( 'apache_get_modules' ) ) {
- global $is_apache;
- $is_apache = true;
-
- // needed for get_home_path() and .htaccess location
- $_SERVER['SCRIPT_FILENAME'] = ABSPATH;
-
- function apache_get_modules() {
- return WP_CLI::get_config( 'apache_modules' );
- }
- }
- }
-
- /**
- * Display a warning if --skip-plugins or --skip-themes are in use.
- *
- * Skipping the loading of plugins or themes can mean some rewrite rules
- * are unregistered, which may cause erroneous behavior.
- */
- private static function check_skip_plugins_themes() {
- $skipped = array();
- if ( WP_CLI::get_config( 'skip-plugins' ) ) {
- $skipped[] = 'plugins';
- }
- if ( WP_CLI::get_config( 'skip-themes' ) ) {
- $skipped[] = 'themes';
- }
- if ( empty( $skipped ) ) {
- return;
- }
- $skipped = implode( ' and ', $skipped );
- WP_CLI::warning( sprintf( "Some rewrite rules may be missing because %s weren't loaded.", $skipped ) );
- }
-}
-
-WP_CLI::add_command( 'rewrite', 'Rewrite_Command' );
-