3use LightnCandy\LightnCandy;
58 $this->templateDir =
$templateDir ?: __DIR__ .
'/templates';
60 wfDeprecated( __CLASS__ .
' with $forceRecompile',
'1.35' );
67 $this->compileFlags = LightnCandy::FLAG_ERROR_EXCEPTION | LightnCandy::FLAG_MUSTACHELOOKUP;
76 $this->compileFlags |= LightnCandy::FLAG_RUNTIMEPARTIAL;
78 $this->compileFlags &= ~LightnCandy::FLAG_RUNTIMEPARTIAL;
93 strcspn( $templateName,
":/\\\000&<>'\"%" ) !== strlen( $templateName )
95 throw new UnexpectedValueException(
"Malformed \$templateName: $templateName" );
98 return "{$this->templateDir}/{$templateName}.mustache";
113 if ( isset( $this->renderers[$templateKey] ) &&
114 is_callable( $this->renderers[$templateKey] )
116 return $this->renderers[$templateKey];
121 $secretKey = MediaWikiServices::hasInstance()
122 ? MediaWikiServices::getInstance()->getMainConfig()->get(
'SecretKey' )
127 $key = $this->cache->makeKey(
128 'lightncandy-compiled',
134 $compiledTemplate = $this->cache->get( $key );
138 if ( $compiledTemplate ) {
141 if ( $filesHash !== $compiledTemplate[
'filesHash'] ) {
142 $compiledTemplate =
null;
148 if ( $compiledTemplate ) {
149 $integrityHash = hash_hmac(
'sha256', $compiledTemplate[
'phpCode'], $secretKey );
151 if ( $integrityHash !== $compiledTemplate[
'integrityHash'] ) {
152 $compiledTemplate =
null;
158 if ( !$compiledTemplate ) {
159 $compiledTemplate = $this->
compile( $templateName );
161 $compiledTemplate[
'integrityHash'] = hash_hmac(
163 $compiledTemplate[
'phpCode'],
167 $this->cache->set( $key, $compiledTemplate, self::CACHE_TTL );
172 $compiledTemplate = $this->
compile( $templateName );
175 $renderer = eval( $compiledTemplate[
'phpCode'] );
176 if ( !is_callable( $renderer ) ) {
177 throw new RuntimeException(
"Compiled template `{$templateName}` is not callable" );
179 $this->renderers[$templateKey] = $renderer;
217 if ( !file_exists( $filename ) ) {
218 throw new RuntimeException(
"Could not find template `{$templateName}` at {$filename}" );
221 $files = [ $filename ];
222 $contents = file_get_contents( $filename );
223 $compiled = LightnCandy::compile(
226 'flags' => $this->compileFlags,
227 'basedir' => $this->templateDir,
228 'fileext' =>
'.mustache',
229 'partialresolver' =>
function ( $cx, $partialName ) use ( $templateName, &$files ) {
230 $filename =
"{$this->templateDir}/{$partialName}.mustache";
231 if ( !file_exists( $filename ) ) {
232 throw new RuntimeException( sprintf(
233 'Could not compile template `%s`: Could not find partial `%s` at %s',
240 $fileContents = file_get_contents( $filename );
242 if ( $fileContents ===
false ) {
243 throw new RuntimeException( sprintf(
244 'Could not compile template `%s`: Could not find partial `%s` at %s',
251 $files[] = $filename;
253 return $fileContents;
261 throw new RuntimeException(
"Could not compile template `{$filename}`" );
265 'phpCode' => $compiled,
293 return $template(
$args, $scopes );
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Class representing a cache/ephemeral data store.
A BagOStuff object with no objects in it.
static getFileContentsHash( $filePaths, $algo='md4')
Get a hash of the combined contents of one or more files, either by retrieving a previously-computed ...
processTemplate( $templateName, $args, array $scopes=[])
Returns HTML for a given template by calling the template function with the given args.
string $templateDir
The path to the Mustache templates.
getTemplate( $templateName)
Returns a given template function if found, otherwise throws an exception.
__construct( $templateDir=null, $cache=null)
int $compileFlags
Compilation flags passed to LightnCandy.
compile( $templateName)
Compile the Mustache template into PHP code using LightnCandy.
enableRecursivePartials( $enable)
Enable/disable the use of recursive partials.
getTemplateFilename( $templateName)
Constructs the location of the source Mustache template.
callable[] $renderers
Array of cached rendering functions.