aspirecloud/app/Values/WpOrg/Plugins/QueryPluginsRequest.php
2025-09-27 10:37:53 -06:00

107 lines
3.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Values\WpOrg\Plugins;
use App\Values\DTO;
use Bag\Attributes\StripExtraParameters;
use Bag\Attributes\Transforms;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
#[StripExtraParameters]
readonly class QueryPluginsRequest extends DTO
{
/** @param list<string>|null $tags
* @param list<string>|null $tagAnd
* @param list<string>|null $tagOr
* @param list<string>|null $tagNot
* @param string|list<string>|null $fields
*/
public function __construct(
public ?string $search = null,
public ?array $tags = null,
public ?string $tag = null,
public ?array $tagAnd = null,
public ?array $tagOr = null,
public ?array $tagNot = null,
public ?string $plugin = null,
public ?string $author = null,
public ?string $browse = null,
public mixed $fields = null,
public int $page = 1,
public int $per_page = 24,
) {}
/** @return array<string, mixed> */
#[Transforms(Request::class)]
public static function fromRequest(Request $request): array
{
$query = $request->query->all();
$query['tags'] = self::mergeQueryTags($query); // @mago-expect analysis:less-specific-argument
return $query;
}
/**
* @param array<string, string|list<string>> $query
* @return list<string>
*/
public static function mergeQueryTags(array $query): array
{
$pull = fn(string $key) => array_filter(Arr::wrap(Arr::pull($query, $key, [])) ?? []);
$key = isset($query['tags']) ? 'tags' : 'tag';
$tags = $pull($key);
// Normalize additional tag operators
$tagAnd = $pull('tag-and');
$tagOr = $pull('tag-or');
$tagNot = $pull('tag-not');
// Merge base tags, ANDs, and ORs
$merged = array_values(array_unique([...$tags, ...$tagAnd, ...$tagOr]));
// Exclude NOT tags if present
if (!empty($tagNot)) {
$merged = array_values(array_diff($merged, $tagNot));
}
return $merged;
}
// [chuck 2025-09-13] These are no longer used, but keeping them commented for future reference.
// If they're still not used after 6 months, just delete them.
//
// /** Normalize a search-like string (trim + compact whitespace + limited punctuation). */
// private static function normalizeSearchString(?string $value): ?string
// {
// if ($value === null) {
// return null;
// }
// $value = trim($value);
// $value = Regex::replace('/\s+/i', ' ', $value);
// return Regex::replace('/[^\w.,!?@#$_-]/i', ' ', $value);
// }
//
// /** @param array<int,mixed> $items @return list<string> */
// private static function normalizeStringList(array $items): array
// {
// $out = [];
// foreach ($items as $v) {
// if (!is_string($v)) {
// if (is_scalar($v)) {
// $v = (string) $v;
// } else {
// continue;
// }
// }
// $v = self::normalizeSearchString($v) ?? '';
// if ($v !== '') {
// $out[] = $v;
// }
// }
// // unique and reindex
// return array_values(array_unique($out));
// }
}