feat(Rule): add new rules

This commit is contained in:
2026-05-09 21:24:10 +03:30
parent fd9d29a0ee
commit aa944bf339
9 changed files with 532 additions and 178 deletions

View File

@@ -22,8 +22,25 @@ class AdminController {
private $allowedBannerDeviceTargets = ['all', 'desktop', 'mobile'];
private $allowedUpsellTriggerTypes = ['product', 'category', 'cart_total'];
private $allowedUpsellDiscountTypes = ['percentage', 'fixed', 'none'];
private $allowedRuleConditionTypes = ['user_type', 'product_category', 'product_ids', 'cart_total_min', 'cart_total_max', 'cart_item_count_min', 'cart_item_count_max'];
private $allowedRuleActionTypes = ['discount_percent', 'discount_fixed', 'set_price', 'free_shipping'];
private $allowedRuleConditionTypes = [
'user_type',
'product_category',
'exclude_product_category',
'product_tag',
'product_ids',
'exclude_product_ids',
'cart_total_min',
'cart_total_max',
'cart_item_count_min',
'cart_item_count_max',
'cart_contains_product',
'cart_contains_category',
'customer_order_count_min',
'customer_order_count_max',
'day_of_week',
];
private $allowedRuleConditionOperators = ['is', 'is_not', 'in', 'not_in'];
private $allowedRuleActionTypes = ['discount_percent', 'discount_fixed', 'set_price', 'increase_percent', 'increase_fixed', 'free_shipping'];
private $allowedStrategies = ['priority', 'highest_discount', 'first_valid'];
public function __construct(RuleRepository $ruleRepository, UpsellRepository $upsellRepository, BannerRepository $bannerRepository) {
@@ -667,6 +684,72 @@ class AdminController {
return $deleted === false ? 0 : (int) $deleted;
}
private function sanitizeRuleConditions($rawConditions) {
$conditions = [];
$rawConditions = is_array($rawConditions) ? wp_unslash($rawConditions) : [];
foreach ($rawConditions as $condition) {
if (!is_array($condition)) {
continue;
}
$type = sanitize_key($condition['type'] ?? '');
if (!in_array($type, $this->allowedRuleConditionTypes, true)) {
continue;
}
$operator = sanitize_key($condition['operator'] ?? 'is');
if (!in_array($operator, $this->allowedRuleConditionOperators, true)) {
$operator = 'is';
}
$value = sanitize_text_field($condition['value'] ?? '');
if ($value === '') {
continue;
}
$conditions[] = [
'type' => $type,
'operator' => $operator,
'value' => $value,
];
}
return $conditions;
}
private function sanitizeRuleActions($rawActions) {
$actions = [];
$rawActions = is_array($rawActions) ? wp_unslash($rawActions) : [];
foreach ($rawActions as $action) {
if (!is_array($action)) {
continue;
}
$type = sanitize_key($action['type'] ?? '');
if (!in_array($type, $this->allowedRuleActionTypes, true)) {
continue;
}
$value = max(0, floatval($action['value'] ?? 0));
if (in_array($type, ['discount_percent', 'increase_percent'], true)) {
$value = min(100, $value);
}
if ($type !== 'free_shipping' && $value <= 0) {
continue;
}
$actions[] = [
'type' => $type,
'value' => $value,
];
}
return $actions;
}
private function getSettingsDefaults() {
return [
'plugin_enabled' => 1,
@@ -764,41 +847,30 @@ class AdminController {
$name = sanitize_text_field($_POST['name'] ?? '');
$this->requireValue($name, __('عنوان قانون الزامی است.', 'sodino'), 'sodino-add-rule');
$conditionType = sanitize_key($_POST['condition_type'] ?? 'user_type');
if (!in_array($conditionType, $this->allowedRuleConditionTypes, true)) {
$conditionType = 'user_type';
$conditions = $this->sanitizeRuleConditions($_POST['conditions'] ?? []);
if (empty($conditions)) {
$this->redirectWithNotice($this->getBackUrl('sodino-add-rule'), __('حداقل یک شرط معتبر برای قانون لازم است.', 'sodino'), 'error');
}
$conditionValue = sanitize_text_field($_POST['condition_value'] ?? '');
$this->requireValue($conditionValue, __('مقدار شرط قانون الزامی است.', 'sodino'), 'sodino-add-rule');
$actionType = sanitize_key($_POST['action_type'] ?? 'discount_percent');
if (!in_array($actionType, $this->allowedRuleActionTypes, true)) {
$actionType = 'discount_percent';
$actions = $this->sanitizeRuleActions($_POST['actions'] ?? []);
if (empty($actions)) {
$this->redirectWithNotice($this->getBackUrl('sodino-add-rule'), __('حداقل یک عملیات معتبر برای قانون لازم است.', 'sodino'), 'error');
}
$actionValue = sanitize_text_field($_POST['action_value'] ?? '0');
if ($actionType !== 'free_shipping' && floatval($actionValue) <= 0) {
$this->redirectWithNotice($this->getBackUrl('sodino-add-rule'), __('مقدار عملیات باید بزرگ‌تر از صفر باشد.', 'sodino'), 'error');
$startDate = $this->normalizeDatetime($_POST['start_date'] ?? '');
$endDate = $this->normalizeDatetime($_POST['end_date'] ?? '');
if ($startDate && $endDate && strtotime($endDate) < strtotime($startDate)) {
$this->redirectWithNotice($this->getBackUrl('sodino-add-rule'), __('تاریخ پایان قانون نباید قبل از تاریخ شروع باشد.', 'sodino'), 'error');
}
$rule->name = $name;
$rule->priority = max(1, intval($_POST['priority'] ?? 10));
$rule->usage_limit = max(0, intval($_POST['usage_limit'] ?? 0));
$rule->user_roles = array_map('sanitize_text_field', (array) ($_POST['user_roles'] ?? []));
$rule->conditions = [
[
'type' => $conditionType,
'value' => $conditionValue,
],
];
$rule->actions = [
[
'type' => $actionType,
'value' => $actionValue,
],
];
$rule->start_date = $startDate;
$rule->end_date = $endDate;
$rule->conditions = $conditions;
$rule->actions = $actions;
$rule->syncLegacyFields();
$rule->enabled = isset($_POST['enabled']) ? 1 : 0;