'card.html.twig','list'=>'list.html.twig','layout'=>'overview.html.twig', 'include'=>'team.html.twig','macro'=>'form.html.twig','email'=>'email.html.twig', 'escape'=>'escape.html.twig','strict'=>'strict.html.twig','cache'=>'card.html.twig' ]; public static function environment(bool $strict=true, string|false $cache=false): Environment { return new Environment(new FilesystemLoader(dirname(__DIR__).'/templates'), [ 'autoescape'=>'html','strict_variables'=>$strict,'cache'=>$cache,'auto_reload'=>true, 'debug'=>false,'charset'=>'UTF-8', ]); } public static function run(string $scenario, array $data, array $options=[]): array { if(!isset(self::TEMPLATES[$scenario])) throw new \InvalidArgumentException('Неизвестный сценарий.'); $strict=$options['strict']??true; if(!is_bool($strict)) throw new \InvalidArgumentException('strict должен быть true или false.'); $template=self::TEMPLATES[$scenario]; if($scenario==='layout' && ($options['page']??'overview')==='details') $template='details.html.twig'; $twig=self::environment($strict); try { $html=$twig->render($template,$data); if(strlen($html)>131072) throw new \InvalidArgumentException('Результат превышает 128 КиБ.'); $text=$scenario==='email'?$twig->render('email.txt.twig',$data):null; // Compile the same trusted template with ArrayLoader so the public // recording has no environment-specific absolute path or byte count. $compiler=$scenario==='cache'?new Environment(new \Twig\Loader\ArrayLoader([$template=>$twig->getLoader()->getSourceContext($template)->getCode()]),['autoescape'=>'html','strict_variables'=>$strict,'cache'=>false]):null; $compiled=$compiler?->compileSource($compiler->getLoader()->getSourceContext($template)); return ['ok'=>true,'engine'=>'Twig PHP','version'=>Environment::VERSION,'scenario'=>$scenario,'template'=>$template,'strict'=>$strict,'html'=>$html,'text'=>$text, 'details'=>['templateBytes'=>strlen($twig->getLoader()->getSourceContext($template)->getCode()),'outputBytes'=>strlen($html),'compiledBytes'=>$compiled===null?null:strlen($compiled),'publicCacheEnabled'=>false,'note'=>$scenario==='cache'?'Настоящая компиляция Twig без записи на диск. Кеш файлов проверяется локальной командой php bin/cache-demo.php.':'Шаблон фиксирован; данные существуют только в этом запросе.']]; } catch(TwigError $e){ return ['ok'=>false,'engine'=>'Twig PHP','version'=>Environment::VERSION,'scenario'=>$scenario,'template'=>$template,'strict'=>$strict,'code'=>'TEMPLATE_ERROR','message'=>$e->getRawMessage(),'line'=>$e->getTemplateLine()]; } } public static function recipe(string $scenario, array $data, array $options): string { $encoded=base64_encode(json_encode($data,JSON_UNESCAPED_UNICODE|JSON_THROW_ON_ERROR)); return "