Skip to content

PoC: Improve RRM publication synchronization efficiency #10507

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 39 additions & 11 deletions assets/js/modules/reader-revenue-manager/datastore/publications.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
PUBLICATION_ONBOARDING_STATES,
} from './constants';
import { actions as errorStoreActions } from '../../../googlesitekit/data/create-error-store';
import { getPaymentOption, getProductIDs } from '../utils/settings';

const fetchGetPublicationsStore = createFetchStore( {
baseName: 'getPublications',
Expand All @@ -51,7 +52,42 @@ const fetchGetPublicationsStore = createFetchStore( {
{},
{ useCache: false }
),
reducerCallback: ( state, publications ) => ( { ...state, publications } ),
reducerCallback: createReducer( ( state, publications ) => {
const { publicationID } = state?.savedSettings || {};

const publication = publications.find(
// eslint-disable-next-line sitekit/acronym-case
( { publicationId } ) => publicationId === publicationID
);

if ( ! publication ) {
return {
...state,
publications,
};
}

const { onboardingState, products, paymentOptions } = publication;

const updatedSettings = {
publicationOnboardingState: onboardingState,
productIDs: getProductIDs( products ),
paymentOption: getPaymentOption( paymentOptions ),
};

return {
...state,
publications,
settings: {
...state.settings,
...updatedSettings,
},
savedSettings: {
...state.savedSettings,
...updatedSettings,
},
};
} ),
} );

const fetchGetSyncPublicationOnboardingStateStore = createFetchStore( {
Expand Down Expand Up @@ -255,23 +291,15 @@ const baseActions = {
};

if ( paymentOptions ) {
const paymentOption = Object.keys( paymentOptions ).find(
( key ) => !! paymentOptions[ key ]
);
const paymentOption = getPaymentOption( paymentOptions );

if ( paymentOption ) {
settings.paymentOption = paymentOption;
}
}

if ( products ) {
settings.productIDs = products.reduce( ( ids, { name } ) => {
if ( ! name ) {
return ids;
}

return [ ...ids, name ];
}, [] );
settings.productIDs = getProductIDs( products );
}

settings.productID = 'openaccess';
Expand Down
40 changes: 40 additions & 0 deletions assets/js/modules/reader-revenue-manager/utils/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,43 @@ export function getProductIDLabel( productID ) {

return productID.substring( separatorIndex + 1 );
}

/**
* Gets an array of product ID names from the products array.
*
* @since n.e.x.t
*
* @param {Array} products Array of products.
* @return {Array} Array of product ID names.
*/
export function getProductIDs( products ) {
if ( ! Array.isArray( products ) || products.length === 0 ) {
return [];
}

return products.reduce( ( ids, { name } ) => {
if ( ! name ) {
return ids;
}

return [ ...ids, name ];
}, [] );
}

/**
* Gets the payment option from the payment options object.
*
* @since n.e.x.t
*
* @param {Object} paymentOptions The payment options object.
* @return {string} The payment option.
*/
export function getPaymentOption( paymentOptions ) {
if ( ! paymentOptions ) {
return '';
}

return Object.keys( paymentOptions ).find(
( key ) => !! paymentOptions[ key ]
);
}
114 changes: 112 additions & 2 deletions includes/Modules/Reader_Revenue_Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
use Google\Site_Kit\Modules\Reader_Revenue_Manager\Web_Tag;
use Google\Site_Kit\Modules\Search_Console\Settings as Search_Console_Settings;
use Google\Site_Kit_Dependencies\Google\Service\SubscribewithGoogle as Google_Service_SubscribewithGoogle;
use Google\Site_Kit_Dependencies\Google\Service\SubscribewithGoogle\Publication;
use Google\Site_Kit_Dependencies\Google\Service\SubscribewithGoogle\PaymentOptions;
use WP_Error;

/**
Expand Down Expand Up @@ -425,13 +427,74 @@ function ( $publication ) use ( $data ) {
protected function parse_data_response( Data_Request $data, $response ) {
switch ( "{$data->method}:{$data->datapoint}" ) {
case 'GET:publications':
$publications = $response->getPublications();
return array_values( $publications );
$list_publications_response = $response->getPublications();
$publications = array_values(
$list_publications_response
);

$this->synchronize_publication_data( $publications );

return $publications;
}

return parent::parse_data_response( $data, $response );
}

/**
* Synchronizes publication data with the module settings.
*
* @since n.e.x.t
*
* @param Publication[] $publications Publications to synchronize.
* @return void
*/
public function synchronize_publication_data( $publications ) {
// If not connected, return early.
if ( ! $this->is_connected() ) {
return;
}

// If publications is empty, return early.
if ( empty( $publications ) ) {
return;
}

$settings = $this->get_settings()->get();
$publication_id = $settings['publicationID'];

$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];

$onboarding_state = $settings['publicationOnboardingState'];
$new_onboarding_state = $publication->getOnboardingState();

$new_settings = array(
'publicationOnboardingState' => $new_onboarding_state,
'productIDs' => $this->get_product_ids( $publication ),
'paymentOption' => $this->get_payment_option( $publication ),
);

// Let the client know if the onboarding state has changed.
if ( $new_onboarding_state !== $onboarding_state ) {
$new_settings['publicationOnboardingStateChanged'] = true;
}

$this->get_settings()->merge( $new_settings );
}

/**
* Sets up information about the module.
*
Expand Down Expand Up @@ -780,4 +843,51 @@ public function get_debug_fields() {

return $debug_fields;
}

/**
* Returns the products IDs for the given publication.
*
* @since 1.146.0
* @since n.e.x.t Relocated from Synchronize_Publication class.
*
* @param Publication $publication Publication object.
* @return array Product IDs.
*/
protected function get_product_ids( Publication $publication ) {
$products = $publication->getProducts();
$product_ids = array();

if ( ! empty( $products ) ) {
foreach ( $products as $product ) {
$product_ids[] = $product->getName();
}
}

return $product_ids;
}

/**
* Returns the payment option for the given publication.
*
* @since 1.146.0
* @since n.e.x.t Relocated from Synchronize_Publication class.
*
* @param Publication $publication Publication object.
* @return string Payment option.
*/
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 $payment_option;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@

use Google\Site_Kit\Core\Permissions\Permissions;
use Google\Site_Kit\Core\Storage\User_Options;
use Google\Site_Kit\Core\Util\Feature_Flags;
use Google\Site_Kit\Modules\Reader_Revenue_Manager;
use Google\Site_Kit_Dependencies\Google\Service\SubscribewithGoogle\Publication;
use Google\Site_Kit_Dependencies\Google\Service\SubscribewithGoogle\PaymentOptions;

/**
* Class for synchronizing the onboarding state.
Expand Down Expand Up @@ -85,104 +82,12 @@ protected function synchronize_publication_data() {
$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;
}

$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 ) {
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];

$onboarding_state = $settings['publicationOnboardingState'];
$new_onboarding_state = $publication->getOnboardingState();

$new_settings = array(
'publicationOnboardingState' => $new_onboarding_state,
'productIDs' => $this->get_product_ids( $publication ),
'paymentOption' => $this->get_payment_option( $publication ),
);

// Let the client know if the onboarding state has changed.
if ( $new_onboarding_state !== $onboarding_state ) {
$new_settings['publicationOnboardingStateChanged'] = true;
}

$this->reader_revenue_manager->get_settings()->merge( $new_settings );
$this->reader_revenue_manager->get_data( 'publications' );
}

$restore_user();
}

/**
* Returns the products IDs for the given publication.
*
* @since 1.146.0
*
* @param Publication $publication Publication object.
* @return array Product IDs.
*/
protected function get_product_ids( Publication $publication ) {
$products = $publication->getProducts();
$product_ids = array();

if ( ! empty( $products ) ) {
foreach ( $products as $product ) {
$product_ids[] = $product->getName();
}
}

return $product_ids;
}

/**
* Returns the payment option for the given publication.
*
* @since 1.146.0
*
* @param Publication $publication Publication object.
* @return string Payment option.
*/
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 $payment_option;
}

/**
* Maybe schedule the synchronize onboarding state cron event.
*
Expand Down
Loading