Fix _parsely_canonical_url storing an http scheme on https sites - #4487
Fix _parsely_canonical_url storing an http scheme on https sites#4487TrivediKavit wants to merge 2 commits into
_parsely_canonical_url storing an http scheme on https sites#4487Conversation
📝 WalkthroughWalkthroughThe change moves HTTPS normalization before canonical URL persistence. Integration tests verify HTTPS conversion on HTTPS sites and HTTP preservation on HTTP-only sites. ChangesCanonical URL persistence
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 PHPStan (2.2.7)The last release in the 1.12.x series with new features Since then more than 65 new PHPStan versions were released To learn about what you're missing out on, check out Upgrade today to PHPStan 2.2 or newer by using Invalid configuration: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
tests/Integration/RestAPI/Stats/EndpointStatsPostTest.php (1)
716-717: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueEnd each line comment with a period.
tests/Integration/RestAPI/Stats/EndpointStatsPostTest.php#L716-L717: make Line 716 a complete sentence ending with a period.tests/Integration/RestAPI/Stats/EndpointStatsPostTest.php#L724-L725: make Line 724 a complete sentence ending with a period.tests/Integration/RestAPI/Stats/EndpointStatsPostTest.php#L814-L815: make Line 814 a complete sentence ending with a period.As per path instructions, “Ensure each line comment concludes with a period.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/Integration/RestAPI/Stats/EndpointStatsPostTest.php` around lines 716 - 717, Update the comments at tests/Integration/RestAPI/Stats/EndpointStatsPostTest.php lines 716-717, 724-725, and 814-815 so each comment line forms a complete sentence ending with a period.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@tests/Integration/RestAPI/Stats/EndpointStatsPostTest.php`:
- Around line 716-717: Update the comments at
tests/Integration/RestAPI/Stats/EndpointStatsPostTest.php lines 716-717,
724-725, and 814-815 so each comment line forms a complete sentence ending with
a period.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 9ea03003-e909-4788-bf2b-c3a59d32ded9
📒 Files selected for processing (2)
src/rest-api/stats/trait-post-data.phptests/Integration/RestAPI/Stats/EndpointStatsPostTest.php
Description
While digging into an
http://URL that had turned up in_parsely_canonical_urlon an https-only site, we traced it back to the order of two blocks inPost_Data_Trait::extract_post_data().This moves the https normalization above the
set_canonical_url()call, so the URL that gets saved is the same normalized one already used for the response fields. It is a straight statement reorder, with no change to logic.Motivation and context
In
src/rest-api/stats/trait-post-data.php,$post_urlcomes from$item['url'], which is whatever the Parse.ly API returned. That is oftenhttp://for sites Parse.ly first crawled before an https migration. The meta was being written first, with the normalization running just after:So
rawUrl,dashUrl,idandurlall came out correct, and only the saved value kept the original scheme.Two things stop it from correcting itself:
The stored value sticks.
get_canonical_url_from_post()prefers the meta and only falls back toget_permalink()when it is empty, so once anhttpvalue is written it keeps winning over the correct permalink.Nothing further down catches it either.
set_canonical_url()runs the value throughsanitize_url( $canonical_url, array( 'http', 'https' ) ), which allowshttp, andget_canonical_url()only swaps the host for the Site ID without looking at the scheme. From there it reachescanonical_urlin the REST metadata endpoint and the Smart Links suggestion payloads, so those can end up carrying anhttpcanonical for an https page.It is also written when the stats sidebar loads rather than on save, which makes it hard to attribute. We found it on a post that had not been edited for five days.
A note on scope
Utils::get_post_id_by_url( $item['url'] )still uses the original, unnormalized URL. It works as it is, and changing it could affect post matching, so it seemed better left alone.A broader fix would be to normalize inside
set_canonical_url(), which would also cover the two callers insrc/Models/class-smart-link.php(lines 670 and 699) that take a caller-supplied URL and look to have the same exposure. That changes the behavior of a public static method, so we left it as your call. Happy to switch if you would prefer it.Either way, meta already written by affected versions will not fix itself, because of the precedence above. Normalizing on read in
get_canonical_url_from_post(), or a small migration, would clear those out. Happy to add either if useful.How has this been tested?
There are two new tests in
EndpointStatsPostTest.php, one for each side of theUtils::parsely_is_https_supported()condition. Both mockpre_http_requestto return anhttp://URL for a test post, dispatch the endpoint, and check the saved_parsely_canonical_url. They assert on the scheme rather than the whole URL, to stay clear of the Site ID host swap inget_canonical_url().test_get_details_stores_canonical_url_with_https_schemeforceshome_url()andsite_url()to https, and expects the saved value to behttps://.test_get_details_keeps_http_canonical_url_without_https_supportleaves the site http-only, and expects the saved value to stayhttp://.The second test guards the http-only path, which this change should leave exactly as it was.
Run against the unfixed code, the https test fails and the http-only one still passes:
With the fix, both pass. So the only behavior that changes is the https case.
The tests are in the first commit and the fix in the second, which does mean the first commit is red on its own. Happy to squash or reorder if you would rather it were not.
Everything run locally against
wp-env, on PHP 8.3 with WordPress 7.0.2:composer testwp: 497 tests, 1509 assertions, no failures. The 3 skips are the usual multisite ones on a single-site run.composer cs: clean.php lint.php: clean.vendor/bin/phpstan analyse: 21 errors, but all of them are already there ondevelopwith these changes stashed, so none are introduced here. They look to be an artifact of running the analysis on PHP 8.3 while the project targets 7.4, and phpstan does not appear to run in CI. Glad to look at them separately if that would be useful.CanonicalURLsTest.phpalso still passes untouched, which is what we would expect givenset_canonical_url()itself is unchanged.Thanks for taking a look.
Screenshots (if appropriate)
N/A
Summary by CodeRabbit
Bug Fixes
Tests