File "Incentive.php"
Full Path: /home/amervokv/ecomlive.net/wp-content/plugins/woocommerce/src/Internal/Admin/Suggestions/Incentives/Incentive.php
File size: 10.01 KB
MIME-type: text/x-php
Charset: utf-8
<?php
declare( strict_types=1 );
namespace Automattic\WooCommerce\Internal\Admin\Suggestions\Incentives;
/**
* Abstract class for payment extension suggestion incentive provider classes.
*/
abstract class Incentive {
const PREFIX = 'woocommerce_admin_pes_incentive_';
/**
* The user meta name for storing dismissed incentives.
*
* @var string
*/
protected string $dismissed_meta_name = self::PREFIX . 'dismissed';
/**
* The suggestion ID this incentive provider is for.
*
* @var string
*/
protected string $suggestion_id;
/**
* Constructor.
*
* @param string $suggestion_id The suggestion ID this incentive provider is for.
*/
public function __construct( string $suggestion_id ) {
$this->suggestion_id = $suggestion_id;
}
/**
* Get the details of all the incentives.
*
* The incentives are filtered based on the country code, incentive type, if provided, and their visibility.
*
* @param string $country_code The business location country code to get incentives for.
* @param string $incentive_type Optional. The type of incentive to check for.
*
* @return array The incentives list with details for each incentive.
*/
public function get_all( string $country_code, string $incentive_type = '' ): array {
$incentives = array_filter(
$this->get_incentives( $country_code ),
fn( $incentive ) => $this->validate_incentive( $incentive )
);
if ( ! empty( $incentive_type ) ) {
$incentives = array_filter(
$incentives,
function ( $incentive ) use ( $incentive_type ) {
return $incentive['type'] === $incentive_type;
}
);
}
return array_values( $incentives );
}
/**
* Get an incentive by promo ID.
*
* The incentives are filtered based on the country code, incentive type, if provided, and their visibility.
*
* @param string $promo_id The incentive promo ID.
* @param string $country_code The business location country code to get incentives for.
* @param string $incentive_type Optional. The type of incentive to search for.
*
* @return ?array The incentive details. Returns null if there is no incentive available.
*/
public function get_by_promo_id( string $promo_id, string $country_code, string $incentive_type = '' ): ?array {
$incentives = array_filter(
$this->get_all( $country_code, $incentive_type ),
function ( $incentive ) use ( $promo_id ) {
return $incentive['promo_id'] === $promo_id;
}
);
if ( empty( $incentives ) ) {
return null;
}
// Get the first found incentive, in the unlikely case there are multiple incentives with the same promo ID.
return reset( $incentives );
}
/**
* Get an incentive by ID.
*
* The incentives are filtered based on the country code, incentive type, if provided, and their visibility.
*
* @param string $incentive_id The incentive ID.
* @param string $country_code The business location country code to get incentives for.
*
* @return ?array The incentive details. Returns null if there is no incentive available.
*/
public function get_by_id( string $incentive_id, string $country_code ): ?array {
$incentives = array_filter(
$this->get_all( $country_code ),
function ( $incentive ) use ( $incentive_id ) {
return $incentive['id'] === $incentive_id;
}
);
if ( empty( $incentives ) ) {
return null;
}
// Get the first found incentive, in the unlikely case there are multiple incentives with the same ID.
return reset( $incentives );
}
/**
* Check if an incentive should be visible.
*
* @param string $id The incentive ID to check for visibility.
* @param string $country_code The business location country code to get incentives for.
* @param bool $skip_extension_active_check Whether to skip the check for the extension plugin being active.
*
* @return boolean Whether the incentive should be visible.
*/
public function is_visible( string $id, string $country_code, bool $skip_extension_active_check = false ): bool {
// The extension plugin must not be active, unless we are asked to skip the check.
if ( ! $skip_extension_active_check && $this->is_extension_active() ) {
return false;
}
// The current WP user must have the required capabilities.
if ( ! $this->user_has_caps() ) {
return false;
}
// An incentive must be available.
if ( empty( $this->get_by_id( $id, $country_code ) ) ) {
return false;
}
// If the incentive has been dismissed in all contexts, don't show it.
// We don't know the full list of contexts, so we can't assume anything beyond `all`.
if ( $this->is_dismissed( $id, 'all' ) ) {
return false;
}
return true;
}
/**
* Dismiss an incentive.
*
* @param string $id The incentive ID to dismiss.
* @param string $context Optional. The context ID in which the incentive is dismissed.
* This can be used to dismiss the same incentive in different contexts.
* If no context ID is provided, the incentive will be dismissed for all contexts.
* @param ?int $timestamp Optional The timestamp when the incentive was dismissed.
* Defaults to the current time.
*
* @return bool True if the incentive was not previously dismissed and now it is.
* False if the incentive was already dismissed, or we failed to persist the dismissal data.
*/
public function dismiss( string $id, string $context = 'all', ?int $timestamp = null ): bool {
// If it is already dismissed, don't dismiss it again.
if ( $this->is_dismissed( $id, $context ) ) {
return false;
}
$all_dismissed_incentives = $this->get_all_dismissed_incentives();
if ( empty( $all_dismissed_incentives[ $this->suggestion_id ] ) ) {
$all_dismissed_incentives[ $this->suggestion_id ] = array();
ksort( $all_dismissed_incentives );
}
$all_dismissed_incentives[ $this->suggestion_id ][] = array(
'id' => $id,
'context' => $context,
'timestamp' => $timestamp ?? time(),
);
return $this->save_all_dismissed_incentives( $all_dismissed_incentives );
}
/**
* Check if an incentive has been manually dismissed.
*
* @param string $id The incentive ID to check for dismissal.
* @param string $context Optional. The context ID in which to check for dismissal.
* If no context ID is provided, we check for dismissal in all contexts.
*
* @return boolean Whether the incentive has been manually dismissed.
*/
public function is_dismissed( string $id, string $context = '' ): bool {
if ( empty( $id ) ) {
return false;
}
$all_dismissed_incentives = $this->get_all_dismissed_incentives();
// If there are no dismissed incentives for the suggestion, return early.
$dismissed_incentives = $all_dismissed_incentives[ $this->suggestion_id ] ?? array();
if ( empty( $dismissed_incentives ) ) {
return false;
}
// Check if the incentive is dismissed in the given context.
if ( in_array(
$id,
array_column(
array_filter(
$dismissed_incentives,
// All context dismissals are always included.
fn( $dismissed_incentive ) => 'all' === $dismissed_incentive['context'] || $context === $dismissed_incentive['context']
),
'id'
),
true
) ) {
return true;
}
return false;
}
/**
* Get the dismissals (contexts) for an incentive.
*
* @param string $id The incentive ID.
*
* @return array The contexts in which the incentive has been dismissed.
*/
public function get_dismissals( string $id ): array {
$all_dismissed_incentives = $this->get_all_dismissed_incentives();
// If there are no dismissed incentives for the suggestion, return early.
$dismissed_incentives = $all_dismissed_incentives[ $this->suggestion_id ] ?? array();
if ( empty( $dismissed_incentives ) ) {
return array();
}
$dismissals = array_filter(
$dismissed_incentives,
fn( $dismissed_incentive ) => $id === $dismissed_incentive['id']
);
return array_column( $dismissals, 'context' );
}
/**
* Get all the dismissed incentives grouped by suggestion.
*
* @return array The dismissed incentives grouped by suggestion.
*/
protected function get_all_dismissed_incentives(): array {
$all_dismissed_incentives = get_user_meta( get_current_user_id(), $this->dismissed_meta_name, true );
if ( empty( $all_dismissed_incentives ) ) {
$all_dismissed_incentives = array();
}
return $all_dismissed_incentives;
}
/**
* Save all the dismissed incentives list.
*
* @param array $dismissed_incentives The dismissed incentives data.
*
* @return bool Whether the dismissed incentives were saved successfully.
*/
protected function save_all_dismissed_incentives( array $dismissed_incentives ): bool {
return (bool) update_user_meta( get_current_user_id(), $this->dismissed_meta_name, $dismissed_incentives );
}
/**
* Check if the current user has the required capabilities to view incentives.
*
* @return bool Whether the current user has the required capabilities view incentives.
*/
protected function user_has_caps(): bool {
return current_user_can( 'manage_woocommerce' );
}
/**
* Validate an incentive details.
*
* It will check if the incentive details have the required keys.
*
* @param array $incentive The incentive details.
*
* @return bool Whether the incentive data is valid.
*/
protected function validate_incentive( array $incentive ): bool {
// The incentive must have an ID, a promo ID, and a type.
$required_keys = array( 'id', 'promo_id', 'type' );
foreach ( $required_keys as $key ) {
if ( empty( $incentive[ $key ] ) ) {
return false;
}
}
return true;
}
/**
* Check if the corresponding extension suggestion plugin is active.
*
* @return boolean Whether the corresponding extension suggestion plugin is active.
*/
abstract protected function is_extension_active(): bool;
/**
* Get eligible incentives.
*
* @param string $country_code The business location country code to get incentives for.
*
* @return array List of eligible incentives.
*/
abstract protected function get_incentives( string $country_code ): array;
}