$maxLimit) { $limit = $maxLimit; } $offset = (int) ($options['offset'] ?? $defaultOffset); if ($offset < 0) { $offset = 0; } return [$limit, $offset]; } public static function sanitizeOrder( array $options, array $allowedOrder, string $defaultOrder = 'id', string $defaultDir = 'desc' ): array { $order = (string) ($options['order'] ?? $defaultOrder); $dir = strtolower((string) ($options['dir'] ?? $defaultDir)); if (!in_array($order, $allowedOrder, true)) { $order = $defaultOrder; } if (!in_array($dir, ['asc', 'desc'], true)) { $dir = $defaultDir; } return [$order, $dir]; } public static function addLikeFilter(array &$where, array &$params, array $fields, string $value): void { $like = self::normalizeLikeValue($value); if ($like === '') { return; } $clauses = []; foreach ($fields as $field) { $clauses[] = $field . " like ? escape '\\\\'"; $params[] = $like; } if ($clauses) { $where[] = '(' . implode(' or ', $clauses) . ')'; } } public static function addEnumFilter(array &$where, array &$params, $value, array $map): void { if ($value === null) { return; } $normalized = strtolower(trim((string) $value)); if ($normalized === '' || $normalized === 'all') { return; } foreach ($map as $entry) { $aliases = $entry['aliases'] ?? []; $aliases = array_map('strtolower', $aliases); if (!in_array($normalized, $aliases, true)) { continue; } $sql = (string) ($entry['sql'] ?? ''); if ($sql === '') { return; } $where[] = $sql; $paramsToAdd = $entry['params'] ?? []; foreach ($paramsToAdd as $param) { $params[] = $param; } return; } } public static function uuidV4(): string { $data = random_bytes(16); $data[6] = chr((ord($data[6]) & 0x0f) | 0x40); $data[8] = chr((ord($data[8]) & 0x3f) | 0x80); return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); } public static function addEqualsFilter(array &$where, array &$params, $value, string $sql, bool $allowEmpty = false): void { // Use for simple "= ?" filters; skip when empty to keep WHERE clean. if ($value === null) { return; } $normalized = trim((string) $value); if ($normalized === '' && !$allowEmpty) { return; } $where[] = $sql; $params[] = $normalized; } public static function normalizeIdList($value): array { if (is_string($value)) { $value = array_filter(array_map('trim', explode(',', $value))); } elseif (!is_array($value)) { return []; } $flat = []; array_walk_recursive($value, static function ($item) use (&$flat): void { $flat[] = $item; }); $ids = []; foreach ($flat as $item) { $id = (int) trim((string) $item); if ($id > 0) { $ids[] = $id; } } $ids = array_values(array_unique($ids)); sort($ids, SORT_NUMERIC); return $ids; } public static function normalizeStringList(mixed $value, int $max = 200, ?callable $sanitizer = null): array { if ($max <= 0) { return []; } if (is_string($value)) { $value = array_filter(array_map('trim', explode(',', $value))); } elseif (!is_array($value)) { return []; } $flat = []; array_walk_recursive($value, static function ($item) use (&$flat): void { $flat[] = $item; }); $items = []; $seen = []; foreach ($flat as $item) { $text = trim((string) $item); if ($text === '') { continue; } if ($sanitizer !== null) { $text = trim((string) $sanitizer($text)); if ($text === '') { continue; } } if (isset($seen[$text])) { continue; } $seen[$text] = true; $items[] = $text; if (count($items) >= $max) { break; } } return $items; } }