Parse and validate AT Protocol Lexicons with DTO generation for Laravel
at main 3.6 kB view raw
1<?php 2 3namespace SocialDept\AtpSchema\Generator; 4 5use SocialDept\AtpSchema\Exceptions\GenerationException; 6 7class StubRenderer 8{ 9 /** 10 * Path to stub files. 11 */ 12 protected string $stubPath; 13 14 /** 15 * Cached stub contents. 16 * 17 * @var array<string, string> 18 */ 19 protected array $stubs = []; 20 21 /** 22 * Create a new StubRenderer. 23 */ 24 public function __construct(?string $stubPath = null) 25 { 26 $this->stubPath = $stubPath ?? $this->getDefaultStubPath(); 27 } 28 29 /** 30 * Render a stub with variables. 31 * 32 * @param array<string, mixed> $variables 33 */ 34 public function render(string $stub, array $variables): string 35 { 36 $template = $this->loadStub($stub); 37 38 return $this->replaceVariables($template, $variables); 39 } 40 41 /** 42 * Load a stub file. 43 */ 44 protected function loadStub(string $name): string 45 { 46 if (isset($this->stubs[$name])) { 47 return $this->stubs[$name]; 48 } 49 50 $path = $this->getStubPath($name); 51 52 if (! file_exists($path)) { 53 throw GenerationException::templateNotFound($name); 54 } 55 56 $content = file_get_contents($path); 57 58 if ($content === false) { 59 throw GenerationException::cannotReadFile($path); 60 } 61 62 $this->stubs[$name] = $content; 63 64 return $content; 65 } 66 67 /** 68 * Replace variables in template. 69 * 70 * @param array<string, mixed> $variables 71 */ 72 protected function replaceVariables(string $template, array $variables): string 73 { 74 $result = $template; 75 76 foreach ($variables as $key => $value) { 77 // Convert value to string 78 $stringValue = $this->valueToString($value); 79 80 // Replace {{ key }} with value 81 $result = str_replace('{{ '.$key.' }}', $stringValue, $result); 82 } 83 84 // Remove any remaining unreplaced variables 85 $result = preg_replace('/\{\{\s*\w+\s*\}\}/', '', $result); 86 87 return $result; 88 } 89 90 /** 91 * Convert a value to string for replacement. 92 */ 93 protected function valueToString(mixed $value): string 94 { 95 if (is_array($value)) { 96 return implode("\n", array_filter($value)); 97 } 98 99 if (is_bool($value)) { 100 return $value ? 'true' : 'false'; 101 } 102 103 if ($value === null) { 104 return ''; 105 } 106 107 return (string) $value; 108 } 109 110 /** 111 * Get the path for a stub file. 112 */ 113 protected function getStubPath(string $name): string 114 { 115 // Check for published stubs first (in Laravel app) 116 $publishedPath = base_path('stubs/schema/'.$name.'.stub'); 117 if (file_exists($publishedPath)) { 118 return $publishedPath; 119 } 120 121 // Fall back to package stubs 122 return $this->stubPath.'/'.$name.'.stub'; 123 } 124 125 /** 126 * Get default stub path. 127 */ 128 protected function getDefaultStubPath(): string 129 { 130 return __DIR__.'/../../stubs'; 131 } 132 133 /** 134 * Clear cached stubs. 135 */ 136 public function clearCache(): void 137 { 138 $this->stubs = []; 139 } 140 141 /** 142 * Set custom stub path. 143 */ 144 public function setStubPath(string $path): void 145 { 146 $this->stubPath = $path; 147 $this->clearCache(); 148 } 149 150 /** 151 * Get available stubs. 152 * 153 * @return array<string> 154 */ 155 public function getAvailableStubs(): array 156 { 157 $stubs = []; 158 159 foreach (glob($this->stubPath.'/*.stub') as $file) { 160 $stubs[] = basename($file, '.stub'); 161 } 162 163 return $stubs; 164 } 165}