Skip to content

Posts: Unstick a post given a password through Quick Edit. - #13246

Open
wppoland wants to merge 3 commits into
WordPress:trunkfrom
wppoland:trac/64810-sticky-password
Open

Posts: Unstick a post given a password through Quick Edit.#13246
wppoland wants to merge 3 commits into
WordPress:trunkfrom
wppoland:trac/64810-sticky-password

Conversation

@wppoland

@wppoland wppoland commented Aug 24, 2026

Copy link
Copy Markdown

Trac ticket: https://core.trac.wordpress.org/ticket/64810

Opened at @audrasjb's request in comment:15: the change from #11180 plus the unit test that was only sitting in a comment there, so the ticket can lose needs-unit-tests and be committed as one changeset.

The change

@Hug0-Drelon's patch from #11180, unmodified, and committed under their authorship.

Quick Edit posts sticky but never posts visibility. edit_post() only unsets sticky inside case 'password' of the visibility switch, so that branch was never reached and a post could end up both sticky and password protected, a combination the block editor itself forbids.

Setting visibility to password whenever a post password is present makes the existing branch run whatever the caller sent.

The test

test_edit_post_unsticks_a_post_when_a_password_is_set_without_visibility() reproduces the Quick Edit payload: sticky is posted, visibility is not.

Verified both directions locally, PHP 8.3 against a single site:

  • with the change: OK (1 test, 3 assertions)
  • with the change reverted, test kept: Failed asserting that true is false. A password protected post was left sticky when no explicit visibility was sent.

The rest of the file is unaffected: tests/phpunit/tests/admin/includesPost.php runs 52 tests, 118 assertions, 0 failures. The 6 warnings are the pre-existing E_DEPRECATED expectation notices PHPUnit 9.6 emits across that file.

phpcs on both touched files: 0 errors. The single warning in src/wp-admin/includes/post.php is at line 901 and predates this branch.

Credit

The fix is @Hug0-Drelon's work and the props on #11180 already list hugod, wildworks, abcd95, motylanogha. If this lands instead of #11180, that props line should carry over.

The open question this PR does not settle

The ticket still carries 2nd-opinion, and this PR is not a vote on it. In comment:13 @wildworks argued the opposite direction: that password protected and sticky should be allowed together in all cases, and that #11180 removes something Quick Edit could previously do.

That is a real disagreement about intended behaviour, not about the code. This PR exists because @audrasjb asked for the change and the test in one place; if the ticket resolves the other way, the same test file is where the inverse expectation would go.

Hug0-Drelon and others added 2 commits August 24, 2026 07:11
Quick Edit posts `sticky` but never posts `visibility`, so `edit_post()`
never reached the `case 'password'` branch that drops the sticky flag. A
post could end up both sticky and password protected, a combination the
block editor itself forbids.

Set `visibility` to `password` whenever a post password is present, so
the existing branch runs whatever the caller sent.

Original patch by Hug0-Drelon in PR WordPress#11180.

See #64810.
…value.

Reproduces the Quick Edit payload: `sticky` is posted, `visibility` is
not. Fails on trunk, where the post keeps both the sticky flag and the
new password, and passes with the preceding change.

See #64810.
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props hugod, motylanogha.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@Hug0-Drelon Hug0-Drelon left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we take the opportunity to improve code coverage for https://github.com/WordPress/wordpress-develop/pull/13246/changes#diff-7c58dcea3675e604ab0caa9263522686924e3dd881d5a36b94865dacfbca129bR309-R323?

i.e. testing with $post_data['visibility'] set to 'public'|'password'|'private'?

Otherwise, thanks for the proposed tests!

Adds the `public`, `password` and `private` cases of the visibility
switch, which had no coverage before, and pins the precedence between an
inferred visibility and a contradicting one sent by the caller.

That last one is a behaviour change worth naming: on trunk, sending
`visibility` as `public` alongside a non-empty `post_password` cleared
the password. Inferring the visibility from the password applies last,
so the password now wins instead. The editors never send that pair,
since choosing Public clears the password field, but `edit_post()` is
also reachable from bulk edit and Quick Edit.

See #64810.
@wppoland

Copy link
Copy Markdown
Author

Good call, done in 5540b57. Three characterisation tests for the switch, plus a fourth that turned out to matter more than I expected.

  • public clears an existing password.
  • password unsticks the post. Same branch as the first test, but reached by a caller sending the value outright rather than by inference.
  • private sets post_status to private, clears the password and unsticks.

The fourth one

While writing those I noticed the change alters behaviour for one input nobody has mentioned on the ticket.

Inferring the visibility from the password happens after the caller's own value is read, so the two can now contradict each other and the inferred one wins. On trunk, visibility => 'public' sent alongside post_password => 'secret' hits case 'public' and the password is discarded. With this change it becomes case 'password', so the password is kept and the post is unstuck instead.

test_edit_post_prefers_the_password_over_a_contradicting_public_visibility() pins that. Both editors clear the password field when Public is selected, so the pair should not arrive from the UI, but edit_post() is reachable from bulk edit and Quick Edit too, and silently keeping a password where trunk dropped it is the kind of thing better written down than discovered later.

If that precedence is wrong, the fix is to infer only when the caller sent no visibility at all. Happy to change it either way, it is a one-line difference. @wildworks this may be relevant to the 2nd-opinion question, since it is a second behaviour the change alters beyond the sticky one.

Verification

Four new tests, negative control run rather than assumed. Against trunk's post.php with the tests kept, exactly two fail: the original inferred-visibility test and the precedence one. The three characterisation tests pass either way, which is what they are for.

Whole file: 56 tests, 125 assertions, 0 failures. The 6 warnings are the pre-existing E_DEPRECATED expectation notices in the test_post_exists_* tests. phpcs clean.

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.

2 participants