auto-patch 638-dev-dev01-2024-05-14T20_44_36
This commit is contained in:
@@ -0,0 +1,288 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs;
|
||||
|
||||
/**
|
||||
* Specs data source poller class.
|
||||
* This handles polling specs from JSON endpoints, and
|
||||
* stores the specs in to the database as an option.
|
||||
*/
|
||||
abstract class DataSourcePoller {
|
||||
|
||||
/**
|
||||
* Get class instance.
|
||||
*/
|
||||
abstract public static function get_instance();
|
||||
|
||||
/**
|
||||
* Name of data sources filter.
|
||||
*/
|
||||
const FILTER_NAME = 'data_source_poller_data_sources';
|
||||
|
||||
/**
|
||||
* Name of data source specs filter.
|
||||
*/
|
||||
const FILTER_NAME_SPECS = 'data_source_poller_specs';
|
||||
|
||||
/**
|
||||
* Id of DataSourcePoller.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $id = array();
|
||||
|
||||
/**
|
||||
* Default data sources array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $data_sources = array();
|
||||
|
||||
/**
|
||||
* Default args.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $args = array();
|
||||
|
||||
/**
|
||||
* The logger instance.
|
||||
*
|
||||
* @var WC_Logger|null
|
||||
*/
|
||||
protected static $logger = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $id id of DataSourcePoller.
|
||||
* @param array $data_sources urls for data sources.
|
||||
* @param array $args Options for DataSourcePoller.
|
||||
*/
|
||||
public function __construct( $id, $data_sources = array(), $args = array() ) {
|
||||
$this->data_sources = $data_sources;
|
||||
$this->id = $id;
|
||||
|
||||
$arg_defaults = array(
|
||||
'spec_key' => 'id',
|
||||
'transient_name' => 'woocommerce_admin_' . $id . '_specs',
|
||||
'transient_expiry' => 7 * DAY_IN_SECONDS,
|
||||
);
|
||||
$this->args = wp_parse_args( $args, $arg_defaults );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the logger instance.
|
||||
*
|
||||
* @return WC_Logger
|
||||
*/
|
||||
protected static function get_logger() {
|
||||
if ( is_null( self::$logger ) ) {
|
||||
self::$logger = wc_get_logger();
|
||||
}
|
||||
|
||||
return self::$logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key identifier of spec, this can easily be overwritten. Defaults to id.
|
||||
*
|
||||
* @param mixed $spec a JSON parsed spec coming from the JSON feed.
|
||||
* @return string|boolean
|
||||
*/
|
||||
protected function get_spec_key( $spec ) {
|
||||
$key = $this->args['spec_key'];
|
||||
if ( isset( $spec->$key ) ) {
|
||||
return $spec->$key;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the data sources for specs and persists those specs.
|
||||
*
|
||||
* @return array list of specs.
|
||||
*/
|
||||
public function get_specs_from_data_sources() {
|
||||
$locale = get_user_locale();
|
||||
$specs_group = get_transient( $this->args['transient_name'] ) ?? array();
|
||||
$specs = isset( $specs_group[ $locale ] ) ? $specs_group[ $locale ] : array();
|
||||
|
||||
if ( ! is_array( $specs ) || empty( $specs ) ) {
|
||||
$this->read_specs_from_data_sources();
|
||||
$specs_group = get_transient( $this->args['transient_name'] );
|
||||
$specs = isset( $specs_group[ $locale ] ) ? $specs_group[ $locale ] : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter specs.
|
||||
*
|
||||
* @param array $specs List of specs.
|
||||
* @param string $this->id Spec identifier.
|
||||
*
|
||||
* @since 8.8.0
|
||||
*/
|
||||
$specs = apply_filters( self::FILTER_NAME_SPECS, $specs, $this->id );
|
||||
return false !== $specs ? $specs : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the data sources for specs and persists those specs.
|
||||
*
|
||||
* @return bool Whether any specs were read.
|
||||
*/
|
||||
public function read_specs_from_data_sources() {
|
||||
$specs = array();
|
||||
|
||||
/**
|
||||
* Filter data sources.
|
||||
*
|
||||
* @param array $this->data_sources List of data sources.
|
||||
* @param string $this->id Spec identifier.
|
||||
*
|
||||
* @since 8.8.0
|
||||
*/
|
||||
$data_sources = apply_filters( self::FILTER_NAME, $this->data_sources, $this->id );
|
||||
|
||||
// Note that this merges the specs from the data sources based on the
|
||||
// id - last one wins.
|
||||
foreach ( $data_sources as $url ) {
|
||||
$specs_from_data_source = self::read_data_source( $url );
|
||||
$this->merge_specs( $specs_from_data_source, $specs, $url );
|
||||
}
|
||||
|
||||
$specs_group = get_transient( $this->args['transient_name'] );
|
||||
$specs_group = is_array( $specs_group ) ? $specs_group : array();
|
||||
$locale = get_user_locale();
|
||||
$specs_group[ $locale ] = $specs;
|
||||
// Persist the specs as a transient.
|
||||
$this->set_specs_transient(
|
||||
$specs_group,
|
||||
$this->args['transient_expiry']
|
||||
);
|
||||
return count( $specs ) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the specs transient.
|
||||
*
|
||||
* @return bool success of failure of transient deletion.
|
||||
*/
|
||||
public function delete_specs_transient() {
|
||||
return delete_transient( $this->args['transient_name'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the specs transient.
|
||||
*
|
||||
* @param array $specs The specs to set in the transient.
|
||||
* @param int $expiration The expiration time for the transient.
|
||||
*/
|
||||
public function set_specs_transient( $specs, $expiration = 0 ) {
|
||||
set_transient(
|
||||
$this->args['transient_name'],
|
||||
$specs,
|
||||
$expiration,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a single data source and return the read specs
|
||||
*
|
||||
* @param string $url The URL to read the specs from.
|
||||
*
|
||||
* @return array The specs that have been read from the data source.
|
||||
*/
|
||||
protected static function read_data_source( $url ) {
|
||||
$logger_context = array( 'source' => $url );
|
||||
$logger = self::get_logger();
|
||||
$response = wp_remote_get(
|
||||
add_query_arg(
|
||||
'locale',
|
||||
get_user_locale(),
|
||||
$url
|
||||
),
|
||||
array(
|
||||
'user-agent' => 'WooCommerce/' . WC_VERSION . '; ' . home_url( '/' ),
|
||||
)
|
||||
);
|
||||
|
||||
if ( is_wp_error( $response ) || ! isset( $response['body'] ) ) {
|
||||
$logger->error(
|
||||
'Error getting data feed',
|
||||
$logger_context
|
||||
);
|
||||
// phpcs:ignore
|
||||
$logger->error( print_r( $response, true ), $logger_context );
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
$body = $response['body'];
|
||||
$specs = json_decode( $body );
|
||||
|
||||
if ( null === $specs ) {
|
||||
$logger->error(
|
||||
'Empty response in data feed',
|
||||
$logger_context
|
||||
);
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
if ( ! is_array( $specs ) ) {
|
||||
$logger->error(
|
||||
'Data feed is not an array',
|
||||
$logger_context
|
||||
);
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
return $specs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the specs.
|
||||
*
|
||||
* @param Array $specs_to_merge_in The specs to merge in to $specs.
|
||||
* @param Array $specs The list of specs being merged into.
|
||||
* @param string $url The url of the feed being merged in (for error reporting).
|
||||
*/
|
||||
protected function merge_specs( $specs_to_merge_in, &$specs, $url ) {
|
||||
foreach ( $specs_to_merge_in as $spec ) {
|
||||
if ( ! $this->validate_spec( $spec, $url ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$id = $this->get_spec_key( $spec );
|
||||
$specs[ $id ] = $spec;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the spec.
|
||||
*
|
||||
* @param object $spec The spec to validate.
|
||||
* @param string $url The url of the feed that provided the spec.
|
||||
*
|
||||
* @return bool The result of the validation.
|
||||
*/
|
||||
protected function validate_spec( $spec, $url ) {
|
||||
$logger = self::get_logger();
|
||||
$logger_context = array( 'source' => $url );
|
||||
|
||||
if ( ! $this->get_spec_key( $spec ) ) {
|
||||
$logger->error(
|
||||
'Spec is invalid because the id is missing in feed',
|
||||
$logger_context
|
||||
);
|
||||
// phpcs:ignore
|
||||
$logger->error( print_r( $spec, true ), $logger_context );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor that performs a comparison operation against the base
|
||||
* location - country.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor that performs a comparison operation against the base
|
||||
* location - country.
|
||||
*/
|
||||
class BaseLocationCountryRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* Performs a comparison operation against the base location - country.
|
||||
*
|
||||
* @param object $rule The specific rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
$base_location = wc_get_base_location();
|
||||
if (
|
||||
! is_array( $base_location ) ||
|
||||
! array_key_exists( 'country', $base_location ) ||
|
||||
! array_key_exists( 'state', $base_location )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$onboarding_profile = get_option( 'woocommerce_onboarding_profile', array() );
|
||||
$is_address_default = 'US' === $base_location['country'] && 'CA' === $base_location['state'] && empty( get_option( 'woocommerce_store_address', '' ) );
|
||||
$is_store_country_set = isset( $onboarding_profile['is_store_country_set'] ) && $onboarding_profile['is_store_country_set'];
|
||||
|
||||
// Return false if the location is the default country and if onboarding hasn't been finished or the store address not been updated.
|
||||
if ( $is_address_default && OnboardingProfile::needs_completion() && ! $is_store_country_set ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ComparisonOperation::compare(
|
||||
$base_location['country'],
|
||||
$rule->value,
|
||||
$rule->operation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
if ( ! isset( $rule->value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->operation ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor that performs a comparison operation against the base
|
||||
* location - state.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor that performs a comparison operation against the base
|
||||
* location - state.
|
||||
*/
|
||||
class BaseLocationStateRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* Performs a comparison operation against the base location - state.
|
||||
*
|
||||
* @param object $rule The specific rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
$base_location = wc_get_base_location();
|
||||
if ( ! is_array( $base_location ) || ! array_key_exists( 'state', $base_location ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ComparisonOperation::compare(
|
||||
$base_location['state'],
|
||||
$rule->value,
|
||||
$rule->operation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
if ( ! isset( $rule->value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->operation ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* Compare two operands using the specified operation.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Compare two operands using the specified operation.
|
||||
*/
|
||||
class ComparisonOperation {
|
||||
/**
|
||||
* Compare two operands using the specified operation.
|
||||
*
|
||||
* @param object $left_operand The left hand operand.
|
||||
* @param object $right_operand The right hand operand -- 'value' from the rule definition.
|
||||
* @param string $operation The operation used to compare the operands.
|
||||
*/
|
||||
public static function compare( $left_operand, $right_operand, $operation ) {
|
||||
switch ( $operation ) {
|
||||
case '=':
|
||||
return $left_operand === $right_operand;
|
||||
case '<':
|
||||
return $left_operand < $right_operand;
|
||||
case '<=':
|
||||
return $left_operand <= $right_operand;
|
||||
case '>':
|
||||
return $left_operand > $right_operand;
|
||||
case '>=':
|
||||
return $left_operand >= $right_operand;
|
||||
case '!=':
|
||||
return $left_operand !== $right_operand;
|
||||
case 'contains':
|
||||
if ( is_array( $left_operand ) && is_string( $right_operand ) ) {
|
||||
return in_array( $right_operand, $left_operand, true );
|
||||
}
|
||||
if ( is_string( $right_operand ) && is_string( $left_operand ) ) {
|
||||
return strpos( $right_operand, $left_operand ) !== false;
|
||||
}
|
||||
break;
|
||||
case '!contains':
|
||||
if ( is_array( $left_operand ) && is_string( $right_operand ) ) {
|
||||
return ! in_array( $right_operand, $left_operand, true );
|
||||
}
|
||||
if ( is_string( $right_operand ) && is_string( $left_operand ) ) {
|
||||
return strpos( $right_operand, $left_operand ) === false;
|
||||
}
|
||||
break;
|
||||
case 'in':
|
||||
if ( is_array( $right_operand ) && is_string( $left_operand ) ) {
|
||||
return in_array( $left_operand, $right_operand, true );
|
||||
}
|
||||
if ( is_string( $left_operand ) && is_string( $right_operand ) ) {
|
||||
return strpos( $left_operand, $right_operand ) !== false;
|
||||
}
|
||||
break;
|
||||
case '!in':
|
||||
if ( is_array( $right_operand ) && is_string( $left_operand ) ) {
|
||||
return ! in_array( $left_operand, $right_operand, true );
|
||||
}
|
||||
if ( is_string( $left_operand ) && is_string( $right_operand ) ) {
|
||||
return strpos( $left_operand, $right_operand ) === false;
|
||||
}
|
||||
break;
|
||||
case 'range':
|
||||
if ( ! is_array( $right_operand ) || count( $right_operand ) !== 2 ) {
|
||||
return false;
|
||||
}
|
||||
return $left_operand >= $right_operand[0] && $left_operand <= $right_operand[1];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* Evaluates the spec and returns a status.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use Automattic\WooCommerce\Admin\Notes\Note;
|
||||
|
||||
/**
|
||||
* Evaluates the spec and returns a status.
|
||||
*/
|
||||
class EvaluateAndGetStatus {
|
||||
/**
|
||||
* Evaluates the spec and returns a status.
|
||||
*
|
||||
* @param array $spec The spec to evaluate.
|
||||
* @param string $current_status The note's current status.
|
||||
* @param object $stored_state Stored state.
|
||||
* @param object $rule_evaluator Evaluates rules into true/false.
|
||||
*
|
||||
* @return string The evaluated status.
|
||||
*/
|
||||
public static function evaluate( $spec, $current_status, $stored_state, $rule_evaluator ) {
|
||||
// No rules should leave the note alone.
|
||||
if ( ! isset( $spec->rules ) ) {
|
||||
return $current_status;
|
||||
}
|
||||
|
||||
$evaluated_result = $rule_evaluator->evaluate(
|
||||
$spec->rules,
|
||||
$stored_state,
|
||||
array(
|
||||
'slug' => $spec->slug,
|
||||
'source' => 'remote-inbox-notifications',
|
||||
)
|
||||
);
|
||||
|
||||
// Pending notes should be the spec status if the spec passes,
|
||||
// left alone otherwise.
|
||||
if ( Note::E_WC_ADMIN_NOTE_PENDING === $current_status ) {
|
||||
return $evaluated_result
|
||||
? $spec->status
|
||||
: Note::E_WC_ADMIN_NOTE_PENDING;
|
||||
}
|
||||
|
||||
// When allow_redisplay isn't set, just leave the note alone.
|
||||
if ( ! isset( $spec->allow_redisplay ) || ! $spec->allow_redisplay ) {
|
||||
return $current_status;
|
||||
}
|
||||
|
||||
// allow_redisplay is set, unaction the note if eval to true.
|
||||
return $evaluated_result
|
||||
? Note::E_WC_ADMIN_NOTE_UNACTIONED
|
||||
: $current_status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
/**
|
||||
* Class EvaluationLogger
|
||||
*
|
||||
* @package Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors
|
||||
*/
|
||||
class EvaluationLogger {
|
||||
/**
|
||||
* Slug of the spec.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $slug;
|
||||
|
||||
/**
|
||||
* Results of rules in the given spec.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $results = array();
|
||||
|
||||
/**
|
||||
* Logger class to use.
|
||||
*
|
||||
* @var WC_Logger_Interface|null
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* Logger source.
|
||||
*
|
||||
* @var string logger source.
|
||||
*/
|
||||
private $source = '';
|
||||
|
||||
/**
|
||||
* EvaluationLogger constructor.
|
||||
*
|
||||
* @param string $slug Slug of a spec that is being evaluated.
|
||||
* @param null $source Logger source.
|
||||
* @param \WC_Logger_Interface $logger Logger class to use.
|
||||
*/
|
||||
public function __construct( $slug, $source = null, \WC_Logger_Interface $logger = null ) {
|
||||
$this->slug = $slug;
|
||||
if ( null === $logger ) {
|
||||
$logger = wc_get_logger();
|
||||
}
|
||||
|
||||
if ( $source ) {
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add evaluation result of a rule.
|
||||
*
|
||||
* @param string $rule_type name of the rule being tested.
|
||||
* @param boolean $result result of a given rule.
|
||||
*/
|
||||
public function add_result( $rule_type, $result ) {
|
||||
array_push(
|
||||
$this->results,
|
||||
array(
|
||||
'rule' => $rule_type,
|
||||
'result' => $result ? 'passed' : 'failed',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the results.
|
||||
*/
|
||||
public function log() {
|
||||
if ( false === defined( 'WC_ADMIN_DEBUG_RULE_EVALUATOR' ) || true !== constant( 'WC_ADMIN_DEBUG_RULE_EVALUATOR' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $this->results as $result ) {
|
||||
$this->logger->debug(
|
||||
"[{$this->slug}] {$result['rule']}: {$result['result']}",
|
||||
array( 'source' => $this->source )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor that fails.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor that fails.
|
||||
*/
|
||||
class FailRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* Fails the rule.
|
||||
*
|
||||
* @param object $rule The specific rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool Always false.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* Gets the processor for the specified rule type.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Class encapsulating getting the processor for a given rule type.
|
||||
*/
|
||||
class GetRuleProcessor {
|
||||
/**
|
||||
* Get the processor for the specified rule type.
|
||||
*
|
||||
* @param string $rule_type The rule type.
|
||||
*
|
||||
* @return RuleProcessorInterface The matching processor for the specified rule type, or a FailRuleProcessor if no matching processor is found.
|
||||
*/
|
||||
public static function get_processor( $rule_type ) {
|
||||
switch ( $rule_type ) {
|
||||
case 'plugins_activated':
|
||||
return new PluginsActivatedRuleProcessor();
|
||||
case 'publish_after_time':
|
||||
return new PublishAfterTimeRuleProcessor();
|
||||
case 'publish_before_time':
|
||||
return new PublishBeforeTimeRuleProcessor();
|
||||
case 'not':
|
||||
return new NotRuleProcessor();
|
||||
case 'or':
|
||||
return new OrRuleProcessor();
|
||||
case 'fail':
|
||||
return new FailRuleProcessor();
|
||||
case 'pass':
|
||||
return new PassRuleProcessor();
|
||||
case 'plugin_version':
|
||||
return new PluginVersionRuleProcessor();
|
||||
case 'stored_state':
|
||||
return new StoredStateRuleProcessor();
|
||||
case 'order_count':
|
||||
return new OrderCountRuleProcessor();
|
||||
case 'wcadmin_active_for':
|
||||
return new WCAdminActiveForRuleProcessor();
|
||||
case 'product_count':
|
||||
return new ProductCountRuleProcessor();
|
||||
case 'onboarding_profile':
|
||||
return new OnboardingProfileRuleProcessor();
|
||||
case 'is_ecommerce':
|
||||
return new IsEcommerceRuleProcessor();
|
||||
case 'is_woo_express':
|
||||
return new IsWooExpressRuleProcessor();
|
||||
case 'base_location_country':
|
||||
return new BaseLocationCountryRuleProcessor();
|
||||
case 'base_location_state':
|
||||
return new BaseLocationStateRuleProcessor();
|
||||
case 'note_status':
|
||||
return new NoteStatusRuleProcessor();
|
||||
case 'option':
|
||||
return new OptionRuleProcessor();
|
||||
case 'wca_updated':
|
||||
return new WooCommerceAdminUpdatedRuleProcessor();
|
||||
case 'total_payments_value':
|
||||
return new TotalPaymentsVolumeProcessor();
|
||||
}
|
||||
|
||||
return new FailRuleProcessor();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor that passes (or fails) when the site is on the eCommerce
|
||||
* plan.
|
||||
*
|
||||
* @package WooCommerce\Admin\Classes
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor that passes (or fails) when the site is on the eCommerce
|
||||
* plan.
|
||||
*/
|
||||
class IsEcommerceRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* Passes (or fails) based on whether the site is on the eCommerce plan or
|
||||
* not.
|
||||
*
|
||||
* @param object $rule The rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
if ( ! function_exists( 'wc_calypso_bridge_is_ecommerce_plan' ) ) {
|
||||
return false === $rule->value;
|
||||
}
|
||||
|
||||
return (bool) wc_calypso_bridge_is_ecommerce_plan() === $rule->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
if ( ! isset( $rule->value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor that passes (or fails) when the site is on a Woo Express plan.
|
||||
*
|
||||
* @package WooCommerce\Admin\Classes
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor that passes (or fails) when the site is on a Woo Express plan.
|
||||
* You may optionally pass a plan name to target a specific Woo Express plan.
|
||||
*/
|
||||
class IsWooExpressRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* Passes (or fails) based on whether the site is a Woo Express plan.
|
||||
*
|
||||
* @param object $rule The rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
if ( ! function_exists( 'wc_calypso_bridge_is_woo_express_plan' ) ) {
|
||||
return false === $rule->value;
|
||||
}
|
||||
|
||||
// If the plan is undefined, only check if it's a Woo Express plan.
|
||||
if ( ! isset( $rule->plan ) ) {
|
||||
return wc_calypso_bridge_is_woo_express_plan() === $rule->value;
|
||||
}
|
||||
|
||||
// If a plan name is defined, only evaluate the plan if we're on the Woo Express plan.
|
||||
if ( wc_calypso_bridge_is_woo_express_plan() ) {
|
||||
$fn = 'wc_calypso_bridge_is_woo_express_' . (string) $rule->plan . '_plan';
|
||||
if ( function_exists( $fn ) ) {
|
||||
return $fn() === $rule->value;
|
||||
}
|
||||
|
||||
// If an invalid plan name is given, only evaluate the rule if we're targeting all plans other than the specified (invalid) one.
|
||||
return false === $rule->value;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
if ( ! isset( $rule->value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( isset( $rule->plan ) ) {
|
||||
if ( ! function_exists( 'wc_calypso_bridge_is_woo_express_plan' ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor that negates the rules in the rule's operand.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor that negates the rules in the rule's operand.
|
||||
*/
|
||||
class NotRuleProcessor implements RuleProcessorInterface {
|
||||
|
||||
/**
|
||||
* The rule evaluator to use.
|
||||
*
|
||||
* @var RuleEvaluator
|
||||
*/
|
||||
protected $rule_evaluator;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param RuleEvaluator $rule_evaluator The rule evaluator to use.
|
||||
*/
|
||||
public function __construct( $rule_evaluator = null ) {
|
||||
$this->rule_evaluator = null === $rule_evaluator
|
||||
? new RuleEvaluator()
|
||||
: $rule_evaluator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the rules in the operand and negates the result.
|
||||
*
|
||||
* @param object $rule The specific rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
$evaluated_operand = $this->rule_evaluator->evaluate(
|
||||
$rule->operand,
|
||||
$stored_state
|
||||
);
|
||||
|
||||
return ! $evaluated_operand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
if ( ! isset( $rule->operand ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor that compares against the status of another note. For
|
||||
* example, this could be used to conditionally create a note only if another
|
||||
* note has not been actioned.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use Automattic\WooCommerce\Admin\Notes\Notes;
|
||||
|
||||
/**
|
||||
* Rule processor that compares against the status of another note.
|
||||
*/
|
||||
class NoteStatusRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* Compare against the status of another note.
|
||||
*
|
||||
* @param object $rule The rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
$status = Notes::get_note_status( $rule->note_name );
|
||||
if ( ! $status ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ComparisonOperation::compare(
|
||||
$status,
|
||||
$rule->status,
|
||||
$rule->operation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
if ( ! isset( $rule->note_name ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->status ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->operation ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor that performs a comparison operation against a value in the
|
||||
* onboarding profile.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor that performs a comparison operation against a value in the
|
||||
* onboarding profile.
|
||||
*/
|
||||
class OnboardingProfileRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* Performs a comparison operation against a value in the onboarding
|
||||
* profile.
|
||||
*
|
||||
* @param object $rule The rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
$onboarding_profile = get_option( 'woocommerce_onboarding_profile' );
|
||||
|
||||
if ( empty( $onboarding_profile ) || ! is_array( $onboarding_profile ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $onboarding_profile[ $rule->index ] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ComparisonOperation::compare(
|
||||
$onboarding_profile[ $rule->index ],
|
||||
$rule->value,
|
||||
$rule->operation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
if ( ! isset( $rule->index ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->operation ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor that performs a comparison operation against an option value.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\TransformerService;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor that performs a comparison operation against an option value.
|
||||
*/
|
||||
class OptionRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* Performs a comparison operation against the option value.
|
||||
*
|
||||
* @param object $rule The specific rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
$is_contains = $rule->operation && strpos( $rule->operation, 'contains' ) !== false;
|
||||
$value_when_default_not_provided = $is_contains ? array() : false;
|
||||
$is_default_set = property_exists( $rule, 'default' );
|
||||
$default_value = $is_default_set ? $rule->default : $value_when_default_not_provided;
|
||||
$option_value = $this->get_option_value( $rule, $default_value, $is_contains );
|
||||
|
||||
if ( isset( $rule->transformers ) && is_array( $rule->transformers ) ) {
|
||||
$option_value = TransformerService::apply( $option_value, $rule->transformers, $is_default_set, $default_value );
|
||||
}
|
||||
|
||||
return ComparisonOperation::compare(
|
||||
$option_value,
|
||||
$rule->value,
|
||||
$rule->operation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the option value and handles logging if necessary.
|
||||
*
|
||||
* @param object $rule The specific rule being processed.
|
||||
* @param mixed $default_value The default value.
|
||||
* @param bool $is_contains Indicates whether the operation is "contains".
|
||||
*
|
||||
* @return mixed The option value.
|
||||
*/
|
||||
private function get_option_value( $rule, $default_value, $is_contains ) {
|
||||
$option_value = get_option( $rule->option_name, $default_value );
|
||||
$is_contains_valid = $is_contains && ( is_array( $option_value ) || ( is_string( $option_value ) && is_string( $rule->value ) ) );
|
||||
|
||||
if ( $is_contains && ! $is_contains_valid ) {
|
||||
$logger = wc_get_logger();
|
||||
$logger->warning(
|
||||
sprintf(
|
||||
'ComparisonOperation "%s" option value "%s" is not an array, defaulting to empty array.',
|
||||
$rule->operation,
|
||||
$rule->option_name
|
||||
),
|
||||
array(
|
||||
'option_value' => $option_value,
|
||||
'rule' => $rule,
|
||||
)
|
||||
);
|
||||
$option_value = array();
|
||||
}
|
||||
|
||||
return $option_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
if ( ! isset( $rule->option_name ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->operation ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( isset( $rule->transformers ) && is_array( $rule->transformers ) ) {
|
||||
foreach ( $rule->transformers as $transform_args ) {
|
||||
$transformer = TransformerService::create_transformer( $transform_args->use );
|
||||
if ( ! $transformer->validate( $transform_args->arguments ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor that performs an OR operation on the rule's left and right
|
||||
* operands.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor that performs an OR operation on the rule's left and right
|
||||
* operands.
|
||||
*/
|
||||
class OrRuleProcessor implements RuleProcessorInterface {
|
||||
|
||||
/**
|
||||
* Rule evaluator to use.
|
||||
*
|
||||
* @var RuleEvaluator
|
||||
*/
|
||||
private $rule_evaluator;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param RuleEvaluator $rule_evaluator The rule evaluator to use.
|
||||
*/
|
||||
public function __construct( $rule_evaluator = null ) {
|
||||
$this->rule_evaluator = null === $rule_evaluator
|
||||
? new RuleEvaluator()
|
||||
: $rule_evaluator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an OR operation on the rule's left and right operands.
|
||||
*
|
||||
* @param object $rule The specific rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
foreach ( $rule->operands as $operand ) {
|
||||
$evaluated_operand = $this->rule_evaluator->evaluate(
|
||||
$operand,
|
||||
$stored_state
|
||||
);
|
||||
|
||||
if ( $evaluated_operand ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
if ( ! isset( $rule->operands ) || ! is_array( $rule->operands ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor for publishing based on the number of orders.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor for publishing based on the number of orders.
|
||||
*/
|
||||
class OrderCountRuleProcessor implements RuleProcessorInterface {
|
||||
|
||||
/**
|
||||
* The orders provider.
|
||||
*
|
||||
* @var OrdersProvider
|
||||
*/
|
||||
protected $orders_provider;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param object $orders_provider The orders provider.
|
||||
*/
|
||||
public function __construct( $orders_provider = null ) {
|
||||
$this->orders_provider = null === $orders_provider
|
||||
? new OrdersProvider()
|
||||
: $orders_provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the rule.
|
||||
*
|
||||
* @param object $rule The rule to process.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool Whether the rule passes or not.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
$count = $this->orders_provider->get_order_count();
|
||||
|
||||
return ComparisonOperation::compare(
|
||||
$count,
|
||||
$rule->value,
|
||||
$rule->operation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
if ( ! isset( $rule->value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->operation ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* Provider for order-related queries and operations.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Provider for order-related queries and operations.
|
||||
*/
|
||||
class OrdersProvider {
|
||||
/**
|
||||
* Allowed order statuses for calculating milestones.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allowed_statuses = array(
|
||||
'pending',
|
||||
'processing',
|
||||
'completed',
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns the number of orders.
|
||||
*
|
||||
* @return integer The number of orders.
|
||||
*/
|
||||
public function get_order_count() {
|
||||
$status_counts = array_map( 'wc_orders_count', $this->allowed_statuses );
|
||||
$orders_count = array_sum( $status_counts );
|
||||
|
||||
return $orders_count;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor that passes. This is required because an empty set of rules
|
||||
* (or predicate) evaluates to false.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor that passes.
|
||||
*/
|
||||
class PassRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* Passes the rule.
|
||||
*
|
||||
* @param object $rule The specific rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool Always true.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor for sending when the provided plugin is activated and
|
||||
* matches the specified version.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use Automattic\WooCommerce\Admin\PluginsProvider\PluginsProvider;
|
||||
|
||||
/**
|
||||
* Rule processor for sending when the provided plugin is activated and
|
||||
* matches the specified version.
|
||||
*/
|
||||
class PluginVersionRuleProcessor implements RuleProcessorInterface {
|
||||
|
||||
/**
|
||||
* Plugins provider instance.
|
||||
*
|
||||
* @var PluginsProviderInterface
|
||||
*/
|
||||
private $plugins_provider;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param PluginsProviderInterface $plugins_provider The plugins provider.
|
||||
*/
|
||||
public function __construct( $plugins_provider = null ) {
|
||||
$this->plugins_provider = null === $plugins_provider
|
||||
? new PluginsProvider()
|
||||
: $plugins_provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the rule.
|
||||
*
|
||||
* @param object $rule The specific rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool Whether the rule passes or not.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
$active_plugin_slugs = $this->plugins_provider->get_active_plugin_slugs();
|
||||
|
||||
if ( ! in_array( $rule->plugin, $active_plugin_slugs, true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$plugin_data = $this->plugins_provider->get_plugin_data( $rule->plugin );
|
||||
|
||||
if ( ! is_array( $plugin_data ) || ! array_key_exists( 'Version', $plugin_data ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$plugin_version = $plugin_data['Version'];
|
||||
|
||||
return version_compare( $plugin_version, $rule->version, $rule->operator );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
if ( ! isset( $rule->plugin ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->version ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->operator ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor for sending when the provided plugins are activated.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use Automattic\WooCommerce\Admin\PluginsProvider\PluginsProvider;
|
||||
|
||||
/**
|
||||
* Rule processor for sending when the provided plugins are activated.
|
||||
*/
|
||||
class PluginsActivatedRuleProcessor implements RuleProcessorInterface {
|
||||
|
||||
/**
|
||||
* The plugins provider.
|
||||
*
|
||||
* @var PluginsProviderInterface
|
||||
*/
|
||||
protected $plugins_provider;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param PluginsProviderInterface $plugins_provider The plugins provider.
|
||||
*/
|
||||
public function __construct( $plugins_provider = null ) {
|
||||
$this->plugins_provider = null === $plugins_provider
|
||||
? new PluginsProvider()
|
||||
: $plugins_provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the rule.
|
||||
*
|
||||
* @param object $rule The specific rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool Whether the rule passes or not.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
if ( ! is_countable( $rule->plugins ) || 0 === count( $rule->plugins ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$active_plugin_slugs = $this->plugins_provider->get_active_plugin_slugs();
|
||||
|
||||
foreach ( $rule->plugins as $plugin_slug ) {
|
||||
if ( ! is_string( $plugin_slug ) ) {
|
||||
$logger = wc_get_logger();
|
||||
$logger->warning(
|
||||
__( 'Invalid plugin slug provided in the plugins activated rule.', 'woocommerce' )
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! in_array( $plugin_slug, $active_plugin_slugs, true ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
if ( ! isset( $rule->plugins ) || ! is_array( $rule->plugins ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor that performs a comparison operation against the number of
|
||||
* products.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor that performs a comparison operation against the number of
|
||||
* products.
|
||||
*/
|
||||
class ProductCountRuleProcessor implements RuleProcessorInterface {
|
||||
|
||||
/**
|
||||
* The product query.
|
||||
*
|
||||
* @var WC_Product_Query
|
||||
*/
|
||||
protected $product_query;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param object $product_query The product query.
|
||||
*/
|
||||
public function __construct( $product_query = null ) {
|
||||
$this->product_query = null === $product_query
|
||||
? new \WC_Product_Query(
|
||||
array(
|
||||
'limit' => 1,
|
||||
'paginate' => true,
|
||||
'return' => 'ids',
|
||||
'status' => array( 'publish' ),
|
||||
)
|
||||
)
|
||||
: $product_query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a comparison operation against the number of products.
|
||||
*
|
||||
* @param object $rule The specific rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
$products = $this->product_query->get_products();
|
||||
|
||||
return ComparisonOperation::compare(
|
||||
$products->total,
|
||||
$rule->value,
|
||||
$rule->operation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
if ( ! isset( $rule->value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->operation ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor for sending after a specified date/time.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use Automattic\WooCommerce\Admin\DateTimeProvider\CurrentDateTimeProvider;
|
||||
|
||||
/**
|
||||
* Rule processor for sending after a specified date/time.
|
||||
*/
|
||||
class PublishAfterTimeRuleProcessor implements RuleProcessorInterface {
|
||||
|
||||
/**
|
||||
* The DateTime provider.
|
||||
*
|
||||
* @var DateTimeProviderInterface
|
||||
*/
|
||||
protected $date_time_provider;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param DateTimeProviderInterface $date_time_provider The DateTime provider.
|
||||
*/
|
||||
public function __construct( $date_time_provider = null ) {
|
||||
$this->date_time_provider = null === $date_time_provider
|
||||
? new CurrentDateTimeProvider()
|
||||
: $date_time_provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the rule.
|
||||
*
|
||||
* @param object $rule The specific rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool Whether the rule passes or not.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
return $this->date_time_provider->get_now() >= new \DateTime( $rule->publish_after );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
if ( ! isset( $rule->publish_after ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
new \DateTime( $rule->publish_after );
|
||||
} catch ( \Throwable $e ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor for sending before a specified date/time.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use Automattic\WooCommerce\Admin\DateTimeProvider\CurrentDateTimeProvider;
|
||||
|
||||
/**
|
||||
* Rule processor for sending before a specified date/time.
|
||||
*/
|
||||
class PublishBeforeTimeRuleProcessor implements RuleProcessorInterface {
|
||||
|
||||
/**
|
||||
* The DateTime provider.
|
||||
*
|
||||
* @var DateTimeProviderInterface
|
||||
*/
|
||||
protected $date_time_provider;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param DateTimeProviderInterface $date_time_provider The DateTime provider.
|
||||
*/
|
||||
public function __construct( $date_time_provider = null ) {
|
||||
$this->date_time_provider = null === $date_time_provider
|
||||
? new CurrentDateTimeProvider()
|
||||
: $date_time_provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the rule.
|
||||
*
|
||||
* @param object $rule The specific rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool Whether the rule passes or not.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
return $this->date_time_provider->get_now() <= new \DateTime( $rule->publish_before );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
if ( ! isset( $rule->publish_before ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
new \DateTime( $rule->publish_before );
|
||||
} catch ( \Throwable $e ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
/**
|
||||
* Evaluate the given rules as an AND operation - return false early if a
|
||||
* rule evaluates to false.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Evaluate the given rules as an AND operation - return false early if a
|
||||
* rule evaluates to false.
|
||||
*/
|
||||
class RuleEvaluator {
|
||||
|
||||
/**
|
||||
* GetRuleProcessor to use.
|
||||
*
|
||||
* @var GetRuleProcessor
|
||||
*/
|
||||
private $get_rule_processor;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param GetRuleProcessor $get_rule_processor The GetRuleProcessor to use.
|
||||
*/
|
||||
public function __construct( $get_rule_processor = null ) {
|
||||
$this->get_rule_processor = null === $get_rule_processor
|
||||
? new GetRuleProcessor()
|
||||
: $get_rule_processor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the given rules as an AND operation - return false early if a
|
||||
* rule evaluates to false.
|
||||
*
|
||||
* @param array|object $rules The rule or rules being processed.
|
||||
* @param object|null $stored_state Stored state.
|
||||
* @param array $logger_args Arguments for the event logger. `slug` is required.
|
||||
*
|
||||
* @throws \InvalidArgumentException Thrown when $logger_args is missing slug.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function evaluate( $rules, $stored_state = null, $logger_args = array() ) {
|
||||
|
||||
if ( is_bool( $rules ) ) {
|
||||
return $rules;
|
||||
}
|
||||
|
||||
if ( ! is_array( $rules ) ) {
|
||||
$rules = array( $rules );
|
||||
}
|
||||
|
||||
if ( 0 === count( $rules ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$evaluation_logger = null;
|
||||
|
||||
if ( count( $logger_args ) ) {
|
||||
if ( ! array_key_exists( 'slug', $logger_args ) ) {
|
||||
throw new \InvalidArgumentException( 'Missing required field: slug in $logger_args.' );
|
||||
}
|
||||
|
||||
array_key_exists( 'source', $logger_args ) ? $source = $logger_args['source'] : $source = null;
|
||||
|
||||
$evaluation_logger = new EvaluationLogger( $logger_args['slug'], $source );
|
||||
}
|
||||
|
||||
foreach ( $rules as $rule ) {
|
||||
if ( ! is_object( $rule ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$processor = $this->get_rule_processor->get_processor( $rule->type );
|
||||
$processor_result = $processor->process( $rule, $stored_state );
|
||||
$evaluation_logger && $evaluation_logger->add_result( $rule->type, $processor_result );
|
||||
|
||||
if ( ! $processor_result ) {
|
||||
$evaluation_logger && $evaluation_logger->log();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$evaluation_logger && $evaluation_logger->log();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* Interface for a rule processor.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor interface
|
||||
*/
|
||||
interface RuleProcessorInterface {
|
||||
/**
|
||||
* Processes a rule, returning the boolean result of the processing.
|
||||
*
|
||||
* @param object $rule The rule to process.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool The result of the processing.
|
||||
*/
|
||||
public function process( $rule, $stored_state );
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule );
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor that performs a comparison operation against a value in the
|
||||
* stored state object.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor that performs a comparison operation against a value in the
|
||||
* stored state object.
|
||||
*/
|
||||
class StoredStateRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* Performs a comparison operation against a value in the stored state object.
|
||||
*
|
||||
* @param object $rule The rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
if ( ! isset( $stored_state->{$rule->index} ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ComparisonOperation::compare(
|
||||
$stored_state->{$rule->index},
|
||||
$rule->value,
|
||||
$rule->operation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
if ( ! isset( $rule->index ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->operation ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles stored state setup for products.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\RemoteInboxNotificationsEngine;
|
||||
|
||||
/**
|
||||
* Handles stored state setup for products.
|
||||
*/
|
||||
class StoredStateSetupForProducts {
|
||||
const ASYNC_RUN_REMOTE_NOTIFICATIONS_ACTION_NAME =
|
||||
'woocommerce_admin/stored_state_setup_for_products/async/run_remote_notifications';
|
||||
|
||||
/**
|
||||
* Initialize the class via the admin_init hook.
|
||||
*/
|
||||
public static function admin_init() {
|
||||
add_action( 'product_page_product_importer', array( __CLASS__, 'run_on_product_importer' ) );
|
||||
add_action( 'transition_post_status', array( __CLASS__, 'run_on_transition_post_status' ), 10, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the class via the init hook.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final public static function init() {
|
||||
add_action( self::ASYNC_RUN_REMOTE_NOTIFICATIONS_ACTION_NAME, array( __CLASS__, 'run_remote_notifications' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the remote notifications engine. This is triggered by
|
||||
* action-scheduler after a product is added. It also cleans up from
|
||||
* setting the product count increment.
|
||||
*/
|
||||
public static function run_remote_notifications() {
|
||||
RemoteInboxNotificationsEngine::run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set initial stored state values.
|
||||
*
|
||||
* @param object $stored_state The stored state.
|
||||
*
|
||||
* @return object The stored state.
|
||||
*/
|
||||
public static function init_stored_state( $stored_state ) {
|
||||
$stored_state->there_were_no_products = ! self::are_there_products();
|
||||
$stored_state->there_are_now_products = ! $stored_state->there_were_no_products;
|
||||
|
||||
return $stored_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are there products query.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function are_there_products() {
|
||||
$query = new \WC_Product_Query(
|
||||
array(
|
||||
'limit' => 1,
|
||||
'paginate' => true,
|
||||
'return' => 'ids',
|
||||
'status' => array( 'publish' ),
|
||||
)
|
||||
);
|
||||
$products = $query->get_products();
|
||||
$count = $products->total;
|
||||
|
||||
return $count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs on product importer steps.
|
||||
*/
|
||||
public static function run_on_product_importer() {
|
||||
// We're only interested in when the importer completes.
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Recommended
|
||||
if ( ! isset( $_REQUEST['step'] ) ) {
|
||||
return;
|
||||
}
|
||||
if ( 'done' !== $_REQUEST['step'] ) {
|
||||
return;
|
||||
}
|
||||
// phpcs:enable
|
||||
|
||||
self::update_stored_state_and_possibly_run_remote_notifications();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs when a post status transitions, but we're only interested if it is
|
||||
* a product being published.
|
||||
*
|
||||
* @param string $new_status The new status.
|
||||
* @param string $old_status The old status.
|
||||
* @param Post $post The post.
|
||||
*/
|
||||
public static function run_on_transition_post_status( $new_status, $old_status, $post ) {
|
||||
if (
|
||||
'product' !== $post->post_type ||
|
||||
'publish' !== $new_status
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::update_stored_state_and_possibly_run_remote_notifications();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues an async action (using action-scheduler) to run remote
|
||||
* notifications.
|
||||
*/
|
||||
private static function update_stored_state_and_possibly_run_remote_notifications() {
|
||||
$stored_state = RemoteInboxNotificationsEngine::get_stored_state();
|
||||
// If the stored_state is the same, we don't need to run remote notifications to avoid unnecessary action scheduling.
|
||||
if ( true === $stored_state->there_are_now_products ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$stored_state->there_are_now_products = true;
|
||||
RemoteInboxNotificationsEngine::update_stored_state( $stored_state );
|
||||
|
||||
// Run self::run_remote_notifications asynchronously.
|
||||
as_enqueue_async_action( self::ASYNC_RUN_REMOTE_NOTIFICATIONS_ACTION_NAME );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor that passes when a store's payments volume exceeds a provided amount.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use Automattic\WooCommerce\Admin\API\Reports\Revenue\Query as RevenueQuery;
|
||||
use Automattic\WooCommerce\Admin\API\Reports\TimeInterval;
|
||||
|
||||
/**
|
||||
* Rule processor that passes when a store's payments volume exceeds a provided amount.
|
||||
*/
|
||||
class TotalPaymentsVolumeProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* Compare against the store's total payments volume.
|
||||
*
|
||||
* @param object $rule The rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
$dates = TimeInterval::get_timeframe_dates( $rule->timeframe );
|
||||
$reports_revenue = $this->get_reports_query(
|
||||
array(
|
||||
'before' => $dates['end'],
|
||||
'after' => $dates['start'],
|
||||
'interval' => 'year',
|
||||
'fields' => array( 'total_sales' ),
|
||||
)
|
||||
);
|
||||
$report_data = $reports_revenue->get_data();
|
||||
|
||||
if ( ! $report_data || ! isset( $report_data->totals->total_sales ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$value = $report_data->totals->total_sales;
|
||||
|
||||
return ComparisonOperation::compare(
|
||||
$value,
|
||||
$rule->value,
|
||||
$rule->operation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
$allowed_timeframes = array(
|
||||
'last_week',
|
||||
'last_month',
|
||||
'last_quarter',
|
||||
'last_6_months',
|
||||
'last_year',
|
||||
);
|
||||
|
||||
if ( ! isset( $rule->timeframe ) || ! in_array( $rule->timeframe, $allowed_timeframes, true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->value ) || ! is_numeric( $rule->value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->operation ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the report query.
|
||||
*
|
||||
* @param array $args The query args.
|
||||
*
|
||||
* @return RevenueQuery The report query.
|
||||
*/
|
||||
protected function get_reports_query( $args ) {
|
||||
return new RevenueQuery(
|
||||
$args
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers;
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\TransformerInterface;
|
||||
use InvalidArgumentException;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Search array value by one of its key.
|
||||
*
|
||||
* @package Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers
|
||||
*/
|
||||
class ArrayColumn implements TransformerInterface {
|
||||
/**
|
||||
* Search array value by one of its key.
|
||||
*
|
||||
* @param mixed $value a value to transform.
|
||||
* @param stdClass|null $arguments required arguments 'key'.
|
||||
* @param string|null $default_value default value.
|
||||
*
|
||||
* @throws InvalidArgumentException Throws when the required argument 'key' is missing.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function transform( $value, stdClass $arguments = null, $default_value = array() ) {
|
||||
if ( ! is_array( $value ) ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
return array_column( $value, $arguments->key );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Transformer arguments.
|
||||
*
|
||||
* @param stdClass|null $arguments arguments to validate.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function validate( stdClass $arguments = null ) {
|
||||
if ( ! isset( $arguments->key ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
null !== $arguments->key &&
|
||||
! is_string( $arguments->key ) &&
|
||||
! is_int( $arguments->key )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers;
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\TransformerInterface;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Flatten nested array.
|
||||
*
|
||||
* @package Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers
|
||||
*/
|
||||
class ArrayFlatten implements TransformerInterface {
|
||||
/**
|
||||
* Search a given value in the array.
|
||||
*
|
||||
* @param mixed $value a value to transform.
|
||||
* @param stdClass|null $arguments arguments.
|
||||
* @param string|null $default_value default value.
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function transform( $value, stdClass $arguments = null, $default_value = array() ) {
|
||||
if ( ! is_array( $value ) ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
$return = array();
|
||||
array_walk_recursive(
|
||||
$value,
|
||||
function ( $item ) use ( &$return ) {
|
||||
$return[] = $item;
|
||||
}
|
||||
);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Transformer arguments.
|
||||
*
|
||||
* @param stdClass|null $arguments arguments to validate.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function validate( stdClass $arguments = null ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers;
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\TransformerInterface;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Search array value by one of its key.
|
||||
*
|
||||
* @package Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers
|
||||
*/
|
||||
class ArrayKeys implements TransformerInterface {
|
||||
/**
|
||||
* Search array value by one of its key.
|
||||
*
|
||||
* @param mixed $value a value to transform.
|
||||
* @param stdClass|null $arguments arguments.
|
||||
* @param string|null $default_value default value.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function transform( $value, stdClass $arguments = null, $default_value = array() ) {
|
||||
if ( ! is_array( $value ) ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
return array_keys( $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Transformer arguments.
|
||||
*
|
||||
* @param stdClass|null $arguments arguments to validate.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function validate( stdClass $arguments = null ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers;
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\TransformerInterface;
|
||||
use InvalidArgumentException;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Searches a given a given value in the array.
|
||||
*
|
||||
* @package Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers
|
||||
*/
|
||||
class ArraySearch implements TransformerInterface {
|
||||
/**
|
||||
* Search a given value in the array.
|
||||
*
|
||||
* @param mixed $value a value to transform.
|
||||
* @param stdClass|null $arguments required argument 'value'.
|
||||
* @param string|null $default_value default value.
|
||||
*
|
||||
* @throws InvalidArgumentException Throws when the required 'value' is missing.
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function transform( $value, stdClass $arguments = null, $default_value = null ) {
|
||||
if ( ! is_array( $value ) ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
$key = array_search( $arguments->value, $value, true );
|
||||
if ( false !== $key ) {
|
||||
return $value[ $key ];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Transformer arguments.
|
||||
*
|
||||
* @param stdClass|null $arguments arguments to validate.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function validate( stdClass $arguments = null ) {
|
||||
if ( ! isset( $arguments->value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers;
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\TransformerInterface;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Search array value by one of its key.
|
||||
*
|
||||
* @package Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers
|
||||
*/
|
||||
class ArrayValues implements TransformerInterface {
|
||||
/**
|
||||
* Search array value by one of its key.
|
||||
*
|
||||
* @param mixed $value a value to transform.
|
||||
* @param stdClass|null $arguments arguments.
|
||||
* @param string|null $default_value default value.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function transform( $value, stdClass $arguments = null, $default_value = array() ) {
|
||||
if ( ! is_array( $value ) ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
return array_values( $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Transformer arguments.
|
||||
*
|
||||
* @param stdClass|null $arguments arguments to validate.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function validate( stdClass $arguments = null ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers;
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\TransformerInterface;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Count elements in Array or Countable object.
|
||||
*
|
||||
* @package Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers
|
||||
*/
|
||||
class Count implements TransformerInterface {
|
||||
/**
|
||||
* Count elements in Array or Countable object.
|
||||
*
|
||||
* @param array|Countable $value an array to count.
|
||||
* @param stdClass|null $arguments arguments.
|
||||
* @param string|null $default_value default value.
|
||||
*
|
||||
* @return number
|
||||
*/
|
||||
public function transform( $value, stdClass $arguments = null, $default_value = null ) {
|
||||
if ( ! is_array( $value ) && ! $value instanceof \Countable ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
return count( $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Transformer arguments.
|
||||
*
|
||||
* @param stdClass|null $arguments arguments to validate.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function validate( stdClass $arguments = null ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers;
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\TransformerInterface;
|
||||
use InvalidArgumentException;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Find an array value by dot notation.
|
||||
*
|
||||
* @package Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers
|
||||
*/
|
||||
class DotNotation implements TransformerInterface {
|
||||
|
||||
/**
|
||||
* Find given path from the given value.
|
||||
*
|
||||
* @param mixed $value a value to transform.
|
||||
* @param stdClass|null $arguments required argument 'path'.
|
||||
* @param string|null $default_value default value.
|
||||
*
|
||||
* @throws InvalidArgumentException Throws when the required 'path' is missing.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function transform( $value, stdclass $arguments = null, $default_value = null ) {
|
||||
if ( is_object( $value ) ) {
|
||||
// if the value is an object, convert it to an array.
|
||||
$value = json_decode( wp_json_encode( $value ), true );
|
||||
}
|
||||
|
||||
return $this->get( $value, $arguments->path, $default_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the given $path in $array_to_search by dot notation.
|
||||
*
|
||||
* @param array $array_to_search an array to search in.
|
||||
* @param string $path a path in the given array.
|
||||
* @param null $default_value default value to return if $path was not found.
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function get( $array_to_search, $path, $default_value = null ) {
|
||||
if ( ! is_array( $array_to_search ) ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
if ( isset( $array_to_search[ $path ] ) ) {
|
||||
return $array_to_search[ $path ];
|
||||
}
|
||||
|
||||
foreach ( explode( '.', $path ) as $segment ) {
|
||||
if ( ! is_array( $array_to_search ) || ! array_key_exists( $segment, $array_to_search ) ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
$array_to_search = $array_to_search[ $segment ];
|
||||
}
|
||||
|
||||
return $array_to_search;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Transformer arguments.
|
||||
*
|
||||
* @param stdClass|null $arguments arguments to validate.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function validate( stdClass $arguments = null ) {
|
||||
if ( ! isset( $arguments->path ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers;
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\TransformerInterface;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Prepare site URL for comparison.
|
||||
*
|
||||
* @package Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers
|
||||
*/
|
||||
class PrepareUrl implements TransformerInterface {
|
||||
/**
|
||||
* Prepares the site URL by removing the protocol and trailing slash.
|
||||
*
|
||||
* @param string $value a value to transform.
|
||||
* @param stdClass|null $arguments arguments.
|
||||
* @param string|null $default_value default value.
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function transform( $value, stdClass $arguments = null, $default_value = null ) {
|
||||
if ( ! is_string( $value ) ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
$url_parts = wp_parse_url( rtrim( $value, '/' ) );
|
||||
|
||||
if ( ! $url_parts ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
if ( ! isset( $url_parts['host'] ) ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
if ( isset( $url_parts['path'] ) ) {
|
||||
return $url_parts['host'] . $url_parts['path'];
|
||||
}
|
||||
|
||||
return $url_parts['host'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Transformer arguments.
|
||||
*
|
||||
* @param stdClass|null $arguments arguments to validate.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function validate( stdClass $arguments = null ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers;
|
||||
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* An interface to define a transformer.
|
||||
*
|
||||
* Interface TransformerInterface
|
||||
*
|
||||
* @package Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers
|
||||
*/
|
||||
interface TransformerInterface {
|
||||
/**
|
||||
* Transform given value to a different value.
|
||||
*
|
||||
* @param mixed $value a value to transform.
|
||||
* @param stdClass|null $arguments arguments.
|
||||
* @param string|null $default_value default value.
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function transform( $value, stdClass $arguments = null, $default_value = null );
|
||||
|
||||
/**
|
||||
* Validate Transformer arguments.
|
||||
*
|
||||
* @param stdClass|null $arguments arguments to validate.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function validate( stdClass $arguments = null );
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* A simple service class for the Transformer classes.
|
||||
*
|
||||
* Class TransformerService
|
||||
*
|
||||
* @package Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers
|
||||
*/
|
||||
class TransformerService {
|
||||
/**
|
||||
* Create a transformer object by name.
|
||||
*
|
||||
* @param string $name name of the transformer.
|
||||
*
|
||||
* @return TransformerInterface|null
|
||||
*/
|
||||
public static function create_transformer( $name ) {
|
||||
$camel_cased = str_replace( ' ', '', ucwords( str_replace( '_', ' ', $name ) ) );
|
||||
|
||||
$classname = __NAMESPACE__ . '\\' . $camel_cased;
|
||||
if ( ! class_exists( $classname ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new $classname();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply transformers to the given value.
|
||||
*
|
||||
* @param mixed $target_value a value to transform.
|
||||
* @param array $transformer_configs transform configuration.
|
||||
* @param bool $is_default_set flag on is default value set.
|
||||
* @param string $default_value default value.
|
||||
*
|
||||
* @throws InvalidArgumentException Throws when one of the requried arguments is missing.
|
||||
* @return mixed|null
|
||||
*/
|
||||
public static function apply( $target_value, array $transformer_configs, $is_default_set, $default_value ) {
|
||||
foreach ( $transformer_configs as $transformer_config ) {
|
||||
if ( ! isset( $transformer_config->use ) ) {
|
||||
throw new InvalidArgumentException( 'Missing required config value: use' );
|
||||
}
|
||||
|
||||
if ( ! isset( $transformer_config->arguments ) ) {
|
||||
$transformer_config->arguments = null;
|
||||
}
|
||||
|
||||
$transformer = self::create_transformer( $transformer_config->use );
|
||||
if ( null === $transformer ) {
|
||||
throw new InvalidArgumentException( "Unable to find a transformer by name: {$transformer_config->use}" ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
|
||||
}
|
||||
|
||||
$target_value = $transformer->transform( $target_value, $transformer_config->arguments, $is_default_set ? $default_value : null );
|
||||
|
||||
// Break early when there's no more value to traverse.
|
||||
if ( null === $target_value ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $is_default_set ) {
|
||||
// Nulls always return the default value.
|
||||
if ( null === $target_value ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
// When type of the default value is different from the target value, return the default value
|
||||
// to ensure type safety.
|
||||
if ( gettype( $default_value ) !== gettype( $target_value ) ) {
|
||||
return $default_value;
|
||||
}
|
||||
}
|
||||
|
||||
return $target_value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* WCAdmin active for provider.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
use Automattic\WooCommerce\Admin\WCAdminHelper;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* WCAdminActiveForProvider class
|
||||
*/
|
||||
class WCAdminActiveForProvider {
|
||||
/**
|
||||
* Get the number of seconds that the store has been active.
|
||||
*
|
||||
* @return number Number of seconds.
|
||||
*/
|
||||
public function get_wcadmin_active_for_in_seconds() {
|
||||
return WCAdminHelper::get_wcadmin_active_for_in_seconds();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor for publishing if wc-admin has been active for at least the
|
||||
* given number of seconds.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor for publishing if wc-admin has been active for at least the
|
||||
* given number of seconds.
|
||||
*/
|
||||
class WCAdminActiveForRuleProcessor implements RuleProcessorInterface {
|
||||
|
||||
/**
|
||||
* Provides the amount of time wcadmin has been active for.
|
||||
*
|
||||
* @var WCAdminActiveForProvider
|
||||
*/
|
||||
protected $wcadmin_active_for_provider;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param object $wcadmin_active_for_provider Provides the amount of time wcadmin has been active for.
|
||||
*/
|
||||
public function __construct( $wcadmin_active_for_provider = null ) {
|
||||
$this->wcadmin_active_for_provider = null === $wcadmin_active_for_provider
|
||||
? new WCAdminActiveForProvider()
|
||||
: $wcadmin_active_for_provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a comparison operation against the amount of time wc-admin has
|
||||
* been active for in days.
|
||||
*
|
||||
* @param object $rule The rule being processed.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
$active_for_seconds = $this->wcadmin_active_for_provider->get_wcadmin_active_for_in_seconds();
|
||||
|
||||
if ( ! $active_for_seconds || ! is_numeric( $active_for_seconds ) || $active_for_seconds < 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$rule_seconds = $rule->days * DAY_IN_SECONDS;
|
||||
|
||||
return ComparisonOperation::compare(
|
||||
$active_for_seconds,
|
||||
$rule_seconds,
|
||||
$rule->operation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
// Ensure that 'days' property is set and is a valid numeric value.
|
||||
if ( ! isset( $rule->days ) || ! is_numeric( $rule->days ) || $rule->days < 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $rule->operation ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* Rule processor for sending when WooCommerce Admin has been updated.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\RemoteInboxNotificationsEngine;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor for sending when WooCommerce Admin has been updated.
|
||||
*/
|
||||
class WooCommerceAdminUpdatedRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* Process the rule.
|
||||
*
|
||||
* @param object $rule The specific rule being processed by this rule processor.
|
||||
* @param object $stored_state Stored state.
|
||||
*
|
||||
* @return bool Whether the rule passes or not.
|
||||
*/
|
||||
public function process( $rule, $stored_state ) {
|
||||
return get_option( RemoteInboxNotificationsEngine::WCA_UPDATED_OPTION_NAME, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user