Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use MiniShop3\Model\msCustomer;
use MiniShop3\Router\HttpStatus;
use MiniShop3\Router\Response;
use MiniShop3\Services\Grid\ManagerListFilterPolicy;
use MODX\Revolution\modX;

/**
Expand Down Expand Up @@ -65,14 +66,9 @@ public function getList(array $params = []): array
}

foreach ($params as $key => $value) {
if (str_starts_with($key, 'filter_') && !empty($value)) {
if (str_starts_with($key, 'filter_') && $value !== '' && $value !== null) {
$fieldName = substr($key, 7);

if ($fieldName === 'active') {
$c->where(['is_active' => (int)$value]);
} else {
$c->where([$fieldName . ':LIKE' => "%{$value}%"]);
}
ManagerListFilterPolicy::applyCustomerFilter($c, $fieldName, $value);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use MiniShop3\Model\msDeliveryMember;
use MiniShop3\Router\HttpStatus;
use MiniShop3\Router\Response;
use MiniShop3\Services\Grid\ManagerListFilterPolicy;
use MiniShop3\Utils\PriceAdjustment;
use MODX\Revolution\modX;

Expand Down Expand Up @@ -95,13 +96,14 @@ public function getList(array $params = []): array

// Filter by active status
foreach ($params as $key => $value) {
if (strpos($key, 'filter_') === 0 && $value !== '' && $value !== null) {
if (str_starts_with($key, 'filter_') && $value !== '' && $value !== null) {
$fieldName = substr($key, 7);
if ($fieldName === 'active') {
$criteria['active'] = (int)$value;
} else {
$criteria[$fieldName . ':LIKE'] = "%{$value}%";
}
ManagerListFilterPolicy::applyCriteriaFilter(
$criteria,
$fieldName,
$value,
ManagerListFilterPolicy::DELIVERY_FILTER_MAP
);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use MiniShop3\Services\CustomerDuplicateChecker;
use MiniShop3\Services\CustomerFactory;
use MiniShop3\Services\FilterConfigManager;
use MiniShop3\Services\Grid\ManagerListFilterPolicy;
use MiniShop3\Services\Order\ManagerOrderCostRecalculator;
use MiniShop3\Services\Order\OrderLogService;
use MiniShop3\Services\Order\OrderService;
Expand Down Expand Up @@ -223,7 +224,7 @@ public function getList(array $params = []): array
}

foreach ($params as $key => $value) {
if (strpos($key, 'filter_') === 0 && !empty($value)) {
if (str_starts_with($key, 'filter_') && $value !== '' && $value !== null) {
$fieldName = substr($key, 7);
$this->applyFilter($c, $fieldName, $value);
}
Expand Down Expand Up @@ -1519,7 +1520,7 @@ protected function getOrdersStats(array $params = []): array

// Apply filter_ prefixed params
foreach ($params as $key => $value) {
if (strpos($key, 'filter_') === 0 && !empty($value)) {
if (str_starts_with($key, 'filter_') && $value !== '' && $value !== null) {
$fieldName = substr($key, 7);
$this->applyFilter($c, $fieldName, $value);
}
Expand Down Expand Up @@ -1597,40 +1598,7 @@ protected function applyDraftVisibilityFilter(\xPDO\Om\xPDOQuery $c, array $para
*/
protected function applyFilter($c, string $fieldName, $value): void
{
switch ($fieldName) {
case 'status':
case 'status_id':
$c->where(['status_id' => (int)$value]);
break;
case 'delivery':
case 'delivery_id':
$c->where(['delivery_id' => (int)$value]);
break;
case 'payment':
case 'payment_id':
$c->where(['payment_id' => (int)$value]);
break;
case 'context':
$c->where(['context' => $value]);
break;
case 'customer':
$c->where([
'Address.first_name:LIKE' => "%{$value}%",
'OR:Address.last_name:LIKE' => "%{$value}%",
]);
break;
case 'email':
$c->where(['Address.email:LIKE' => "%{$value}%"]);
break;
case 'phone':
$c->where(['Address.phone:LIKE' => "%{$value}%"]);
break;
case 'num':
$c->where(['num:LIKE' => "{$value}%"]);
break;
default:
break;
}
ManagerListFilterPolicy::applyOrderFilter($c, $fieldName, $value);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use MiniShop3\Model\msDeliveryMember;
use MiniShop3\Router\HttpStatus;
use MiniShop3\Router\Response;
use MiniShop3\Services\Grid\ManagerListFilterPolicy;
use MiniShop3\Utils\PriceAdjustment;
use MODX\Revolution\modX;

Expand Down Expand Up @@ -52,13 +53,14 @@ public function getList(array $params = []): array

// Filter by active status
foreach ($params as $key => $value) {
if (strpos($key, 'filter_') === 0 && $value !== '' && $value !== null) {
if (str_starts_with($key, 'filter_') && $value !== '' && $value !== null) {
$fieldName = substr($key, 7);
if ($fieldName === 'active') {
$criteria['active'] = (int)$value;
} else {
$criteria[$fieldName . ':LIKE'] = "%{$value}%";
}
ManagerListFilterPolicy::applyCriteriaFilter(
$criteria,
$fieldName,
$value,
ManagerListFilterPolicy::PAYMENT_FILTER_MAP
);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
<?php

namespace MiniShop3\Services\Grid;

/**
* Whitelist for Manager API filter_* query params on list endpoints.
*
* Blocks filtering on secret/integration columns (token, password, properties, …).
*/
final class ManagerListFilterPolicy
{
/** @var list<string> */
public const BLOCKED_FILTER_FIELDS = [
'token',
'password',
'properties',
'class',
'validation_rules',
];

/**
* UI filter key => msCustomer column or virtual handler key.
*
* @var array<string, string>
*/
public const CUSTOMER_FILTER_MAP = [
'customer_name' => 'customer_name',
'email' => 'email',
'phone' => 'phone',
'is_active' => 'is_active',
'active' => 'is_active',
];

/**
* UI filter key => msDelivery column.
*
* @var array<string, string>
*/
public const DELIVERY_FILTER_MAP = [
'name' => 'name',
'active' => 'active',
];

/**
* UI filter key => msPayment column.
*
* @var array<string, string>
*/
public const PAYMENT_FILTER_MAP = [
'name' => 'name',
'active' => 'active',
];

/**
* UI filter key => order filter handler (column or virtual key).
*
* @var array<string, string>
*/
public const ORDER_FILTER_MAP = [
'num' => 'num',
'customer' => 'customer',
'status' => 'status_id',
'status_id' => 'status_id',
'status_name' => 'status_id',
'delivery' => 'delivery_id',
'delivery_id' => 'delivery_id',
'payment' => 'payment_id',
'payment_id' => 'payment_id',
'context' => 'context',
'email' => 'email',
'phone' => 'phone',
];

public static function isAllowedFilter(string $fieldName, array $allowedMap): bool
{
if ($fieldName === '' || in_array($fieldName, self::BLOCKED_FILTER_FIELDS, true)) {
return false;
}

return array_key_exists($fieldName, $allowedMap);
}

/**
* @param \xPDO\Om\xPDOQuery $query
*/
public static function applyCustomerFilter($query, string $fieldName, mixed $value): void
{
if (!self::isAllowedFilter($fieldName, self::CUSTOMER_FILTER_MAP)) {
return;
}

$column = self::CUSTOMER_FILTER_MAP[$fieldName];

if ($column === 'customer_name') {
$query->where([
'first_name:LIKE' => "%{$value}%",
'OR:last_name:LIKE' => "%{$value}%",
]);

return;
}

if ($column === 'is_active') {
$query->where(['is_active' => (int)$value]);

return;
}

$query->where([$column . ':LIKE' => "%{$value}%"]);
}

/**
* @param \xPDO\Om\xPDOQuery $query
*/
public static function applyOrderFilter($query, string $fieldName, mixed $value): void
{
if (!self::isAllowedFilter($fieldName, self::ORDER_FILTER_MAP)) {
return;
}

switch (self::ORDER_FILTER_MAP[$fieldName]) {
case 'status_id':
$query->where(['status_id' => (int)$value]);
break;
case 'delivery_id':
$query->where(['delivery_id' => (int)$value]);
break;
case 'payment_id':
$query->where(['payment_id' => (int)$value]);
break;
case 'context':
$query->where(['context' => $value]);
break;
case 'customer':
$query->where([
'Address.first_name:LIKE' => "%{$value}%",
'OR:Address.last_name:LIKE' => "%{$value}%",
]);
break;
case 'email':
$query->where(['Address.email:LIKE' => "%{$value}%"]);
break;
case 'phone':
$query->where(['Address.phone:LIKE' => "%{$value}%"]);
break;
case 'num':
$query->where(['num:LIKE' => "{$value}%"]);
break;
}
}

/**
* @param array<string, mixed> $criteria
*/
public static function applyCriteriaFilter(array &$criteria, string $fieldName, mixed $value, array $allowedMap): void
{
if (!self::isAllowedFilter($fieldName, $allowedMap)) {
return;
}

$column = $allowedMap[$fieldName];

if ($column === 'active') {
$criteria['active'] = (int)$value;

return;
}

$criteria[$column . ':LIKE'] = "%{$value}%";
}
}
Loading