Commit d77c01ce462 for woocommerce
commit d77c01ce46285af05ed7ce0bf14b5569971f671a
Author: daledupreez <dale@automattic.com>
Date: Wed Jun 24 20:39:13 2026 +0200
Rename plan_groups app_id column to extension_slug in subscriptions engine (#65959)
* Rename app_id to extension_slug in plan_groups
* Changelog
* Fix indentation
diff --git a/packages/php/woocommerce-subscriptions-engine/changelog/fix-subscriptions-engine-plan-group-column-name b/packages/php/woocommerce-subscriptions-engine/changelog/fix-subscriptions-engine-plan-group-column-name
new file mode 100644
index 00000000000..a76434e6a0b
--- /dev/null
+++ b/packages/php/woocommerce-subscriptions-engine/changelog/fix-subscriptions-engine-plan-group-column-name
@@ -0,0 +1,4 @@
+Significance: major
+Type: dev
+
+Rename app_id column to extension slug for plan groups
diff --git a/packages/php/woocommerce-subscriptions-engine/src/Core/Entity/PlanGroup.php b/packages/php/woocommerce-subscriptions-engine/src/Core/Entity/PlanGroup.php
index a3714b72349..b0b62a2b537 100644
--- a/packages/php/woocommerce-subscriptions-engine/src/Core/Entity/PlanGroup.php
+++ b/packages/php/woocommerce-subscriptions-engine/src/Core/Entity/PlanGroup.php
@@ -4,7 +4,7 @@
*
* `merchant_code` is an optional stable external identifier; when present it is
* unique at the storage layer and is the deduplication key consumers use to
- * make group creation idempotent. `app_id` scopes a group to a solution family.
+ * make group creation idempotent. `extension_slug` scopes a group to a specific extension.
*
* @package Automattic\WooCommerce\SubscriptionsEngine\Core\Entity
*/
@@ -56,11 +56,11 @@ final class PlanGroup {
private $options_display;
/**
- * Solution-family scope, e.g. a third-party app slug.
+ * Extension slug, e.g. a third-party extension slug.
*
* @var string|null
*/
- private $app_id;
+ private $extension_slug;
/**
* Use {@see self::create()} or {@see self::from_storage()}.
@@ -69,14 +69,14 @@ final class PlanGroup {
* @param string $name Display name.
* @param string|null $merchant_code Optional stable external identifier.
* @param array<int, mixed> $options_display Display ordering metadata.
- * @param string|null $app_id Solution-family scope.
+ * @param string|null $extension_slug Extension slug.
*/
- private function __construct( ?int $id, string $name, ?string $merchant_code, array $options_display, ?string $app_id ) {
+ private function __construct( ?int $id, string $name, ?string $merchant_code, array $options_display, ?string $extension_slug ) {
$this->id = $id;
$this->name = $name;
$this->merchant_code = $merchant_code;
$this->options_display = $options_display;
- $this->app_id = $app_id;
+ $this->extension_slug = $extension_slug;
}
/**
@@ -90,7 +90,7 @@ final class PlanGroup {
self::coerce_string( $args['name'] ?? null ),
self::coerce_nullable_string( $args['merchant_code'] ?? null ),
is_array( $args['options_display'] ?? null ) ? $args['options_display'] : array(),
- self::coerce_nullable_string( $args['app_id'] ?? null )
+ self::coerce_nullable_string( $args['extension_slug'] ?? null )
);
}
@@ -105,7 +105,7 @@ final class PlanGroup {
self::coerce_string( $row['name'] ?? null ),
self::coerce_nullable_string( $row['merchant_code'] ?? null ),
is_array( $row['options_display'] ?? null ) ? $row['options_display'] : array(),
- self::coerce_nullable_string( $row['app_id'] ?? null )
+ self::coerce_nullable_string( $row['extension_slug'] ?? null )
);
}
@@ -167,10 +167,10 @@ final class PlanGroup {
}
/**
- * Solution-family scope.
+ * Extension slug.
*/
- public function get_app_id(): ?string {
- return $this->app_id;
+ public function get_extension_slug(): ?string {
+ return $this->extension_slug;
}
/**
@@ -183,7 +183,7 @@ final class PlanGroup {
'name' => $this->name,
'merchant_code' => $this->merchant_code,
'options_display' => $this->options_display,
- 'app_id' => $this->app_id,
+ 'extension_slug' => $this->extension_slug,
);
}
}
diff --git a/packages/php/woocommerce-subscriptions-engine/src/Integration/Storage/PlanGroupRepository.php b/packages/php/woocommerce-subscriptions-engine/src/Integration/Storage/PlanGroupRepository.php
index e52589418c9..c93c2126b0c 100644
--- a/packages/php/woocommerce-subscriptions-engine/src/Integration/Storage/PlanGroupRepository.php
+++ b/packages/php/woocommerce-subscriptions-engine/src/Integration/Storage/PlanGroupRepository.php
@@ -40,7 +40,7 @@ final class PlanGroupRepository {
'name' => $data['name'],
'merchant_code' => $data['merchant_code'],
'options_display' => wp_json_encode( $data['options_display'] ),
- 'app_id' => $data['app_id'],
+ 'extension_slug' => $data['extension_slug'],
'date_created_gmt' => $now,
'date_updated_gmt' => $now,
)
diff --git a/packages/php/woocommerce-subscriptions-engine/src/Integration/Storage/SchemaInstaller.php b/packages/php/woocommerce-subscriptions-engine/src/Integration/Storage/SchemaInstaller.php
index 878140b7af9..7b288ba0f89 100644
--- a/packages/php/woocommerce-subscriptions-engine/src/Integration/Storage/SchemaInstaller.php
+++ b/packages/php/woocommerce-subscriptions-engine/src/Integration/Storage/SchemaInstaller.php
@@ -32,13 +32,14 @@ final class SchemaInstaller {
* 2.0.0 - cycle-chain model: contract as live source of truth (schedule, snapshot
* references, totals, stamps); immutable cycle records keyed on
* `(contract_id, kind)`; per-contract snapshots deduped by copy-forward.
+ * 2.1.0 - rename `app_id` to `extension_slug` in plan_groups table.
*
* Pre-freeze, tables are recreated rather than migrated. dbDelta adds columns but
* does not change an existing column's nullability or drop unused ones, so a dev box
* on an earlier schema must drop and recreate the tables (and clear VERSION_OPTION)
* to pick up such changes - in-place ALTERs and backfills arrive with the freeze.
*/
- const VERSION = '2.0.0';
+ const VERSION = '2.1.0';
/**
* Option key tracking the installed schema version.
@@ -179,12 +180,12 @@ final class SchemaInstaller {
name VARCHAR(255) NOT NULL,
merchant_code VARCHAR(64) NULL,
options_display JSON NULL,
- app_id VARCHAR(64) NULL,
+ extension_slug VARCHAR(64) NULL,
date_created_gmt DATETIME NOT NULL,
date_updated_gmt DATETIME NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY merchant_code (merchant_code),
- KEY app_id (app_id)
+ KEY extension_slug (extension_slug)
) {$collate};";
// `extension_slug` records the creating extension's registered slug. Nullable
diff --git a/packages/php/woocommerce-subscriptions-engine/tests/integration/Integration/Storage/PlanRepositoryTest.php b/packages/php/woocommerce-subscriptions-engine/tests/integration/Integration/Storage/PlanRepositoryTest.php
index 5a5d0fb0758..17f93ac5de5 100644
--- a/packages/php/woocommerce-subscriptions-engine/tests/integration/Integration/Storage/PlanRepositoryTest.php
+++ b/packages/php/woocommerce-subscriptions-engine/tests/integration/Integration/Storage/PlanRepositoryTest.php
@@ -43,7 +43,7 @@ class PlanRepositoryTest extends EngineIntegrationTestCase {
'name' => 'Boxes',
'merchant_code' => 'boxes',
'options_display' => array( array( 'name' => 'Size' ) ),
- 'app_id' => 'wc-subscriptions',
+ 'extension_slug' => 'wc-subscriptions',
)
)
);
@@ -54,7 +54,7 @@ class PlanRepositoryTest extends EngineIntegrationTestCase {
$this->assertSame( $id, $fetched->get_id() );
$this->assertSame( 'Boxes', $fetched->get_name() );
$this->assertSame( 'boxes', $fetched->get_merchant_code() );
- $this->assertSame( 'wc-subscriptions', $fetched->get_app_id() );
+ $this->assertSame( 'wc-subscriptions', $fetched->get_extension_slug() );
$this->assertSame( array( array( 'name' => 'Size' ) ), $fetched->get_options_display() );
}