Maintain local ⭤ remote in sync with automatic AT Protocol parity for Laravel (alpha & unstable)
at dev 152 lines 3.3 kB view raw
1<?php 2 3namespace SocialDept\AtpParity\Concerns; 4 5use SocialDept\AtpParity\Contracts\RecordMapper; 6use SocialDept\AtpParity\MapperRegistry; 7use SocialDept\AtpSchema\Data\Data; 8 9/** 10 * Trait for Eloquent models that map to AT Protocol records. 11 * 12 * @mixin \Illuminate\Database\Eloquent\Model 13 */ 14trait HasAtpRecord 15{ 16 /** 17 * Get the AT Protocol URI for this model. 18 */ 19 public function getAtpUri(): ?string 20 { 21 $column = config('parity.columns.uri', 'atp_uri'); 22 23 return $this->getAttribute($column); 24 } 25 26 /** 27 * Get the AT Protocol CID for this model. 28 */ 29 public function getAtpCid(): ?string 30 { 31 $column = config('parity.columns.cid', 'atp_cid'); 32 33 return $this->getAttribute($column); 34 } 35 36 /** 37 * Get the DID from the AT Protocol URI. 38 */ 39 public function getAtpDid(): ?string 40 { 41 $uri = $this->getAtpUri(); 42 43 if (! $uri) { 44 return null; 45 } 46 47 // at://did:plc:xxx/app.bsky.feed.post/rkey 48 if (preg_match('#^at://([^/]+)/#', $uri, $matches)) { 49 return $matches[1]; 50 } 51 52 return null; 53 } 54 55 /** 56 * Get the collection (lexicon NSID) from the AT Protocol URI. 57 */ 58 public function getAtpCollection(): ?string 59 { 60 $uri = $this->getAtpUri(); 61 62 if (! $uri) { 63 return null; 64 } 65 66 // at://did:plc:xxx/app.bsky.feed.post/rkey 67 if (preg_match('#^at://[^/]+/([^/]+)/#', $uri, $matches)) { 68 return $matches[1]; 69 } 70 71 return null; 72 } 73 74 /** 75 * Get the rkey from the AT Protocol URI. 76 */ 77 public function getAtpRkey(): ?string 78 { 79 $uri = $this->getAtpUri(); 80 81 if (! $uri) { 82 return null; 83 } 84 85 // at://did:plc:xxx/app.bsky.feed.post/rkey 86 if (preg_match('#^at://[^/]+/[^/]+/([^/]+)$#', $uri, $matches)) { 87 return $matches[1]; 88 } 89 90 return null; 91 } 92 93 /** 94 * Check if this model has been synced to AT Protocol. 95 */ 96 public function hasAtpRecord(): bool 97 { 98 return $this->getAtpUri() !== null; 99 } 100 101 /** 102 * Get the mapper for this model. 103 */ 104 public function getAtpMapper(): ?RecordMapper 105 { 106 return app(MapperRegistry::class)->forModel(static::class); 107 } 108 109 /** 110 * Convert this model to an AT Protocol record DTO. 111 */ 112 public function toAtpRecord(): ?Data 113 { 114 $mapper = $this->getAtpMapper(); 115 116 if (! $mapper) { 117 return null; 118 } 119 120 return $mapper->toRecord($this); 121 } 122 123 /** 124 * Scope to query models that have been synced to AT Protocol. 125 */ 126 public function scopeWithAtpRecord($query) 127 { 128 $column = config('parity.columns.uri', 'atp_uri'); 129 130 return $query->whereNotNull($column); 131 } 132 133 /** 134 * Scope to query models that have not been synced to AT Protocol. 135 */ 136 public function scopeWithoutAtpRecord($query) 137 { 138 $column = config('parity.columns.uri', 'atp_uri'); 139 140 return $query->whereNull($column); 141 } 142 143 /** 144 * Scope to find by AT Protocol URI. 145 */ 146 public function scopeWhereAtpUri($query, string $uri) 147 { 148 $column = config('parity.columns.uri', 'atp_uri'); 149 150 return $query->where($column, $uri); 151 } 152}