| @@ -10,9 +10,8 @@ | ||
| 10 | 10 | use FluentCart\App\Services\DateTime\DateTime; |
| 11 | 11 | |
| 12 | 12 | class ReportHelper |
| 13 | 13 | { |
| 14 | - | |
| 15 | 14 | /** |
| 16 | 15 | * Define the group key based on the data density between the start and end dates. |
| 17 | 16 | * |
| 18 | 17 | * @param \DateTime $startDate The start date as a DateTime object. |
| @@ -152,10 +151,23 @@ | ||
| 152 | 151 | |
| 153 | 152 | return $attributes; |
| 154 | 153 | } |
| 155 | 154 | |
| 155 | + /** | |
| 156 | + * Whitelist a groupKey value used to build raw SQL (SELECT/GROUP BY clauses) | |
| 157 | + * so an unrecognized or missing value never reaches the query builder. | |
| 158 | + * | |
| 159 | + * @param mixed $value | |
| 160 | + * @return string | |
| 161 | + */ | |
| 162 | + public static function sanitizeGroupKey($value) | |
| 163 | + { | |
| 164 | + $acceptedValues = ['billing_country', 'shipping_country', 'payment_method', 'payment_status', 'default', 'daily', 'monthly', 'yearly']; | |
| 165 | + return in_array($value, $acceptedValues) ? $value : 'payment_method'; | |
| 166 | + } | |
| 167 | + | |
| 156 | 168 | protected static function sanitizeParams($params) |
| 157 | - { | |
| 169 | + { | |
| 158 | 170 | $rules = [ |
| 159 | 171 | 'startDate' => 'sanitize_text_field', |
| 160 | 172 | 'endDate' => 'sanitize_text_field', |
| 161 | 173 | 'compareType' => 'sanitize_text_field', |
| @@ -160,21 +172,37 @@ | ||
| 160 | 172 | 'endDate' => 'sanitize_text_field', |
| 161 | 173 | 'compareType' => 'sanitize_text_field', |
| 162 | 174 | 'compareDate' => 'sanitize_text_field', |
| 163 | 175 | 'groupKey' => function ($value) { |
| 164 | - $acceptedValues = ['billing_country', 'shipping_country', 'payment_method', 'payment_status', 'default', 'monthly', 'yearly']; | |
| 165 | - return in_array($value, $acceptedValues) ? $value : 'payment_method'; | |
| 176 | + return static::sanitizeGroupKey($value); | |
| 166 | 177 | }, |
| 167 | 178 | 'currency' => 'sanitize_text_field', |
| 168 | 179 | 'filterMode' => 'sanitize_text_field', |
| 169 | 180 | 'storeMode' => 'sanitize_text_field', |
| 170 | 181 | 'variation_ids.*' => 'intval', |
| 182 | + 'customDays' => 'intval', | |
| 171 | 183 | 'subscriptionType' => 'sanitize_text_field', |
| 172 | 184 | 'orderStatus.*' => 'sanitize_text_field', |
| 173 | 185 | 'orderTypes.*' => 'sanitize_text_field', |
| 186 | + 'filter_type' => 'sanitize_text_field', | |
| 174 | 187 | ]; |
| 175 | - | |
| 176 | - return Sanitizer::sanitize($params, $rules); | |
| 188 | + | |
| 189 | + /** | |
| 190 | + * Report params whose shape this plugin does not own. | |
| 191 | + * | |
| 192 | + * `advanced_filters` deliberately has no rule above. Its payload describes | |
| 193 | + * filter conditions, and only whoever consumes it knows what shape is | |
| 194 | + * valid — so only they can sanitize it without mangling it (running | |
| 195 | + * sanitize_text_field() over a JSON blob eats everything after the first | |
| 196 | + * '<'). A consumer pushes its own rule in here, and Sanitizer::sanitize() | |
| 197 | + * leaves any key with no rule untouched. | |
| 198 | + * | |
| 199 | + * @param array $rules Sanitization rules, keyed like $params. | |
| 200 | + * @param array $params The raw, unsanitized params. | |
| 201 | + */ | |
| 202 | + $rules = apply_filters('fluent_cart/report/sanitize_params_rules', $rules, $params); | |
| 203 | + | |
| 204 | + return Sanitizer::sanitize($params, is_array($rules) ? $rules : []); | |
| 177 | 205 | } |
| 178 | 206 | |
| 179 | 207 | /** |
| 180 | 208 | * @param string $type |