TemplateService.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <?php
  2. namespace App\Services\Template;
  3. use App\Services\Template\Renderers\RendererFactory;
  4. use Illuminate\Support\Facades\Cache;
  5. use Illuminate\Support\Facades\Log;
  6. class TemplateService
  7. {
  8. private TemplateParser $parser;
  9. private bool $cacheEnabled;
  10. private int $cacheTtl;
  11. public function __construct(bool $cacheEnabled = true, int $cacheTtl = 3600)
  12. {
  13. $this->parser = new TemplateParser;
  14. $this->cacheEnabled = $cacheEnabled;
  15. $this->cacheTtl = $cacheTtl;
  16. }
  17. /**
  18. * 解析并渲染内容
  19. */
  20. public function parseAndRender(string $content, string $format = 'json'): array
  21. {
  22. try {
  23. // 生成缓存键
  24. $cacheKey = $this->generateCacheKey($content, $format);
  25. if ($this->cacheEnabled && Cache::has($cacheKey)) {
  26. return Cache::get($cacheKey);
  27. }
  28. // 解析内容
  29. $document = $this->parser->parse($content);
  30. // 渲染内容
  31. $renderer = RendererFactory::create($format);
  32. $renderedContent = $renderer->render($document);
  33. $result = [
  34. 'data' => $format === 'json' ? json_decode($renderedContent, true) : $renderedContent,
  35. 'meta' => $document->meta,
  36. ];
  37. // 缓存结果
  38. if ($this->cacheEnabled) {
  39. Cache::put($cacheKey, $result, $this->cacheTtl);
  40. }
  41. return $result;
  42. } catch (\Exception $e) {
  43. Log::error('Template parsing failed', [
  44. 'content' => substr($content, 0, 200),
  45. 'format' => $format,
  46. 'error' => $e->getMessage(),
  47. ]);
  48. throw $e;
  49. }
  50. }
  51. /**
  52. * 仅解析,不渲染
  53. */
  54. public function parse(string $content): ParsedDocument
  55. {
  56. return $this->parser->parse($content);
  57. }
  58. /**
  59. * 仅渲染已解析的文档
  60. */
  61. public function render(ParsedDocument $document, string $format): string
  62. {
  63. $renderer = RendererFactory::create($format);
  64. return $renderer->render($document);
  65. }
  66. /**
  67. * 注册新模板
  68. */
  69. public function registerTemplate(string $name, array $config): void
  70. {
  71. $registry = $this->parser->getRegistry();
  72. $registry->registerTemplate($name, $config);
  73. // 清除相关缓存
  74. if ($this->cacheEnabled) {
  75. $this->clearTemplateCache($name);
  76. }
  77. }
  78. /**
  79. * 获取可用模板列表
  80. */
  81. public function getAvailableTemplates(): array
  82. {
  83. $registry = $this->parser->getRegistry();
  84. $templates = [];
  85. // 这里需要添加一个方法来获取所有模板
  86. // 为了示例,我们返回一些基本信息
  87. $basicTemplates = ['note', 'info', 'warning'];
  88. foreach ($basicTemplates as $templateName) {
  89. $template = $registry->getTemplate($templateName);
  90. if ($template) {
  91. $templates[$templateName] = [
  92. 'name' => $templateName,
  93. 'config' => $template,
  94. 'example' => $this->generateTemplateExample($templateName, $template),
  95. ];
  96. }
  97. }
  98. return $templates;
  99. }
  100. /**
  101. * 生成模板使用示例
  102. */
  103. private function generateTemplateExample(string $name, array $config): string
  104. {
  105. $params = [];
  106. $defaultParams = $config['defaultParams'] ?? [];
  107. foreach ($defaultParams as $index => $paramName) {
  108. $params[] = $paramName.'=示例值'.($index + 1);
  109. }
  110. return '{{'.$name.'|'.implode('|', $params).'}}';
  111. }
  112. /**
  113. * 生成缓存键
  114. */
  115. private function generateCacheKey(string $content, string $format): string
  116. {
  117. return 'template_'.$format.'_'.md5($content);
  118. }
  119. /**
  120. * 清除模板相关缓存
  121. */
  122. private function clearTemplateCache(string $templateName): void
  123. {
  124. // 这里可以实现更精确的缓存清除逻辑
  125. Cache::flush(); // 简单起见,清除所有缓存
  126. }
  127. /**
  128. * 批量处理内容
  129. */
  130. public function batchProcess(array $contents, string $format = 'json'): array
  131. {
  132. $results = [];
  133. foreach ($contents as $index => $content) {
  134. try {
  135. $results[$index] = $this->parseAndRender($content, $format);
  136. } catch (\Exception $e) {
  137. $results[$index] = [
  138. 'success' => false,
  139. 'error' => $e->getMessage(),
  140. ];
  141. }
  142. }
  143. return $results;
  144. }
  145. /**
  146. * 验证模板语法
  147. */
  148. public function validateSyntax(string $content): array
  149. {
  150. $errors = [];
  151. try {
  152. $document = $this->parser->parse($content);
  153. // 检查是否有未知模板
  154. foreach ($document->content as $node) {
  155. if ($node instanceof TemplateNode) {
  156. $registry = $this->parser->getRegistry();
  157. if (! $registry->hasTemplate($node->name)) {
  158. $errors[] = [
  159. 'type' => 'unknown_template',
  160. 'template' => $node->name,
  161. 'position' => $node->position,
  162. 'message' => "Unknown template: {$node->name}",
  163. ];
  164. }
  165. }
  166. }
  167. } catch (\Exception $e) {
  168. $errors[] = [
  169. 'type' => 'parse_error',
  170. 'message' => $e->getMessage(),
  171. ];
  172. }
  173. return $errors;
  174. }
  175. }