7use LightnCandy\LightnCandy;
11use UnexpectedValueException;
37 private const CACHE_VERSION =
'2.2.0';
38 private const CACHE_TTL = BagOStuff::TTL_WEEK;
65 $this->templateDir =
$templateDir ?: __DIR__ .
'/../templates';
71 $this->compileFlags = LightnCandy::FLAG_ERROR_EXCEPTION | LightnCandy::FLAG_MUSTACHELOOKUP;
80 $this->compileFlags |= LightnCandy::FLAG_RUNTIMEPARTIAL;
82 $this->compileFlags &= ~LightnCandy::FLAG_RUNTIMEPARTIAL;
96 if ( strcspn( $templateName,
":/\\\000&<>'\"%" ) !== strlen( $templateName ) ) {
97 throw new UnexpectedValueException(
"Malformed \$templateName: $templateName" );
100 return "{$this->templateDir}/{$templateName}.mustache";
115 if ( isset( $this->renderers[$templateKey] ) &&
116 is_callable( $this->renderers[$templateKey] )
118 return $this->renderers[$templateKey];
129 $key = $this->cache->makeKey(
130 'lightncandy-compiled',
136 $compiledTemplate = $this->cache->get( $key );
140 if ( $compiledTemplate ) {
143 if ( $filesHash !== $compiledTemplate[
'filesHash'] ) {
144 $compiledTemplate =
null;
150 if ( $compiledTemplate ) {
151 $integrityHash = hash_hmac(
'sha256', $compiledTemplate[
'phpCode'], $secretKey );
153 if ( $integrityHash !== $compiledTemplate[
'integrityHash'] ) {
154 $compiledTemplate =
null;
160 if ( !$compiledTemplate ) {
161 $compiledTemplate = $this->
compile( $templateName );
163 $compiledTemplate[
'integrityHash'] = hash_hmac(
165 $compiledTemplate[
'phpCode'],
169 $this->cache->set( $key, $compiledTemplate, self::CACHE_TTL );
174 $compiledTemplate = $this->
compile( $templateName );
178 $renderer = eval( $compiledTemplate[
'phpCode'] );
179 if ( !is_callable( $renderer ) ) {
180 throw new RuntimeException(
"Compiled template `{$templateName}` is not callable" );
182 $this->renderers[$templateKey] = $renderer;
220 if ( !file_exists( $filename ) ) {
221 throw new RuntimeException(
"Could not find template `{$templateName}` at {$filename}" );
224 $files = [ $filename ];
225 $contents = file_get_contents( $filename );
226 $compiled = LightnCandy::compile(
229 'flags' => $this->compileFlags,
230 'basedir' => $this->templateDir,
231 'fileext' =>
'.mustache',
232 'partialresolver' =>
function ( $cx, $partialName ) use ( $templateName, &$files ) {
233 $filename =
"{$this->templateDir}/{$partialName}.mustache";
234 if ( !file_exists( $filename ) ) {
235 throw new RuntimeException( sprintf(
236 'Could not compile template `%s`: Could not find partial `%s` at %s',
243 $fileContents = file_get_contents( $filename );
245 if ( $fileContents ===
false ) {
246 throw new RuntimeException( sprintf(
247 'Could not compile template `%s`: Could not find partial `%s` at %s',
254 $files[] = $filename;
256 return $fileContents;
264 throw new RuntimeException(
"Could not compile template `{$filename}`" );
267 $files = array_values( array_unique( $files ) );
270 'phpCode' => $compiled,
298 return $template( $args, $scopes );
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()