Remote inbox notification delivery (https://github.com/woocommerce/woocommerce-admin/pull/4143)
* Poll and persist specs * Process specs into admin notes * Add send at time rule processor * Fix style issues * Clear actions before recreating them to avoid dupes * Trigger the RINDS engine when a plugin is activated * Unit test SendAtTimeRuleProcessor * Implement plugins activated rule processor * Don't throw exception for unrecognised rule type. Also unit test around this. * add url_is_action_query to tell whether to wrap the URL in wc_admin_url() call or not * Add NOT rule * revert change to install.php * Drop unimplemented resend after dismissal rule * Add OR rule * Explicitly make "fail" a type of rule that can be applied to a spec * Add plugin version rule processor * Tidy up, don't need to pass $spec everywhere * Remove meta record for action state - not really needed * Move spec runner into it's own class, add some checks around re-unactioning a note * Replace if..else with switch * Just update the option * Check that the JSON coming in is an array * Change OR rule to accept an array of operands * Add Pass rule processor * Fix specs that are initially not published * Rename send at rule to publish after * Add publish before rule * Remove unused interface * Can't use PHP7's anonymous classes * New notification: How to draw attention to your online store * Add feature flag for rule-base inbox notes * rename everything to RemoteInboxNotifications from RINDS * Fix merge fail * fix test * Change preunactioned to pending * Move feature flag check into Events.php * Refactor reading a data source * Rename poll_data_sources function * Refactor EvaluateAndGetStatus::evaluate to take the rule evaluator directly * Check that the response body exists * Add validation and defensive checks * Add rule processor interface * Update note created time on status change * Move non-test dependencies into processor constructors * Update to proposed live URL * Remove setting icon as it's being deprecated Co-authored-by: Rebecca Scott <me@becdetat.com>
This commit is contained in:
parent
b4c735f0de
commit
a3ae3569c3
|
@ -8,6 +8,7 @@
|
|||
"marketing": true,
|
||||
"navigation": false,
|
||||
"onboarding": true,
|
||||
"remote-inbox-notifications": false,
|
||||
"shipping-label-banner": true,
|
||||
"store-alerts": true,
|
||||
"wcpay": true,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"marketing": true,
|
||||
"navigation": true,
|
||||
"onboarding": true,
|
||||
"remote-inbox-notifications": true,
|
||||
"shipping-label-banner": true,
|
||||
"store-alerts": true,
|
||||
"wcpay": true,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"marketing": true,
|
||||
"navigation": false,
|
||||
"onboarding": true,
|
||||
"remote-inbox-notifications": false,
|
||||
"shipping-label-banner": true,
|
||||
"store-alerts": true,
|
||||
"wcpay": true,
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
/**
|
||||
* A provider for getting the current DateTime.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\DateTimeProvider;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use Automattic\WooCommerce\Admin\DateTimeProvider\DateTimeProviderInterface;
|
||||
|
||||
/**
|
||||
* Current DateTime Provider.
|
||||
*
|
||||
* Uses the current DateTime.
|
||||
*/
|
||||
class CurrentDateTimeProvider implements DateTimeProviderInterface {
|
||||
/**
|
||||
* Returns the current DateTime.
|
||||
*
|
||||
* @return DateTime
|
||||
*/
|
||||
public function get_now() {
|
||||
return new \DateTime();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
/**
|
||||
* Interface for a provider for getting the current DateTime,
|
||||
* designed to be mockable for unit tests.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\DateTimeProvider;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* DateTime Provider Interface.
|
||||
*/
|
||||
interface DateTimeProviderInterface {
|
||||
/**
|
||||
* Returns the current DateTime.
|
||||
*
|
||||
* @return DateTime
|
||||
*/
|
||||
public function get_now();
|
||||
}
|
|
@ -22,6 +22,9 @@ use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes_WooCommerce_Payments;
|
|||
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes_Marketing;
|
||||
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes_WooCommerce_Subscriptions;
|
||||
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes_Migrate_From_Shopify;
|
||||
use \Automattic\WooCommerce\Admin\RemoteInboxNotifications\DataSourcePoller;
|
||||
use \Automattic\WooCommerce\Admin\RemoteInboxNotifications\RemoteInboxNotificationsEngine;
|
||||
use \Automattic\WooCommerce\Admin\Loader;
|
||||
|
||||
/**
|
||||
* WC_Admin_Events Class.
|
||||
|
@ -78,5 +81,10 @@ class Events {
|
|||
WC_Admin_Notes_Giving_Feedback_Notes::possibly_add_note();
|
||||
WC_Admin_Notes_WooCommerce_Subscriptions::possibly_add_note();
|
||||
WC_Admin_Notes_Migrate_From_Shopify::possibly_add_note();
|
||||
|
||||
if ( Loader::is_feature_enabled( 'remote-inbox-notifications' ) ) {
|
||||
DataSourcePoller::read_specs_from_data_sources();
|
||||
RemoteInboxNotificationsEngine::run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,11 +12,13 @@ defined( 'ABSPATH' ) || exit;
|
|||
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes;
|
||||
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes_Historical_Data;
|
||||
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes_Order_Milestones;
|
||||
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes_Welcome_Message;
|
||||
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes_Woo_Subscriptions_Notes;
|
||||
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes_Tracking_Opt_In;
|
||||
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes_WooCommerce_Payments;
|
||||
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes_Install_JP_And_WCS_Plugins;
|
||||
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes_Draw_Attention;
|
||||
use \Automattic\WooCommerce\Admin\RemoteInboxNotifications\RemoteInboxNotificationsEngine;
|
||||
|
||||
/**
|
||||
* Feature plugin main class.
|
||||
|
@ -188,6 +190,9 @@ class FeaturePlugin {
|
|||
new WC_Admin_Notes_WooCommerce_Payments();
|
||||
new WC_Admin_Notes_Install_JP_And_WCS_Plugins();
|
||||
new WC_Admin_Notes_Draw_Attention();
|
||||
|
||||
// Initialize RemoteInboxNotificationsEngine.
|
||||
RemoteInboxNotificationsEngine::init();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,7 +40,7 @@ class Install {
|
|||
'wc_admin_update_0251_remove_unsnooze_action',
|
||||
'wc_admin_update_0251_db_version',
|
||||
),
|
||||
'1.1.0' => array(
|
||||
'1.1.0' => array(
|
||||
'wc_admin_update_110_remove_facebook_note',
|
||||
'wc_admin_update_110_db_version',
|
||||
),
|
||||
|
|
|
@ -24,6 +24,7 @@ class WC_Admin_Note extends \WC_Data {
|
|||
const E_WC_ADMIN_NOTE_MARKETING = 'marketing'; // used for adding marketing messages.
|
||||
|
||||
// Note status codes.
|
||||
const E_WC_ADMIN_NOTE_PENDING = 'pending'; // the note is not actioned but shouldn't be displayed.
|
||||
const E_WC_ADMIN_NOTE_UNACTIONED = 'unactioned'; // the note has not yet been actioned by a user.
|
||||
const E_WC_ADMIN_NOTE_ACTIONED = 'actioned'; // the note has had its action completed by a user.
|
||||
const E_WC_ADMIN_NOTE_SNOOZED = 'snoozed'; // the note has been snoozed by a user.
|
||||
|
@ -137,6 +138,7 @@ class WC_Admin_Note extends \WC_Data {
|
|||
*/
|
||||
public static function get_allowed_statuses() {
|
||||
$allowed_statuses = array(
|
||||
self::E_WC_ADMIN_NOTE_PENDING,
|
||||
self::E_WC_ADMIN_NOTE_ACTIONED,
|
||||
self::E_WC_ADMIN_NOTE_UNACTIONED,
|
||||
self::E_WC_ADMIN_NOTE_SNOOZED,
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
/**
|
||||
* A provider for getting access to plugin queries.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\PluginsProvider;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use Automattic\WooCommerce\Admin\PluginsProvider\PluginsProviderInterface;
|
||||
use Automattic\WooCommerce\Admin\PluginsHelper;
|
||||
|
||||
/**
|
||||
* Plugins Provider.
|
||||
*
|
||||
* Uses the live PluginsHelper.
|
||||
*/
|
||||
class PluginsProvider implements PluginsProviderInterface {
|
||||
/**
|
||||
* The deactivated plugin slug.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $deactivated_plugin_slug = '';
|
||||
|
||||
/**
|
||||
* Get an array of active plugin slugs.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_active_plugin_slugs() {
|
||||
return array_filter(
|
||||
PluginsHelper::get_active_plugin_slugs(),
|
||||
function( $p ) {
|
||||
return $p !== self::$deactivated_plugin_slug;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the deactivated plugin. This is needed because the deactivated_plugin
|
||||
* hook happens before the option is updated which means that getting the
|
||||
* active plugins includes the deactivated plugin.
|
||||
*
|
||||
* @param string $plugin_path The path to the plugin being deactivated.
|
||||
*/
|
||||
public static function set_deactivated_plugin( $plugin_path ) {
|
||||
self::$deactivated_plugin_slug = explode( '/', $plugin_path )[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plugin data.
|
||||
*
|
||||
* @param string $plugin Path to the plugin file relative to the plugins directory or the plugin directory name.
|
||||
*
|
||||
* @return array|false
|
||||
*/
|
||||
public function get_plugin_data( $plugin ) {
|
||||
return PluginsHelper::get_plugin_data( $plugin );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to the plugin file relative to the plugins directory from the plugin slug.
|
||||
*
|
||||
* E.g. 'woocommerce' returns 'woocommerce/woocommerce.php'
|
||||
*
|
||||
* @param string $slug Plugin slug to get path for.
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function get_plugin_path_from_slug( $slug ) {
|
||||
return PluginsHelper::get_plugin_path_from_slug( $slug );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
/**
|
||||
* Interface for a provider for getting access to plugin queries,
|
||||
* designed to be mockable for unit tests.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\PluginsProvider;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Plugins Provider Interface
|
||||
*/
|
||||
interface PluginsProviderInterface {
|
||||
/**
|
||||
* Get an array of active plugin slugs.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_active_plugin_slugs();
|
||||
|
||||
/**
|
||||
* Get plugin data.
|
||||
*
|
||||
* @param string $plugin Path to the plugin file relative to the plugins directory or the plugin directory name.
|
||||
*
|
||||
* @return array|false
|
||||
*/
|
||||
public function get_plugin_data( $plugin );
|
||||
|
||||
/**
|
||||
* Get the path to the plugin file relative to the plugins directory from the plugin slug.
|
||||
*
|
||||
* E.g. 'woocommerce' returns 'woocommerce/woocommerce.php'
|
||||
*
|
||||
* @param string $slug Plugin slug to get path for.
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function get_plugin_path_from_slug( $slug );
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
<?php
|
||||
/**
|
||||
* Handles polling and storage of specs
|
||||
*
|
||||
* @package WooCommerce Admin/Classes
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Specs data source poller class.
|
||||
* This handles polling specs from JSON endpoints, and
|
||||
* stores the specs in to the database as an option.
|
||||
*/
|
||||
class DataSourcePoller {
|
||||
const DATA_SOURCES = array(
|
||||
'https://woocommerce.com/wp-json/wccom//inbox-notifications/1.0/notifications.json',
|
||||
);
|
||||
|
||||
/**
|
||||
* Reads the data sources for specs and persists those specs.
|
||||
*/
|
||||
public static function read_specs_from_data_sources() {
|
||||
$specs = array();
|
||||
|
||||
// Note that this merges the specs from the data sources based on the
|
||||
// slug - last one wins.
|
||||
foreach ( self::DATA_SOURCES as $url ) {
|
||||
$specs_from_data_source = self::read_data_source( $url, $specs );
|
||||
self::merge_specs( $specs_from_data_source, $specs );
|
||||
}
|
||||
|
||||
// Persist the specs as an option.
|
||||
update_option( RemoteInboxNotificationsEngine::SPECS_OPTION_NAME, $specs );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private static function read_data_source( $url ) {
|
||||
$response = wp_remote_get( $url );
|
||||
|
||||
if ( is_wp_error( $response ) || ! isset( $response['body'] ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$body = $response['body'];
|
||||
$specs = json_decode( $body );
|
||||
|
||||
if ( null === $specs ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if ( ! is_array( $specs ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $specs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the specs.
|
||||
*
|
||||
* @param Array $specs_to_merge_in The specs to merge in to $specs.
|
||||
* @param Array $specs The master list of specs.
|
||||
*/
|
||||
private static function merge_specs( $specs_to_merge_in, &$specs ) {
|
||||
foreach ( $specs_to_merge_in as $spec ) {
|
||||
if ( ! self::validate_spec( $spec ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$slug = $spec->slug;
|
||||
$specs[ $slug ] = $spec;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the spec.
|
||||
*
|
||||
* @param object $spec The spec to validate.
|
||||
*
|
||||
* @return bool The result of the validation.
|
||||
*/
|
||||
private static function validate_spec( $spec ) {
|
||||
if ( ! isset( $spec->slug ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $spec->status ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $spec->locales ) || ! is_array( $spec->locales ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( null === SpecRunner::get_locale( $spec->locales ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $spec->type ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $spec->slug ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( isset( $spec->actions ) && is_array( $spec->actions ) ) {
|
||||
foreach ( $spec->actions as $action ) {
|
||||
if ( ! self::validate_action( $action ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $spec->rules ) && is_array( $spec->rules ) ) {
|
||||
foreach ( $spec->rules as $rule ) {
|
||||
if ( ! isset( $rule->type ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$processor = GetRuleProcessor::get_processor( $rule->type );
|
||||
|
||||
if ( ! $processor->validate( $rule ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the action.
|
||||
*
|
||||
* @param object $action The action to validate.
|
||||
*
|
||||
* @return bool The result of the validation.
|
||||
*/
|
||||
private static function validate_action( $action ) {
|
||||
if ( ! isset( $action->locales ) || ! is_array( $action->locales ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( null === SpecRunner::get_action_locale( $action->locales ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $action->name ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $action->status ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
/**
|
||||
* Evaluates the spec and returns a status.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_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 $rule_evaluator Evaluates rules into true/false.
|
||||
*
|
||||
* @return string The evaluated status.
|
||||
*/
|
||||
public static function evaluate( $spec, $current_status, $rule_evaluator ) {
|
||||
// No rules should leave the note alone.
|
||||
if ( ! isset( $spec->rules ) ) {
|
||||
return $current_status;
|
||||
}
|
||||
|
||||
$evaluated_result = $rule_evaluator->evaluate( $spec->rules );
|
||||
|
||||
// Pending notes should be the spec status if the spec passes,
|
||||
// left alone otherwise.
|
||||
if ( WC_Admin_Note::E_WC_ADMIN_NOTE_PENDING === $current_status ) {
|
||||
return $evaluated_result
|
||||
? $spec->status
|
||||
: WC_Admin_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
|
||||
? WC_Admin_Note::E_WC_ADMIN_NOTE_UNACTIONED
|
||||
: $current_status;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
/**
|
||||
* Rule processor that fails.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes;
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor that fails.
|
||||
*/
|
||||
class FailRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* Fails the rule.
|
||||
*
|
||||
* @param object $rule The rule to process.
|
||||
*
|
||||
* @return bool Always false.
|
||||
*/
|
||||
public function process( $rule ) {
|
||||
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,45 @@
|
|||
<?php
|
||||
/**
|
||||
* Gets the processor for the specified rule type.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
return new FailRuleProcessor();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
/**
|
||||
* Rule processor that negates the rules in the rule's operand.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor that negates the rules in the rule's operand.
|
||||
*/
|
||||
class NotRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function process( $rule ) {
|
||||
$evaluated_operand = $this->rule_evaluator->evaluate( $rule->operand );
|
||||
|
||||
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,62 @@
|
|||
<?php
|
||||
/**
|
||||
* Rule processor that performs an OR operation on the rule's left and right
|
||||
* operands.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Rule processor that performs an OR operation on the rule's left and right
|
||||
* operands.
|
||||
*/
|
||||
class OrRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function process( $rule ) {
|
||||
foreach ( $rule->operands as $operand ) {
|
||||
$evaluated_operand = $this->rule_evaluator->evaluate( $operand );
|
||||
|
||||
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,38 @@
|
|||
<?php
|
||||
/**
|
||||
* Rule processor that passes. This is required because an empty set of rules
|
||||
* (or predicate) evaluates to false.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes;
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
|
||||
|
||||
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.
|
||||
*
|
||||
* @return bool Always true.
|
||||
*/
|
||||
public function process( $rule ) {
|
||||
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,78 @@
|
|||
<?php
|
||||
/**
|
||||
* Rule processor for sending when the provided plugin is activated and
|
||||
* matches the specified version.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes;
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
|
||||
|
||||
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 {
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return bool Whether the rule passes or not.
|
||||
*/
|
||||
public function process( $rule ) {
|
||||
$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 ( ! $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,66 @@
|
|||
<?php
|
||||
/**
|
||||
* Rule processor for sending when the provided plugins are activated.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes;
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use \Automattic\WooCommerce\Admin\PluginsProvider\PluginsProvider;
|
||||
|
||||
/**
|
||||
* Rule processor for sending when the provided plugins are activated.
|
||||
*/
|
||||
class PluginsActivatedRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return bool Whether the rule passes or not.
|
||||
*/
|
||||
public function process( $rule ) {
|
||||
if ( 0 === count( $rule->plugins ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$active_plugin_slugs = $this->plugins_provider->get_active_plugin_slugs();
|
||||
|
||||
foreach ( $rule->plugins as $plugin_slug ) {
|
||||
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,54 @@
|
|||
<?php
|
||||
/**
|
||||
* Rule processor for sending after a specified date/time.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes;
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use \Automattic\WooCommerce\Admin\DateTimeProvider\CurrentDateTimeProvider;
|
||||
|
||||
/**
|
||||
* Rule processor for sending after a specified date/time.
|
||||
*/
|
||||
class PublishAfterTimeRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return bool Whether the rule passes or not.
|
||||
*/
|
||||
public function process( $rule ) {
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
/**
|
||||
* Rule processor for sending before a specified date/time.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes;
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use \Automattic\WooCommerce\Admin\DateTimeProvider\CurrentDateTimeProvider;
|
||||
|
||||
/**
|
||||
* Rule processor for sending before a specified date/time.
|
||||
*/
|
||||
class PublishBeforeTimeRuleProcessor implements RuleProcessorInterface {
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return bool Whether the rule passes or not.
|
||||
*/
|
||||
public function process( $rule ) {
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
/**
|
||||
* Handles running specs
|
||||
*
|
||||
* @package WooCommerce Admin/Classes
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Note;
|
||||
use \Automattic\WooCommerce\Admin\PluginsProvider\PluginsProvider;
|
||||
|
||||
/**
|
||||
* RemoteInboxNotifications engine.
|
||||
* This goes through the specs and runs (creates admin notes) for those
|
||||
* specs that are able to be triggered.
|
||||
*/
|
||||
class RemoteInboxNotificationsEngine {
|
||||
const SPECS_OPTION_NAME = 'wc_remote_inbox_notifications_specs';
|
||||
|
||||
/**
|
||||
* Initialize the engine.
|
||||
*/
|
||||
public static function init() {
|
||||
add_action( 'activated_plugin', array( __CLASS__, 'run' ) );
|
||||
add_action( 'deactivated_plugin', array( __CLASS__, 'run_on_deactivated_plugin' ), 10, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through the specs and run them.
|
||||
*/
|
||||
public static function run() {
|
||||
$specs = get_option( self::SPECS_OPTION_NAME );
|
||||
|
||||
if ( false === $specs ) {
|
||||
// We are running too early, need to poll data sources first.
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $specs as $spec ) {
|
||||
SpecRunner::run_spec( $spec );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The deactivated_plugin hook happens before the option is updated
|
||||
* (https://github.com/WordPress/WordPress/blob/master/wp-admin/includes/plugin.php#L826)
|
||||
* so this captures the deactivated plugin path and pushes it into the
|
||||
* PluginsProvider.
|
||||
*
|
||||
* @param string $plugin Path to the plugin file relative to the plugins directory.
|
||||
*/
|
||||
public static function run_on_deactivated_plugin( $plugin ) {
|
||||
PluginsProvider::set_deactivated_plugin( $plugin );
|
||||
self::run();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
/**
|
||||
* Evaluate the given rules as an AND operation - return false early if a
|
||||
* rule evaluates to false.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Evaluate the given rules as an AND operation - return false early if a
|
||||
* rule evaluates to false.
|
||||
*/
|
||||
class RuleEvaluator {
|
||||
/**
|
||||
* 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 $rules The rules being processed.
|
||||
*
|
||||
* @return bool The result of the operation.
|
||||
*/
|
||||
public function evaluate( $rules ) {
|
||||
if ( 0 === count( $rules ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ( $rules as $rule ) {
|
||||
$processor = $this->get_rule_processor->get_processor( $rule->type );
|
||||
$processor_result = $processor->process( $rule );
|
||||
|
||||
if ( ! $processor_result ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
/**
|
||||
* Interface for a rule processor.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
|
||||
|
||||
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.
|
||||
*
|
||||
* @return bool The result of the processing.
|
||||
*/
|
||||
public function process( $rule );
|
||||
|
||||
/**
|
||||
* Validates the rule.
|
||||
*
|
||||
* @param object $rule The rule to validate.
|
||||
*
|
||||
* @return bool Pass/fail.
|
||||
*/
|
||||
public function validate( $rule );
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
<?php
|
||||
/**
|
||||
* Runs a single spec.
|
||||
*
|
||||
* @package WooCommerce Admin/Classes
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Note;
|
||||
|
||||
/**
|
||||
* Runs a single spec.
|
||||
*/
|
||||
class SpecRunner {
|
||||
/**
|
||||
* Run the spec.
|
||||
*
|
||||
* @param object $spec The spec to run.
|
||||
*/
|
||||
public static function run_spec( $spec ) {
|
||||
$data_store = \WC_Data_Store::load( 'admin-note' );
|
||||
|
||||
// Create or update the note.
|
||||
$existing_note_ids = $data_store->get_notes_with_name( $spec->slug );
|
||||
if ( 0 === count( $existing_note_ids ) ) {
|
||||
$note = new WC_Admin_Note();
|
||||
$note->set_status( WC_Admin_Note::E_WC_ADMIN_NOTE_PENDING );
|
||||
} else {
|
||||
$note = new WC_Admin_Note( $existing_note_ids[0] );
|
||||
}
|
||||
|
||||
// Evaluate the spec and get the new note status.
|
||||
$rule_evaluator = new RuleEvaluator(
|
||||
new GetRuleProcessor()
|
||||
);
|
||||
|
||||
$previous_status = $note->get_status();
|
||||
$status = EvaluateAndGetStatus::evaluate(
|
||||
$spec,
|
||||
$previous_status,
|
||||
$rule_evaluator
|
||||
);
|
||||
|
||||
// If the status is changing, update the created date to now.
|
||||
if ( $previous_status !== $status ) {
|
||||
$note->set_date_created( time() );
|
||||
}
|
||||
|
||||
// Get the matching locale or fall back to en-US.
|
||||
$locale = self::get_locale( $spec->locales );
|
||||
|
||||
if ( null === $locale ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set up the note.
|
||||
$note->set_title( $locale->title );
|
||||
$note->set_content( $locale->content );
|
||||
$note->set_content_data( (object) array() );
|
||||
$note->set_status( $status );
|
||||
$note->set_type( $spec->type );
|
||||
$note->set_name( $spec->slug );
|
||||
if ( isset( $spec->source ) ) {
|
||||
$note->set_source( $spec->source );
|
||||
}
|
||||
|
||||
// Clear then create actions.
|
||||
$note->clear_actions();
|
||||
$actions = isset( $spec->actions ) ? $spec->actions : array();
|
||||
foreach ( $actions as $action ) {
|
||||
$action_locale = self::get_action_locale( $action->locales );
|
||||
|
||||
$url = self::get_url( $action );
|
||||
|
||||
$note->add_action(
|
||||
$action->name,
|
||||
( null === $action_locale || ! isset( $action_locale->label ) )
|
||||
? ''
|
||||
: $action_locale->label,
|
||||
$url,
|
||||
$action->status,
|
||||
isset( $action->is_primary ) ? $action->is_primary : false
|
||||
);
|
||||
}
|
||||
|
||||
$note->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL for an action.
|
||||
*
|
||||
* @param object $action The action.
|
||||
*
|
||||
* @return string The URL for the action.
|
||||
*/
|
||||
private static function get_url( $action ) {
|
||||
if ( ! isset( $action->url ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( isset( $action->url_is_admin_query ) && $action->url_is_admin_query ) {
|
||||
return wc_admin_url( $action->url );
|
||||
}
|
||||
|
||||
return $action->url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the locale for the WordPress locale, or fall back to the en_US
|
||||
* locale.
|
||||
*
|
||||
* @param Array $locales The locales to search through.
|
||||
*
|
||||
* @returns object The locale that was found, or null if no matching locale was found.
|
||||
*/
|
||||
public static function get_locale( $locales ) {
|
||||
$wp_locale = get_locale();
|
||||
$matching_wp_locales = array_values(
|
||||
array_filter(
|
||||
$locales,
|
||||
function( $l ) use ( $wp_locale ) {
|
||||
return $wp_locale === $l->locale;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
if ( 0 !== count( $matching_wp_locales ) ) {
|
||||
return $matching_wp_locales[0];
|
||||
}
|
||||
|
||||
// Fall back to en_US locale.
|
||||
$en_us_locales = array_values(
|
||||
array_filter(
|
||||
$locales,
|
||||
function( $l ) {
|
||||
return 'en_US' === $l->locale;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
if ( 0 !== count( $en_us_locales ) ) {
|
||||
return $en_us_locales[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the action locale that matches the note locale, or fall back to the
|
||||
* en_US locale.
|
||||
*
|
||||
* @param Array $action_locales The locales from the spec's action.
|
||||
*
|
||||
* @return object The matching locale, or the en_US fallback locale, or null if neither was found.
|
||||
*/
|
||||
public static function get_action_locale( $action_locales ) {
|
||||
$wp_locale = get_locale();
|
||||
$matching_wp_locales = array_values(
|
||||
array_filter(
|
||||
$action_locales,
|
||||
function ( $l ) use ( $wp_locale ) {
|
||||
return $wp_locale === $l->locale;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
if ( 0 !== count( $matching_wp_locales ) ) {
|
||||
return $matching_wp_locales[0];
|
||||
}
|
||||
|
||||
// Fall back to en_US locale.
|
||||
$en_us_locales = array_values(
|
||||
array_filter(
|
||||
$action_locales,
|
||||
function( $l ) {
|
||||
return 'en_US' === $l->locale;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
if ( 0 !== count( $en_us_locales ) ) {
|
||||
return $en_us_locales[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
<?php
|
||||
/**
|
||||
* Evaluate and get status tests.
|
||||
*
|
||||
* @package WooCommerce\Tests\RemoteInboxNotifications
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\EvaluateAndGetStatus;
|
||||
|
||||
/**
|
||||
* class WC_Tests_RemoteInboxNotifications_EvaluateAndGetStatus
|
||||
*/
|
||||
class WC_Tests_RemoteInboxNotifications_EvaluateAndGetStatus extends WC_Unit_Test_Case {
|
||||
/**
|
||||
* Build up a spec given the supplied parameters.
|
||||
*
|
||||
* @param bool $allow_redisplay Allow note redisplay after it has been actioned.
|
||||
*
|
||||
* @return object The spec object.
|
||||
*/
|
||||
private function get_spec( $allow_redisplay ) {
|
||||
return json_decode(
|
||||
'{
|
||||
"status": "unactioned",
|
||||
"rules": [],
|
||||
"allow_redisplay": ' . ( $allow_redisplay ? 'true' : 'false' ) . '
|
||||
}'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a spec with no rules property.
|
||||
*
|
||||
* @return object The spec object.
|
||||
*/
|
||||
private function get_no_rules_spec() {
|
||||
return json_decode(
|
||||
'{
|
||||
"status": "unactioned",
|
||||
"allow_redisplay": false
|
||||
}'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that for a pending note evaling to true, status is changed
|
||||
* to the spec status.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_pending_note_eval_to_true() {
|
||||
$spec = $this->get_spec( false );
|
||||
|
||||
$result = EvaluateAndGetStatus::evaluate(
|
||||
$spec,
|
||||
'unactioned',
|
||||
new PassingRuleEvaluator()
|
||||
);
|
||||
|
||||
$this->assertEquals( 'unactioned', $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that for a pending note evaluating to false, status is
|
||||
* left at pending.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_pending_note_eval_to_false() {
|
||||
$spec = $this->get_spec( false );
|
||||
|
||||
$result = EvaluateAndGetStatus::evaluate(
|
||||
$spec,
|
||||
'pending',
|
||||
new FailingRuleEvaluator()
|
||||
);
|
||||
|
||||
$this->assertEquals( 'pending', $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that for a snoozed note evaluating to true without allow_redisplay
|
||||
* set, status is left as snoozed.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_snoozed_note_eval_to_true_without_allow_redisplay() {
|
||||
$spec = $this->get_spec( false );
|
||||
|
||||
$result = EvaluateAndGetStatus::evaluate(
|
||||
$spec,
|
||||
'snoozed',
|
||||
new PassingRuleEvaluator()
|
||||
);
|
||||
|
||||
$this->assertEquals( 'snoozed', $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that for a snoozed note evaluating to false without
|
||||
* allow_redisplay set, status is left as snoozed
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_snoozed_note_eval_to_false_without_allow_redisplay() {
|
||||
$spec = $this->get_spec( false );
|
||||
|
||||
$result = EvaluateAndGetStatus::evaluate(
|
||||
$spec,
|
||||
'snoozed',
|
||||
new FailingRuleEvaluator()
|
||||
);
|
||||
|
||||
$this->assertEquals( 'snoozed', $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that for an actioned note eval to true with allow_redisplay set,
|
||||
* status is changed to unactioned.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_actioned_note_eval_to_true_with_allow_redisplay_set() {
|
||||
$spec = $this->get_spec( true );
|
||||
|
||||
$result = EvaluateAndGetStatus::evaluate(
|
||||
$spec,
|
||||
'actioned',
|
||||
new PassingRuleEvaluator()
|
||||
);
|
||||
|
||||
$this->assertEquals( 'unactioned', $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that for an actioned note eval to false with allow_redirect set,
|
||||
* status is left at actioned.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_actioned_note_eval_to_false_with_allow_redisplay_set() {
|
||||
$spec = $this->get_spec( true );
|
||||
|
||||
$result = EvaluateAndGetStatus::evaluate(
|
||||
$spec,
|
||||
'actioned',
|
||||
new FailingRuleEvaluator()
|
||||
);
|
||||
|
||||
$this->assertEquals( 'actioned', $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that for a pending note eval to true with allow_redirect
|
||||
* set, status is changed to unactioned.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_pending_note_eval_to_true_with_allow_redirect_set() {
|
||||
$spec = $this->get_spec( true );
|
||||
|
||||
$result = EvaluateAndGetStatus::evaluate(
|
||||
$spec,
|
||||
'pending',
|
||||
new PassingRuleEvaluator()
|
||||
);
|
||||
|
||||
$this->assertEquals( 'unactioned', $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that for a pending note eval to false with allow_redirect
|
||||
* set, status is left as pending.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_pending_note_eval_to_false_with_allow_redirect_set() {
|
||||
$spec = $this->get_spec( true );
|
||||
|
||||
$result = EvaluateAndGetStatus::evaluate(
|
||||
$spec,
|
||||
'pending',
|
||||
new FailingRuleEvaluator()
|
||||
);
|
||||
|
||||
$this->assertEquals( 'pending', $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that for a spec with no rules the current status is returned.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_with_no_rules_returns_current_status() {
|
||||
$spec = $this->get_no_rules_spec();
|
||||
|
||||
$result = EvaluateAndGetStatus::evaluate(
|
||||
$spec,
|
||||
'unactioned',
|
||||
new FailingRuleEvaluator()
|
||||
);
|
||||
|
||||
$this->assertEquals( 'unactioned', $result );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
/**
|
||||
* FailingRuleEvaluator
|
||||
*
|
||||
* @package WooCommerce\Tests\RemoteInboxNotifications
|
||||
*/
|
||||
|
||||
/**
|
||||
* class FailingRuleEvaluator
|
||||
*/
|
||||
class FailingRuleEvaluator {
|
||||
/**
|
||||
* Evaluate to false.
|
||||
*
|
||||
* @param array $rules The rules to evaluate.
|
||||
*
|
||||
* @return bool The evaluated result.
|
||||
*/
|
||||
public function evaluate( $rules ) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
/**
|
||||
* Get rule processor tests.
|
||||
*
|
||||
* @package WooCommerce\Tests\RemoteInboxNotifications
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\GetRuleProcessor;
|
||||
|
||||
/**
|
||||
* class WC_Tests_RemoteInboxNotifications_GetRuleProcessor
|
||||
*/
|
||||
class WC_Tests_RemoteInboxNotifications_GetRuleProcessor extends WC_Unit_Test_Case {
|
||||
/**
|
||||
* Tests that an unknown rule processor returns a FailRuleProcessor
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_unknown_rule_processor_returns_fail_rule_processor() {
|
||||
$get_rule_processor = new GetRuleProcessor();
|
||||
|
||||
$result = $get_rule_processor->get_processor( 'unknown rule type' );
|
||||
|
||||
$this->assertEquals( 'Automattic\\WooCommerce\\Admin\\RemoteInboxNotifications\\FailRuleProcessor', get_class( $result ) );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* Mock DateTime Provider.
|
||||
*
|
||||
* @package WooCommerce\Tests\RemoteInboxNotifications
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Admin\DateTimeProvider\DateTimeProviderInterface;
|
||||
|
||||
/**
|
||||
* Mock DateTime Provider.
|
||||
*/
|
||||
class MockDateTimeProvider implements DateTimeProviderInterface {
|
||||
/**
|
||||
* Construct the mock DateTime provider using the specified value for now.
|
||||
*
|
||||
* @param DateTime $now The value to use for now.
|
||||
*/
|
||||
public function __construct( $now ) {
|
||||
$this->now = $now;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the specified DateTime.
|
||||
*
|
||||
* @return DateTime
|
||||
*/
|
||||
public function get_now() {
|
||||
return $this->now;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* MockGetRuleProcessor.
|
||||
*
|
||||
* @package WooCommerce\Tests\RemoteInboxNotifications
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\PublishAfterTimeRuleProcessor;
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\FailRuleProcessor;
|
||||
|
||||
/**
|
||||
* MockGetRuleProcessor.
|
||||
*/
|
||||
class MockGetRuleProcessor {
|
||||
/**
|
||||
* Get the processor for the specified rule type.
|
||||
*
|
||||
* @param string $rule_type The rule type.
|
||||
*
|
||||
* @return object The matching processor for the specified rule type, or a FailRuleProcessor if no matching processor is found.
|
||||
*/
|
||||
public static function get_processor( $rule_type ) {
|
||||
if ( 'publish_after_time' === $rule_type ) {
|
||||
return new PublishAfterTimeRuleProcessor(
|
||||
new MockDateTimeProvider( new \DateTime( '2020-04-24 10:00:00' ) )
|
||||
);
|
||||
}
|
||||
|
||||
return new FailRuleProcessor();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
/**
|
||||
* Mock plugins Provider.
|
||||
*
|
||||
* @package WooCommerce\Tests\RemoteInboxNotifications
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Admin\PluginsProvider\PluginsProviderInterface;
|
||||
|
||||
/**
|
||||
* Mock plugins Provider.
|
||||
*
|
||||
* Returns the provided plugins instead of the current plugins. Needed for
|
||||
* unit tests.
|
||||
*/
|
||||
class MockPluginsProvider implements PluginsProviderInterface {
|
||||
/**
|
||||
* Construct the mock plugins provider using the specified value for the
|
||||
* active plugins slugs.
|
||||
*
|
||||
* @param array $active_plugin_slugs The value to use for the active plugin slugs.
|
||||
* @param array $get_plugins_data The data to be used instead of get_plugins() calls.
|
||||
*/
|
||||
public function __construct(
|
||||
$active_plugin_slugs,
|
||||
$get_plugins_data = array()
|
||||
) {
|
||||
$this->active_plugin_slugs = $active_plugin_slugs;
|
||||
$this->get_plugins_data = $get_plugins_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of provided plugin slugs.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_active_plugin_slugs() {
|
||||
return $this->active_plugin_slugs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plugin data.
|
||||
*
|
||||
* @param string $plugin Path to the plugin file relative to the plugins directory or the plugin directory name.
|
||||
*
|
||||
* @return array|false
|
||||
*/
|
||||
public function get_plugin_data( $plugin ) {
|
||||
$plugin_path = $this->get_plugin_path_from_slug( $plugin );
|
||||
$plugins = $this->get_plugins_data;
|
||||
|
||||
return isset( $plugins[ $plugin_path ] ) ? $plugins[ $plugin_path ] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to the plugin file relative to the plugins directory from the plugin slug.
|
||||
*
|
||||
* E.g. 'woocommerce' returns 'woocommerce/woocommerce.php'
|
||||
*
|
||||
* @param string $slug Plugin slug to get path for.
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function get_plugin_path_from_slug( $slug ) {
|
||||
$plugins = $this->get_plugins_data;
|
||||
|
||||
if ( strstr( $slug, '/' ) ) {
|
||||
return $slug;
|
||||
}
|
||||
|
||||
foreach ( $plugins as $plugin_path => $data ) {
|
||||
$path_parts = explode( '/', $plugin_path );
|
||||
if ( $path_parts[0] === $slug ) {
|
||||
return $plugin_path;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
/**
|
||||
* Not rule processor tests.
|
||||
*
|
||||
* @package WooCommerce\Tests\RemoteInboxNotifications
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\NotRuleProcessor;
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\RuleEvaluator;
|
||||
|
||||
/**
|
||||
* class WC_Tests_RemoteInboxNotifications_NotRuleProcessor
|
||||
*/
|
||||
class WC_Tests_RemoteInboxNotifications_NotRuleProcessor extends WC_Unit_Test_Case {
|
||||
/**
|
||||
* An empty operand evaluates to false, so negating that should
|
||||
* evaluate to true.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_passes_for_empty_operand() {
|
||||
$get_rule_processor = new MockGetRuleProcessor();
|
||||
$processor = new NotRuleProcessor(
|
||||
new RuleEvaluator(
|
||||
$get_rule_processor
|
||||
)
|
||||
);
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "not",
|
||||
"operand": []
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( true, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Operand that evaluates to true negated to false.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_fails_for_passing_operand() {
|
||||
$get_rule_processor = new MockGetRuleProcessor();
|
||||
$processor = new NotRuleProcessor(
|
||||
new RuleEvaluator(
|
||||
$get_rule_processor
|
||||
)
|
||||
);
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "not",
|
||||
"operand": [
|
||||
{
|
||||
"type": "publish_after_time",
|
||||
"publish_after": "2020-04-24 09:00:00"
|
||||
}
|
||||
]
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( false, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Operand that evaluates to false negated to true.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_passes_for_failing_operand() {
|
||||
$get_rule_processor = new MockGetRuleProcessor();
|
||||
$processor = new NotRuleProcessor(
|
||||
new RuleEvaluator(
|
||||
$get_rule_processor
|
||||
)
|
||||
);
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "not",
|
||||
"operand": [
|
||||
{
|
||||
"type": "publish_after_time",
|
||||
"publish_after": "2020-04-24 11:00:00"
|
||||
}
|
||||
]
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( true, $result );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
<?php
|
||||
/**
|
||||
* Or rule processor tests.
|
||||
*
|
||||
* @package WooCommerce\Tests\RemoteInboxNotifications
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\OrRuleProcessor;
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\RuleEvaluator;
|
||||
|
||||
/**
|
||||
* class WC_Tests_RemoteInboxNotifications_OrRuleProcessor
|
||||
*/
|
||||
class WC_Tests_RemoteInboxNotifications_OrRuleProcessor extends WC_Unit_Test_Case {
|
||||
/**
|
||||
* Both operands evaluating to false and ORed together evaluates to false.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_fails_for_both_operands_false() {
|
||||
$get_rule_processor = new MockGetRuleProcessor();
|
||||
$processor = new OrRuleProcessor(
|
||||
new RuleEvaluator(
|
||||
$get_rule_processor
|
||||
)
|
||||
);
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "or",
|
||||
"operands": [
|
||||
[
|
||||
{
|
||||
"type": "publish_after_time",
|
||||
"publish_after": "2020-04-24 11:00:00"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"type": "publish_after_time",
|
||||
"publish_after": "2020-04-24 11:00:00"
|
||||
}
|
||||
]
|
||||
]
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( false, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* First operand evaluating to true and ORed together evaluates to true.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_passes_for_first_operand_true() {
|
||||
$get_rule_processor = new MockGetRuleProcessor();
|
||||
$processor = new OrRuleProcessor(
|
||||
new RuleEvaluator(
|
||||
$get_rule_processor
|
||||
)
|
||||
);
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "or",
|
||||
"operands": [
|
||||
[
|
||||
{
|
||||
"type": "publish_after_time",
|
||||
"publish_after": "2020-04-24 09:00:00"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"type": "publish_after_time",
|
||||
"publish_after": "2020-04-24 11:00:00"
|
||||
}
|
||||
]
|
||||
]
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( true, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Second operand evaluating to true and ORed together evaluates to true.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_passes_for_second_operand_true() {
|
||||
$get_rule_processor = new MockGetRuleProcessor();
|
||||
$processor = new OrRuleProcessor(
|
||||
new RuleEvaluator(
|
||||
$get_rule_processor
|
||||
)
|
||||
);
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "or",
|
||||
"operands": [
|
||||
[
|
||||
{
|
||||
"type": "publish_after_time",
|
||||
"publish_after": "2020-04-24 11:00:00"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"type": "publish_after_time",
|
||||
"publish_after": "2020-04-24 09:00:00"
|
||||
}
|
||||
]
|
||||
]
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( true, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Both operands evaluating to true and ORed together evaluates to true.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_passes_for_both_operands_true() {
|
||||
$get_rule_processor = new MockGetRuleProcessor();
|
||||
$processor = new OrRuleProcessor(
|
||||
new RuleEvaluator(
|
||||
$get_rule_processor
|
||||
)
|
||||
);
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "or",
|
||||
"operands": [
|
||||
[
|
||||
{
|
||||
"type": "publish_after_time",
|
||||
"publish_after": "2020-04-24 09:00:00"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"type": "publish_after_time",
|
||||
"publish_after": "2020-04-24 09:00:00"
|
||||
}
|
||||
]
|
||||
]
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( true, $result );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
/**
|
||||
* PassingRuleEvaluator
|
||||
*
|
||||
* @package WooCommerce\Tests\RemoteInboxNotifications
|
||||
*/
|
||||
|
||||
/**
|
||||
* class PassingRuleEvaluator
|
||||
*/
|
||||
class PassingRuleEvaluator {
|
||||
/**
|
||||
* Evaluate to true.
|
||||
*
|
||||
* @param array $rules The rules to evaluate.
|
||||
*
|
||||
* @return bool The evaluated result.
|
||||
*/
|
||||
public function evaluate( $rules ) {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
<?php
|
||||
/**
|
||||
* Plugin version rule processor tests.
|
||||
*
|
||||
* @package WooCommerce\Tests\RemoteInboxNotifications
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\PluginVersionRuleProcessor;
|
||||
|
||||
/**
|
||||
* class WC_Tests_RemoteInboxNotifications_PluginVersionRuleProcessor
|
||||
*/
|
||||
class WC_Tests_RemoteInboxNotifications_PluginVersionRuleProcessor extends WC_Unit_Test_Case {
|
||||
/**
|
||||
* Test that the processor does not pass if the plugin is not activated.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_does_not_pass_if_plugin_not_activated() {
|
||||
$mock_plugins_provider = new MockPluginsProvider( array(), array() );
|
||||
$processor = new PluginVersionRuleProcessor( $mock_plugins_provider );
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "plugin_version",
|
||||
"plugin": "jetpack",
|
||||
"version": "1.2.3",
|
||||
"operator": "<"
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( false, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the processor does not pass if the plugin is not activated.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_does_not_pass_if_plugin_not_in_data() {
|
||||
$mock_plugins_provider = new MockPluginsProvider(
|
||||
array(
|
||||
'jetpack',
|
||||
),
|
||||
array()
|
||||
);
|
||||
$processor = new PluginVersionRuleProcessor( $mock_plugins_provider );
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "plugin_version",
|
||||
"plugin": "jetpack",
|
||||
"version": "1.2.3",
|
||||
"operator": "<"
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( false, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the processor does not pass if the installed version is less
|
||||
* than the required version.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_does_not_pass_if_installed_version_less_than_required_version() {
|
||||
$mock_plugins_provider = new MockPluginsProvider(
|
||||
array(
|
||||
'jetpack',
|
||||
),
|
||||
array(
|
||||
'jetpack/jetpack.php' => array(
|
||||
'Version' => '1.2.4',
|
||||
),
|
||||
)
|
||||
);
|
||||
$processor = new PluginVersionRuleProcessor( $mock_plugins_provider );
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "plugin_version",
|
||||
"plugin": "jetpack",
|
||||
"version": "1.2.3",
|
||||
"operator": "<"
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( false, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the processor passes if the installed version is equal
|
||||
* to the required version.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_passes_if_installed_version_equals_required_version() {
|
||||
$mock_plugins_provider = new MockPluginsProvider(
|
||||
array(
|
||||
'jetpack',
|
||||
),
|
||||
array(
|
||||
'jetpack/jetpack.php' => array(
|
||||
'Version' => '1.2.3',
|
||||
),
|
||||
)
|
||||
);
|
||||
$processor = new PluginVersionRuleProcessor( $mock_plugins_provider );
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "plugin_version",
|
||||
"plugin": "jetpack",
|
||||
"version": "1.2.3",
|
||||
"operator": "="
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( true, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the processor passes if the installed version is later than
|
||||
* the required version.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_passes_if_installed_version_is_later_than_required_version() {
|
||||
$mock_plugins_provider = new MockPluginsProvider(
|
||||
array(
|
||||
'jetpack',
|
||||
),
|
||||
array(
|
||||
'jetpack/jetpack.php' => array(
|
||||
'Version' => '1.2.4',
|
||||
),
|
||||
)
|
||||
);
|
||||
$processor = new PluginVersionRuleProcessor( $mock_plugins_provider );
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "plugin_version",
|
||||
"plugin": "jetpack",
|
||||
"version": "1.2.3",
|
||||
"operator": ">"
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( true, $result );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
/**
|
||||
* Plugins activated rule processor tests.
|
||||
*
|
||||
* @package WooCommerce\Tests\RemoteInboxNotifications
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\PluginsActivatedRuleProcessor;
|
||||
use Automattic\WooCommerce\Admin\PluginsProvider\PluginsProviderInterface;
|
||||
|
||||
/**
|
||||
* class WC_Tests_RemoteInboxNotifications_PluginsActivatedRuleProcessor
|
||||
*/
|
||||
class WC_Tests_RemoteInboxNotifications_PluginsActivatedRuleProcessor extends WC_Unit_Test_Case {
|
||||
/**
|
||||
* Tests that the processor does not pass a plugins_activated rule with
|
||||
* no plugins to verify.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_does_not_pass_with_no_plugins_to_verify() {
|
||||
$mock_plugins_provider = new MockPluginsProvider( array() );
|
||||
$processor = new PluginsActivatedRuleProcessor( $mock_plugins_provider );
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "plugins_activated",
|
||||
"plugins": [
|
||||
]
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( false, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the processor does not pass a plugins_activated rule with
|
||||
* no active plugins.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_does_not_pass_with_no_active_plugins() {
|
||||
$mock_plugins_provider = new MockPluginsProvider( array() );
|
||||
$processor = new PluginsActivatedRuleProcessor( $mock_plugins_provider );
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "plugins_activated",
|
||||
"plugins": [
|
||||
"plugin-slug-1"
|
||||
]
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( false, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the processor does not pass a plugins_activated rule with
|
||||
* no matching active plugins.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_does_not_pass_with_no_matching_plugins() {
|
||||
$mock_plugins_provider = new MockPluginsProvider(
|
||||
array(
|
||||
'non-matching-slug',
|
||||
)
|
||||
);
|
||||
$processor = new PluginsActivatedRuleProcessor( $mock_plugins_provider );
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "plugins_activated",
|
||||
"plugins": [
|
||||
"plugin-slug-1"
|
||||
]
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( false, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the processor does not pass a plugins_activated rule with
|
||||
* only one matching plugin.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_does_not_pass_with_only_one_matching_plugin() {
|
||||
$mock_plugins_provider = new MockPluginsProvider(
|
||||
array(
|
||||
'plugin-slug-1',
|
||||
'plugin-slug-2',
|
||||
)
|
||||
);
|
||||
$processor = new PluginsActivatedRuleProcessor( $mock_plugins_provider );
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "plugins_activated",
|
||||
"plugins": [
|
||||
"plugin-slug-1",
|
||||
"plugin-slug-3"
|
||||
]
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( false, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the processor passes a plugins_activated rule with both
|
||||
* matching plugins.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_does_pass_with_both_matching_plugins() {
|
||||
$mock_plugins_provider = new MockPluginsProvider(
|
||||
array(
|
||||
'plugin-slug-1',
|
||||
'plugin-slug-2',
|
||||
)
|
||||
);
|
||||
$processor = new PluginsActivatedRuleProcessor( $mock_plugins_provider );
|
||||
$rule = json_decode(
|
||||
'{
|
||||
"type": "plugins_activated",
|
||||
"plugins": [
|
||||
"plugin-slug-1",
|
||||
"plugin-slug-2"
|
||||
]
|
||||
}'
|
||||
);
|
||||
|
||||
$result = $processor->process( $rule );
|
||||
|
||||
$this->assertEquals( true, $result );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
/**
|
||||
* Publish after time rule processor tests.
|
||||
*
|
||||
* @package WooCommerce\Tests\RemoteInboxNotifications
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\PublishAfterTimeRuleProcessor;
|
||||
use Automattic\WooCommerce\Admin\DateTimeProvider\DateTimeProviderInterface;
|
||||
|
||||
/**
|
||||
* class WC_Tests_RemoteInboxNotifications_PublishAfterTimeRuleProcessor
|
||||
*/
|
||||
class WC_Tests_RemoteInboxNotifications_PublishAfterTimeRuleProcessor extends WC_Unit_Test_Case {
|
||||
/**
|
||||
* Get the publish_after rule.
|
||||
*
|
||||
* @return object The rule.
|
||||
*/
|
||||
private function get_rule() {
|
||||
return json_decode(
|
||||
'{
|
||||
"type": "publish_after_time",
|
||||
"publish_after": "2020-04-22 12:00:00"
|
||||
}'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the processor passes a publish_after_time rule with a
|
||||
* publish_after time in the past.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_passes_for_time_in_the_past() {
|
||||
$mock_date_time_provider = new MockDateTimeProvider(
|
||||
new \DateTime( '2020-04-22 14:00:00' )
|
||||
);
|
||||
$processor = new PublishAfterTimeRuleProcessor( $mock_date_time_provider );
|
||||
|
||||
$result = $processor->process( $this->get_rule() );
|
||||
|
||||
$this->assertEquals( true, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the processor passes a publish_after_time rule with a
|
||||
* publish_after time right now.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_passes_for_time_now() {
|
||||
$mock_date_time_provider = new MockDateTimeProvider(
|
||||
new \DateTime( '2020-04-22 12:00:00' )
|
||||
);
|
||||
$processor = new PublishAfterTimeRuleProcessor( $mock_date_time_provider );
|
||||
|
||||
$result = $processor->process( $this->get_rule() );
|
||||
|
||||
$this->assertEquals( true, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the processor does not pass a publish_after_time rule with a
|
||||
* publish_after time in the future.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_does_not_pass_for_time_in_future() {
|
||||
$mock_date_time_provider = new MockDateTimeProvider(
|
||||
new \DateTime( '2020-04-22 09:00:00' )
|
||||
);
|
||||
$processor = new PublishAfterTimeRuleProcessor( $mock_date_time_provider );
|
||||
|
||||
$result = $processor->process( $this->get_rule() );
|
||||
|
||||
$this->assertEquals( false, $result );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
/**
|
||||
* Publish before time rule processor tests.
|
||||
*
|
||||
* @package WooCommerce\Tests\RemoteInboxNotifications
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\PublishBeforeTimeRuleProcessor;
|
||||
use Automattic\WooCommerce\Admin\DateTimeProvider\DateTimeProviderInterface;
|
||||
|
||||
/**
|
||||
* class WC_Tests_RemoteInboxNotifications_PublishBeforeTimeRuleProcessor
|
||||
*/
|
||||
class WC_Tests_RemoteInboxNotifications_PublishBeforeTimeRuleProcessor extends WC_Unit_Test_Case {
|
||||
/**
|
||||
* Get the publish_before rule.
|
||||
*
|
||||
* @return object The rule.
|
||||
*/
|
||||
private function get_rule() {
|
||||
return json_decode(
|
||||
'{
|
||||
"type": "publish_before_time",
|
||||
"publish_before": "2020-04-22 12:00:00"
|
||||
}'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the processor passes a publish_before_time rule with a
|
||||
* publish_before time in the future.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_passes_for_time_in_the_future() {
|
||||
$mock_date_time_provider = new MockDateTimeProvider(
|
||||
new \DateTime( '2020-04-22 08:00:00' )
|
||||
);
|
||||
$processor = new PublishBeforeTimeRuleProcessor( $mock_date_time_provider );
|
||||
|
||||
$result = $processor->process( $this->get_rule() );
|
||||
|
||||
$this->assertEquals( true, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the processor passes a publish_before_time rule with a
|
||||
* publish_before time right now.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_passes_for_time_now() {
|
||||
$mock_date_time_provider = new MockDateTimeProvider(
|
||||
new \DateTime( '2020-04-22 12:00:00' )
|
||||
);
|
||||
$processor = new PublishBeforeTimeRuleProcessor( $mock_date_time_provider );
|
||||
|
||||
$result = $processor->process( $this->get_rule() );
|
||||
|
||||
$this->assertEquals( true, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the processor does not pass a publish_before_time rule with a
|
||||
* publish_before time in the past.
|
||||
*
|
||||
* @group fast
|
||||
*/
|
||||
public function test_spec_does_not_pass_for_time_in_the_future() {
|
||||
$mock_date_time_provider = new MockDateTimeProvider(
|
||||
new \DateTime( '2020-04-22 14:00:00' )
|
||||
);
|
||||
$processor = new PublishBeforeTimeRuleProcessor( $mock_date_time_provider );
|
||||
|
||||
$result = $processor->process( $this->get_rule() );
|
||||
|
||||
$this->assertEquals( false, $result );
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue