29 protected $templateDir;
39 protected $forceRecompile =
false;
46 protected $compileFlags = LightnCandy::FLAG_ERROR_EXCEPTION;
52 public function __construct( $templateDir =
null, $forceRecompile =
false ) {
53 $this->templateDir = $templateDir ?: __DIR__ .
'/templates';
54 $this->forceRecompile = $forceRecompile;
61 public function enableRecursivePartials( $enable ) {
63 $this->compileFlags = $this->compileFlags | LightnCandy::FLAG_RUNTIMEPARTIAL;
65 $this->compileFlags = $this->compileFlags & ~LightnCandy::FLAG_RUNTIMEPARTIAL;
75 protected function getTemplateFilename( $templateName ) {
80 strcspn( $templateName,
":/\\\000&<>'\"%" ) !== strlen( $templateName )
82 throw new UnexpectedValueException(
"Malformed \$templateName: $templateName" );
85 return "{$this->templateDir}/{$templateName}.mustache";
94 protected function getTemplate( $templateName ) {
95 $templateKey = $templateName .
'|' . $this->compileFlags;
98 if ( isset( $this->renderers[$templateKey] ) &&
99 is_callable( $this->renderers[$templateKey] )
101 return $this->renderers[$templateKey];
104 $filename = $this->getTemplateFilename( $templateName );
106 if ( !file_exists( $filename ) ) {
107 throw new RuntimeException(
"Could not locate template: {$filename}" );
111 $fileContents = file_get_contents( $filename );
114 $fastHash = md5( $this->compileFlags .
'|' . $fileContents );
117 $config = MediaWikiServices::getInstance()->getMainConfig();
118 $secretKey = $config->get(
'SecretKey' );
123 $key =
$cache->makeKey(
'template', $templateName, $fastHash );
124 $code = $this->forceRecompile ? null :
$cache->get( $key );
128 $keyedHash = substr(
$code, 0, 64 );
130 if ( $keyedHash !== hash_hmac(
'sha256',
$code, $secretKey ) ) {
137 $code = $this->compileForEval( $fileContents, $filename );
144 $code = $this->compileForEval( $fileContents, $filename );
147 $renderer = eval(
$code );
148 if ( !is_callable( $renderer ) ) {
149 throw new RuntimeException(
"Requested template, {$templateName}, is not callable" );
151 $this->renderers[$templateKey] = $renderer;
163 protected function compileForEval( $fileContents, $filename ) {
165 $code = $this->compile( $fileContents );
168 throw new RuntimeException(
"Could not compile template: {$filename}" );
172 if ( substr(
$code, 0, 5 ) ===
'<?php' ) {
185 protected function compile(
$code ) {
186 if ( !class_exists(
'LightnCandy' ) ) {
187 throw new RuntimeException(
'LightnCandy class not defined' );
189 return LightnCandy::compile(
192 'flags' => $this->compileFlags,
193 'basedir' => $this->templateDir,
194 'fileext' =>
'.mustache',
216 public function processTemplate( $templateName,
$args, array $scopes = [] ) {
217 $template = $this->getTemplate( $templateName );
static getLocalServerInstance( $fallback=CACHE_NONE)
Factory function for CACHE_ACCEL (referenced from DefaultSettings.php)
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping $template
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output modifiable & $code