Skip to content

Commit

Permalink
Allow orphan terms to be exported with --allow_orphan_terms flag (#109
Browse files Browse the repository at this point in the history
)

---------

Co-authored-by: Daniel Bachhuber <[email protected]>
  • Loading branch information
jacksonwp and danielbachhuber authored Sep 18, 2023
1 parent c0dec81 commit 31e3d71
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 33 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Quick links: [Using](#using) | [Installing](#installing) | [Contributing](#contr
## Using

~~~
wp export [--dir=<dirname>] [--stdout] [--skip_comments] [--max_file_size=<MB>] [--filename_format=<format>] [--include_once=<before_posts>] [--start_date=<date>] [--end_date=<date>] [--post_type=<post-type>] [--post_type__not_in=<post-type>] [--post__in=<pid>] [--with_attachments] [--start_id=<pid>] [--max_num_posts=<num>] [--author=<author>] [--category=<name|id>] [--post_status=<status>]
wp export [--dir=<dirname>] [--stdout] [--skip_comments] [--max_file_size=<MB>] [--filename_format=<format>] [--include_once=<before_posts>] [--allow_orphan_terms] [--start_date=<date>] [--end_date=<date>] [--post_type=<post-type>] [--post_type__not_in=<post-type>] [--post__in=<pid>] [--with_attachments] [--start_id=<pid>] [--max_num_posts=<num>] [--author=<author>] [--category=<name|id>] [--post_status=<status>]
~~~

Generates one or more WXR files containing authors, terms, posts,
Expand Down Expand Up @@ -43,6 +43,9 @@ comments, and attachments. WXR files do not include site configuration
are categories, tags, nav_menu_items, custom_taxonomies_terms. Separate multiple
sections with a comma. Defaults to none.

[--allow_orphan_terms]
Export orphaned terms with `parent=0`, instead of throwing an exception.

**FILTERS**

[--start_date=<date>]
Expand Down
88 changes: 88 additions & 0 deletions features/export.feature
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,10 @@ Feature: Export content.
Then STDOUT should be a number
And save STDOUT as {EXPORT_CATEGORY_ID}

When I run `wp term create category National --parent={EXPORT_CATEGORY_ID} --porcelain`
Then STDOUT should be a number
And save STDOUT as {EXPORT_SUBCATEGORY_ID}

When I run `wp term create post_tag Tech --description="Technology-related" --porcelain`
Then STDOUT should be a number
And save STDOUT as {EXPORT_TAG_ID}
Expand Down Expand Up @@ -1028,6 +1032,10 @@ Feature: Export content.
"""
<wp:term_id>{EXPORT_CATEGORY_ID}</wp:term_id>
"""
And the {EXPORT_FILE} file should contain:
"""
<wp:category_parent>news</wp:category_parent>
"""
And the {EXPORT_FILE} file should contain:
"""
<wp:cat_name><![CDATA[News]]></wp:cat_name>
Expand Down Expand Up @@ -1104,6 +1112,20 @@ Feature: Export content.
"""
News
"""
And STDOUT should contain:
"""
National
"""

When I run `wp term get category news --by=slug --field=id`
Then STDOUT should be a number
And save STDOUT as {IMPORT_CATEGORY_ID}

When I run `wp term get category national --by=slug --field=parent`
Then STDOUT should be:
"""
{IMPORT_CATEGORY_ID}
"""

When I run `wp term list post_tag`
Then STDOUT should contain:
Expand Down Expand Up @@ -1148,3 +1170,69 @@ Feature: Export content.
"""
Test User
"""

@require-wp-5.2
Scenario: Allow export to proceed when orphaned terms are found
Given a WP install
And I run `wp term create category orphan --parent=1`
And I run `wp term create category parent`
And I run `wp term create category child --parent=3`
And I run `wp term create post_tag atag`
And I run `wp term create post_tag btag`
And I run `wp term create post_tag ctag`
And I run `wp db query "DELETE FROM wp_terms WHERE term_id = 1"`

When I run `wp export --allow_orphan_terms`
Then save STDOUT 'Writing to file %s' as {EXPORT_FILE}
And the {EXPORT_FILE} file should contain:
"""
<wp:category_nicename>orphan</wp:category_nicename>
"""
And the {EXPORT_FILE} file should contain:
"""
<wp:tag_slug>atag</wp:tag_slug>
"""

When I run `wp site empty --yes`
And I run `wp plugin install wordpress-importer --activate`
And I run `wp import {EXPORT_FILE} --authors=skip`
Then STDOUT should contain:
"""
Success:
"""

When I run `wp term get post_tag atag --by=slug --field=id`
Then STDOUT should be a number

When I run `wp term get post_tag btag --by=slug --field=id`
Then STDOUT should be a number

When I run `wp term get post_tag ctag --by=slug --field=id`
Then STDOUT should be a number

When I run `wp term get category parent --by=slug --field=id`
Then STDOUT should be a number
And save STDOUT as {EXPORT_CATEGORY_PARENT_ID}

When I run `wp term get category child --by=slug --field=parent`
Then STDOUT should be:
"""
{EXPORT_CATEGORY_PARENT_ID}
"""

When I run `wp term get category orphan --by=slug --field=parent`
Then STDOUT should be:
"""
0
"""

Scenario: Throw exception when orphaned terms are found
Given a WP install
And I run `wp term create category orphan --parent=1`
And I run `wp db query "DELETE FROM wp_terms WHERE term_id = 1"`

When I try `wp export`
Then STDERR should contain:
"""
Error: Term is missing a parent
"""
51 changes: 34 additions & 17 deletions src/Export_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ class Export_Command extends WP_CLI_Command {
* are categories, tags, nav_menu_items, custom_taxonomies_terms. Separate multiple
* sections with a comma. Defaults to none.
*
* [--allow_orphan_terms]
* : Export orphaned terms with `parent=0`, instead of throwing an exception.
*
* ## FILTERS
*
* [--start_date=<date>]
Expand Down Expand Up @@ -128,23 +131,24 @@ class Export_Command extends WP_CLI_Command {
*/
public function __invoke( $_, $assoc_args ) {
$defaults = [
'dir' => null,
'stdout' => false,
'start_date' => null,
'end_date' => null,
'post_type' => null,
'post_type__not_in' => null,
'max_num_posts' => null,
'author' => null,
'category' => null,
'post_status' => null,
'post__in' => null,
'with_attachments' => true, // or FALSE if user requested some post__in
'start_id' => null,
'skip_comments' => null,
'max_file_size' => 15,
'filename_format' => '{site}.wordpress.{date}.{n}.xml',
'include_once' => null,
'dir' => null,
'stdout' => false,
'start_date' => null,
'end_date' => null,
'post_type' => null,
'post_type__not_in' => null,
'max_num_posts' => null,
'author' => null,
'category' => null,
'post_status' => null,
'post__in' => null,
'with_attachments' => true, // or FALSE if user requested some post__in
'start_id' => null,
'skip_comments' => null,
'max_file_size' => 15,
'filename_format' => '{site}.wordpress.{date}.{n}.xml',
'include_once' => null,
'allow_orphan_terms' => null,
];

if ( ! empty( $assoc_args['stdout'] ) && ( ! empty( $assoc_args['dir'] ) || ! empty( $assoc_args['filename_format'] ) ) ) {
Expand Down Expand Up @@ -492,4 +496,17 @@ private function check_include_once( $once ) {

return true;
}

private function check_allow_orphan_terms( $allow_orphan_terms ) {
if ( null === $allow_orphan_terms ) {
return true;
}

if ( 0 !== (int) $allow_orphan_terms && 1 !== (int) $allow_orphan_terms ) {
WP_CLI::warning( 'allow_orphan_terms needs to be 0 (no) or 1 (yes).' );
return false;
}
$this->export_args['allow_orphan_terms'] = $allow_orphan_terms;
return true;
}
}
53 changes: 38 additions & 15 deletions src/WP_Export_Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ class WP_Export_Query {
const QUERY_CHUNK = 100;

private static $defaults = [
'post_ids' => null,
'post_type' => null,
'status' => null,
'author' => null,
'start_date' => null,
'end_date' => null,
'start_id' => null,
'max_num_posts' => null,
'category' => null,
'post_ids' => null,
'post_type' => null,
'status' => null,
'author' => null,
'start_date' => null,
'end_date' => null,
'start_id' => null,
'max_num_posts' => null,
'category' => null,
'allow_orphan_terms' => null,
];

private $post_ids;
Expand Down Expand Up @@ -97,7 +98,7 @@ public function categories() {
}
$categories = (array) get_categories( [ 'get' => 'all' ] );

$this->check_for_orphaned_terms( $categories );
$categories = $this->process_orphaned_terms( $categories );

$categories = self::topologically_sort_terms( $categories );

Expand All @@ -110,7 +111,7 @@ public function tags() {
}
$tags = (array) get_tags( [ 'get' => 'all' ] );

$this->check_for_orphaned_terms( $tags );
$tags = $this->process_orphaned_terms( $tags );

return $tags;
}
Expand All @@ -122,7 +123,7 @@ public function custom_taxonomies_terms() {
$custom_taxonomies = get_taxonomies( [ '_builtin' => false ] );
// phpcs:ignore WordPress.WP.DeprecatedParameters.Get_termsParam2Found -- Deprecated, but we need to support older versions of WordPress.
$custom_terms = (array) get_terms( $custom_taxonomies, [ 'get' => 'all' ] );
$this->check_for_orphaned_terms( $custom_terms );
$custom_terms = $this->process_orphaned_terms( $custom_terms );
$custom_terms = self::topologically_sort_terms( $custom_terms );
return $custom_terms;
}
Expand Down Expand Up @@ -356,9 +357,11 @@ private static function topologically_sort_terms( $terms ) {
return $sorted;
}

private function check_for_orphaned_terms( $terms ) {
private function process_orphaned_terms( $terms ) {

$term_ids = [];
$have_parent = [];
$orphans = [];

foreach ( $terms as $term ) {
$term_ids[ $term->term_id ] = true;
Expand All @@ -369,10 +372,30 @@ private function check_for_orphaned_terms( $terms ) {

foreach ( $have_parent as $has_parent ) {
if ( ! isset( $term_ids[ $has_parent->parent ] ) ) {
$this->missing_parents = $has_parent;
throw new WP_Export_Term_Exception( "Term is missing a parent: {$has_parent->slug} ({$has_parent->term_taxonomy_id})" );
if ( $this->filters['allow_orphan_terms'] ) {
$orphans[ $has_parent->term_id ] = true;
} else {
$this->missing_parents = $has_parent;
throw new WP_Export_Term_Exception( "Term is missing a parent: {$has_parent->slug} ({$has_parent->term_taxonomy_id})" );
}
}
}

if ( ! $this->filters['allow_orphan_terms'] ) {
return $terms;
}

if ( count( $orphans ) > 0 ) {
$terms_return = [];
foreach ( $terms as $term ) {
if ( isset( $orphans[ $term->term_id ] ) ) {
$term->parent = 0;
}
$terms_return[] = $term;
}
$terms = $terms_return;
}
return $terms;
}

private static function get_terms_for_post( $post ) {
Expand Down

0 comments on commit 31e3d71

Please sign in to comment.