Skip to content

Fix: Ensure Media Attachments Are Properly Linked to Posts When Reusing WP_CLI::runcommand() - #6066

Closed
karthick-murugan wants to merge 1 commit into
wp-cli:mainfrom
karthick-murugan:wpcli/runcommand-reuse
Closed

karthick-murugan wants to merge 1 commit into
wp-cli:mainfrom
karthick-murugan:wpcli/runcommand-reuse

Conversation

@karthick-murugan

Copy link
Copy Markdown
Contributor

This pull request fixes issue #6025, where media imported using WP_CLI::runcommand() with launch => false does not get attached to the specified post.

Problem Description:

  • When running WP_CLI::runcommand() with launch => false, the media import command creates an attachment but does not correctly associate it with the provided --post_id.
  • When running with launch => true, the attachment is correctly linked to the post (expected behavior).

Solution Implemented:

  • Manually retrieve the last inserted attachment ID if --porcelain is used and WP_CLI::runcommand() is executed with launch => false.
  • Explicitly set the post_parent of the attachment to the specified post_id.
  • Ensure the attachment is properly linked as the featured image if --featured_image is provided.

Testing Instructions:

  1. Run the following command and verify that the media is attached to the post:

wp media import "/path/to/image.jpg" --post_id=123 --featured_image --porcelain

  1. Run WP_CLI::runcommand() with both launch => true and launch => false, and ensure the attachment is linked correctly:
WP_CLI::runcommand(
    sprintf('media import "%s" --post_id="%d" --featured_image --porcelain', $img_path, $post_id),
    ['return' => true, 'launch' => false]
);
  1. Verify that the imported media appears under the correct post in the WordPress admin panel.

@karthick-murugan
karthick-murugan requested a review from a team as a code owner March 11, 2025 12:57
@codecov

codecov Bot commented Mar 11, 2025

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 0% with 19 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
php/class-wp-cli.php 0.00% 19 Missing ⚠️

📢 Thoughts on this report? Let us know!

@swissspidy

Copy link
Copy Markdown
Member

Thanks for your PR!

We shouldn't add command-specific code into the main framework in this repo. If there's a bug in runcommand() we'd need to fix it in a command-agnostic way. And if it's a bug within the command itself, it needs to be in the command's respective repo.

  • When running WP_CLI::runcommand() with launch => false, the media import command creates an attachment but does not correctly associate it with the provided --post_id.

So why is this happening exactly?

@karthick-murugan

karthick-murugan commented Mar 11, 2025 •

Copy link
Copy Markdown
Contributor Author

So why is this happening exactly?

Thanks for the review! @swissspidy

The issue occurs because WP_CLI::runcommand() with launch => false does not create a new process, meaning the standard output (stdout) does not behave the same way as when launch => true is used. In the media import command, when --porcelain is used, the expected attachment ID is typically retrieved from stdout. However, with launch => false, the stdout value does not persist reliably, leading to a missing attachment ID.

Since the attachment ID isn't captured, the media file is imported but remains unattached to the specified post. The solution ensures that if --porcelain is used and WP_CLI::runcommand() is run with launch => false, we retrieve the last inserted attachment ID as a fallback.

Would you suggest an alternative way to address this within the command itself rather than the framework? I'm happy to adjust the PR accordingly.

@swissspidy

Copy link
Copy Markdown
Member

In the media import command, when --porcelain is used, the expected attachment ID is typically retrieved from stdout.

Where is this happening? Is this something you're doing in your own code? Not sure I follow 🤔

AFAICT, the attachment's post_parent is set here by media_handle_sideload():

https://github.com/wp-cli/media-command/blob/09e7ccde11f587cc75f3141aa2ee5397181a12f2/src/Media_Command.php#L415C16-L415C37

And the _thumbnail_id meta value is set here:

https://github.com/wp-cli/media-command/blob/09e7ccde11f587cc75f3141aa2ee5397181a12f2/src/Media_Command.php#L434-L437

I don't see how this is relates to --porcelain usage.

Maybe it would help writing a test first to demonstrate the problem, e.g. in features/runcommand.feature

@karthick-murugan

Copy link
Copy Markdown
Contributor Author

You're right—the issue isn't directly related to --porcelain. The core problem is that when using WP_CLI::runcommand() with launch => false, the media import command completes successfully, but the attachment isn’t linked to the post as expected.

Since media_handle_sideload() is responsible for setting post_parent, it seems like this behavior might be affected when the command runs in-process instead of spawning a new one. I'll investigate further and look into writing a test case to demonstrate the issue clearly.

Would you suggest a preferred approach to confirm the expected behavior in a test?

@swissspidy

Copy link
Copy Markdown
Member

Would you suggest a preferred approach to confirm the expected behavior in a test?

A Behat test works great for this. Anything that demonstrates the bug that an attachment isn't linked properly :-)

@karthick-murugan

Copy link
Copy Markdown
Contributor Author

A Behat test works great for this. Anything that demonstrates the bug that an attachment isn't linked properly :-)

@swissspidy Below is a screenshot and video demonstrating the Behat test I have written for this demo. I am encountering some undefined errors and missing step definitions. Could you please guide me on how to proceed and outline the next steps required to resolve these issues?

REC-20250312171110.mp4

runcommand

@swissspidy

Copy link
Copy Markdown
Member

I recommend looking at other tests to see how they're written.

"And a post exists" is not a step that is supported.

What you are looking for is

When I run `wp post create --post_title='Test post' --porcelain`

That creates a post for you.

If you then want to use that post's ID in the next step, you can do:

When I run `wp post create --post_title="Foo Bar" --porcelain`
Then STDOUT should be a number
And save STDOUT as {POST_ID}

When I run `wp media import 'http://wp-cli.org/behat-data/codeispoetry.png' --post_id={POST_ID} --title='My\Title' --caption='Caption\Here' --alt='Alt\Here' --desc='Desc\Here' --porcelain`

For regex matching STDOUT you should write it on one line:

Then STDOUT should match /^\d$/

Only if it's not a regex you need to use the quotes and multiline:

Then STDOUT should contain:
  """
  mystring
  """

@swissspidy

Copy link
Copy Markdown
Member

Checking in here, what's the current status?

Ideally there are some reproduction steps for this reported issue. I recommend sharing them on #6025 first so that they can be validated. Right now it sounds more like a configuration issue or anything, not a bug in WP-CLI.

@swissspidy

Copy link
Copy Markdown
Member

Closing this PR in favor of discussion on the reported issue as it a) needs reproduction steps and b) this is the wrong approach, as mentioned further above.

@swissspidy swissspidy closed this Mar 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WP_CLI::runcommand() reusing the process does not attach media to a post

2 participants