10use LightnCandy\LightnCandy;
15use UnexpectedValueException;
25 private const CACHE_VERSION =
'2.2.0';
26 private const CACHE_TTL = BagOStuff::TTL_WEEK;
50 $this->templateDir =
$templateDir ?: __DIR__ .
'/../../resources/templates';
56 $this->compileFlags = LightnCandy::FLAG_ERROR_EXCEPTION | LightnCandy::FLAG_MUSTACHELOOKUP;
65 $this->compileFlags |= LightnCandy::FLAG_RUNTIMEPARTIAL;
67 $this->compileFlags &= ~LightnCandy::FLAG_RUNTIMEPARTIAL;
81 if ( strcspn( $templateName,
":/\\\000&<>'\"%" ) !== strlen( $templateName ) ) {
82 throw new UnexpectedValueException(
"Malformed \$templateName: $templateName" );
85 return "{$this->templateDir}/{$templateName}.mustache";
100 if ( isset( $this->renderers[$templateKey] ) &&
101 is_callable( $this->renderers[$templateKey] )
103 return $this->renderers[$templateKey];
114 $key = $this->cache->makeKey(
115 'lightncandy-compiled',
121 $compiledTemplate = $this->cache->get( $key );
125 if ( $compiledTemplate ) {
128 if ( $filesHash !== $compiledTemplate[
'filesHash'] ) {
129 $compiledTemplate =
null;
135 if ( $compiledTemplate ) {
136 $integrityHash = hash_hmac(
'sha256', $compiledTemplate[
'phpCode'], $secretKey );
138 if ( $integrityHash !== $compiledTemplate[
'integrityHash'] ) {
139 $compiledTemplate =
null;
145 if ( !$compiledTemplate ) {
146 $compiledTemplate = $this->
compile( $templateName );
148 $compiledTemplate[
'integrityHash'] = hash_hmac(
150 $compiledTemplate[
'phpCode'],
154 $this->cache->set( $key, $compiledTemplate, self::CACHE_TTL );
159 $compiledTemplate = $this->
compile( $templateName );
163 $renderer = eval( $compiledTemplate[
'phpCode'] );
164 if ( !is_callable( $renderer ) ) {
165 throw new RuntimeException(
"Compiled template `{$templateName}` is not callable" );
167 $this->renderers[$templateKey] = $renderer;
205 if ( !file_exists( $filename ) ) {
206 throw new RuntimeException(
"Could not find template `{$templateName}` at {$filename}" );
209 $files = [ $filename ];
210 $contents = file_get_contents( $filename );
211 $compiled = LightnCandy::compile(
214 'flags' => $this->compileFlags,
215 'basedir' => $this->templateDir,
216 'fileext' =>
'.mustache',
217 'partialresolver' =>
function ( $cx, $partialName ) use ( $templateName, &$files ) {
218 $filename =
"{$this->templateDir}/{$partialName}.mustache";
219 if ( !file_exists( $filename ) ) {
220 throw new RuntimeException( sprintf(
221 'Could not compile template `%s`: Could not find partial `%s` at %s',
228 $fileContents = file_get_contents( $filename );
230 if ( $fileContents ===
false ) {
231 throw new RuntimeException( sprintf(
232 'Could not compile template `%s`: Could not find partial `%s` at %s',
239 $files[] = $filename;
241 return $fileContents;
249 throw new RuntimeException(
"Could not compile template `{$filename}`" );
252 $files = array_values( array_unique( $files ) );
255 'phpCode' => $compiled,
283 return $template( $args, $scopes );
A class containing constants representing the names of configuration variables.
const SecretKey
Name constant for the SecretKey setting, for use with Config::get()
Generate hash digests of file contents to help with cache invalidation.
static getFileContentsHash( $filePaths)
Get a hash of the combined contents of one or more files, either by retrieving a previously-computed ...