Parse and validate AT Protocol Lexicons with DTO generation for Laravel
1<?php
2
3namespace SocialDept\AtpSchema\Generator;
4
5use SocialDept\AtpSchema\Parser\Nsid;
6
7class NamespaceResolver
8{
9 /**
10 * Base namespace for generated classes.
11 */
12 protected string $baseNamespace;
13
14 /**
15 * Create a new NamespaceResolver.
16 */
17 public function __construct(string $baseNamespace = 'App\\Lexicons')
18 {
19 $this->baseNamespace = rtrim($baseNamespace, '\\');
20 }
21
22 /**
23 * Resolve NSID to PHP namespace.
24 */
25 public function resolveNamespace(string $nsidString): string
26 {
27 $nsid = Nsid::parse($nsidString);
28
29 // Convert authority to namespace parts (com.example.feed -> Com\Example\Feed)
30 $parts = explode('.', $nsid->getAuthority());
31 $namespaceParts = array_map(fn ($part) => $this->toPascalCase($part), $parts);
32
33 return $this->baseNamespace.'\\'.implode('\\', $namespaceParts);
34 }
35
36 /**
37 * Resolve NSID to PHP class name.
38 */
39 public function resolveClassName(string $nsidString, ?string $defName = null): string
40 {
41 $nsid = Nsid::parse($nsidString);
42
43 // Use definition name if provided, otherwise use the name from NSID
44 $name = $defName ?? $nsid->getName();
45
46 return $this->toPascalCase($name);
47 }
48
49 /**
50 * Resolve full qualified class name.
51 */
52 public function resolveFullyQualifiedName(string $nsidString, ?string $defName = null): string
53 {
54 $namespace = $this->resolveNamespace($nsidString);
55 $className = $this->resolveClassName($nsidString, $defName);
56
57 return $namespace.'\\'.$className;
58 }
59
60 /**
61 * Convert string to PascalCase.
62 */
63 protected function toPascalCase(string $string): string
64 {
65 // Replace dots, hyphens, and underscores with spaces
66 $string = str_replace(['.', '-', '_'], ' ', $string);
67
68 // Capitalize each word
69 $string = ucwords($string);
70
71 // Remove spaces
72 return str_replace(' ', '', $string);
73 }
74
75 /**
76 * Convert NSID to file path.
77 */
78 public function resolveFilePath(string $nsidString, string $baseDirectory, ?string $defName = null): string
79 {
80 $namespace = $this->resolveNamespace($nsidString);
81 $className = $this->resolveClassName($nsidString, $defName);
82
83 // Remove base namespace from full namespace
84 $relativePath = str_replace($this->baseNamespace.'\\', '', $namespace);
85 $relativePath = str_replace('\\', '/', $relativePath);
86
87 return rtrim($baseDirectory, '/').'/'.$relativePath.'/'.$className.'.php';
88 }
89
90 /**
91 * Get the base namespace.
92 */
93 public function getBaseNamespace(): string
94 {
95 return $this->baseNamespace;
96 }
97}