From d19b66ce8613be71a17805b7bc1d362d5217da91 Mon Sep 17 00:00:00 2001 From: Ankit Gade Date: Tue, 21 Jan 2025 13:52:39 +0530 Subject: [PATCH 1/6] Add synchronization of RRM publication information. --- includes/Modules/Reader_Revenue_Manager.php | 4 +- .../Synchronize_OnboardingState.php | 163 ------------ .../Synchronize_Publication.php | 242 ++++++++++++++++++ ...st.php => Synchronize_PublicationTest.php} | 35 ++- 4 files changed, 270 insertions(+), 174 deletions(-) delete mode 100644 includes/Modules/Reader_Revenue_Manager/Synchronize_OnboardingState.php create mode 100644 includes/Modules/Reader_Revenue_Manager/Synchronize_Publication.php rename tests/phpunit/integration/Modules/Reader_Revenue_Manager/{Synchronize_OnboardingStateTest.php => Synchronize_PublicationTest.php} (78%) diff --git a/includes/Modules/Reader_Revenue_Manager.php b/includes/Modules/Reader_Revenue_Manager.php index 05a6e0e16d1..6bca7bc67aa 100644 --- a/includes/Modules/Reader_Revenue_Manager.php +++ b/includes/Modules/Reader_Revenue_Manager.php @@ -38,7 +38,7 @@ use Google\Site_Kit\Core\Util\URL; use Google\Site_Kit\Modules\Reader_Revenue_Manager\Post_Product_ID; use Google\Site_Kit\Modules\Reader_Revenue_Manager\Settings; -use Google\Site_Kit\Modules\Reader_Revenue_Manager\Synchronize_OnboardingState; +use Google\Site_Kit\Modules\Reader_Revenue_Manager\Synchronize_Publication; use Google\Site_Kit\Modules\Reader_Revenue_Manager\Tag_Guard; use Google\Site_Kit\Modules\Reader_Revenue_Manager\Tag_Matchers; use Google\Site_Kit\Modules\Reader_Revenue_Manager\Web_Tag; @@ -73,7 +73,7 @@ final class Reader_Revenue_Manager extends Module implements Module_With_Scopes, public function register() { $this->register_scopes_hook(); - $synchronize_onboarding_state = new Synchronize_OnboardingState( + $synchronize_onboarding_state = new Synchronize_Publication( $this, $this->user_options ); diff --git a/includes/Modules/Reader_Revenue_Manager/Synchronize_OnboardingState.php b/includes/Modules/Reader_Revenue_Manager/Synchronize_OnboardingState.php deleted file mode 100644 index f295d867a54..00000000000 --- a/includes/Modules/Reader_Revenue_Manager/Synchronize_OnboardingState.php +++ /dev/null @@ -1,163 +0,0 @@ -reader_revenue_manager = $reader_revenue_manager; - $this->user_options = $user_options; - } - - /** - * Registers functionality through WordPress hooks. - * - * @since 1.141.0 - * - * @return void - */ - public function register() { - add_action( - self::CRON_SYNCHRONIZE_ONBOARDING_STATE, - function () { - $this->synchronize_publication_data(); - } - ); - } - - /** - * Cron callback for synchronizing the publication. - * - * @since 1.141.0 - * - * @return void - */ - protected function synchronize_publication_data() { - $owner_id = $this->reader_revenue_manager->get_owner_id(); - $restore_user = $this->user_options->switch_user( $owner_id ); - - if ( user_can( $owner_id, Permissions::VIEW_AUTHENTICATED_DASHBOARD ) ) { - $this->synchronize_onboarding_state(); - } - - $restore_user(); - } - - /** - * Synchronizes the onboarding state. - * - * @since 1.141.0 - * - * @return void - */ - protected function synchronize_onboarding_state() { - $connected = $this->reader_revenue_manager->is_connected(); - - // If not connected, return early. - if ( ! $connected ) { - return; - } - - $settings = $this->reader_revenue_manager->get_settings()->get(); - $publication_id = $settings['publicationID']; - $onboarding_state = $settings['publicationOnboardingState']; - - if ( 'ONBOARDING_COMPLETE' !== $onboarding_state ) { - $publications = $this->reader_revenue_manager->get_data( 'publications' ); - - // If publications is empty, return early. - if ( empty( $publications ) ) { - return; - } - - $filtered_publications = array_filter( - $publications, - function ( $pub ) use ( $publication_id ) { - return $pub->getPublicationId() === $publication_id; - } - ); - - // If there are no filtered publications, return early. - if ( empty( $filtered_publications ) ) { - return; - } - - // Re-index the filtered array to ensure sequential keys. - $filtered_publications = array_values( $filtered_publications ); - $publication = $filtered_publications[0]; - - if ( $publication->getOnboardingState() !== $onboarding_state ) { - $this->reader_revenue_manager->get_settings()->merge( - array( - 'publicationOnboardingState' => $publication->getOnboardingState(), - 'publicationOnboardingStateChanged' => true, - ) - ); - } - } - } - - /** - * Maybe schedule the synchronize onboarding state cron event. - * - * @since 1.141.0 - * - * @return void - */ - public function maybe_schedule_synchronize_onboarding_state() { - $connected = $this->reader_revenue_manager->is_connected(); - $cron_already_scheduled = wp_next_scheduled( self::CRON_SYNCHRONIZE_ONBOARDING_STATE ); - - if ( $connected && ! $cron_already_scheduled ) { - wp_schedule_single_event( - time() + HOUR_IN_SECONDS, - self::CRON_SYNCHRONIZE_ONBOARDING_STATE - ); - } - } -} diff --git a/includes/Modules/Reader_Revenue_Manager/Synchronize_Publication.php b/includes/Modules/Reader_Revenue_Manager/Synchronize_Publication.php new file mode 100644 index 00000000000..d85a2db3454 --- /dev/null +++ b/includes/Modules/Reader_Revenue_Manager/Synchronize_Publication.php @@ -0,0 +1,242 @@ +reader_revenue_manager = $reader_revenue_manager; + $this->user_options = $user_options; + } + + /** + * Registers functionality through WordPress hooks. + * + * @since 1.141.0 + * + * @return void + */ + public function register() { + add_action( + self::CRON_SYNCHRONIZE_PUBLICATION, + function () { + $this->synchronize_publication_data(); + } + ); + } + + /** + * Cron callback for synchronizing the publication. + * + * @since 1.141.0 + * + * @return void + */ + protected function synchronize_publication_data() { + $owner_id = $this->reader_revenue_manager->get_owner_id(); + $restore_user = $this->user_options->switch_user( $owner_id ); + + if ( user_can( $owner_id, Permissions::VIEW_AUTHENTICATED_DASHBOARD ) ) { + $connected = $this->reader_revenue_manager->is_connected(); + + // If not connected, return early. + if ( ! $connected ) { + return; + } + + $settings = $this->reader_revenue_manager->get_settings()->get(); + $publication_id = $settings['publicationID']; + $publications = $this->reader_revenue_manager->get_data( 'publications' ); + + // If publications is empty, return early. + if ( empty( $publications ) ) { + return; + } + + $filtered_publications = array_filter( + $publications, + function ( $pub ) use ( $publication_id ) { + return $pub->getPublicationId() === $publication_id; + } + ); + + // If there are no filtered publications, return early. + if ( empty( $filtered_publications ) ) { + return; + } + + // Re-index the filtered array to ensure sequential keys. + $filtered_publications = array_values( $filtered_publications ); + $publication = $filtered_publications[0]; + $new_product_ids = array(); + $new_payment_options = array(); + $new_onboarding_state = $this->get_new_onboarding_state( $publication ); + + if ( Feature_Flags::enabled( 'rrmModuleV2' ) ) { + $new_product_ids = $this->get_new_product_ids( $publication ); + $new_payment_options = $this->get_new_payment_options( $publication ); + } + + $new_settings = array_merge( $new_onboarding_state, $new_product_ids, $new_payment_options ); + + if ( ! empty( $new_settings ) ) { + $this->reader_revenue_manager->get_settings()->merge( $new_settings ); + } + } + + $restore_user(); + } + + /** + * Returns the updated products IDs for the publication. + * + * @since n.e.x.t + * + * @param Publication $publication Publication object. + * @return array New product IDs. + */ + protected function get_new_product_ids( Publication $publication ) { + $new_product_ids = array(); + $settings = $this->reader_revenue_manager->get_settings()->get(); + $product_ids = $settings['productIDs']; + $products = $publication->getProducts(); + + if ( ! empty( $products ) ) { + $product_ids = array_map( + function ( $product ) { + $name = $product->getName(); + return substr( $name, strpos( $name, ':' ) + 1 ); + }, + $products + ); + + // Sort the array alphabetically in ascending order. + sort( $product_ids ); + $product_ids = array_values( $product_ids ); + + if ( ( count( $product_ids ) !== count( $settings['productIDs'] ) ) || ( $product_ids !== $settings['productIDs'] ) ) { + $new_product_ids = array( + 'productIDs' => $product_ids, + ); + } + } + + return $new_product_ids; + } + + /** + * Returns the new payment option for the publication. + * + * @since n.e.x.t + * + * @param Publication $publication Publication object. + * @return string New payment option. + */ + protected function get_new_payment_options( Publication $publication ) { + $settings = $this->reader_revenue_manager->get_settings()->get(); + $saved_payment_option = $settings['paymentOption']; + $current_payment_options = $publication->getPaymentOptions(); + + if ( $current_payment_options instanceof PaymentOptions ) { + foreach ( $current_payment_options as $property => $value ) { + if ( true === $value && $property !== $saved_payment_option ) { + return array( + 'paymentOption' => $property, + ); + } + } + } + + return array(); + } + + /** + * Returns the new onboarding state data. + * + * @since 1.141.0 + * + * @param Publication $publication Publication object. + * @return array New onboarding state data. + */ + protected function get_new_onboarding_state( Publication $publication ) { + $new_onboarding_state = array(); + $settings = $this->reader_revenue_manager->get_settings()->get(); + $onboarding_state = $settings['publicationOnboardingState']; + + if ( $publication->getOnboardingState() !== $onboarding_state ) { + $new_onboarding_state = array( + 'publicationOnboardingState' => $publication->getOnboardingState(), + 'publicationOnboardingStateChanged' => true, + ); + } + + return $new_onboarding_state; + } + + /** + * Maybe schedule the synchronize onboarding state cron event. + * + * @since 1.141.0 + * + * @return void + */ + public function maybe_schedule_synchronize_onboarding_state() { + $connected = $this->reader_revenue_manager->is_connected(); + $cron_already_scheduled = wp_next_scheduled( self::CRON_SYNCHRONIZE_PUBLICATION ); + + if ( $connected && ! $cron_already_scheduled ) { + wp_schedule_single_event( + time() + HOUR_IN_SECONDS, + self::CRON_SYNCHRONIZE_PUBLICATION + ); + } + } +} diff --git a/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_OnboardingStateTest.php b/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php similarity index 78% rename from tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_OnboardingStateTest.php rename to tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php index 59e01324e49..679c0aa5bc0 100644 --- a/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_OnboardingStateTest.php +++ b/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php @@ -15,7 +15,7 @@ use Google\Site_Kit\Core\Storage\Options; use Google\Site_Kit\Modules\Reader_Revenue_Manager; use Google\Site_Kit\Core\Storage\User_Options; -use Google\Site_Kit\Modules\Reader_Revenue_Manager\Synchronize_OnboardingState; +use Google\Site_Kit\Modules\Reader_Revenue_Manager\Synchronize_Publication; use Google\Site_Kit\Tests\Fake_Site_Connection_Trait; use Google\Site_Kit\Tests\ModulesHelperTrait; use Google\Site_Kit\Tests\TestCase; @@ -24,18 +24,19 @@ use Google\Site_Kit\Tests\FakeHttp; use Google\Site_Kit_Dependencies\Google\Service\SubscribewithGoogle\Publication; use Google\Site_Kit_Dependencies\Google\Service\SubscribewithGoogle\ListPublicationsResponse; +use Google\Site_Kit_Dependencies\Google\Service\SubscribewithGoogle\Product; /** * @group Modules * @group Reader_Revenue_Manager */ -class Synchronize_OnboardingStateTest extends TestCase { +class Synchronize_PublicationTest extends TestCase { use Fake_Site_Connection_Trait; use ModulesHelperTrait; /** - * @var Synchronize_OnboardingState + * @var Synchronize_Publication */ protected $synchronize_onboarding_state; @@ -87,11 +88,14 @@ public function set_up() { 'publicationID' => '123456789', 'publicationOnboardingState' => 'ONBOARDING_ACTION_REQUIRED', 'publicationOnboardingStateChanged' => false, + 'productID' => 'openaccess', + 'productIDs' => array(), + 'paymentOption' => '', 'ownerID' => $user_id, ), ); - $this->synchronize_onboarding_state = new Synchronize_OnboardingState( $this->reader_revenue_manager, $this->user_options ); + $this->synchronize_onboarding_state = new Synchronize_Publication( $this->reader_revenue_manager, $this->user_options ); } public function fake_sync_onboarding_state() { @@ -105,8 +109,21 @@ function ( Request $request ) use ( $publication_id ) { if ( '/v1/publications' === $url['path'] ) { $response = new ListPublicationsResponse(); $publication = new Publication(); + + $basic_product = new Product(); + $basic_product->setName( 'testpubID:basic' ); + + $advanced_product = new Product(); + $advanced_product->setName( 'testpubID:subscriptions' ); + $publication->setPublicationId( $publication_id ); $publication->setOnboardingState( 'ONBOARDING_COMPLETE' ); + $publication->setProducts( + array( + $basic_product, + $advanced_product, + ) + ); $response->setPublications( array( $publication ) ); return new Response( @@ -122,10 +139,10 @@ function ( Request $request ) use ( $publication_id ) { } public function test_register() { - remove_all_actions( Synchronize_OnboardingState::CRON_SYNCHRONIZE_ONBOARDING_STATE ); + remove_all_actions( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ); $this->synchronize_onboarding_state->register(); - $this->assertEquals( 10, has_action( Synchronize_OnboardingState::CRON_SYNCHRONIZE_ONBOARDING_STATE ) ); + $this->assertEquals( 10, has_action( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ) ); } public function test_cron_synchronize_publication_data() { @@ -138,18 +155,18 @@ public function test_cron_synchronize_publication_data() { $this->assertFalse( $settings['publicationOnboardingStateChanged'] ); - do_action( Synchronize_OnboardingState::CRON_SYNCHRONIZE_ONBOARDING_STATE ); + do_action( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ); $settings = $this->reader_revenue_manager->get_settings()->get(); $this->assertTrue( $settings['publicationOnboardingStateChanged'] ); } public function test_maybe_schedule_synchronize_onboarding_state() { - $this->assertFalse( wp_next_scheduled( Synchronize_OnboardingState::CRON_SYNCHRONIZE_ONBOARDING_STATE ) ); + $this->assertFalse( wp_next_scheduled( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ) ); $this->synchronize_onboarding_state->maybe_schedule_synchronize_onboarding_state(); $this->assertTrue( - (bool) wp_next_scheduled( Synchronize_OnboardingState::CRON_SYNCHRONIZE_ONBOARDING_STATE ) + (bool) wp_next_scheduled( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ) ); } } From c13c2d5e2b5a01efbdea2754cfdf14ddd0b15f3b Mon Sep 17 00:00:00 2001 From: Ankit Gade Date: Tue, 21 Jan 2025 16:48:42 +0530 Subject: [PATCH 2/6] Add tests for new methods. --- .../Synchronize_PublicationTest.php | 109 +++++++++++++++++- 1 file changed, 105 insertions(+), 4 deletions(-) diff --git a/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php b/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php index 679c0aa5bc0..89221bd4316 100644 --- a/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php +++ b/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php @@ -25,6 +25,7 @@ use Google\Site_Kit_Dependencies\Google\Service\SubscribewithGoogle\Publication; use Google\Site_Kit_Dependencies\Google\Service\SubscribewithGoogle\ListPublicationsResponse; use Google\Site_Kit_Dependencies\Google\Service\SubscribewithGoogle\Product; +use Google\Site_Kit_Dependencies\Google\Service\SubscribewithGoogle\PaymentOptions; /** * @group Modules @@ -110,11 +111,13 @@ function ( Request $request ) use ( $publication_id ) { $response = new ListPublicationsResponse(); $publication = new Publication(); - $basic_product = new Product(); - $basic_product->setName( 'testpubID:basic' ); + $payment_options = new PaymentOptions(); $advanced_product = new Product(); - $advanced_product->setName( 'testpubID:subscriptions' ); + $advanced_product->setName( 'testpubID:advanced' ); + + $basic_product = new Product(); + $basic_product->setName( 'testpubID:basic' ); $publication->setPublicationId( $publication_id ); $publication->setOnboardingState( 'ONBOARDING_COMPLETE' ); @@ -124,6 +127,10 @@ function ( Request $request ) use ( $publication_id ) { $advanced_product, ) ); + + $payment_options->subscriptions = true; + $publication->setPaymentOptions( $payment_options ); + $response->setPublications( array( $publication ) ); return new Response( @@ -145,7 +152,7 @@ public function test_register() { $this->assertEquals( 10, has_action( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ) ); } - public function test_cron_synchronize_publication_data() { + public function test_get_new_onboarding_state() { $this->fake_sync_onboarding_state(); $this->assertTrue( $this->reader_revenue_manager->is_connected() ); @@ -161,6 +168,100 @@ public function test_cron_synchronize_publication_data() { $this->assertTrue( $settings['publicationOnboardingStateChanged'] ); } + public function test_get_new_onboarding_state_with_no_publications() { + $this->fake_sync_onboarding_state(); + + $this->assertTrue( $this->reader_revenue_manager->is_connected() ); + + $settings = $this->reader_revenue_manager->get_settings()->get(); + $this->synchronize_onboarding_state->register(); + + $this->assertFalse( $settings['publicationOnboardingStateChanged'] ); + + $this->reader_revenue_manager->get_settings()->merge( + array( + 'publicationID' => '987654321', + ), + ); + + do_action( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ); + + $settings = $this->reader_revenue_manager->get_settings()->get(); + $this->assertFalse( $settings['publicationOnboardingStateChanged'] ); + } + + public function test_get_new_publication_product_ids() { + $this->enable_feature( 'rrmModuleV2' ); + $this->fake_sync_onboarding_state(); + + $this->assertTrue( $this->reader_revenue_manager->is_connected() ); + + $settings = $this->reader_revenue_manager->get_settings()->get(); + $this->synchronize_onboarding_state->register(); + + do_action( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ); + + $settings = $this->reader_revenue_manager->get_settings()->get(); + $this->assertEquals( array( 'advanced', 'basic' ), $settings['productIDs'] ); + } + + public function test_get_new_publication_product_ids_with_no_products() { + $this->enable_feature( 'rrmModuleV2' ); + $this->fake_sync_onboarding_state(); + + $this->assertTrue( $this->reader_revenue_manager->is_connected() ); + + $settings = $this->reader_revenue_manager->get_settings()->get(); + $this->synchronize_onboarding_state->register(); + + $this->reader_revenue_manager->get_settings()->merge( + array( + 'publicationID' => '987654321', + ), + ); + + do_action( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ); + + $settings = $this->reader_revenue_manager->get_settings()->get(); + $this->assertEmpty( $settings['productIDs'] ); + } + + public function test_get_new_publication_payment_option() { + $this->enable_feature( 'rrmModuleV2' ); + $this->fake_sync_onboarding_state(); + + $this->assertTrue( $this->reader_revenue_manager->is_connected() ); + + $settings = $this->reader_revenue_manager->get_settings()->get(); + $this->synchronize_onboarding_state->register(); + + do_action( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ); + + $settings = $this->reader_revenue_manager->get_settings()->get(); + $this->assertEquals( 'subscriptions', $settings['paymentOption'] ); + } + + public function test_get_new_publication_payment_option_with_no_payment_options() { + $this->enable_feature( 'rrmModuleV2' ); + $this->fake_sync_onboarding_state(); + + $this->assertTrue( $this->reader_revenue_manager->is_connected() ); + + $settings = $this->reader_revenue_manager->get_settings()->get(); + $this->synchronize_onboarding_state->register(); + + $this->reader_revenue_manager->get_settings()->merge( + array( + 'publicationID' => '987654321', + ), + ); + + do_action( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ); + + $settings = $this->reader_revenue_manager->get_settings()->get(); + $this->assertEmpty( $settings['paymentOption'] ); + } + public function test_maybe_schedule_synchronize_onboarding_state() { $this->assertFalse( wp_next_scheduled( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ) ); $this->synchronize_onboarding_state->maybe_schedule_synchronize_onboarding_state(); From 3688680a2ccb76aa105c8a3c8da610724c597175 Mon Sep 17 00:00:00 2001 From: Ankit Gade Date: Tue, 21 Jan 2025 22:02:51 +0530 Subject: [PATCH 3/6] Update doc block. --- .../Modules/Reader_Revenue_Manager/Synchronize_Publication.php | 2 +- .../Reader_Revenue_Manager/Synchronize_PublicationTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/Modules/Reader_Revenue_Manager/Synchronize_Publication.php b/includes/Modules/Reader_Revenue_Manager/Synchronize_Publication.php index d85a2db3454..5f6b1fbfb4a 100644 --- a/includes/Modules/Reader_Revenue_Manager/Synchronize_Publication.php +++ b/includes/Modules/Reader_Revenue_Manager/Synchronize_Publication.php @@ -3,7 +3,7 @@ * Class Google\Site_Kit\Modules\Reader_Revenue_Manager\Synchronize_Publication * * @package Google\Site_Kit\Modules\Reader_Revenue_Manager - * @copyright 2024 Google LLC + * @copyright 2025 Google LLC * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 * @link https://sitekit.withgoogle.com */ diff --git a/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php b/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php index 89221bd4316..d970c534a05 100644 --- a/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php +++ b/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php @@ -3,7 +3,7 @@ * Class Google\Site_Kit\Tests\Modules\Reader_Revenue_Manager\Synchronize_OnboardingStateTest * * @package Google\Site_Kit\Tests\Modules\Reader_Revenue_Manager - * @copyright 2024 Google LLC + * @copyright 2025 Google LLC * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 * @link https://sitekit.withgoogle.com */ From fa44904aac3638c89e5fdb2b5920579fe321d488 Mon Sep 17 00:00:00 2001 From: Ankit Gade Date: Wed, 22 Jan 2025 09:24:00 +0530 Subject: [PATCH 4/6] Filter out empty publication ID values. --- .../Reader_Revenue_Manager/Synchronize_Publication.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/includes/Modules/Reader_Revenue_Manager/Synchronize_Publication.php b/includes/Modules/Reader_Revenue_Manager/Synchronize_Publication.php index 5f6b1fbfb4a..c5d1282d301 100644 --- a/includes/Modules/Reader_Revenue_Manager/Synchronize_Publication.php +++ b/includes/Modules/Reader_Revenue_Manager/Synchronize_Publication.php @@ -153,11 +153,13 @@ protected function get_new_product_ids( Publication $publication ) { $product_ids = array_map( function ( $product ) { $name = $product->getName(); - return substr( $name, strpos( $name, ':' ) + 1 ); + return strpos( $name, ':' ) !== false ? substr( $name, strpos( $name, ':' ) + 1 ) : false; }, $products ); + $product_ids = array_filter( $product_ids ); + // Sort the array alphabetically in ascending order. sort( $product_ids ); $product_ids = array_values( $product_ids ); From 0276433477c9532f30d81eeb4dfd8037703a7539 Mon Sep 17 00:00:00 2001 From: nfmohit Date: Tue, 28 Jan 2025 05:39:52 +0600 Subject: [PATCH 5/6] Apply CR feedback. --- includes/Modules/Reader_Revenue_Manager.php | 8 +- .../Synchronize_Publication.php | 131 +++++++----------- .../Synchronize_PublicationTest.php | 124 ++++++++++------- 3 files changed, 128 insertions(+), 135 deletions(-) diff --git a/includes/Modules/Reader_Revenue_Manager.php b/includes/Modules/Reader_Revenue_Manager.php index df2f9b886be..846849cc826 100644 --- a/includes/Modules/Reader_Revenue_Manager.php +++ b/includes/Modules/Reader_Revenue_Manager.php @@ -75,11 +75,11 @@ final class Reader_Revenue_Manager extends Module implements Module_With_Scopes, public function register() { $this->register_scopes_hook(); - $synchronize_onboarding_state = new Synchronize_Publication( + $synchronize_publication = new Synchronize_Publication( $this, $this->user_options ); - $synchronize_onboarding_state->register(); + $synchronize_publication->register(); if ( Feature_Flags::enabled( 'rrmModuleV2' ) && $this->is_connected() ) { $post_meta = new Post_Meta(); @@ -92,8 +92,8 @@ public function register() { $term_product_id->register(); } - add_action( 'load-toplevel_page_googlesitekit-dashboard', array( $synchronize_onboarding_state, 'maybe_schedule_synchronize_onboarding_state' ) ); - add_action( 'load-toplevel_page_googlesitekit-settings', array( $synchronize_onboarding_state, 'maybe_schedule_synchronize_onboarding_state' ) ); + add_action( 'load-toplevel_page_googlesitekit-dashboard', array( $synchronize_publication, 'maybe_schedule_synchronize_publication' ) ); + add_action( 'load-toplevel_page_googlesitekit-settings', array( $synchronize_publication, 'maybe_schedule_synchronize_publication' ) ); // Reader Revenue Manager tag placement logic. add_action( 'template_redirect', array( $this, 'register_tag' ) ); diff --git a/includes/Modules/Reader_Revenue_Manager/Synchronize_Publication.php b/includes/Modules/Reader_Revenue_Manager/Synchronize_Publication.php index c5d1282d301..8515a7c1716 100644 --- a/includes/Modules/Reader_Revenue_Manager/Synchronize_Publication.php +++ b/includes/Modules/Reader_Revenue_Manager/Synchronize_Publication.php @@ -20,7 +20,7 @@ /** * Class for synchronizing the onboarding state. * - * @since 1.141.0 + * @since n.e.x.t * @access private * @ignore */ @@ -47,7 +47,7 @@ class Synchronize_Publication { /** * Constructor. * - * @since 1.141.0 + * @since n.e.x.t * * @param Reader_Revenue_Manager $reader_revenue_manager Reader Revenue Manager instance. * @param User_Options $user_options User_Options instance. @@ -60,7 +60,7 @@ public function __construct( Reader_Revenue_Manager $reader_revenue_manager, Use /** * Registers functionality through WordPress hooks. * - * @since 1.141.0 + * @since n.e.x.t * * @return void */ @@ -76,7 +76,7 @@ function () { /** * Cron callback for synchronizing the publication. * - * @since 1.141.0 + * @since n.e.x.t * * @return void */ @@ -92,15 +92,16 @@ protected function synchronize_publication_data() { return; } - $settings = $this->reader_revenue_manager->get_settings()->get(); - $publication_id = $settings['publicationID']; - $publications = $this->reader_revenue_manager->get_data( 'publications' ); + $publications = $this->reader_revenue_manager->get_data( 'publications' ); // If publications is empty, return early. if ( empty( $publications ) ) { return; } + $settings = $this->reader_revenue_manager->get_settings()->get(); + $publication_id = $settings['publicationID']; + $filtered_publications = array_filter( $publications, function ( $pub ) use ( $publication_id ) { @@ -116,121 +117,89 @@ function ( $pub ) use ( $publication_id ) { // Re-index the filtered array to ensure sequential keys. $filtered_publications = array_values( $filtered_publications ); $publication = $filtered_publications[0]; - $new_product_ids = array(); - $new_payment_options = array(); - $new_onboarding_state = $this->get_new_onboarding_state( $publication ); - if ( Feature_Flags::enabled( 'rrmModuleV2' ) ) { - $new_product_ids = $this->get_new_product_ids( $publication ); - $new_payment_options = $this->get_new_payment_options( $publication ); - } + $onboarding_state = $settings['publicationOnboardingState']; + $new_onboarding_state = $publication->getOnboardingState(); - $new_settings = array_merge( $new_onboarding_state, $new_product_ids, $new_payment_options ); + $new_settings = array( + 'publicationOnboardingState' => $new_onboarding_state, + ); - if ( ! empty( $new_settings ) ) { - $this->reader_revenue_manager->get_settings()->merge( $new_settings ); + // Let the client know if the onboarding state has changed. + if ( $new_onboarding_state !== $onboarding_state ) { + $new_settings['publicationOnboardingStateChanged'] = true; } + + if ( Feature_Flags::enabled( 'rrmModuleV2' ) ) { + $new_settings['productIDs'] = $this->get_product_ids( $publication ); + $new_settings['paymentOption'] = $this->get_payment_option( $publication ); + } + + $this->reader_revenue_manager->get_settings()->merge( $new_settings ); } $restore_user(); } /** - * Returns the updated products IDs for the publication. + * Returns the products IDs for the given publication. * * @since n.e.x.t * * @param Publication $publication Publication object. - * @return array New product IDs. + * @return array Product IDs. */ - protected function get_new_product_ids( Publication $publication ) { - $new_product_ids = array(); - $settings = $this->reader_revenue_manager->get_settings()->get(); - $product_ids = $settings['productIDs']; - $products = $publication->getProducts(); + protected function get_product_ids( Publication $publication ) { + $products = $publication->getProducts(); + $product_ids = array(); if ( ! empty( $products ) ) { - $product_ids = array_map( - function ( $product ) { - $name = $product->getName(); - return strpos( $name, ':' ) !== false ? substr( $name, strpos( $name, ':' ) + 1 ) : false; - }, - $products - ); - - $product_ids = array_filter( $product_ids ); + foreach ( $products as $product ) { + $name = $product->getName(); - // Sort the array alphabetically in ascending order. - sort( $product_ids ); - $product_ids = array_values( $product_ids ); - - if ( ( count( $product_ids ) !== count( $settings['productIDs'] ) ) || ( $product_ids !== $settings['productIDs'] ) ) { - $new_product_ids = array( - 'productIDs' => $product_ids, - ); + // Extract the product ID from the name, which is in + // the format of `publicationID:productID`. + if ( strpos( $name, ':' ) !== false ) { + $product_ids[] = substr( $name, strpos( $name, ':' ) + 1 ); + } } } - return $new_product_ids; + return $product_ids; } /** - * Returns the new payment option for the publication. + * Returns the payment option for the given publication. * * @since n.e.x.t * * @param Publication $publication Publication object. - * @return string New payment option. + * @return string Payment option. */ - protected function get_new_payment_options( Publication $publication ) { - $settings = $this->reader_revenue_manager->get_settings()->get(); - $saved_payment_option = $settings['paymentOption']; - $current_payment_options = $publication->getPaymentOptions(); - - if ( $current_payment_options instanceof PaymentOptions ) { - foreach ( $current_payment_options as $property => $value ) { - if ( true === $value && $property !== $saved_payment_option ) { - return array( - 'paymentOption' => $property, - ); + protected function get_payment_option( Publication $publication ) { + $payment_options = $publication->getPaymentOptions(); + $payment_option = ''; + + if ( $payment_options instanceof PaymentOptions ) { + foreach ( $payment_options as $option => $value ) { + if ( true === $value ) { + $payment_option = $option; + break; } } } - return array(); - } - - /** - * Returns the new onboarding state data. - * - * @since 1.141.0 - * - * @param Publication $publication Publication object. - * @return array New onboarding state data. - */ - protected function get_new_onboarding_state( Publication $publication ) { - $new_onboarding_state = array(); - $settings = $this->reader_revenue_manager->get_settings()->get(); - $onboarding_state = $settings['publicationOnboardingState']; - - if ( $publication->getOnboardingState() !== $onboarding_state ) { - $new_onboarding_state = array( - 'publicationOnboardingState' => $publication->getOnboardingState(), - 'publicationOnboardingStateChanged' => true, - ); - } - - return $new_onboarding_state; + return $payment_option; } /** * Maybe schedule the synchronize onboarding state cron event. * - * @since 1.141.0 + * @since n.e.x.t * * @return void */ - public function maybe_schedule_synchronize_onboarding_state() { + public function maybe_schedule_synchronize_publication() { $connected = $this->reader_revenue_manager->is_connected(); $cron_already_scheduled = wp_next_scheduled( self::CRON_SYNCHRONIZE_PUBLICATION ); diff --git a/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php b/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php index d970c534a05..5d39840db89 100644 --- a/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php +++ b/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php @@ -1,6 +1,6 @@ synchronize_onboarding_state = new Synchronize_Publication( $this->reader_revenue_manager, $this->user_options ); + $this->synchronize_publication = new Synchronize_Publication( $this->reader_revenue_manager, $this->user_options ); } - public function fake_sync_onboarding_state() { + public function fake_sync_publication() { $publication_id = $this->reader_revenue_manager->get_settings()->get()['publicationID']; FakeHttp::fake_google_http_handler( @@ -108,17 +108,16 @@ function ( Request $request ) use ( $publication_id ) { $url = parse_url( $request->getUri() ); if ( '/v1/publications' === $url['path'] ) { - $response = new ListPublicationsResponse(); - $publication = new Publication(); - - $payment_options = new PaymentOptions(); + $basic_product = new Product(); + $basic_product->setName( 'testpubID:basic' ); $advanced_product = new Product(); $advanced_product->setName( 'testpubID:advanced' ); - $basic_product = new Product(); - $basic_product->setName( 'testpubID:basic' ); + $payment_options = new PaymentOptions(); + $payment_options->subscriptions = true; + $publication = new Publication(); $publication->setPublicationId( $publication_id ); $publication->setOnboardingState( 'ONBOARDING_COMPLETE' ); $publication->setProducts( @@ -127,10 +126,9 @@ function ( Request $request ) use ( $publication_id ) { $advanced_product, ) ); - - $payment_options->subscriptions = true; $publication->setPaymentOptions( $payment_options ); + $response = new ListPublicationsResponse(); $response->setPublications( array( $publication ) ); return new Response( @@ -147,35 +145,48 @@ function ( Request $request ) use ( $publication_id ) { public function test_register() { remove_all_actions( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ); - $this->synchronize_onboarding_state->register(); + $this->synchronize_publication->register(); $this->assertEquals( 10, has_action( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ) ); } - public function test_get_new_onboarding_state() { - $this->fake_sync_onboarding_state(); + public function test_synchronize_onboarding_state() { + $this->fake_sync_publication(); $this->assertTrue( $this->reader_revenue_manager->is_connected() ); $settings = $this->reader_revenue_manager->get_settings()->get(); - $this->synchronize_onboarding_state->register(); + $this->synchronize_publication->register(); + $this->assertEquals( + 'ONBOARDING_ACTION_REQUIRED', + $settings['publicationOnboardingState'] + ); $this->assertFalse( $settings['publicationOnboardingStateChanged'] ); do_action( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ); $settings = $this->reader_revenue_manager->get_settings()->get(); + + $this->assertEquals( + 'ONBOARDING_COMPLETE', + $settings['publicationOnboardingState'] + ); $this->assertTrue( $settings['publicationOnboardingStateChanged'] ); } - public function test_get_new_onboarding_state_with_no_publications() { - $this->fake_sync_onboarding_state(); + public function test_synchronize_onboarding_state_with_non_existent_publication() { + $this->fake_sync_publication(); $this->assertTrue( $this->reader_revenue_manager->is_connected() ); $settings = $this->reader_revenue_manager->get_settings()->get(); - $this->synchronize_onboarding_state->register(); + $this->synchronize_publication->register(); + $this->assertEquals( + 'ONBOARDING_ACTION_REQUIRED', + $settings['publicationOnboardingState'] + ); $this->assertFalse( $settings['publicationOnboardingStateChanged'] ); $this->reader_revenue_manager->get_settings()->merge( @@ -187,32 +198,39 @@ public function test_get_new_onboarding_state_with_no_publications() { do_action( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ); $settings = $this->reader_revenue_manager->get_settings()->get(); + + $this->assertEquals( + 'ONBOARDING_ACTION_REQUIRED', + $settings['publicationOnboardingState'] + ); $this->assertFalse( $settings['publicationOnboardingStateChanged'] ); } - public function test_get_new_publication_product_ids() { + public function test_synchronize_product_ids() { $this->enable_feature( 'rrmModuleV2' ); - $this->fake_sync_onboarding_state(); + $this->fake_sync_publication(); $this->assertTrue( $this->reader_revenue_manager->is_connected() ); $settings = $this->reader_revenue_manager->get_settings()->get(); - $this->synchronize_onboarding_state->register(); + $this->synchronize_publication->register(); + + $this->assertEmpty( $settings['productIDs'] ); do_action( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ); $settings = $this->reader_revenue_manager->get_settings()->get(); - $this->assertEquals( array( 'advanced', 'basic' ), $settings['productIDs'] ); + $this->assertEquals( array( 'basic', 'advanced' ), $settings['productIDs'] ); } - public function test_get_new_publication_product_ids_with_no_products() { + public function test_synchronize_product_ids_with_non_existent_publication() { $this->enable_feature( 'rrmModuleV2' ); - $this->fake_sync_onboarding_state(); + $this->fake_sync_publication(); $this->assertTrue( $this->reader_revenue_manager->is_connected() ); $settings = $this->reader_revenue_manager->get_settings()->get(); - $this->synchronize_onboarding_state->register(); + $this->synchronize_publication->register(); $this->reader_revenue_manager->get_settings()->merge( array( @@ -220,20 +238,24 @@ public function test_get_new_publication_product_ids_with_no_products() { ), ); + $this->assertEmpty( $settings['productIDs'] ); + do_action( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ); $settings = $this->reader_revenue_manager->get_settings()->get(); $this->assertEmpty( $settings['productIDs'] ); } - public function test_get_new_publication_payment_option() { + public function test_synchronize_payment_option() { $this->enable_feature( 'rrmModuleV2' ); - $this->fake_sync_onboarding_state(); + $this->fake_sync_publication(); $this->assertTrue( $this->reader_revenue_manager->is_connected() ); $settings = $this->reader_revenue_manager->get_settings()->get(); - $this->synchronize_onboarding_state->register(); + $this->synchronize_publication->register(); + + $this->assertEmpty( $settings['paymentOption'] ); do_action( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ); @@ -241,14 +263,14 @@ public function test_get_new_publication_payment_option() { $this->assertEquals( 'subscriptions', $settings['paymentOption'] ); } - public function test_get_new_publication_payment_option_with_no_payment_options() { + public function test_synchronize_payment_option_with_non_existent_publication() { $this->enable_feature( 'rrmModuleV2' ); - $this->fake_sync_onboarding_state(); + $this->fake_sync_publication(); $this->assertTrue( $this->reader_revenue_manager->is_connected() ); $settings = $this->reader_revenue_manager->get_settings()->get(); - $this->synchronize_onboarding_state->register(); + $this->synchronize_publication->register(); $this->reader_revenue_manager->get_settings()->merge( array( @@ -256,15 +278,17 @@ public function test_get_new_publication_payment_option_with_no_payment_options( ), ); + $this->assertEmpty( $settings['paymentOption'] ); + do_action( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ); $settings = $this->reader_revenue_manager->get_settings()->get(); $this->assertEmpty( $settings['paymentOption'] ); } - public function test_maybe_schedule_synchronize_onboarding_state() { + public function test_maybe_schedule_synchronize_publication() { $this->assertFalse( wp_next_scheduled( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ) ); - $this->synchronize_onboarding_state->maybe_schedule_synchronize_onboarding_state(); + $this->synchronize_publication->maybe_schedule_synchronize_publication(); $this->assertTrue( (bool) wp_next_scheduled( Synchronize_Publication::CRON_SYNCHRONIZE_PUBLICATION ) From 2baac2b290ef3bb94991d5cd1098239434699843 Mon Sep 17 00:00:00 2001 From: nfmohit Date: Tue, 28 Jan 2025 05:51:28 +0600 Subject: [PATCH 6/6] Fix indentation. --- .../Synchronize_PublicationTest.php | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php b/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php index 5d39840db89..676cde34e6a 100644 --- a/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php +++ b/tests/phpunit/integration/Modules/Reader_Revenue_Manager/Synchronize_PublicationTest.php @@ -33,33 +33,33 @@ */ class Synchronize_PublicationTest extends TestCase { - use Fake_Site_Connection_Trait; - use ModulesHelperTrait; - - /** - * @var Synchronize_Publication - */ - protected $synchronize_publication; - - /** - * @var Reader_Revenue_Manager - */ - protected $reader_revenue_manager; - - /** - * @var User_Options - */ - protected $user_options; - - /** - * @var Options - */ - protected $options; - - /** - * @var Authentication - */ - protected $authentication; + use Fake_Site_Connection_Trait; + use ModulesHelperTrait; + + /** + * @var Synchronize_Publication + */ + protected $synchronize_publication; + + /** + * @var Reader_Revenue_Manager + */ + protected $reader_revenue_manager; + + /** + * @var User_Options + */ + protected $user_options; + + /** + * @var Options + */ + protected $options; + + /** + * @var Authentication + */ + protected $authentication; public function set_up() { parent::set_up();