format($string, $minFractionDigits, $maxFractionDigits);
}
function piwik_fix_lbrace($string)
{
return Common::fixLbrace($string);
}
function piwik_escape_filter(Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false) {
$string = twig_escape_filter($env, $string, $strategy, $charset, $autoescape);
switch ($strategy) {
case 'html':
case 'html_attr':
return piwik_fix_lbrace($string);
case 'url':
$encoded = rawurlencode('{');
return str_replace('{{', $encoded . $encoded, $string);
case 'css':
case 'js':
default:
return $string;
}
}
function piwik_format_money($amount, $idSite)
{
$currencySymbol = Site::getCurrencySymbolFor($idSite);
$numberFormatter = NumberFormatter::getInstance();
return $numberFormatter->formatCurrency($amount, $currencySymbol, GoalManager::REVENUE_PRECISION);
}
class PiwikTwigFilterExtension extends \Twig\Extension\AbstractExtension
{
public function getFilters()
{
return array(
new TwigFilter('e', '\Piwik\piwik_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
new TwigFilter('escape', '\Piwik\piwik_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe'))
);
}
/**
* Returns the name of the extension.
*
* @return string The extension name
*/
public function getName()
{
return 'escaper2';
}
}
/**
* Twig class
*
*/
class Twig
{
const SPARKLINE_TEMPLATE = '
';
/**
* @var Environment
*/
private $twig;
private $formatter;
public function __construct()
{
$loader = $this->getDefaultThemeLoader();
$this->addPluginNamespaces($loader);
//get current theme
$manager = Plugin\Manager::getInstance();
$theme = $manager->getThemeEnabled();
$loaders = array();
$this->formatter = new Formatter();
//create loader for custom theme to overwrite twig templates
if ($theme && $theme->getPluginName() != \Piwik\Plugin\Manager::DEFAULT_THEME) {
$customLoader = $this->getCustomThemeLoader($theme);
if ($customLoader) {
//make it possible to overwrite plugin templates
$this->addCustomPluginNamespaces($customLoader, $theme->getPluginName());
$loaders[] = $customLoader;
}
}
$loaders[] = $loader;
$chainLoader = new ChainLoader($loaders);
// Create new Twig Environment and set cache dir
$cache = StaticContainer::get('twig.cache');
$this->twig = new Environment($chainLoader,
array(
'debug' => true, // to use {{ dump(var) }} in twig templates
'strict_variables' => true, // throw an exception if variables are invalid
'cache' => $cache,
)
);
$this->twig->addExtension(new DebugExtension());
$this->addFilter_translate();
$this->addFilter_urlRewriteWithParameters();
$this->addFilter_sumTime();
$this->addFilter_money();
$this->addFilter_truncate();
$this->addFilter_notification();
$this->addFilter_percent();
$this->addFilter_percentage();
$this->addFilter_percentEvolution();
$this->addFilter_prettyDate();
$this->addFilter_safeDecodeRaw();
$this->addFilter_number();
$this->addFilter_anonymiseSystemInfo();
$this->addFilter_nonce();
$this->addFilter_md5();
$this->addFilter_onlyDomain();
$this->addFilter_safelink();
$this->addFilter_implode();
$this->twig->addFilter(new TwigFilter('ucwords', 'ucwords'));
$this->twig->addFilter(new TwigFilter('lcfirst', 'lcfirst'));
$this->twig->addFilter(new TwigFilter('ucfirst', 'ucfirst'));
$this->twig->addFilter(new TwigFilter('preg_replace', function ($subject, $pattern, $replacement) {
return preg_replace($pattern, $replacement, $subject);
}));
$this->addFunction_includeAssets();
$this->addFunction_linkTo();
$this->addFunction_sparkline();
$this->addFunction_postEvent();
$this->addFunction_isPluginLoaded();
$this->addFunction_getJavascriptTranslations();
$this->twig->addTokenParser(new RenderTokenParser());
$this->addTest_false();
$this->addTest_true();
$this->addTest_emptyString();
$this->addTest_isNumeric();
$this->twig->addExtension(new PiwikTwigFilterExtension());
}
private function addTest_false()
{
$test = new TwigTest(
'false',
function ($value) {
return false === $value;
}
);
$this->twig->addTest($test);
}
private function addTest_true()
{
$test = new TwigTest(
'true',
function ($value) {
return true === $value;
}
);
$this->twig->addTest($test);
}
private function addTest_emptyString()
{
$test = new TwigTest(
'emptyString',
function ($value) {
return '' === $value;
}
);
$this->twig->addTest($test);
}
protected function addFunction_getJavascriptTranslations()
{
$getJavascriptTranslations = new TwigFunction(
'getJavascriptTranslations',
array(StaticContainer::get('Piwik\Translation\Translator'), 'getJavascriptTranslations')
);
$this->twig->addFunction($getJavascriptTranslations);
}
protected function addFunction_isPluginLoaded()
{
$isPluginLoadedFunction = new TwigFunction('isPluginLoaded', function ($pluginName) {
return \Piwik\Plugin\Manager::getInstance()->isPluginLoaded($pluginName);
});
$this->twig->addFunction($isPluginLoadedFunction);
}
protected function addFunction_includeAssets()
{
$includeAssetsFunction = new TwigFunction('includeAssets', function ($params) {
if (!isset($params['type'])) {
throw new Exception("The function includeAssets needs a 'type' parameter.");
}
$assetType = strtolower($params['type']);
switch ($assetType) {
case 'css':
return AssetManager::getInstance()->getCssInclusionDirective();
case 'js':
return AssetManager::getInstance()->getJsInclusionDirective();
default:
throw new Exception("The twig function includeAssets 'type' parameter needs to be either 'css' or 'js'.");
}
});
$this->twig->addFunction($includeAssetsFunction);
}
protected function addFunction_postEvent()
{
$postEventFunction = new TwigFunction('postEvent', function ($eventName) {
// get parameters to twig function
$params = func_get_args();
// remove the first value (event name)
array_shift($params);
// make the first value the string that will get output in the template
// plugins can modify this string
$str = '';
$params = array_merge(array( &$str ), $params);
Piwik::postEvent($eventName, $params);
return $str;
}, array('is_safe' => array('html')));
$this->twig->addFunction($postEventFunction);
}
protected function addFunction_sparkline()
{
$sparklineFunction = new TwigFunction('sparkline', function ($src) {
$width = Sparkline::DEFAULT_WIDTH;
$height = Sparkline::DEFAULT_HEIGHT;
return sprintf(Twig::SPARKLINE_TEMPLATE, $src, $width, $height);
}, array('is_safe' => array('html')));
$this->twig->addFunction($sparklineFunction);
}
protected function addFunction_linkTo()
{
$urlFunction = new TwigFunction('linkTo', function ($params) {
return 'index.php' . Url::getCurrentQueryStringWithParametersModified($params);
});
$this->twig->addFunction($urlFunction);
}
/**
* @return FilesystemLoader
*/
private function getDefaultThemeLoader()
{
$themeDir = Manager::getPluginDirectory(\Piwik\Plugin\Manager::DEFAULT_THEME) . '/templates/';
$themeLoader = new FilesystemLoader(array($themeDir), PIWIK_DOCUMENT_ROOT.DIRECTORY_SEPARATOR);
return $themeLoader;
}
/**
* create template loader for a custom theme
* @param \Piwik\Plugin $theme
* @return FilesystemLoader|bool
*/
protected function getCustomThemeLoader(Plugin $theme)
{
$pluginsDir = Manager::getPluginDirectory($theme->getPluginName());
$themeDir = $pluginsDir . '/templates/';
if (!file_exists($themeDir)) {
return false;
}
$themeLoader = new FilesystemLoader(array($themeDir), PIWIK_DOCUMENT_ROOT.DIRECTORY_SEPARATOR);
return $themeLoader;
}
public function getTwigEnvironment()
{
return $this->twig;
}
protected function addFilter_notification()
{
$twigEnv = $this->getTwigEnvironment();
$notificationFunction = new TwigFilter('notification', function ($message, $options) use ($twigEnv) {
$template = '