5

I want to use WP-CLI to create some new posts with custom taxonomy terms assigned. The challenge is that wp_insert_post's tax_input argument only accepts arrays, which I would have to specify on the command line. According to the codex, here is the format required:

$post = array(
    'tax_input' => [ array( 'taxonomy_name' => array( 'term', 'term2', 'term3' ) ) ] // support for custom taxonomies
}

But I need something like this:

wp post create --post_type=lecture --post_title='Test Post #1' --tax-input=[BIG FAT ARRAY]

So my idea was to write a PHP script that executes the WP-CLI command with the array serialized:

//DEFINE VARIABLES
$post_title = "Test Post #1";
$tax_items = array( 9,11,17 );
$tax_input = array( 'course' => $tax_items );

//SERIALIZE THIS ARRAY
$tax_escaped = escapeshellarg(serialize($tax_input));

//WRITE THE COMMAND
$exec_string = 'wp post create --post_type=lecture --post_status=publish --post_title="%1$s" --tax_input=%2$s --porcelain';
$exec_command = sprintf($exec_string, $post_title, $tax_escaped );
$post_id = shell_exec($exec_command);

//THE OUTPUT
//wp post create --post_type=lecture --post_status=publish --post_title="Test Post #1" --tax_input='a:1:{s:5:"class";a:3:{i:0;i:9;i:1;i:11;i:2;i:17;}}' --porcelain

//RELATE THE NEW POST TO THE TAXONOMY TERMS
wp_set_object_terms( $post_id, $tax_items,'course');

Alas, this doesn't work. It creates the new post alright, but it fails to assign the 'course' taxonomy categories I want. Any help would be appreciated.

I know that this overall strategy works, because I succeeded in creating and taxonomizing my posts using wp_insert_posts. So this exercise is for educational purposes and future reference.

1

4 Answers 4

2

This is probably impossible since WP-CLI pass the arguments directly to wp_insert_posts. I'm automating this with wp eval. For example:

wp eval 'wp_set_object_terms(12 , array(1, 2, 3), "course");'

The post id can be obtained when you create the post with --porcelain:

wp post create ... --porcelain

Or by normal query with post title:

wp eval 'wp_set_object_terms(get_page_by_title("Test Post #1", OBJECT, "lecture")->ID, array(1, 2, 3), "course");'
1

It's 10 years old, but WP-CLI still doesn't handle the taxonomies while using wp post create.

So let's say you have the command:

wp post create --post_type=book --post_title="The Book" --tax_input={"year":"2023", "section": "drama"}

If you run it, wp-cli will create the post but not attach the taxonomies year and section with the terms "2023" and "drama", respectively, to the post.

I've found a hack to temporarily fix this (You'll need to revert the changes after you run your wp-cli commands!).

The steps are:

  • Open the file wp-includes/post.php;
  • Search for if ( ! empty( $postarr['tax_input'] ) ) {. As of today, it's on line 4564

If you var_dump($postarr['tax_input']), you'll see it's a string like "{\"year\":\"2023\", \"section\": \"drama\"}". We need to remove the slashes and convert it to a php array.

So, replace the code:

    if ( ! empty( $postarr['tax_input'] ) ) {
        foreach ( $postarr['tax_input'] as $taxonomy => $tags ) {
            $taxonomy_obj = get_taxonomy( $taxonomy );

            if ( ! $taxonomy_obj ) {
                _doing_it_wrong( __FUNCTION__, sprintf( __( 'Invalid taxonomy: %s.' ), $taxonomy ), '4.4.0' );
                continue;
            }

            if ( is_array( $tags ) ) {
                $tags = array_filter( $tags );
            }

            if ( current_user_can( $taxonomy_obj->cap->assign_terms ) ) {
                wp_set_post_terms( $post_id, $tags, $taxonomy );
            }
        }
    }

With:

    // Remove slashes
    $postarr['tax_input'] = stripslashes($postarr['tax_input']);

    // Convert json to array
    $postarr['tax_input'] = json_decode($postarr['tax_input']);

    // New-style support for all custom taxonomies.
    if ( ! empty( $postarr['tax_input'] ) ) {
        foreach ( $postarr['tax_input'] as $taxonomy => $tags ) {
            $taxonomy_obj = get_taxonomy( $taxonomy );

            if ( ! $taxonomy_obj ) {
                /* translators: %s: Taxonomy name. */
                _doing_it_wrong( __FUNCTION__, sprintf( __( 'Invalid taxonomy: %s.' ), $taxonomy ), '4.4.0' );
                continue;
            }

            // array = hierarchical, string = non-hierarchical.
            if ( is_array( $tags ) ) {
                $tags = array_filter( $tags );
            }

            // remove the capability check here
            wp_set_post_terms( $post_id, $tags, $taxonomy );
        }
    }

Pay attention to the end of the code where I removed the current_user_can check.

Now you can use the wp post create command to create your posts with custom taxonomies attached.

REMEMBER TO REVERT THE CHANGES BEFORE YOU USE THE SITE AGAIN!

1
  • Hey Saulo, thanks for your answer, I've built upon it and created an answer that doesn't modify core. ✌️
    – Davey
    Commented Apr 25 at 14:44
1

A solution inspired by @Saulo Padilha . <- the only person on the whole internet taking this cr*p seriously 😂

Add this snipped to functions.php , set the user argument, and JSON input should work. e.g

  • wp post create --user=1 --tax_input='{"taxonomy":"aTag"}
  • wp post create --user=1 --tax_input='{"taxonomy":["aTag","bTag"]}
add_filter('pre_tax_input', 'parse_tax_input_json');
add_filter('pre_post_tax_input', 'parse_tax_input_json');

function parse_tax_input_json($value)
{
    if (gettype($value) !== 'string') {
        return $value;
    }

    // Remove slashes
    $value = stripslashes($value);

    // Convert json to array
    $value = json_decode($value);

    return $value;
}
1
  • 1
    Thanks @Davey! I’ll use your snippet when I need this again. Commented Apr 26 at 15:40
0

Normally you'd pass an array to a script on the command line using the following

# Our array is named "foo"
php yourscript.php foo[]=bar&foo[]=baz&foo[some_key]=some_value

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.