Resolve AT Protocol DIDs, handles, and schemas with intelligent caching for Laravel
1<?php
2
3namespace SocialDept\AtpResolver\Data;
4
5class DidDocument
6{
7 /**
8 * Create a new DID Document instance.
9 *
10 * @param string $id The DID (e.g., "did:plc:abc123")
11 * @param array $alsoKnownAs Alternative identifiers (handles)
12 * @param array $verificationMethod Verification methods (keys)
13 * @param array $service Service endpoints (PDS, etc.)
14 * @param array $raw The raw DID document
15 */
16 public function __construct(
17 public readonly string $id,
18 public readonly array $alsoKnownAs = [],
19 public readonly array $verificationMethod = [],
20 public readonly array $service = [],
21 public readonly array $raw = [],
22 ) {
23 }
24
25 /**
26 * Create a DID Document from a raw array.
27 *
28 * @param array $data
29 */
30 public static function fromArray(array $data): self
31 {
32 return new self(
33 id: $data['id'] ?? '',
34 alsoKnownAs: $data['alsoKnownAs'] ?? [],
35 verificationMethod: $data['verificationMethod'] ?? [],
36 service: $data['service'] ?? [],
37 raw: $data,
38 );
39 }
40
41 /**
42 * Get the PDS (Personal Data Server) endpoint.
43 */
44 public function getPdsEndpoint(): ?string
45 {
46 foreach ($this->service as $service) {
47 if (($service['type'] ?? '') === 'AtprotoPersonalDataServer') {
48 return $service['serviceEndpoint'] ?? null;
49 }
50 }
51
52 return null;
53 }
54
55 /**
56 * Get the handle from alsoKnownAs.
57 */
58 public function getHandle(): ?string
59 {
60 foreach ($this->alsoKnownAs as $alias) {
61 if (str_starts_with($alias, 'at://')) {
62 return substr($alias, 5);
63 }
64 }
65
66 return null;
67 }
68
69 /**
70 * Convert to array.
71 */
72 public function toArray(): array
73 {
74 return $this->raw;
75 }
76}