Skip to content

Merges the feature branch into trunk#23424

Merged
JorPV merged 295 commits into
trunkfrom
feature/bulk-editor
Jul 3, 2026
Merged

Merges the feature branch into trunk#23424
JorPV merged 295 commits into
trunkfrom
feature/bulk-editor

Conversation

@thijsoo

@thijsoo thijsoo commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Context

  • We want to prepare the 28.1 release by merging the feature branch feature/bulk-editor to trunk.

Summary

This PR can be summarized in the following changelog entry:

  • Redesigns the bulk editor page, which allows users to edit Metadata for multiple posts at once.

Relevant technical choices:

Test instructions

Test instructions for the acceptance test before the PR gets merged

This PR can be acceptance tested by following these steps:

  • There is a test plan in place for this feature so no specific instructions needed in the PR.

Relevant test scenarios

  • Changes should be tested with the browser console open
  • Changes should be tested on different posts/pages/taxonomies/custom post types/custom taxonomies
  • Changes should be tested on different editors (Default Block/Gutenberg/Classic/Elementor/other)
  • Changes should be tested on different browsers
  • Changes should be tested on multisite

Test instructions for QA when the code is in the RC

  • QA should use the same steps as above.

QA can test this PR by following these steps:

Impact check

This PR affects the following parts of the plugin, which may require extra testing:

Other environments

  • This PR also affects Shopify. I have added a changelog entry starting with [shopify-seo], added test instructions for Shopify and attached the Shopify label to this PR.
  • This PR also affects Yoast SEO for Google Docs. I have added a changelog entry starting with [yoast-doc-extension], added test instructions for Yoast SEO for Google Docs and attached the Google Docs Add-on label to this PR.

Documentation

  • I have written documentation for this change. For example, comments in the Relevant technical choices, comments in the code, documentation on Confluence / shared Google Drive / Yoast developer portal, or other.

Quality assurance

  • I have tested this code to the best of my abilities.
  • During testing, I had activated all plugins that Yoast SEO provides integrations for.
  • I have added unit tests to verify the code works as intended.
  • If any part of the code is behind a feature flag, my test instructions also cover cases where the feature flag is switched off.
  • I have written this PR in accordance with my team's definition of done.
  • I have checked that the base branch is correctly set.
  • I have run grunt build:images and committed the results, if my PR introduces or edits images or SVGs.

Innovation

  • No innovation project is applicable for this PR.
  • This PR falls under an innovation project. I have attached the innovation label.
  • I have added my hours to the WBSO document.

Fixes #

JorPV and others added 30 commits June 5, 2026 08:41
Verifies the Search and Social field sets, their labels, the field
key/label mappings, and that each call returns a fresh object.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ntions

Sources the field set ids from the central constants, removes the
PropTypes per the React 19 convention, and sizes the loading skeleton
to the new shared PAGE_SIZE so the loading state matches a full page.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replaces the tab panel placeholders with the field-set data table,
deriving the tabs from the field sets so both share one source. The
rows come from a temporary 20-row fixture matching the design's page
size until the list endpoint (Free-BE) feeds the provider.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add PSR-3 logging to the bulk update flow following the myyoast-client
pattern: classes implement LoggerAwareInterface and default to a
NullLogger, with the real Logger auto-injected by Logger_Aware_Pass.

Bulk_Updater now logs a warning with the post id and exception message
when a meta write throws, which was previously swallowed silently behind
the SAVE_FAILED result. The route logs the incoming batch and each
validation rejection at debug level to aid request debugging.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Jordi-PV <88150345+JorPV@users.noreply.github.com>
Co-authored-by: Jordi-PV <88150345+JorPV@users.noreply.github.com>
The getters return an empty string (not undefined) for unknown ids,
which silently defeats ?? fallbacks; spell that out in the JSDoc.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Aligns the new bulk edit Tools page with the existing legacy bulk editor,
which is gated at the menu level by wpseo_manage_options. The previously
used wpseo_bulk_edit capability is registered but dormant and gates nothing
elsewhere; per-post authorization is still handled separately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The collector now skips post types with show_ui === false, but the test
fixtures had no show_ui property, causing an undefined-property error.
Adds show_ui to the fixtures and a case asserting UI-less types are skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…m:Yoast/wordpress-seo into bulk-editor/page-title-search-social-tabs
…m:Yoast/wordpress-seo into bulk-editor/page-title-search-social-tabs
…tegration

feat(bulk-editor): scaffold bulk edit page and React provider seam
…cial-tabs' into bulk-editor/page-title-search-social-tabs
…cial-tabs

Add Bulk editor page header and Search/Social appearance tabs
- Move the select-all checkbox out of the column header row into the
  multi-select toolbar row, where Free-FE 9 adds the Select menu and
  Free-FE 7 the Filters button.
- Name the row-checkbox column for assistive tech only; the design
  shows no visible header for it.
- Render the content status as plain muted text instead of a badge,
  limited to the design's status vocabulary (draft, pending, future).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Match the Support/Settings page construction: responsive page padding,
the navigation in an aside, the content column growing up to
max-w-page (instead of capping the layout at max-w-7xl), and the card
as the main landmark.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
thijsoo and others added 8 commits June 30, 2026 14:56
feat(bulk-editor): expose unsaved-edits state to the bulk-actions slot
…-suggested-pending-changes-alert

feat(bulk-editor): add pending-changes guard seam for external plugins
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…dpress-seo into bulk-editor/add-learnmore-link
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add learn more link to the bulk editor AI upsell modal
@thijsoo thijsoo added the changelog: enhancement Needs to be included in the 'Enhancements' category in the changelog label Jul 1, 2026
@thijsoo thijsoo marked this pull request as ready for review July 1, 2026 09:27
@thijsoo thijsoo requested a review from a team as a code owner July 1, 2026 09:27
@coveralls

coveralls commented Jul 1, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 815133

Warning

Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes.
Quick fix: rebase this PR. Learn more →

Coverage increased (+1.4%) to 55.017%

Details

  • Coverage increased (+1.4%) from the base build.
  • Patch coverage: 102 uncovered changes across 21 files (994 of 1096 lines covered, 90.69%).
  • 78 coverage regressions across 7 files.

Uncovered Changes

Top 10 Files by Coverage Impact Changed Covered %
src/bulk-editor/infrastructure/posts/post-meta-posts-collector.php 57 18 31.58%
src/bulk-editor/infrastructure/posts/searchable-fields-trait.php 8 0 0.0%
admin/pages/tools.php 7 0 0.0%
src/bulk-editor/user-interface/search-bulk-update-route.php 8 2 25.0%
src/bulk-editor/user-interface/social-bulk-update-route.php 8 2 25.0%
src/bulk-editor/user-interface/abstract-bulk-update-route.php 84 79 94.05%
packages/js/src/bulk-editor/components/table/table-row.js 28 24 85.71%
src/bulk-editor/application/posts/posts-repository.php 8 4 50.0%
packages/js/src/bulk-editor/components/bulk-editor-content.js 44 41 93.18%
src/bulk-editor/user-interface/posts-route.php 81 78 96.3%
Total (67 files) 1096 994 90.69%

Coverage Regressions

78 previously-covered lines in 7 files lost coverage.

File Lines Losing Coverage Coverage
src/ai-authorization/application/token-manager.php 46 0.0%
src/ai-consent/application/consent-handler.php 17 0.0%
src/ai/authentication/application/ai-request-sender-factory.php 4 82.14%
src/integrations/admin/integrations-page.php 3 80.0%
src/ai/authorization/application/token-manager.php 3 90.8%
admin/class-admin-asset-manager.php 3 15.79%
admin/pages/tools.php 2 0.0%

Coverage Stats

Coverage Status
Relevant Lines: 71646
Covered Lines: 39299
Line Coverage: 54.85%
Relevant Branches: 18537
Covered Branches: 10317
Branch Coverage: 55.66%
Branches in Coverage %: Yes
Coverage Strength: 42005.43 hits per line

💛 - Coveralls

thijsoo and others added 11 commits July 1, 2026 15:12
Update the bulk AI upsell body text to mention products, posts and pages,
and expose the UpsellModal and useAiUpsell on window.yoast.bulkEditor so
Premium can reuse the same modal for its WooCommerce SEO subscription
upsell instead of duplicating it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the upsell body copy into useAiUpsell so the product-specific text
("products, posts, pages and more") is shown only for the product content
type, while all other content types keep the original generic copy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ange

Previously only a status-filter change reset the row selection. A search
change or content-type switch also changes which rows are shown, so a bulk
action could still act on rows the user can no longer see. Consolidate all
three resets in the selection slice and drop the separate content-type
reset effect from the content component.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rename the per-cell slot fill prop onApplied to onFieldApplied to match its
sibling props onSaveField and onDiscardField, and expose the underlying
editing setter under the same on-handler name for consistency.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…inline-feedback

# Conflicts:
#	packages/js/src/bulk-editor/components/bulk-editor-content.js
The non-product upsell body copy was duplicated in the useAiUpsell hook
and as the UpsellModal default description. Move it to a single
AI_UPSELL_DESCRIPTION constant so both reference one source of truth.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(bulk-editor): clear selection on filter change and expose onApplied slot prop
…-modal

feat(bulk-editor): update AI upsell copy and expose modal for Premium
style(bulk-editor): add page styles for Premium AI error notices
@JorPV JorPV modified the milestones: 28.0, 28.1 Jul 3, 2026
@JorPV JorPV added the innovation Innovative issue. Relating to performance, memory or data-flow. label Jul 3, 2026
@JorPV JorPV merged commit dd0a35d into trunk Jul 3, 2026
48 checks passed
@JorPV JorPV deleted the feature/bulk-editor branch July 3, 2026 09:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog: enhancement Needs to be included in the 'Enhancements' category in the changelog innovation Innovative issue. Relating to performance, memory or data-flow.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants