TemplateGenerator.class.php (4981B)
1 <?php 2 3 4 namespace cms\generator; 5 6 7 use cms\base\Configuration; 8 use cms\generator\dsl\DslCms; 9 use cms\generator\dsl\DslConsole; 10 use cms\generator\dsl\DslHttp; 11 use cms\generator\dsl\DslJson; 12 use cms\generator\dsl\DslPage; 13 use cms\generator\PageContext; 14 use cms\model\File; 15 use cms\model\Folder; 16 use cms\model\Language; 17 use cms\model\Page; 18 use cms\model\Project; 19 use cms\model\Template; 20 use cms\model\TemplateModel; 21 use cms\model\Value; 22 use dsl\DslException; 23 use dsl\DslTemplate; 24 use dsl\executor\DslInterpreter; 25 use logger\Logger; 26 use util\exception\GeneratorException; 27 use util\Mustache; 28 use util\text\TextMessage; 29 30 31 class TemplateGenerator 32 { 33 34 private $templateId; 35 private $modelId; 36 private $scheme; 37 38 public function __construct($templateId, $modelId, $scheme ) 39 { 40 $this->templateId = $templateId; 41 $this->modelId = $modelId; 42 $this->scheme = $scheme; 43 } 44 45 46 /** 47 * Generates the template content. 48 * 49 * @param $data array values 50 * @return String Inhalt 51 */ 52 public function generateValue( $data ) 53 { 54 $template = new Template( $this->templateId ); 55 $template->load(); 56 57 // Get a List with ElementId->ElementName 58 $elements = array_map(function($element) { 59 return $element->name; 60 },$template->getElements() ); 61 62 $templatemodel = new TemplateModel( $template->templateid, $this->modelId ); 63 if ( $this->scheme == Producer::SCHEME_PREVIEW ) 64 $templatemodel->load(); 65 else 66 $templatemodel->loadForPublic(); 67 68 $src = $templatemodel->src; 69 70 // No we are collecting the data and are fixing some old stuff. 71 72 foreach( $elements as $elementId=>$elementName ) 73 { 74 // The following code is for old template values: 75 76 // convert {{<id>}} to {{<name>}} 77 $src = str_replace( '{{'.$elementId.'}}','{{'.$elementName.'}}',$src ); 78 79 $src = str_replace( '{{IFNOTEMPTY:'.$elementId.':BEGIN}}','{{#'.$elementName.'}}',$src ); 80 $src = str_replace( '{{IFNOTEMPTY:'.$elementId.':END}}' ,'{{/'.$elementName.'}}',$src ); 81 $src = str_replace( '{{IFEMPTY:' .$elementId.':BEGIN}}','{{^'.$elementName.'}}',$src ); 82 $src = str_replace( '{{IFEMPTY:' .$elementId.':END}}' ,'{{/'.$elementName.'}}',$src ); 83 84 $src = str_replace( '{{->'.$elementId.'}}','',$src ); 85 } 86 87 if ( DEVELOPMENT ) 88 Logger::trace( 'generating template with data: '.print_r($data,true) ); 89 90 // Now we have collected all data, lets call the template engine: 91 92 $mustache = new Mustache(); 93 $mustache->escape = null; // No HTML escaping, this is the job of this CMS ;) 94 $mustache->partialLoader = function( $name ) use ($template) { 95 96 if ( substr($name,0,5) == 'file:') { 97 $fileid = intval( substr($name,5) ); 98 $file = new File( $fileid ); 99 return $file->loadValue(); 100 } 101 102 103 $project = Project::create( $template->projectid ); 104 $templateid = array_search($name,$project->getTemplates() ); 105 106 if ( ! $templateid ) 107 throw new \InvalidArgumentException( TextMessage::create('template ${name} not found',['name'=>$name]) ); 108 109 if ( $templateid == $template->templateid ) 110 throw new \InvalidArgumentException('Template recursion detected on template-id '.$templateid); 111 112 113 $templatemodel = new TemplateModel( $templateid, $this->modelId ); 114 $templatemodel->load(); 115 116 return $templatemodel->src; 117 }; 118 119 try { 120 $mustache->parse($src); 121 } catch (\Exception $e) { 122 // Should we throw it to the caller? 123 // No, because it is not a technical error. So let's only log it. 124 Logger::warn("Template rendering failed: ".$e->getMessage() ); 125 return $e->getMessage(); 126 } 127 $src = $mustache->render( $data ); 128 129 // now we have the fully generated source. 130 131 try { 132 133 $templateParser = new DslTemplate(); 134 $templateParser->parseTemplate($src); 135 if ($templateParser->tagsFound) { 136 $executor = new DslInterpreter( DslInterpreter::FLAG_THROW_ERROR + DslInterpreter::FLAG_SECURE ); 137 $executor->addContext([ 138 'console' => new DslConsole(), 139 'cms' => new DslCms(), 140 'http' => new DslHttp(), 141 'json' => new DslJson(), 142 ]); 143 $executor->addContext( $data ); 144 145 $executor->runCode($templateParser->script); 146 147 // Ausgabe ermitteln. 148 $src = $executor->getOutput(); 149 } 150 } catch (DslException $e) { 151 Logger::warn($e); 152 $src = $e->getMessage()."\nscript source:\n".$templateParser->script; 153 } 154 155 // should we do a UTF-8-escaping here? 156 // Default should be off, because if you are fully using utf-8 (you should do), this is unnecessary. 157 if ( Configuration::subset('publish' )->is('escape_8bit_characters') ) 158 if ( substr($this->mimeType(),-4) == 'html' ) 159 { 160 /* 161 * 162 $src = htmlentities($src,ENT_NOQUOTES,'UTF-8'); 163 $src = str_replace('<' , '<', $src); 164 $src = str_replace('>' , '>', $src); 165 $src = str_replace('&', '&', $src); 166 */ 167 $src = translateutf8tohtml($src); 168 } 169 170 return $src; 171 } 172 173 174 public function getMimeType() 175 { 176 $templateModel = new TemplateModel( $this->templateId,$this->modelId ); 177 $templateModel->load(); 178 179 return $templateModel->mimeType(); 180 } 181 }