1: <?php
2:
3: declare(strict_types=1);
4:
5: /**
6: * This file is part of the Nexus MCP SDK package.
7: *
8: * (c) 2025 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
9: *
10: * For the full copyright and license information, please view
11: * the LICENSE file that was distributed with this source code.
12: */
13:
14: namespace Nexus\Mcp\Schema\Tool\ToolSchema;
15:
16: /**
17: * The `string` type is used for validating strings/texts containing Unicode characters.
18: *
19: * @extends ToolSchema<string, array{
20: * type: 'string',
21: * description?: non-empty-string,
22: * title?: non-empty-string,
23: * minLength?: int<0, max>,
24: * maxLength?: int<0, max>,
25: * pattern?: non-empty-string,
26: * default?: string
27: * }>
28: */
29: final class StringType extends ToolSchema
30: {
31: /**
32: * @var null|int<0, max>
33: */
34: private ?int $minLength = null;
35:
36: /**
37: * @var null|int<0, max>
38: */
39: private ?int $maxLength = null;
40:
41: /**
42: * @var null|non-empty-string
43: */
44: private ?string $pattern = null;
45:
46: public function minLength(int $minLength): self
47: {
48: if ($minLength < 0) {
49: throw new \InvalidArgumentException('The minimum length must be a non-negative integer.');
50: }
51:
52: $this->minLength = $minLength;
53:
54: return $this;
55: }
56:
57: public function maxLength(int $maxLength): self
58: {
59: if ($maxLength < 0) {
60: throw new \InvalidArgumentException('The maximum length must be a non-negative integer.');
61: }
62:
63: $this->maxLength = $maxLength;
64:
65: return $this;
66: }
67:
68: /**
69: * @param non-empty-string $pattern
70: */
71: public function pattern(string $pattern): self
72: {
73: set_error_handler(static function (int $errno, string $errstr): bool {
74: $errstr = str_replace('preg_match(): Compilation failed: ', '', $errstr);
75:
76: throw new \InvalidArgumentException(\sprintf('Invalid regex pattern: %s', ucfirst($errstr)), $errno);
77: });
78:
79: try {
80: preg_match(\sprintf('/%s/uD', $pattern), '');
81: $this->pattern = $pattern;
82: } finally {
83: restore_error_handler();
84: }
85:
86: return $this;
87: }
88:
89: #[\Override]
90: public function toArray(): array
91: {
92: if (isset($this->minLength, $this->maxLength) && $this->minLength > $this->maxLength) {
93: throw new \LogicException('The minimum length cannot be greater than the maximum length.');
94: }
95:
96: if (isset($this->default, $this->minLength) && \strlen($this->default) < $this->minLength) {
97: throw new \LogicException('The default value length cannot be less than the minimum length.');
98: }
99:
100: if (isset($this->default, $this->maxLength) && \strlen($this->default) > $this->maxLength) {
101: throw new \LogicException('The default value length cannot be greater than the maximum length.');
102: }
103:
104: return array_filter([
105: 'type' => 'string',
106: 'description' => $this->description,
107: 'title' => $this->title,
108: 'minLength' => $this->minLength,
109: 'maxLength' => $this->maxLength,
110: 'pattern' => $this->pattern,
111: 'default' => $this->default,
112: ], static fn(mixed $value): bool => null !== $value);
113: }
114: }
115: