From 77084baa288589c010649f51f6a0132650e1120a Mon Sep 17 00:00:00 2001 From: Max Schmeling Date: Mon, 26 Jan 2026 15:48:48 -0600 Subject: [PATCH 1/4] Support staged roll-out for the RTC integration --- integrations/real-time-collaboration.php | 53 ++++++++++++------- .../test-real-time-collaboration.php | 12 ++--- 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/integrations/real-time-collaboration.php b/integrations/real-time-collaboration.php index 0580517ccb..e93ad0b42c 100644 --- a/integrations/real-time-collaboration.php +++ b/integrations/real-time-collaboration.php @@ -8,6 +8,19 @@ namespace Automattic\VIP\Integrations; +/** + * Version of the vip-real-time-collaboration plugin to load. + * Used to control staged rollouts (e.g., staging gets new version first). + */ +const VIP_RTC_PLUGIN_VERSION = '0.1'; + +/** + * Version of the Gutenberg plugin to load. + * Empty string means load from the unversioned 'gutenberg' folder. + * A version number (e.g., '1.0') loads from 'gutenberg-1.0' folder. + */ +const VIP_RTC_GUTENBERG_VERSION = ''; + /** * Loads Real-Time Collaboration VIP Integration. * @@ -50,8 +63,20 @@ private function can_load(): bool { return true; } + /** + * Get the path to the Gutenberg plugin. + * + * @return string|false The path to the Gutenberg plugin, or false if not found. + */ private function get_gutenberg_path(): string|false { - $gutenberg_path = WPVIP_MU_PLUGIN_DIR . '/vip-integrations/gutenberg/gutenberg.php'; + // Empty string means use the unversioned folder + if ( '' === VIP_RTC_GUTENBERG_VERSION ) { + $gutenberg_folder = 'gutenberg'; + } else { + $gutenberg_folder = 'gutenberg-' . VIP_RTC_GUTENBERG_VERSION; + } + + $gutenberg_path = WPVIP_MU_PLUGIN_DIR . '/vip-integrations/' . $gutenberg_folder . '/gutenberg.php'; if ( ! file_exists( $gutenberg_path ) ) { return false; } @@ -59,14 +84,15 @@ private function get_gutenberg_path(): string|false { return $gutenberg_path; } + /** + * Get the path to the RTC plugin. + * + * @return string|false The path to the RTC plugin, or false if not found. + */ private function get_plugin_path(): string|false { - $latest_directory = $this->get_latest_version(); - if ( empty( $latest_directory ) ) { - return false; - } - // Load the plugin. - $load_path = WPVIP_MU_PLUGIN_DIR . '/vip-integrations/' . $latest_directory . '/vip-real-time-collaboration.php'; - // This check isn't strictly necessary, but better safe than sorry. + $plugin_directory = 'vip-real-time-collaboration-' . VIP_RTC_PLUGIN_VERSION; + + $load_path = WPVIP_MU_PLUGIN_DIR . '/vip-integrations/' . $plugin_directory . '/vip-real-time-collaboration.php'; if ( ! file_exists( $load_path ) ) { return false; } @@ -110,22 +136,13 @@ public function load(): void { /** * Load the custom build of Gutenberg from vip-integrations - * and the latest version of the vip-real-time-collaboration plugin. + * and the configured version of the vip-real-time-collaboration plugin. */ require_once $gutenberg_path; require_once $load_path; }, 1); } - /** - * Get the latest version of Real-Time Collaboration. - * - * @return string|null The latest version of Real-Time Collaboration or null if no versions are found. - */ - public function get_latest_version() { - return get_latest_version( WPVIP_MU_PLUGIN_DIR . '/vip-integrations/', 'vip-real-time-collaboration', 'vip-real-time-collaboration.php' ); - } - /** * Configure Real-Time Collaboration for VIP Platform. * diff --git a/tests/integrations/test-real-time-collaboration.php b/tests/integrations/test-real-time-collaboration.php index e05fc19115..0f9fdd951e 100644 --- a/tests/integrations/test-real-time-collaboration.php +++ b/tests/integrations/test-real-time-collaboration.php @@ -55,7 +55,7 @@ public function test_load_returns_early_if_plugin_already_loaded(): void { do_action( 'plugins_loaded' ); } - public function test_load_sets_inactive_if_no_versions_found(): void { + public function test_load_sets_inactive_if_plugin_file_not_found(): void { // Set up required constants Constant_Mocker::define( 'VIP_RTC_WS_AUTH_SECRET', 'test-secret' ); Constant_Mocker::define( 'VIP_RTC_WS_URL', 'wss://test.example.com' ); @@ -150,11 +150,11 @@ public function test_configure_handles_missing_config_values(): void { $this->assertFalse( defined( 'VIP_RTC_WS_URL' ) ); } - public function test_get_latest_version_returns_null_when_no_versions_are_found(): void { - $rtc_integration = new RealTimeCollaborationIntegration( $this->slug ); - $latest_version = $rtc_integration->get_latest_version(); - - $this->assertNull( $latest_version ); + public function test_version_constants_are_defined(): void { + $this->assertTrue( defined( 'Automattic\VIP\Integrations\VIP_RTC_PLUGIN_VERSION' ) ); + $this->assertTrue( defined( 'Automattic\VIP\Integrations\VIP_RTC_GUTENBERG_VERSION' ) ); + $this->assertSame( '0.1', VIP_RTC_PLUGIN_VERSION ); + $this->assertSame( '', VIP_RTC_GUTENBERG_VERSION ); } public function test_load_sets_inactive_when_ws_auth_secret_missing(): void { From 876442a1e774be6b40c7a61f9d7e7b41ea9ad629 Mon Sep 17 00:00:00 2001 From: Max Schmeling Date: Mon, 26 Jan 2026 15:59:35 -0600 Subject: [PATCH 2/4] Remove unnecessary test --- tests/integrations/test-real-time-collaboration.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/integrations/test-real-time-collaboration.php b/tests/integrations/test-real-time-collaboration.php index 0f9fdd951e..1cb4e15660 100644 --- a/tests/integrations/test-real-time-collaboration.php +++ b/tests/integrations/test-real-time-collaboration.php @@ -150,13 +150,6 @@ public function test_configure_handles_missing_config_values(): void { $this->assertFalse( defined( 'VIP_RTC_WS_URL' ) ); } - public function test_version_constants_are_defined(): void { - $this->assertTrue( defined( 'Automattic\VIP\Integrations\VIP_RTC_PLUGIN_VERSION' ) ); - $this->assertTrue( defined( 'Automattic\VIP\Integrations\VIP_RTC_GUTENBERG_VERSION' ) ); - $this->assertSame( '0.1', VIP_RTC_PLUGIN_VERSION ); - $this->assertSame( '', VIP_RTC_GUTENBERG_VERSION ); - } - public function test_load_sets_inactive_when_ws_auth_secret_missing(): void { Constant_Mocker::define( 'VIP_RTC_WS_URL', 'wss://test.example.com' ); // VIP_RTC_WS_AUTH_SECRET is intentionally not defined From 41b6753e807a33b930e941f88d76604da58107dd Mon Sep 17 00:00:00 2001 From: Max Schmeling Date: Mon, 26 Jan 2026 16:32:34 -0600 Subject: [PATCH 3/4] Add defined() check for constants before accessing --- integrations/real-time-collaboration.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/integrations/real-time-collaboration.php b/integrations/real-time-collaboration.php index e93ad0b42c..2d807e2605 100644 --- a/integrations/real-time-collaboration.php +++ b/integrations/real-time-collaboration.php @@ -69,6 +69,10 @@ private function can_load(): bool { * @return string|false The path to the Gutenberg plugin, or false if not found. */ private function get_gutenberg_path(): string|false { + if ( ! defined( 'VIP_RTC_GUTENBERG_VERSION' ) ) { + return false; + } + // Empty string means use the unversioned folder if ( '' === VIP_RTC_GUTENBERG_VERSION ) { $gutenberg_folder = 'gutenberg'; @@ -90,6 +94,10 @@ private function get_gutenberg_path(): string|false { * @return string|false The path to the RTC plugin, or false if not found. */ private function get_plugin_path(): string|false { + if ( ! defined( 'VIP_RTC_PLUGIN_VERSION' ) ) { + return false; + } + $plugin_directory = 'vip-real-time-collaboration-' . VIP_RTC_PLUGIN_VERSION; $load_path = WPVIP_MU_PLUGIN_DIR . '/vip-integrations/' . $plugin_directory . '/vip-real-time-collaboration.php'; From 6b8a19b371cbbcef12be0c59efa089b92d6a00d1 Mon Sep 17 00:00:00 2001 From: Max Schmeling Date: Mon, 26 Jan 2026 16:56:54 -0600 Subject: [PATCH 4/4] Update defined check --- integrations/real-time-collaboration.php | 42 +++++++++++------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/integrations/real-time-collaboration.php b/integrations/real-time-collaboration.php index 2d807e2605..f31062dafa 100644 --- a/integrations/real-time-collaboration.php +++ b/integrations/real-time-collaboration.php @@ -8,25 +8,25 @@ namespace Automattic\VIP\Integrations; -/** - * Version of the vip-real-time-collaboration plugin to load. - * Used to control staged rollouts (e.g., staging gets new version first). - */ -const VIP_RTC_PLUGIN_VERSION = '0.1'; - -/** - * Version of the Gutenberg plugin to load. - * Empty string means load from the unversioned 'gutenberg' folder. - * A version number (e.g., '1.0') loads from 'gutenberg-1.0' folder. - */ -const VIP_RTC_GUTENBERG_VERSION = ''; - /** * Loads Real-Time Collaboration VIP Integration. * * @private */ class RealTimeCollaborationIntegration extends Integration { + /** + * Version of the vip-real-time-collaboration plugin to load. + * Used to control staged rollouts (e.g., staging gets new version first). + */ + const VIP_RTC_PLUGIN_VERSION = '0.1'; + + /** + * Version of the Gutenberg plugin to load. + * Empty string means load from the unversioned 'gutenberg' folder. + * A version number (e.g., '1.0') loads from 'gutenberg-1.0' folder. + */ + const VIP_RTC_GUTENBERG_VERSION = ''; + /** * Enable Pendo tracking for this integration. * @@ -69,15 +69,13 @@ private function can_load(): bool { * @return string|false The path to the Gutenberg plugin, or false if not found. */ private function get_gutenberg_path(): string|false { - if ( ! defined( 'VIP_RTC_GUTENBERG_VERSION' ) ) { - return false; - } - // Empty string means use the unversioned folder - if ( '' === VIP_RTC_GUTENBERG_VERSION ) { + if ( defined( 'VIP_RTC_GUTENBERG_VERSION' ) && '' === constant( 'VIP_RTC_GUTENBERG_VERSION' ) ) { $gutenberg_folder = 'gutenberg'; + } elseif ( defined( 'VIP_RTC_GUTENBERG_VERSION' ) && '' !== constant( 'VIP_RTC_GUTENBERG_VERSION' ) ) { + $gutenberg_folder = 'gutenberg-' . constant( 'VIP_RTC_GUTENBERG_VERSION' ); } else { - $gutenberg_folder = 'gutenberg-' . VIP_RTC_GUTENBERG_VERSION; + return false; } $gutenberg_path = WPVIP_MU_PLUGIN_DIR . '/vip-integrations/' . $gutenberg_folder . '/gutenberg.php'; @@ -94,12 +92,12 @@ private function get_gutenberg_path(): string|false { * @return string|false The path to the RTC plugin, or false if not found. */ private function get_plugin_path(): string|false { - if ( ! defined( 'VIP_RTC_PLUGIN_VERSION' ) ) { + if ( defined( 'VIP_RTC_PLUGIN_VERSION' ) ) { + $plugin_directory = 'vip-real-time-collaboration-' . constant( 'VIP_RTC_PLUGIN_VERSION' ); + } else { return false; } - $plugin_directory = 'vip-real-time-collaboration-' . VIP_RTC_PLUGIN_VERSION; - $load_path = WPVIP_MU_PLUGIN_DIR . '/vip-integrations/' . $plugin_directory . '/vip-real-time-collaboration.php'; if ( ! file_exists( $load_path ) ) { return false;