6use LightnCandy\LightnCandy;
10use UnexpectedValueException;
36 private const CACHE_VERSION =
'2.2.0';
37 private const CACHE_TTL = BagOStuff::TTL_WEEK;
64 $this->templateDir =
$templateDir ?: __DIR__ .
'/../templates';
70 $this->compileFlags = LightnCandy::FLAG_ERROR_EXCEPTION | LightnCandy::FLAG_MUSTACHELOOKUP;
79 $this->compileFlags |= LightnCandy::FLAG_RUNTIMEPARTIAL;
81 $this->compileFlags &= ~LightnCandy::FLAG_RUNTIMEPARTIAL;
95 if ( strcspn( $templateName,
":/\\\000&<>'\"%" ) !== strlen( $templateName ) ) {
96 throw new UnexpectedValueException(
"Malformed \$templateName: $templateName" );
99 return "{$this->templateDir}/{$templateName}.mustache";
114 if ( isset( $this->renderers[$templateKey] ) &&
115 is_callable( $this->renderers[$templateKey] )
117 return $this->renderers[$templateKey];
128 $key = $this->cache->makeKey(
129 'lightncandy-compiled',
135 $compiledTemplate = $this->cache->get( $key );
139 if ( $compiledTemplate ) {
142 if ( $filesHash !== $compiledTemplate[
'filesHash'] ) {
143 $compiledTemplate =
null;
149 if ( $compiledTemplate ) {
150 $integrityHash = hash_hmac(
'sha256', $compiledTemplate[
'phpCode'], $secretKey );
152 if ( $integrityHash !== $compiledTemplate[
'integrityHash'] ) {
153 $compiledTemplate =
null;
159 if ( !$compiledTemplate ) {
160 $compiledTemplate = $this->
compile( $templateName );
162 $compiledTemplate[
'integrityHash'] = hash_hmac(
164 $compiledTemplate[
'phpCode'],
168 $this->cache->set( $key, $compiledTemplate, self::CACHE_TTL );
173 $compiledTemplate = $this->
compile( $templateName );
177 $renderer = eval( $compiledTemplate[
'phpCode'] );
178 if ( !is_callable( $renderer ) ) {
179 throw new RuntimeException(
"Compiled template `{$templateName}` is not callable" );
181 $this->renderers[$templateKey] = $renderer;
219 if ( !file_exists( $filename ) ) {
220 throw new RuntimeException(
"Could not find template `{$templateName}` at {$filename}" );
223 $files = [ $filename ];
224 $contents = file_get_contents( $filename );
225 $compiled = LightnCandy::compile(
228 'flags' => $this->compileFlags,
229 'basedir' => $this->templateDir,
230 'fileext' =>
'.mustache',
231 'partialresolver' =>
function ( $cx, $partialName ) use ( $templateName, &$files ) {
232 $filename =
"{$this->templateDir}/{$partialName}.mustache";
233 if ( !file_exists( $filename ) ) {
234 throw new RuntimeException( sprintf(
235 'Could not compile template `%s`: Could not find partial `%s` at %s',
242 $fileContents = file_get_contents( $filename );
244 if ( $fileContents ===
false ) {
245 throw new RuntimeException( sprintf(
246 'Could not compile template `%s`: Could not find partial `%s` at %s',
253 $files[] = $filename;
255 return $fileContents;
263 throw new RuntimeException(
"Could not compile template `{$filename}`" );
266 $files = array_values( array_unique( $files ) );
269 'phpCode' => $compiled,
297 return $template( $args, $scopes );
302class_alias( TemplateParser::class,
'TemplateParser' );
static getFileContentsHash( $filePaths)
Get a hash of the combined contents of one or more files, either by retrieving a previously-computed ...
A class containing constants representing the names of configuration variables.
const SecretKey
Name constant for the SecretKey setting, for use with Config::get()