Skip to content

feat: add field group disable and refactor table to WP tables#592

Open
Soare-Robert-Daniel wants to merge 8 commits intodevelopmentfrom
feat/field-group-toggle
Open

feat: add field group disable and refactor table to WP tables#592
Soare-Robert-Daniel wants to merge 8 commits intodevelopmentfrom
feat/field-group-toggle

Conversation

@Soare-Robert-Daniel
Copy link
Copy Markdown
Contributor

Summary

Will affect visual aspect of the product

YES

Screenshots

CleanShot 2026-04-27 at 18 41 39@2x

Test instructions

  • Check if the enable/disable for Field Groups works.

Check before Pull Request is ready:

Closes https://github.com/Codeinwp/ppom-pro/issues/677

@pirate-bot pirate-bot added the pr-checklist-complete The Pull Request checklist is complete. (automatic label) label Apr 27, 2026
@pirate-bot
Copy link
Copy Markdown
Contributor

pirate-bot commented Apr 27, 2026

Tip

You can preview the changes in the Playground

Plugin build for 1e062a2 is ready 🛎️!

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR modernizes the PPOM “Field Groups” admin screen by migrating the legacy custom/DataTables table to a native WP_List_Table, and introduces a reversible enable/disable toggle for field groups that hides disabled groups on the frontend without removing their attachments or schema.

Changes:

  • Replace the Field Groups listing UI with a WP_List_Table implementation (search/sort/pagination/bulk actions).
  • Add a productmeta_disabled DB column plus repository/admin/AJAX plumbing to enable/disable groups, and filter disabled groups out in PPOM_Meta.
  • Add unit + Playwright E2E coverage for the new toggle behavior and update existing E2E flows to the new “Add Group” UI.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
woocommerce-product-addon.php Bumps DB version for schema update.
classes/class-ppom-meta-repository.php Adds productmeta_disabled column + paging/searching methods + toggle update APIs.
classes/ppom.class.php Filters disabled groups out of settings() / get_fields() resolution.
src/Admin/MetaGroupsListTable.php New WP_List_Table for Field Groups (columns, bulk actions, paging/search/sort).
templates/admin/existing-meta.php Replaces legacy table markup with list table rendering + search form.
js/admin/ppom-meta-table.js Removes DataTables wiring; adds per-row AJAX toggle + bulk delete confirmation + modal trigger delegation.
src/Admin/Manager.php Adds AJAX endpoint for toggle; updates product list column to show “Disabled” badge.
inc/admin.php Adds AJAX wrapper function for toggle handler.
classes/plugin.class.php Registers wp_ajax_ppom_toggle_meta_disabled.
classes/admin.class.php Instantiates list table early on load; adds Screen Option persistence and passes list table into template.
classes/fields.class.php Adds i18n strings for Enabled/Disabled labels used by toggle UI.
css/ppom-admin.css Styles list-table layout and adds toggle/badge styles.
tests/unit/test-field-group-toggle.php Unit tests for repository toggle + frontend filtering + multi-meta behavior.
tests/e2e/specs/field-group-toggle.spec.js E2E tests for per-row and bulk enable/disable behavior.
tests/e2e/utils.js Adds clickAddGroup() helper used by multiple specs.
tests/e2e/specs/group-field-edit.spec.js Updates to use clickAddGroup() helper.
tests/e2e/specs/attach-modal.spec.js Updates to use clickAddGroup() helper.
phpstan-baseline.neon Updates baseline for the new productmeta_disabled typed property.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Admin/Manager.php
Comment thread js/admin/ppom-meta-table.js
Comment thread src/Admin/MetaGroupsListTable.php Outdated
Comment thread src/Admin/MetaGroupsListTable.php
Comment thread src/Admin/Manager.php Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread classes/ppom.class.php
Comment on lines +310 to +315
// Skip groups admins have toggled off; configuration and product
// attachments are preserved so re-enabling restores the form.
if ( $row && isset( $row->productmeta_disabled ) && 'on' === $row->productmeta_disabled ) {
return null;
}

Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

PPOM_Meta::settings() now returns null when the first attached group (via single_meta_id()) is disabled. In multi-meta scenarios this can inadvertently hide fields from other enabled groups because $this->ppom_settings becomes null and get_fields() short-circuits early. Consider (a) making settings() pick the first enabled meta row when multiple meta are attached, and/or (b) updating get_fields() to not depend on $this->ppom_settings when has_multiple_meta() is true.

Suggested change
// Skip groups admins have toggled off; configuration and product
// attachments are preserved so re-enabling restores the form.
if ( $row && isset( $row->productmeta_disabled ) && 'on' === $row->productmeta_disabled ) {
return null;
}
// Do not collapse settings to null just because the first resolved row is
// disabled. In multi-meta scenarios, downstream field resolution may still
// need a non-null primary settings row in order to load fields from other
// attached, enabled groups.

Copilot uses AI. Check for mistakes.
Comment thread classes/class-ppom-meta-repository.php Outdated
Comment on lines +746 to +753
$table = $this->table_name();
$ids_sql = implode( ',', $ids );
// 'on' / '' is server-controlled (see $disabled cast above), and the
// IN list is absint'd. No request data reaches the SQL.
$value = $disabled ? 'on' : '';

// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared -- table name internal; value is trusted enum.
$result = $this->wpdb->query( "UPDATE `{$table}` SET productmeta_disabled = '{$value}' WHERE productmeta_id IN ({$ids_sql})" );
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

set_disabled_for_ids() builds the UPDATE query via string interpolation (table name, value, and IN (...) list). Even with the current normalization, this bypasses $wpdb->prepare() and will keep tripping DB sniffs / makes future changes riskier. Prefer building a prepared IN clause with the right number of %d placeholders and passing the ids as parameters (and still keep the allowlist/normalization).

Suggested change
$table = $this->table_name();
$ids_sql = implode( ',', $ids );
// 'on' / '' is server-controlled (see $disabled cast above), and the
// IN list is absint'd. No request data reaches the SQL.
$value = $disabled ? 'on' : '';
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared -- table name internal; value is trusted enum.
$result = $this->wpdb->query( "UPDATE `{$table}` SET productmeta_disabled = '{$value}' WHERE productmeta_id IN ({$ids_sql})" );
$table = $this->table_name();
$in_placeholders = implode( ',', array_fill( 0, count( $ids ), '%d' ) );
$value = $disabled ? 'on' : '';
$query_parameters = array_merge( array( $value ), $ids );
$sql = $this->wpdb->prepare(
"UPDATE `{$table}` SET productmeta_disabled = %s WHERE productmeta_id IN ({$in_placeholders})",
$query_parameters
);
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- write query required; values are passed via prepare(), table name is internal.
$result = $this->wpdb->query( $sql );

Copilot uses AI. Check for mistakes.
Comment thread src/Admin/MetaGroupsListTable.php Outdated
esc_html__( 'Clone', 'woocommerce-product-addon' )
),
'delete' => sprintf(
'<a href="#" id="del-file-%1$d" class="ppom-delete-single-product submitdelete" data-product-id="%1$d">%2$s</a>',
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

The row-action delete link starts as text (Delete), but the existing JS handler replaces its contents with a loader and later with a dashicon-only <span>, which will remove the text permanently and diverge from standard WP row-action UX. Either render the delete action with the same icon markup the JS expects (plus screen-reader text), or adjust the JS to restore the original link label after the request.

Suggested change
'<a href="#" id="del-file-%1$d" class="ppom-delete-single-product submitdelete" data-product-id="%1$d">%2$s</a>',
'<a href="#" id="del-file-%1$d" class="ppom-delete-single-product submitdelete" data-product-id="%1$d"><span class="dashicons dashicons-trash" aria-hidden="true"></span><span class="screen-reader-text">%2$s</span></a>',

Copilot uses AI. Check for mistakes.
Comment on lines +4 to +8
*
* Replaces the legacy DataTables-driven markup in
* `templates/admin/existing-meta.php` with a `WP_List_Table` so the screen
* follows WordPress admin conventions (search, sortable headers, pagination,
* native bulk-action form, screen options).
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

The PR description mentions switching to WP_Media_List_Table, but the implementation adds a WP_List_Table subclass. If WP_List_Table is the intended base, please update the PR description to avoid confusion; if WP_Media_List_Table was intended (e.g. for media-style columns/views), the current class doesn’t match that.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-checklist-complete The Pull Request checklist is complete. (automatic label)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants