134 lines
7.2 KiB
PHP
134 lines
7.2 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Esun\Reward\Model;
|
|
|
|
use Magento\Framework\App\Config\ScopeConfigInterface;
|
|
use Magento\Framework\Serialize\Serializer\Json;
|
|
use Magento\Store\Model\ScopeInterface;
|
|
|
|
class Config
|
|
{
|
|
public function __construct(
|
|
private readonly ScopeConfigInterface $scopeConfig,
|
|
private readonly Json $serializer
|
|
) {}
|
|
|
|
public function isEnabled(?int $storeId = null): bool { return $this->flag('general/enabled', $storeId); }
|
|
public function registrationPoints(?int $storeId = null): int { return (int)$this->earningRule('registration', $storeId)['points']; }
|
|
public function firstAddressPoints(?int $storeId = null): int { return (int)$this->earningRule('first_shipping_address', $storeId)['points']; }
|
|
public function orderRate(?int $storeId = null): float { return (float)$this->earningRule('order_earned', $storeId)['points']; }
|
|
public function reviewTextPoints(?int $storeId = null): int { return (int)$this->earningRule('review_text', $storeId)['points']; }
|
|
public function reviewMediaPoints(?int $storeId = null): int { return (int)$this->earningRule('review_media', $storeId)['points']; }
|
|
public function socialPoints(?int $storeId = null): int { return (int)$this->earningRule('social_share', $storeId)['points']; }
|
|
public function redemptionRate(?int $storeId = null): int { return max(1, $this->int('spending/points_per_dollar', $storeId)); }
|
|
public function maxCheckoutPoints(?int $storeId = null): int { return $this->int('spending/max_checkout_points', $storeId); }
|
|
public function reviewEligibility(?int $storeId = null): string { return (string)$this->value('review/eligibility', $storeId); }
|
|
public function silverThreshold(?int $storeId = null): float { return $this->float('tiers/silver_threshold', $storeId); }
|
|
public function silverMultiplier(?int $storeId = null): float { return $this->float('tiers/silver_multiplier', $storeId); }
|
|
public function goldThreshold(?int $storeId = null): float { return $this->float('tiers/gold_threshold', $storeId); }
|
|
public function goldMultiplier(?int $storeId = null): float { return $this->float('tiers/gold_multiplier', $storeId); }
|
|
|
|
/** @return array{code: string, points: float, name: string, reason: string} */
|
|
public function earningRule(string $code, ?int $storeId = null): array
|
|
{
|
|
$rules = $this->earningRules($storeId);
|
|
return $rules[$code] ?? ['code' => $code, 'points' => 0.0, 'name' => ucwords(str_replace('_', ' ', $code)), 'reason' => ''];
|
|
}
|
|
|
|
/** @return array<string, array{code: string, points: float, name: string, reason: string}> */
|
|
public function earningRules(?int $storeId = null): array
|
|
{
|
|
$defaults = [
|
|
'registration' => ['points' => (float)$this->int('earning/registration_points', $storeId), 'name' => 'Account Registration', 'reason' => 'Account registration reward'],
|
|
'first_shipping_address' => ['points' => (float)$this->int('earning/first_address_points', $storeId), 'name' => 'First Shipping Address', 'reason' => 'First saved shipping address reward'],
|
|
'order_earned' => ['points' => $this->float('earning/points_per_dollar', $storeId), 'name' => 'Order Reward', 'reason' => 'Points earned from order %1'],
|
|
'review_text' => ['points' => (float)$this->int('earning/review_text_points', $storeId), 'name' => 'Product Review', 'reason' => 'Approved product review reward'],
|
|
'review_media' => ['points' => (float)$this->int('earning/review_media_points', $storeId), 'name' => 'Product Review with Media', 'reason' => 'Approved product review reward'],
|
|
'social_share' => ['points' => (float)$this->int('earning/social_share_points', $storeId), 'name' => 'Social Share', 'reason' => 'Social share reward'],
|
|
];
|
|
foreach ($defaults as $code => &$rule) {
|
|
$rule['code'] = $code;
|
|
}
|
|
unset($rule);
|
|
|
|
$value = $this->value('earning/items', $storeId);
|
|
try {
|
|
$items = is_array($value) ? $value : (empty($value) ? [] : $this->serializer->unserialize((string)$value));
|
|
} catch (\InvalidArgumentException) {
|
|
$items = [];
|
|
}
|
|
if (!is_array($items) || !$items) {
|
|
return $defaults;
|
|
}
|
|
|
|
$rules = [];
|
|
foreach ($items as $item) {
|
|
if (!is_array($item)) {
|
|
continue;
|
|
}
|
|
$code = strtolower(trim((string)($item['code'] ?? '')));
|
|
$name = trim((string)($item['name'] ?? ''));
|
|
if ($code === '' || $name === '') {
|
|
continue;
|
|
}
|
|
$rules[$code] = [
|
|
'code' => $code,
|
|
'points' => max(0.0, (float)($item['points'] ?? 0)),
|
|
'name' => $name,
|
|
'reason' => trim((string)($item['reason'] ?? '')),
|
|
];
|
|
}
|
|
return $rules ?: $defaults;
|
|
}
|
|
|
|
/** @return array<int, array{code: string, label: string, threshold: float, multiplier: float}> */
|
|
public function tiers(?int $storeId = null): array
|
|
{
|
|
$value = $this->value('tiers/items', $storeId);
|
|
try {
|
|
$items = is_array($value) ? $value : (empty($value) ? [] : $this->serializer->unserialize((string)$value));
|
|
} catch (\InvalidArgumentException) {
|
|
$items = [];
|
|
}
|
|
if (!is_array($items)) {
|
|
$items = [];
|
|
}
|
|
|
|
$tiers = [];
|
|
foreach ($items as $item) {
|
|
if (!is_array($item)) {
|
|
continue;
|
|
}
|
|
$label = trim((string)($item['label'] ?? ''));
|
|
$threshold = max(0.0, (float)($item['threshold'] ?? 0));
|
|
$multiplier = (float)($item['multiplier'] ?? 0);
|
|
if ($label === '' || $multiplier <= 0) {
|
|
continue;
|
|
}
|
|
$tiers[] = [
|
|
'code' => strtolower((string)preg_replace('/[^a-z0-9]+/i', '_', $label)),
|
|
'label' => $label,
|
|
'threshold' => $threshold,
|
|
'multiplier' => $multiplier,
|
|
];
|
|
}
|
|
|
|
if (!$tiers) {
|
|
$tiers = [
|
|
['code' => 'bronze', 'label' => 'Bronze Maker', 'threshold' => 0.0, 'multiplier' => 1.0],
|
|
['code' => 'silver', 'label' => 'Silver Maker', 'threshold' => $this->silverThreshold($storeId), 'multiplier' => $this->silverMultiplier($storeId)],
|
|
['code' => 'gold', 'label' => 'Gold Maker', 'threshold' => $this->goldThreshold($storeId), 'multiplier' => $this->goldMultiplier($storeId)],
|
|
];
|
|
}
|
|
|
|
usort($tiers, static fn(array $left, array $right): int => $left['threshold'] <=> $right['threshold']);
|
|
return $tiers;
|
|
}
|
|
|
|
private function value(string $path, ?int $storeId): mixed { return $this->scopeConfig->getValue('esun_reward/' . $path, ScopeInterface::SCOPE_STORE, $storeId); }
|
|
private function int(string $path, ?int $storeId): int { return max(0, (int)$this->value($path, $storeId)); }
|
|
private function float(string $path, ?int $storeId): float { return max(0.0, (float)$this->value($path, $storeId)); }
|
|
private function flag(string $path, ?int $storeId): bool { return $this->scopeConfig->isSetFlag('esun_reward/' . $path, ScopeInterface::SCOPE_STORE, $storeId); }
|
|
}
|