HEX
Server: LiteSpeed
System: Linux eko108.isimtescil.net 4.18.0-477.21.1.lve.1.el8.x86_64 #1 SMP Tue Sep 5 23:08:35 UTC 2023 x86_64
User: uyarreklamcomtr (11202)
PHP: 7.4.33
Disabled: opcache_get_status
Upload Files
File: /var/www/vhosts/uyarreklam.com.tr/httpdocs/RemoteInboxNotifications.tar
BaseLocationCountryRuleProcessor.php000064400000003560151541727620013752 0ustar00<?php
/**
 * Rule processor that performs a comparison operation against the base
 * location - country.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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 ( ! $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;
	}
}
BaseLocationStateRuleProcessor.php000064400000002256151541727620013370 0ustar00<?php
/**
 * Rule processor that performs a comparison operation against the base
 * location - state.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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 ( ! $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;
	}
}
ComparisonOperation.php000064400000003510151541727620011261 0ustar00<?php
/**
 * Compare two operands using the specified operation.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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.
	 * @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 );
				}
				return strpos( $right_operand, $left_operand ) !== false;
			case '!contains':
				if ( is_array( $left_operand ) && is_string( $right_operand ) ) {
					return ! in_array( $right_operand, $left_operand, true );
				}
				return strpos( $right_operand, $left_operand ) === false;
			case 'in':
				if ( is_array( $right_operand ) && is_string( $left_operand ) ) {
					return in_array( $left_operand, $right_operand, true );
				}
				return strpos( $left_operand, $right_operand ) !== false;
			case '!in':
				if ( is_array( $right_operand ) && is_string( $left_operand ) ) {
					return ! in_array( $left_operand, $right_operand, true );
				}
				return strpos( $left_operand, $right_operand ) === false;
		}

		return false;
	}
}
DataSourcePoller.php000064400000012316151541727620010502 0ustar00<?php
/**
 * Handles polling and storage of specs
 */

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 extends \Automattic\WooCommerce\Admin\DataSourcePoller {
	const ID           = 'remote_inbox_notifications';
	const DATA_SOURCES = array(
		'https://woocommerce.com/wp-json/wccom/inbox-notifications/1.0/notifications.json',
	);
	/**
	 * Class instance.
	 *
	 * @var Analytics instance
	 */
	protected static $instance = null;

	/**
	 * Get class instance.
	 */
	public static function get_instance() {
		if ( ! self::$instance ) {
			self::$instance = new self(
				self::ID,
				self::DATA_SOURCES,
				array(
					'spec_key' => 'slug',
				)
			);
		}
		return self::$instance;
	}

	/**
	 * 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 ( ! isset( $spec->slug ) ) {
			$logger->error(
				'Spec is invalid because the slug is missing in feed',
				$logger_context
			);
			// phpcs:ignore
			$logger->error( print_r( $spec, true ), $logger_context );

			return false;
		}

		if ( ! isset( $spec->status ) ) {
			$logger->error(
				'Spec is invalid because the status is missing in feed',
				$logger_context
			);
			// phpcs:ignore
			$logger->error( print_r( $spec, true ), $logger_context );

			return false;
		}

		if ( ! isset( $spec->locales ) || ! is_array( $spec->locales ) ) {
			$logger->error(
				'Spec is invalid because the status is missing or empty in feed',
				$logger_context
			);
			// phpcs:ignore
			$logger->error( print_r( $spec, true ), $logger_context );

			return false;
		}

		if ( null === SpecRunner::get_locale( $spec->locales ) ) {
			$logger->error(
				'Spec is invalid because the locale could not be retrieved in feed',
				$logger_context
			);
			// phpcs:ignore
			$logger->error( print_r( $spec, true ), $logger_context );

			return false;
		}

		if ( ! isset( $spec->type ) ) {
			$logger->error(
				'Spec is invalid because the type is missing in feed',
				$logger_context
			);
			// phpcs:ignore
			$logger->error( print_r( $spec, true ), $logger_context );

			return false;
		}

		if ( isset( $spec->actions ) && is_array( $spec->actions ) ) {
			foreach ( $spec->actions as $action ) {
				if ( ! $this->validate_action( $action, $url ) ) {
					$logger->error(
						'Spec is invalid because an action is invalid in feed',
						$logger_context
					);
					// phpcs:ignore
					$logger->error( print_r( $spec, true ), $logger_context );

					return false;
				}
			}
		}

		if ( isset( $spec->rules ) && is_array( $spec->rules ) ) {
			foreach ( $spec->rules as $rule ) {
				if ( ! isset( $rule->type ) ) {
					$logger->error(
						'Spec is invalid because a rule type is empty in feed',
						$logger_context
					);
					// phpcs:ignore
					$logger->error( print_r( $rule, true ), $logger_context );
					// phpcs:ignore
					$logger->error( print_r( $spec, true ), $logger_context );

					return false;
				}

				$processor = GetRuleProcessor::get_processor( $rule->type );

				if ( ! $processor->validate( $rule ) ) {
					$logger->error(
						'Spec is invalid because a rule is invalid in feed',
						$logger_context
					);
					// phpcs:ignore
					$logger->error( print_r( $rule, true ), $logger_context );
					// phpcs:ignore
					$logger->error( print_r( $spec, true ), $logger_context );

					return false;
				}
			}
		}

		return true;
	}

	/**
	 * Validate the action.
	 *
	 * @param object $action The action to validate.
	 * @param string $url    The url of the feed containing the action (for error reporting).
	 *
	 * @return bool The result of the validation.
	 */
	private function validate_action( $action, $url ) {
		$logger         = self::get_logger();
		$logger_context = array( 'source' => $url );

		if ( ! isset( $action->locales ) || ! is_array( $action->locales ) ) {
			$logger->error(
				'Action is invalid because it has empty or missing locales in feed',
				$logger_context
			);
			// phpcs:ignore
			$logger->error( print_r( $action, true ), $logger_context );

			return false;
		}

		if ( null === SpecRunner::get_action_locale( $action->locales ) ) {
			$logger->error(
				'Action is invalid because the locale could not be retrieved in feed',
				$logger_context
			);
			// phpcs:ignore
			$logger->error( print_r( $action, true ), $logger_context );

			return false;
		}

		if ( ! isset( $action->name ) ) {
			$logger->error(
				'Action is invalid because the name is missing in feed',
				$logger_context
			);
			// phpcs:ignore
			$logger->error( print_r( $action, true ), $logger_context );

			return false;
		}

		if ( ! isset( $action->status ) ) {
			$logger->error(
				'Action is invalid because the status is missing in feed',
				$logger_context
			);
			// phpcs:ignore
			$logger->error( print_r( $action, true ), $logger_context );

			return false;
		}

		return true;
	}
}
EvaluateAndGetStatus.php000064400000003026151541727620011325 0ustar00<?php
/**
 * Evaluates the spec and returns a status.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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;
	}
}
EvaluationLogger.php000064400000003360151541727620010540 0ustar00<?php

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

/**
 * Class EvaluationLogger
 *
 * @package Automattic\WooCommerce\Admin\RemoteInboxNotifications
 */
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 )
			);
		}
	}
}
FailRuleProcessor.php000064400000001261151541727620010672 0ustar00<?php
/**
 * Rule processor that fails.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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;
	}
}
GetRuleProcessor.php000064400000003745151541727620010547 0ustar00<?php
/**
 * Gets the processor for the specified rule type.
 */

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();
			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 '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();
	}
}
IsEcommerceRuleProcessor.php000064400000002161151541727620012212 0ustar00<?php
/**
 * Rule processor that passes (or fails) when the site is on the eCommerce
 * plan.
 *
 * @package WooCommerce\Admin\Classes
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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;
	}
}
NotRuleProcessor.php000064400000002476151541727620010570 0ustar00<?php
/**
 * Rule processor that negates the rules in the rule's operand.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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;
	}
}
NoteStatusRuleProcessor.php000064400000002452151541727620012133 0ustar00<?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\RemoteInboxNotifications;

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;
	}
}
OnboardingProfileRuleProcessor.php000064400000002600151541727620013420 0ustar00<?php
/**
 * Rule processor that performs a comparison operation against a value in the
 * onboarding profile.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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 ) ) {
			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;
	}
}
OptionRuleProcessor.php000064400000005523151541727620011274 0ustar00<?php
/**
 * Rule processor that performs a comparison operation against an option value.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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;
		$default_value = $is_contains ? array() : false;
		$default       = isset( $rule->default ) ? $rule->default : $default_value;
		$option_value  = $this->get_option_value( $rule, $default, $is_contains );

		if ( isset( $rule->transformers ) && is_array( $rule->transformers ) ) {
			$option_value = TransformerService::apply( $option_value, $rule->transformers, $default );
		}

		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      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, $is_contains ) {
		$option_value      = get_option( $rule->option_name, $default );
		$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;
	}
}
OrRuleProcessor.php000064400000002750151541727620010403 0ustar00<?php
/**
 * Rule processor that performs an OR operation on the rule's left and right
 * operands.
 */

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 {

	/**
	 * 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;
	}
}
OrderCountRuleProcessor.php000064400000002474151541727620012112 0ustar00<?php
/**
 * Rule processor for publishing based on the number of orders.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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;
	}
}
OrdersProvider.php000064400000001277151541727620010247 0ustar00<?php
/**
 * Provider for order-related queries and operations.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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;
	}
}
PassRuleProcessor.php000064400000001407151541727620010727 0ustar00<?php
/**
 * Rule processor that passes. This is required because an empty set of rules
 * (or predicate) evaluates to false.
 */

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.
	 * @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;
	}
}
PluginVersionRuleProcessor.php000064400000003554151541727620012632 0ustar00<?php
/**
 * Rule processor for sending when the provided plugin is activated and
 * matches the specified version.
 */

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 {

	/**
	 * 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 ( ! $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;
	}
}
PluginsActivatedRuleProcessor.php000064400000003131151541727620013263 0ustar00<?php
/**
 * Rule processor for sending when the provided plugins are activated.
 */

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 {

	/**
	 * 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 ( 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;
	}
}
ProductCountRuleProcessor.php000064400000003104151541727620012446 0ustar00<?php
/**
 * Rule processor that performs a comparison operation against the number of
 * products.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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;
	}
}
PublishAfterTimeRuleProcessor.php000064400000002566151541727620013237 0ustar00<?php
/**
 * Rule processor for sending after a specified date/time.
 */

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 {

	/**
	 * 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;
		}

		return true;
	}
}
PublishBeforeTimeRuleProcessor.php000064400000002573151541727620013376 0ustar00<?php
/**
 * Rule processor for sending before a specified date/time.
 */

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 {

	/**
	 * 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;
		}

		return true;
	}
}
RemoteInboxNotificationsEngine.php000064400000014770151541727620013413 0ustar00<?php
/**
 * Handles running specs
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

defined( 'ABSPATH' ) || exit;

use Automattic\WooCommerce\Admin\PluginsProvider\PluginsProvider;
use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
use Automattic\WooCommerce\Admin\Notes\Note;

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

	/**
	 * Initialize the engine.
	 */
	public static function init() {
		// Init things that need to happen before admin_init.
		add_action( 'init', array( __CLASS__, 'on_init' ), 0, 0 );

		// Continue init via admin_init.
		add_action( 'admin_init', array( __CLASS__, 'on_admin_init' ) );

		// Trigger when the profile data option is updated (during onboarding).
		add_action(
			'update_option_' . OnboardingProfile::DATA_OPTION,
			array( __CLASS__, 'update_profile_option' ),
			10,
			2
		);

		// Hook into WCA updated. This is hooked up here rather than in
		// on_admin_init because that runs too late to hook into the action.
		add_action( 'woocommerce_run_on_woocommerce_admin_updated', array( __CLASS__, 'run_on_woocommerce_admin_updated' ) );
		add_action(
			'woocommerce_updated',
			function() {
				$next_hook = WC()->queue()->get_next(
					'woocommerce_run_on_woocommerce_admin_updated',
					array(),
					'woocommerce-remote-inbox-engine'
				);
				if ( null === $next_hook ) {
					WC()->queue()->schedule_single(
						time(),
						'woocommerce_run_on_woocommerce_admin_updated',
						array(),
						'woocommerce-remote-inbox-engine'
					);
				}
			}
		);

		add_filter( 'woocommerce_get_note_from_db', array( __CLASS__, 'get_note_from_db' ), 10, 1 );
	}

	/**
	 * This is triggered when the profile option is updated and if the
	 * profiler is being completed, triggers a run of the engine.
	 *
	 * @param mixed $old_value Old value.
	 * @param mixed $new_value New value.
	 */
	public static function update_profile_option( $old_value, $new_value ) {
		// Return early if we're not completing the profiler.
		if (
			( isset( $old_value['completed'] ) && $old_value['completed'] ) ||
			! isset( $new_value['completed'] ) ||
			! $new_value['completed']
		) {
			return;
		}

		self::run();
	}

	/**
	 * Init is continued via admin_init so that WC is loaded when the product
	 * query is used, otherwise the query generates a "0 = 1" in the WHERE
	 * condition and thus doesn't return any results.
	 */
	public static function on_admin_init() {
		add_action( 'activated_plugin', array( __CLASS__, 'run' ) );
		add_action( 'deactivated_plugin', array( __CLASS__, 'run_on_deactivated_plugin' ), 10, 1 );
		StoredStateSetupForProducts::admin_init();

		// Pre-fetch stored state so it has the correct initial values.
		self::get_stored_state();
	}

	/**
	 * An init hook is used here so that StoredStateSetupForProducts can set
	 * up a hook that gets triggered by action-scheduler - this is needed
	 * because the admin_init hook doesn't get triggered by WP Cron.
	 */
	public static function on_init() {
		StoredStateSetupForProducts::init();
	}

	/**
	 * Go through the specs and run them.
	 */
	public static function run() {
		$specs = DataSourcePoller::get_instance()->get_specs_from_data_sources();

		if ( $specs === false || count( $specs ) === 0 ) {
			return;
		}

		$stored_state = self::get_stored_state();

		foreach ( $specs as $spec ) {
			SpecRunner::run_spec( $spec, $stored_state );
		}
	}

	/**
	 * Set an option indicating that WooCommerce Admin has just been updated,
	 * run the specs, then clear that option. This lets the
	 * WooCommerceAdminUpdatedRuleProcessor trigger on WCA update.
	 */
	public static function run_on_woocommerce_admin_updated() {
		update_option( self::WCA_UPDATED_OPTION_NAME, true, false );

		self::run();

		update_option( self::WCA_UPDATED_OPTION_NAME, false, false );
	}

	/**
	 * Gets the stored state option, and does the initial set up if it doesn't
	 * already exist.
	 *
	 * @return object The stored state option.
	 */
	public static function get_stored_state() {
		$stored_state = get_option( self::STORED_STATE_OPTION_NAME );

		if ( $stored_state === false ) {
			$stored_state = new \stdClass();

			$stored_state = StoredStateSetupForProducts::init_stored_state(
				$stored_state
			);

			add_option(
				self::STORED_STATE_OPTION_NAME,
				$stored_state,
				'',
				false
			);
		}

		return $stored_state;
	}

	/**
	 * 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();
	}

	/**
	 * Update the stored state option.
	 *
	 * @param object $stored_state The stored state.
	 */
	public static function update_stored_state( $stored_state ) {
		update_option( self::STORED_STATE_OPTION_NAME, $stored_state, false );
	}

	/**
	 * Get the note. This is used to display localized note.
	 *
	 * @param Note $note_from_db The note object created from db.
	 * @return Note The note.
	 */
	public static function get_note_from_db( $note_from_db ) {
		if ( ! $note_from_db instanceof Note || get_user_locale() === $note_from_db->get_locale() ) {
			return $note_from_db;
		}
		$specs = DataSourcePoller::get_instance()->get_specs_from_data_sources();
		foreach ( $specs as $spec ) {
			if ( $spec->slug !== $note_from_db->get_name() ) {
				continue;
			}
			$locale = SpecRunner::get_locale( $spec->locales, true );
			if ( $locale === null ) {
				// No locale found, so don't update the note.
				break;
			}

			$localized_actions = SpecRunner::get_actions( $spec );

			// Manually copy the action id from the db to the localized action, since they were not being provided.
			foreach ( $localized_actions as $localized_action ) {
				$action = $note_from_db->get_action( $localized_action->name );
				if ( $action ) {
					$localized_action->id = $action->id;
				}
			}

			$note_from_db->set_title( $locale->title );
			$note_from_db->set_content( $locale->content );
			$note_from_db->set_actions( $localized_actions );
		}

		return $note_from_db;
	}
}
RuleEvaluator.php000064400000004474151541727620010072 0ustar00<?php
/**
 * Evaluate the given rules as an AND operation - return false early if a
 * rule evaluates to false.
 */

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 {

	/**
	 * 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;
	}
}
RuleProcessorInterface.php000064400000001221151541727630011714 0ustar00<?php
/**
 * Interface for a rule processor.
 */

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.
	 * @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 );
}
SpecRunner.php000064400000011143151541727630007354 0ustar00<?php
/**
 * Runs a single spec.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

defined( 'ABSPATH' ) || exit;

use Automattic\WooCommerce\Admin\Notes\Note;
use Automattic\WooCommerce\Admin\Notes\Notes;

/**
 * Runs a single spec.
 */
class SpecRunner {
	/**
	 * Run the spec.
	 *
	 * @param object $spec         The spec to run.
	 * @param object $stored_state Stored state.
	 */
	public static function run_spec( $spec, $stored_state ) {
		$data_store = Notes::load_data_store();

		// Create or update the note.
		$existing_note_ids = $data_store->get_notes_with_name( $spec->slug );
		if ( count( $existing_note_ids ) === 0 ) {
			$note = new Note();
			$note->set_status( Note::E_WC_ADMIN_NOTE_PENDING );
		} else {
			$note = Notes::get_note( $existing_note_ids[0] );
			if ( $note === false ) {
				return;
			}
		}

		// Evaluate the spec and get the new note status.
		$previous_status = $note->get_status();
		$status          = EvaluateAndGetStatus::evaluate(
			$spec,
			$previous_status,
			$stored_state,
			new RuleEvaluator()
		);

		// 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 ( $locale === null ) {
			return;
		}

		// Set up the note.
		$note->set_title( $locale->title );
		$note->set_content( $locale->content );
		$note->set_content_data( isset( $spec->content_data ) ? $spec->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 );
		}

		// Recreate actions.
		$note->set_actions( self::get_actions( $spec ) );

		$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 ) {
			if ( strpos( $action->url, '&path' ) === 0 ) {
				return wc_admin_url( $action->url );
			}
			return 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_user_locale();
		$matching_wp_locales = array_values(
			array_filter(
				$locales,
				function( $l ) use ( $wp_locale ) {
					return $wp_locale === $l->locale;
				}
			)
		);

		if ( count( $matching_wp_locales ) !== 0 ) {
			return $matching_wp_locales[0];
		}

		// Fall back to en_US locale.
		$en_us_locales = array_values(
			array_filter(
				$locales,
				function( $l ) {
					return $l->locale === 'en_US';
				}
			)
		);

		if ( count( $en_us_locales ) !== 0 ) {
			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_user_locale();
		$matching_wp_locales = array_values(
			array_filter(
				$action_locales,
				function ( $l ) use ( $wp_locale ) {
					return $wp_locale === $l->locale;
				}
			)
		);

		if ( count( $matching_wp_locales ) !== 0 ) {
			return $matching_wp_locales[0];
		}

		// Fall back to en_US locale.
		$en_us_locales = array_values(
			array_filter(
				$action_locales,
				function( $l ) {
					return $l->locale === 'en_US';
				}
			)
		);

		if ( count( $en_us_locales ) !== 0 ) {
			return $en_us_locales[0];
		}

		return null;
	}

	/**
	 * Get the actions for a note.
	 *
	 * @param object $spec The spec.
	 *
	 * @return array The actions.
	 */
	public static function get_actions( $spec ) {
		$note    = new Note();
		$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,
				( $action_locale === null || ! isset( $action_locale->label ) )
					? ''
					: $action_locale->label,
				$url,
				$action->status
			);
		}
		return $note->get_actions();
	}
}
StoredStateRuleProcessor.php000064400000002346151541727630012266 0ustar00<?php
/**
 * Rule processor that performs a comparison operation against a value in the
 * stored state object.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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;
	}
}
StoredStateSetupForProducts.php000064400000007200151541727630012744 0ustar00<?php
/**
 * Handles stored state setup for products.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

defined( 'ABSPATH' ) || exit;

use Automattic\WooCommerce\Admin\PluginsProvider\PluginsProvider;
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\SpecRunner;

/**
 * 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.
	 */
	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 );
	}
}
TotalPaymentsVolumeProcessor.php000064400000003410151541727630013162 0ustar00<?php
/**
 * Rule processor that passes when a store's payments volume exceeds a provided amount.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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 = new RevenueQuery(
			array(
				'before' => $dates['end'],
				'after'  => $dates['start'],
				'interval' => 'year',
				'fields' => array( 'total_sales' ),
			)
		);
		$report_data    = $reports_revenue->get_data();
		$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 ) ) {
			return false;
		}

		if ( ! isset( $rule->operation ) ) {
			return false;
		}

		return true;
	}
}
TransformerInterface.php000064400000001424151541727630011414 0ustar00<?php

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

use stdClass;

/**
 * An interface to define a transformer.
 *
 * Interface TransformerInterface
 *
 * @package Automattic\WooCommerce\Admin\RemoteInboxNotifications
 */
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 default value.
	 *
	 * @return mixed|null
	 */
	public function transform( $value, stdClass $arguments = null, $default = null);

	/**
	 * Validate Transformer arguments.
	 *
	 * @param stdClass|null $arguments arguments to validate.
	 *
	 * @return mixed
	 */
	public function validate( stdClass $arguments = null );
}
TransformerService.php000064400000003756151541727630011126 0ustar00<?php

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

use InvalidArgumentException;
use stdClass;

/**
 * A simple service class for the Transformer classes.
 *
 * Class TransformerService
 *
 * @package Automattic\WooCommerce\Admin\RemoteInboxNotifications
 */
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__ . '\\Transformers\\' . $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 string $default 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, $default ) {
		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}" );
			}

			$transformed_value = $transformer->transform( $target_value, $transformer_config->arguments, $default );
			// if the transformer returns null, then return the previously transformed value.
			if ( null === $transformed_value ) {
				return $target_value;
			}

			$target_value = $transformed_value;
		}

		return $target_value;
	}
}
Transformers/ArrayColumn.php000064400000002161151541727630012211 0ustar00<?php

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications\Transformers;

use Automattic\WooCommerce\Admin\RemoteInboxNotifications\TransformerInterface;
use InvalidArgumentException;
use stdClass;

/**
 * Search array value by one of its key.
 *
 * @package Automattic\WooCommerce\Admin\RemoteInboxNotifications\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 default value.
	 *
	 * @throws InvalidArgumentException Throws when the required argument 'key' is missing.
	 *
	 * @return mixed
	 */
	public function transform( $value, stdClass $arguments = null, $default = null ) {
		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;
		}

		return true;
	}
}
Transformers/ArrayFlatten.php000064400000002000151541727630012341 0ustar00<?php

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications\Transformers;

use Automattic\WooCommerce\Admin\RemoteInboxNotifications\TransformerInterface;
use stdClass;

/**
 * Flatten nested array.
 *
 * @package Automattic\WooCommerce\Admin\RemoteInboxNotifications\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 default value.
	 *
	 * @return mixed|null
	 */
	public function transform( $value, stdClass $arguments = null, $default = null ) {
		$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;
	}
}
Transformers/ArrayKeys.php000064400000001626151541727630011674 0ustar00<?php

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications\Transformers;

use Automattic\WooCommerce\Admin\RemoteInboxNotifications\TransformerInterface;
use stdClass;

/**
 * Search array value by one of its key.
 *
 * @package Automattic\WooCommerce\Admin\RemoteInboxNotifications\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 default value.
	 *
	 * @return mixed
	 */
	public function transform( $value, stdClass $arguments = null, $default = null ) {
		return array_keys( $value );
	}

	/**
	 * Validate Transformer arguments.
	 *
	 * @param stdClass|null $arguments arguments to validate.
	 *
	 * @return mixed
	 */
	public function validate( stdClass $arguments = null ) {
		return true;
	}
}
Transformers/ArraySearch.php000064400000002306151541727630012162 0ustar00<?php

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications\Transformers;

use Automattic\WooCommerce\Admin\RemoteInboxNotifications\TransformerInterface;
use InvalidArgumentException;
use stdClass;

/**
 * Searches a given a given value in the array.
 *
 * @package Automattic\WooCommerce\Admin\RemoteInboxNotifications\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 default value.
	 *
	 * @throws InvalidArgumentException Throws when the required 'value' is missing.
	 *
	 * @return mixed|null
	 */
	public function transform( $value, stdClass $arguments = null, $default = null ) {
		$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;
	}
}
Transformers/ArrayValues.php000064400000001632151541727630012215 0ustar00<?php

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications\Transformers;

use Automattic\WooCommerce\Admin\RemoteInboxNotifications\TransformerInterface;
use stdClass;

/**
 * Search array value by one of its key.
 *
 * @package Automattic\WooCommerce\Admin\RemoteInboxNotifications\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 default value.
	 *
	 * @return mixed
	 */
	public function transform( $value, stdClass $arguments = null, $default = null ) {
		return array_values( $value );
	}

	/**
	 * Validate Transformer arguments.
	 *
	 * @param stdClass|null $arguments arguments to validate.
	 *
	 * @return mixed
	 */
	public function validate( stdClass $arguments = null ) {
		return true;
	}
}
Transformers/Count.php000064400000001562151541727630011051 0ustar00<?php

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications\Transformers;

use Automattic\WooCommerce\Admin\RemoteInboxNotifications\TransformerInterface;
use stdClass;

/**
 * Count elements in Array.
 *
 * @package Automattic\WooCommerce\Admin\RemoteInboxNotifications\Transformers
 */
class Count implements TransformerInterface {
	/**
	 *  Count elements in Array.
	 *
	 * @param array         $value an array to count.
	 * @param stdClass|null $arguments arguments.
	 * @param string|null   $default default value.
	 *
	 * @return number
	 */
	public function transform( $value, stdClass $arguments = null, $default = null ) {
		return count( $value );
	}

	/**
	 * Validate Transformer arguments.
	 *
	 * @param stdClass|null $arguments arguments to validate.
	 *
	 * @return mixed
	 */
	public function validate( stdClass $arguments = null ) {
		return true;
	}
}
Transformers/DotNotation.php000064400000003545151541727630012226 0ustar00<?php

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications\Transformers;

use Automattic\WooCommerce\Admin\RemoteInboxNotifications\TransformerInterface;
use InvalidArgumentException;
use stdClass;

/**
 * Find an array value by dot notation.
 *
 * @package Automattic\WooCommerce\Admin\RemoteInboxNotifications\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 default value.
	 *
	 * @throws InvalidArgumentException Throws when the required 'path' is missing.
	 *
	 * @return mixed
	 */
	public function transform( $value, stdclass $arguments = null, $default = 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 );
	}

	/**
	 * Find the given $path in $array by dot notation.
	 *
	 * @param array  $array an array to search in.
	 * @param string $path a path in the given array.
	 * @param null   $default default value to return if $path was not found.
	 *
	 * @return mixed|null
	 */
	public function get( $array, $path, $default = null ) {
		if ( isset( $array[ $path ] ) ) {
			return $array[ $path ];
		}

		foreach ( explode( '.', $path ) as $segment ) {
			if ( ! is_array( $array ) || ! array_key_exists( $segment, $array ) ) {
				return $default;
			}

			$array = $array[ $segment ];
		}

		return $array;
	}

	/**
	 * 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;
	}
}
Transformers/PrepareUrl.php000064400000002057151541727630012042 0ustar00<?php

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications\Transformers;

use Automattic\WooCommerce\Admin\RemoteInboxNotifications\TransformerInterface;
use stdClass;

/**
 * Prepare site URL for comparison.
 *
 * @package Automattic\WooCommerce\Admin\RemoteInboxNotifications\Transformers
 */
class PrepareUrl implements TransformerInterface {
	/**
	 * Prepares the site URL by removing the protocol and trailing slash.
	 *
	 * @param mixed         $value a value to transform.
	 * @param stdClass|null $arguments arguments.
	 * @param string|null   $default default value.
	 *
	 * @return mixed|null
	 */
	public function transform( $value, stdClass $arguments = null, $default = null ) {
		$url_parts = wp_parse_url( rtrim( $value, '/' ) );
		return isset( $url_parts['path'] ) ? $url_parts['host'] . $url_parts['path'] : $url_parts['host'];
	}

	/**
	 * Validate Transformer arguments.
	 *
	 * @param stdClass|null $arguments arguments to validate.
	 *
	 * @return mixed
	 */
	public function validate( stdClass $arguments = null ) {
		return true;
	}
}
WCAdminActiveForProvider.php000064400000000767151541727630012102 0ustar00<?php
/**
 * WCAdmin active for provider.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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();
	}
}
WCAdminActiveForRuleProcessor.php000064400000003374151541727630013114 0ustar00<?php
/**
 * Rule processor for publishing if wc-admin has been active for at least the
 * given number of seconds.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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();
		$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 ) {
		if ( ! isset( $rule->days ) ) {
			return false;
		}

		if ( ! isset( $rule->operation ) ) {
			return false;
		}

		return true;
	}
}
WooCommerceAdminUpdatedRuleProcessor.php000064400000001561151541727640014523 0ustar00<?php
/**
 * Rule processor for sending when WooCommerce Admin has been updated.
 */

namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;

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;
	}
}