| 1: | <?php |
| 2: | |
| 3: | declare(strict_types=1); |
| 4: | |
| 5: | namespace LaravelUi5\OData\Http; |
| 6: | |
| 7: | /** |
| 8: | * OData **custom query options** — the non-`$`, non-`@` parameters on a request |
| 9: | * URL (e.g. `?roleCode=customer`). |
| 10: | * |
| 11: | * Carried as a property on {@see ODataRequest} (populated by the HTTP entry points |
| 12: | * from the parsed URL), threaded through the query plan, and handed to an entity |
| 13: | * set's `query(CustomQueryOptions $options)` by the resolver. Passing it as data — |
| 14: | * rather than reaching for the global Illuminate request — is what makes it correct |
| 15: | * under `$batch`: each inner request builds its own `ODataRequest` with its own |
| 16: | * options, so there is no shared state and nothing to read off the outer envelope. |
| 17: | */ |
| 18: | final readonly class CustomQueryOptions |
| 19: | { |
| 20: | /** @param array<string, string> $options */ |
| 21: | public function __construct(private array $options = []) {} |
| 22: | |
| 23: | public function get(string $key, ?string $default = null): ?string |
| 24: | { |
| 25: | return $this->options[$key] ?? $default; |
| 26: | } |
| 27: | |
| 28: | /** @return array<string, string> */ |
| 29: | public function all(): array |
| 30: | { |
| 31: | return $this->options; |
| 32: | } |
| 33: | |
| 34: | /** |
| 35: | * Build from a parsed query map, keeping only custom query options — string |
| 36: | * keys that don't begin with `$` (system options) or `@` (parameter aliases). |
| 37: | * |
| 38: | * @param array<string, mixed> $query |
| 39: | */ |
| 40: | public static function fromQuery(array $query): self |
| 41: | { |
| 42: | $custom = []; |
| 43: | |
| 44: | foreach ($query as $key => $value) { |
| 45: | if (is_string($key) && $key !== '' && $key[0] !== '$' && $key[0] !== '@' && is_string($value)) { |
| 46: | $custom[$key] = $value; |
| 47: | } |
| 48: | } |
| 49: | |
| 50: | return new self($custom); |
| 51: | } |
| 52: | } |
| 53: |