Parse and validate AT Protocol Lexicons with DTO generation for Laravel
1<?php
2
3namespace SocialDept\AtpSchema\Validation\Rules;
4
5use Closure;
6use Illuminate\Contracts\Validation\ValidationRule;
7
8class Handle implements ValidationRule
9{
10 /**
11 * Run the validation rule.
12 */
13 public function validate(string $attribute, mixed $value, Closure $fail): void
14 {
15 if (! is_string($value)) {
16 $fail("The {$attribute} must be a string.");
17
18 return;
19 }
20
21 // Check if Resolver package is available
22 if (class_exists('SocialDept\AtpResolver\Support\Identity')) {
23 if (! \SocialDept\AtpResolver\Support\Identity::isHandle($value)) {
24 $fail("The {$attribute} is not a valid handle.");
25 }
26
27 return;
28 }
29
30 // Fallback validation if Resolver is not available
31 if (! $this->isValidHandle($value)) {
32 $fail("The {$attribute} is not a valid handle.");
33 }
34 }
35
36 /**
37 * Fallback handle validation.
38 */
39 protected function isValidHandle(string $value): bool
40 {
41 // Handle format: domain.tld (DNS name)
42 // Must be at least 3 chars, no spaces, valid DNS characters
43 if (strlen($value) < 3 || strlen($value) > 253) {
44 return false;
45 }
46
47 // Check for valid DNS hostname format
48 return (bool) preg_match('/^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/', $value);
49 }
50}