ACC SHELL
<?php
/**
* This file is part of the Nette Framework (http://nette.org)
* Copyright (c) 2004 David Grudl (http://davidgrudl.com)
*/
namespace Latte;
/**
* Templating engine Latte.
*
* @author David Grudl
*/
class Engine extends Object
{
/** Content types */
const CONTENT_HTML = Compiler::CONTENT_HTML,
CONTENT_XHTML = Compiler::CONTENT_XHTML,
CONTENT_XML = Compiler::CONTENT_XML,
CONTENT_JS = Compiler::CONTENT_JS,
CONTENT_CSS = Compiler::CONTENT_CSS,
CONTENT_ICAL = Compiler::CONTENT_ICAL,
CONTENT_TEXT = Compiler::CONTENT_TEXT;
/** @var array */
public $onCompile = array();
/** @var Parser */
private $parser;
/** @var Compiler */
private $compiler;
/** @var ILoader */
private $loader;
/** @var string */
private $contentType = self::CONTENT_HTML;
/** @var string */
private $tempDirectory;
/** @var bool */
private $autoRefresh = TRUE;
/** @var array run-time filters */
private $filters = array(
NULL => array(), // dynamic
'bytes' => 'Latte\Runtime\Filters::bytes',
'capitalize' => 'Latte\Runtime\Filters::capitalize',
'datastream' => 'Latte\Runtime\Filters::dataStream',
'date' => 'Latte\Runtime\Filters::date',
'escapecss' => 'Latte\Runtime\Filters::escapeCss',
'escapehtml' => 'Latte\Runtime\Filters::escapeHtml',
'escapehtmlcomment' => 'Latte\Runtime\Filters::escapeHtmlComment',
'escapeical' => 'Latte\Runtime\Filters::escapeICal',
'escapejs' => 'Latte\Runtime\Filters::escapeJs',
'escapeurl' => 'rawurlencode',
'escapexml' => 'Latte\Runtime\Filters::escapeXML',
'firstupper' => 'Latte\Runtime\Filters::firstUpper',
'implode' => 'implode',
'indent' => 'Latte\Runtime\Filters::indent',
'lower' => 'Latte\Runtime\Filters::lower',
'nl2br' => 'Latte\Runtime\Filters::nl2br',
'number' => 'number_format',
'repeat' => 'str_repeat',
'replace' => 'Latte\Runtime\Filters::replace',
'replacere' => 'Latte\Runtime\Filters::replaceRe',
'safeurl' => 'Latte\Runtime\Filters::safeUrl',
'strip' => 'Latte\Runtime\Filters::strip',
'striptags' => 'strip_tags',
'substr' => 'Latte\Runtime\Filters::substring',
'trim' => 'Latte\Runtime\Filters::trim',
'truncate' => 'Latte\Runtime\Filters::truncate',
'upper' => 'Latte\Runtime\Filters::upper',
);
/** @var string */
private $baseTemplateClass = 'Latte\Template';
/**
* Renders template to output.
* @return void
*/
public function render($name, array $params = array())
{
$template = new $this->baseTemplateClass($params, $this->filters, $this, $name);
$this->loadCacheFile($name, $template->getParameters());
}
/**
* Renders template to string.
* @return string
*/
public function renderToString($name, array $params = array())
{
ob_start();
try {
$this->render($name, $params);
} catch (\Exception $e) {
ob_end_clean();
throw $e;
}
return ob_get_clean();
}
/**
* Compiles template to PHP code.
* @return string
*/
public function compile($name)
{
foreach ($this->onCompile ?: array() as $cb) {
call_user_func(Helpers::checkCallback($cb), $this);
}
$this->onCompile = array();
$source = $this->getLoader()->getContent($name);
try {
$tokens = $this->getParser()->setContentType($this->contentType)
->parse($source);
$code = $this->getCompiler()->setContentType($this->contentType)
->compile($tokens);
if (!preg_match('#\n|\?#', $name)) {
$code = "<?php\n// source: $name\n?>" . $code;
}
} catch (\Exception $e) {
$e = $e instanceof CompileException ? $e : new CompileException("Thrown exception '{$e->getMessage()}'", NULL, $e);
throw $e->setSource($source, $this->getCompiler()->getLine(), $name);
}
$code = Helpers::optimizePhp($code);
return $code;
}
/**
* @return void
*/
private function loadCacheFile($name, $params)
{
if (!$this->tempDirectory) {
return call_user_func(function() {
foreach (func_get_arg(1) as $__k => $__v) {
$$__k = $__v;
}
unset($__k, $__v);
eval('?>' . func_get_arg(0));
}, $this->compile($name), $params);
}
$file = $this->getCacheFile($name);
$handle = fopen($file, 'c+');
if (!$handle) {
throw new \RuntimeException("Unable to open or create file '$file'.");
}
flock($handle, LOCK_SH);
$stat = fstat($handle);
if (!$stat['size'] || ($this->autoRefresh && $this->getLoader()->isExpired($name, $stat['mtime']))) {
ftruncate($handle, 0);
flock($handle, LOCK_EX);
$stat = fstat($handle);
if (!$stat['size']) {
$code = $this->compile($name);
if (fwrite($handle, $code, strlen($code)) !== strlen($code)) {
ftruncate($handle, 0);
throw new \RuntimeException("Unable to write file '$file'.");
}
}
flock($handle, LOCK_SH); // holds the lock
}
call_user_func(function() {
foreach (func_get_arg(1) as $__k => $__v) {
$$__k = $__v;
}
unset($__k, $__v);
include func_get_arg(0);
}, $file, $params);
}
/**
* @return string
*/
public function getCacheFile($name)
{
if (!$this->tempDirectory) {
throw new \RuntimeException('Set path to temporary directory using setTempDirectory().');
} elseif (!is_dir($this->tempDirectory)) {
@mkdir($this->tempDirectory); // High concurrency
if (!is_dir($this->tempDirectory)) {
throw new \RuntimeException("Temporary directory cannot be created. Check access rights");
}
}
$file = md5($name);
if (preg_match('#\b\w.{10,50}$#', $name, $m)) {
$file = trim(preg_replace('#\W+#', '-', $m[0]), '-') . '-' . $file;
}
return $this->tempDirectory . '/' . $file . '.php';
}
/**
* Registers run-time filter.
* @param string|NULL
* @param callable
* @return self
*/
public function addFilter($name, $callback)
{
if ($name == NULL) { // intentionally ==
array_unshift($this->filters[NULL], $callback);
} else {
$this->filters[strtolower($name)] = $callback;
}
return $this;
}
/**
* Returns all run-time filters.
* @return callable[]
*/
public function getFilters()
{
return $this->filters;
}
/**
* Call a run-time filter.
* @param string filter name
* @param array arguments
* @return mixed
*/
public function invokeFilter($name, array $args)
{
$lname = strtolower($name);
if (!isset($this->filters[$lname])) {
$args2 = $args;
array_unshift($args2, $lname);
foreach ($this->filters[NULL] as $filter) {
$res = call_user_func_array(Helpers::checkCallback($filter), $args2);
if ($res !== NULL) {
return $res;
} elseif (isset($this->filters[$lname])) {
return call_user_func_array(Helpers::checkCallback($this->filters[$lname]), $args);
}
}
throw new \LogicException("Filter '$name' is not defined.");
}
return call_user_func_array(Helpers::checkCallback($this->filters[$lname]), $args);
}
/**
* Adds new macro.
* @return self
*/
public function addMacro($name, IMacro $macro)
{
$this->getCompiler()->addMacro($name, $macro);
return $this;
}
/**
* @return self
*/
public function setContentType($type)
{
$this->contentType = $type;
return $this;
}
/**
* Sets path to temporary directory.
* @return self
*/
public function setTempDirectory($path)
{
$this->tempDirectory = $path;
return $this;
}
/**
* Sets auto-refresh mode.
* @return self
*/
public function setAutoRefresh($on = TRUE)
{
$this->autoRefresh = (bool) $on;
return $this;
}
/**
* @return Parser
*/
public function getParser()
{
if (!$this->parser) {
$this->parser = new Parser;
}
return $this->parser;
}
/**
* @return Compiler
*/
public function getCompiler()
{
if (!$this->compiler) {
$this->compiler = new Compiler;
Macros\CoreMacros::install($this->compiler);
Macros\BlockMacros::install($this->compiler);
}
return $this->compiler;
}
/**
* @return self
*/
public function setLoader(ILoader $loader)
{
$this->loader = $loader;
return $this;
}
/**
* @return ILoader
*/
public function getLoader()
{
if (!$this->loader) {
$this->loader = new Loaders\FileLoader;
}
return $this->loader;
}
}
ACC SHELL 2018