Skip to content
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

Add base RemoteSpecsEngine class, add logging for errors in all remote specs #44775

Merged
merged 5 commits into from Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,4 @@
Significance: patch
Type: dev

Add base RemoteSpecsEngine class, add logging for errors in all remote specs
Expand Up @@ -9,12 +9,13 @@

use Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions\DefaultPaymentGateways;
use Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions\PaymentGatewaysController;
use Automattic\WooCommerce\Admin\RemoteSpecs\RemoteSpecsEngine;

/**
* Remote Payment Methods engine.
* This goes through the specs and gets eligible payment gateways.
*/
class Init {
class Init extends RemoteSpecsEngine {
/**
* Option name for dismissed payment method suggestions.
*/
Expand All @@ -37,22 +38,29 @@ public function __construct() {
public static function get_suggestions( array $specs = null ) {
$locale = get_user_locale();

$specs = is_array( $specs ) ? $specs : self::get_specs();
$results = EvaluateSuggestion::evaluate_specs( $specs );

// When suggestions is empty, replace it with defaults and save for 3 hours.
if ( empty( $results['suggestions'] ) ) {
PaymentGatewaySuggestionsDataSourcePoller::get_instance()->set_specs_transient( array( $locale => DefaultPaymentGateways::get_all() ), 3 * HOUR_IN_SECONDS );

return EvaluateSuggestion::evaluate_specs( DefaultPaymentGateways::get_all() )['suggestions'];
$specs = is_array( $specs ) ? $specs : self::get_specs();
$results = EvaluateSuggestion::evaluate_specs( $specs );
$specs_to_return = $results['suggestions'];
$specs_to_save = null;

if ( empty( $specs_to_return ) ) {
// When suggestions is empty, replace it with defaults and save for 3 hours.
$specs_to_save = DefaultPaymentGateways::get_all();
$specs_to_return = EvaluateSuggestion::evaluate_specs( $specs_to_save )['suggestions'];
} elseif ( count( $results['errors'] ) > 0 ) {
// When suggestions is not empty but has errors, save it for 3 hours.
$specs_to_save = $specs;
}

// When suggestions is not empty but has errors, save it for 3 hours.
if ( count( $results['errors'] ) > 0 ) {
PaymentGatewaySuggestionsDataSourcePoller::get_instance()->set_specs_transient( array( $locale => $specs ), 3 * HOUR_IN_SECONDS );
self::log_errors( $results['errors'] );
}

if ( $specs_to_save ) {
PaymentGatewaySuggestionsDataSourcePoller::get_instance()->set_specs_transient( array( $locale => $specs_to_save ), 3 * HOUR_IN_SECONDS );
}

return $results['suggestions'];
return $specs_to_return;
}

/**
Expand Down
Expand Up @@ -3,11 +3,12 @@
namespace Automattic\WooCommerce\Admin\Features\ShippingPartnerSuggestions;

use Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions\EvaluateSuggestion;
use Automattic\WooCommerce\Admin\RemoteSpecs\RemoteSpecsEngine;

/**
* Class ShippingPartnerSuggestions
*/
class ShippingPartnerSuggestions {
class ShippingPartnerSuggestions extends RemoteSpecsEngine {

/**
* Go through the specs and run them.
Expand All @@ -18,22 +19,25 @@ class ShippingPartnerSuggestions {
public static function get_suggestions( array $specs = null ) {
$locale = get_user_locale();

$specs = is_array( $specs ) ? $specs : self::get_specs();
$results = EvaluateSuggestion::evaluate_specs( $specs );
$specs = is_array( $specs ) ? $specs : self::get_specs();
$results = EvaluateSuggestion::evaluate_specs( $specs );
$specs_to_return = $results['suggestions'];
$specs_to_save = null;

// When suggestions is empty, replace it with defaults and save for 3 hours.
if ( empty( $results['suggestions'] ) ) {
ShippingPartnerSuggestionsDataSourcePoller::get_instance()->set_specs_transient( array( $locale => DefaultShippingPartners::get_all() ), 3 * HOUR_IN_SECONDS );

return EvaluateSuggestion::evaluate_specs( DefaultShippingPartners::get_all() )['suggestions'];
if ( empty( $specs_to_return ) ) {
// When suggestions is empty, replace it with defaults and save for 3 hours.
$specs_to_save = DefaultShippingPartners::get_all();
$specs_to_return = EvaluateSuggestion::evaluate_specs( $specs_to_save )['suggestions'];
} elseif ( count( $results['errors'] ) > 0 ) {
// When suggestions is not empty but has errors, save it for 3 hours.
$specs_to_save = $specs;
}

// When suggestions is not empty but has errors, save it for 3 hours.
if ( count( $results['errors'] ) > 0 ) {
ShippingPartnerSuggestionsDataSourcePoller::get_instance()->set_specs_transient( array( $locale => $specs ), 3 * HOUR_IN_SECONDS );
if ( $specs_to_save ) {
ShippingPartnerSuggestionsDataSourcePoller::get_instance()->set_specs_transient( array( $locale => $specs_to_save ), 3 * HOUR_IN_SECONDS );
}

return $results['suggestions'];
return $specs_to_return;
}

/**
Expand Down
Expand Up @@ -10,13 +10,14 @@
use Automattic\WooCommerce\Admin\PluginsProvider\PluginsProvider;
use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
use Automattic\WooCommerce\Admin\Notes\Note;
use Automattic\WooCommerce\Admin\RemoteSpecs\RemoteSpecsEngine;

/**
* Remote Inbox Notifications engine.
* This goes through the specs and runs (creates admin notes) for those
* specs that are able to be triggered.
*/
class RemoteInboxNotificationsEngine {
class RemoteInboxNotificationsEngine extends RemoteSpecsEngine {
const STORED_STATE_OPTION_NAME = 'wc_remote_inbox_notifications_stored_state';
const WCA_UPDATED_OPTION_NAME = 'wc_remote_inbox_notifications_wca_updated';

Expand Down Expand Up @@ -117,9 +118,17 @@ public static function run() {
}

$stored_state = self::get_stored_state();
$errors = array();

foreach ( $specs as $spec ) {
SpecRunner::run_spec( $spec, $stored_state );
$error = SpecRunner::run_spec( $spec, $stored_state );
if ( isset( $error ) ) {
$errors[] = $error;
}
}

if ( count( $errors ) > 0 ) {
self::log_errors( $errors );
}
}

Expand Down
Expand Up @@ -45,7 +45,7 @@ public static function run_spec( $spec, $stored_state ) {
new RuleEvaluator()
);
} catch ( \Throwable $e ) {
return;
return $e;
}

// If the status is changing, update the created date to now.
Expand Down
39 changes: 39 additions & 0 deletions plugins/woocommerce/src/Admin/RemoteSpecs/RemoteSpecsEngine.php
@@ -0,0 +1,39 @@
<?php

namespace Automattic\WooCommerce\Admin\RemoteSpecs;

/**
* RemoteSpecsEngine class.
*/
abstract class RemoteSpecsEngine {
/**
* Log errors.
*
* @param array $errors Array of errors from \Throwable interface.
*/
public static function log_errors( $errors = array() ) {
if (
true !== defined( 'WP_ENVIRONMENT_TYPE' ) ||
! in_array( constant( 'WP_ENVIRONMENT_TYPE' ), array( 'development', 'local' ), true )
) {
return;
}
$logger = wc_get_logger();
$error_messages = array();

foreach ( $errors as $error ) {
if ( isset( $error ) && method_exists( $error, 'getMessage' ) ) {
$error_messages[] = $error->getMessage();
}
}

$logger->error(
'Error while evaluating specs',
array(
'source' => 'remotespecsengine-errors',
'class' => static::class,
'errors' => $error_messages,
),
);
}
}
Expand Up @@ -20,16 +20,13 @@ class EvaluateExtension {
* @param object $extension The extension to evaluate.
* @return object The evaluated extension.
*/
public static function evaluate( $extension ) {
private static function evaluate( $extension ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Set to private since this can now produce fatal errors.

global $wp_version;
$rule_evaluator = new RuleEvaluator();

if ( isset( $extension->is_visible ) ) {
try {
$is_visible = $rule_evaluator->evaluate( $extension->is_visible );
$extension->is_visible = $is_visible;
} catch ( \Throwable $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
}
$is_visible = $rule_evaluator->evaluate( $extension->is_visible );
$extension->is_visible = $is_visible;
} else {
$extension->is_visible = true;
}
Expand Down
Expand Up @@ -8,12 +8,13 @@
defined( 'ABSPATH' ) || exit;

use Automattic\WooCommerce\Internal\Admin\RemoteFreeExtensions\DefaultFreeExtensions;
use Automattic\WooCommerce\Admin\RemoteSpecs\RemoteSpecsEngine;

/**
* Remote Payment Methods engine.
* This goes through the specs and gets eligible payment methods.
*/
class Init {
class Init extends RemoteSpecsEngine {

/**
* Constructor.
Expand All @@ -31,8 +32,10 @@ public function __construct() {
public static function get_extensions( $allowed_bundles = array() ) {
$locale = get_user_locale();

$specs = self::get_specs();
$results = EvaluateExtension::evaluate_bundles( $specs, $allowed_bundles );
$specs = self::get_specs();
$results = EvaluateExtension::evaluate_bundles( $specs, $allowed_bundles );
$specs_to_return = $results['bundles'];
$specs_to_save = null;

$plugins = array_filter(
$results['bundles'],
Expand All @@ -41,19 +44,25 @@ function( $bundle ) {
}
);

// When no plugins are visible, replace it with defaults and save for 3 hours.
if ( empty( $plugins ) ) {
RemoteFreeExtensionsDataSourcePoller::get_instance()->set_specs_transient( array( $locale => DefaultFreeExtensions::get_all() ), 3 * HOUR_IN_SECONDS );

return EvaluateExtension::evaluate_bundles( DefaultFreeExtensions::get_all(), $allowed_bundles )['bundles'];
// When no plugins are visible, replace it with defaults and save for 3 hours.
$specs_to_save = DefaultFreeExtensions::get_all();
$specs_to_return = EvaluateExtension::evaluate_bundles( $specs_to_save, $allowed_bundles )['bundles'];
} elseif ( count( $results['errors'] ) > 0 ) {
// When suggestions is not empty but has errors, save it for 3 hours.
$specs_to_save = $specs;
}

// When plugins is not empty but has errors, save it for 3 hours.
if ( count( $results['errors'] ) > 0 ) {
RemoteFreeExtensionsDataSourcePoller::get_instance()->set_specs_transient( array( $locale => $specs ), 3 * HOUR_IN_SECONDS );
self::log_errors( $results['errors'] );
}

if ( $specs_to_save ) {
RemoteFreeExtensionsDataSourcePoller::get_instance()->set_specs_transient( array( $locale => $specs_to_save ), 3 * HOUR_IN_SECONDS );
}

return $results['bundles'];
return $specs_to_return;
}

/**
Expand Down
Expand Up @@ -7,15 +7,14 @@

defined( 'ABSPATH' ) || exit;

use Automattic\WooCommerce\Admin\DataSourcePoller;
use Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions\EvaluateSuggestion;
use Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions\PaymentGatewaySuggestionsDataSourcePoller as PaymentGatewaySuggestionsDataSourcePoller;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unused imports

use Automattic\WooCommerce\Internal\Admin\WCAdminAssets;
use Automattic\WooCommerce\Admin\RemoteSpecs\RemoteSpecsEngine;

/**
* WC Pay Promotion engine.
*/
class Init {
class Init extends RemoteSpecsEngine {
const EXPLAT_VARIATION_PREFIX = 'woocommerce_wc_pay_promotion_payment_methods_table_';

/**
Expand Down Expand Up @@ -131,6 +130,7 @@ public static function get_promotions() {
// Unlike payment gateway suggestions, we don't have a non-empty default set of promotions to fall back to.
// So just set the specs transient with expired time to 3 hours.
WCPayPromotionDataSourcePoller::get_instance()->set_specs_transient( array( $locale => $specs ), 3 * HOUR_IN_SECONDS );
self::log_errors( $results['errors'] );
}

return $results['suggestions'];
Expand Down