'WpCafe Pro is not installed. Discounts require WpCafe Pro.' ]; } if ( ! wpc_is_module_enable( 'discount' ) ) { return [ 'error' => 'The Discount module is not enabled. Go to WpCafe → Extensions to enable it.' ]; } return null; } /** * Shape a Discount_Model instance into an AI-friendly flat array. * * WordPress unserialises post meta on read, so maybe_unserialize() is a * no-op on arrays but safely handles any edge case where the raw string * is returned (e.g. a meta value stored before the model existed). * * @param \WpCafePro\Models\Discount_Model $discount Model instance. * @return array */ protected function shape_discount( \WpCafePro\Models\Discount_Model $discount ): array { $date_rule = maybe_unserialize( $discount->date_rule ); $product_rule = maybe_unserialize( $discount->product_rule ); return [ 'id' => $discount->id, 'discount_title' => $discount->discount_title, 'discount_type' => $discount->discount_type, 'discount_amount' => floatval( $discount->discount_amount ), 'status' => $discount->discount_status, 'is_active' => (bool) $discount->is_active, 'product_rule' => is_array( $product_rule ) ? $product_rule : [], 'date_rule' => is_array( $date_rule ) ? $date_rule : [], 'addon_discount_applicable' => $discount->addon_discount_applicable, ]; } /** * Build the product_rule array accepted by Discount_Model::create/update. * * @param string|null $rule_type Product scope type. * @param array|null $specific_products WC product IDs to include. * @param array|null $excluded_products WC product IDs to exclude. * @param array|null $specific_categories WC category IDs to include. * @return array */ protected function build_product_rule( ?string $rule_type, ?array $specific_products, ?array $excluded_products, ?array $specific_categories ): array { return [ 'type' => $rule_type ?? 'all_products', 'specific_products' => array_map( 'intval', $specific_products ?? [] ), 'excluded_products' => array_map( 'intval', $excluded_products ?? [] ), 'specific_categories' => array_map( 'intval', $specific_categories ?? [] ), ]; } /** * Build the date_rule array accepted by Discount_Model::create/update. * * Returns an empty array when $rule_type is null (no date rule). * * @param string|null $rule_type Date rule type. * @param string|null $date Exact date (Y-m-d) for on_date. * @param string|null $start_date Start date (Y-m-d) for date_range. * @param string|null $end_date End date (Y-m-d) for date_range. * @param string|null $start_time Start time (HH:MM) for time_range. * @param string|null $end_time End time (HH:MM) for time_range. * @param array|null $days Day abbreviations for day_of_week. * @return array */ protected function build_date_rule( ?string $rule_type, ?string $date, ?string $start_date, ?string $end_date, ?string $start_time, ?string $end_time, ?array $days ): array { if ( null === $rule_type ) { return []; } return [ 'type' => sanitize_text_field( $rule_type ), 'date' => sanitize_text_field( $date ?? '' ), 'start_date' => sanitize_text_field( $start_date ?? '' ), 'end_date' => sanitize_text_field( $end_date ?? '' ), 'start_time' => sanitize_text_field( $start_time ?? '' ), 'end_time' => sanitize_text_field( $end_time ?? '' ), 'days' => array_map( 'sanitize_text_field', $days ?? [] ), ]; } /** * Validate that a discount_type value is an accepted enum member. * * @param string $type Value to validate. * @return array|null Error array on failure, null on success. */ protected function validate_discount_type( string $type ): ?array { if ( ! in_array( $type, [ 'percentage', 'fixed_amount', 'standard' ], true ) ) { return [ 'error' => "Invalid discount_type \"{$type}\". Accepted: percentage, fixed_amount, standard." ]; } return null; } /** * Validate that a discount_status value is an accepted enum member. * * @param string $status Value to validate. * @return array|null Error array on failure, null on success. */ protected function validate_discount_status( string $status ): ?array { if ( ! in_array( $status, [ 'active', 'inactive' ], true ) ) { return [ 'error' => "Invalid discount_status \"{$status}\". Accepted: active, inactive." ]; } return null; } /** * Validate that an addon_discount_applicable value is an accepted enum member. * * @param string $applicable Value to validate. * @return array|null Error array on failure, null on success. */ protected function validate_addon_applicable( string $applicable ): ?array { if ( ! in_array( $applicable, [ 'total_amount', 'addons_total_amount' ], true ) ) { return [ 'error' => "Invalid addon_discount_applicable \"{$applicable}\". Accepted: total_amount, addons_total_amount." ]; } return null; } }