Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Winkler <git@lw1.at>2020-06-04 14:47:54 +0300
committerGitHub <noreply@github.com>2020-06-04 14:47:54 +0300
commita35070be5146539999fdd02d5323f466d314192b (patch)
treea7f280e0f371f5b5370547b67ae63d142e341126
parent2851045e2ffd0f71fa1a56b2b6cab35cc7b1b4ab (diff)
Twig 3 upgrade (#15573)
* proof of concept of Twig 3 upgrade * some for if template fixes * potentially fix RenderTokenParser * comment out RenderTokenParser * clearCompiledTemplates() using unlinkRecursive() * macro imported in block and used in subblock is not valid twigphp/Twig#3090 * more template fixes * remove non existing clearTemplateCache() * add missing parameter to unlinkRecursive * Use custom MethodCallExpression to fix RenderTokenParser * increase minimum php version to 7.2.5 * submodule update * fix twig loop filter * updates expected UI files * fix twig loop filter * fix twig loop filter * fix neutral evolution check * fix macro usage * convert some conditions to filters * fix macro include * remove debug code as default logging is good enough * submodule updates Co-authored-by: sgiehl <stefan@matomo.org>
-rw-r--r--composer.json8
-rw-r--r--composer.lock89
-rw-r--r--core/FrontController.php2
-rw-r--r--core/Twig.php103
-rw-r--r--core/View.php29
-rw-r--r--core/View/MethodCallExpression.php48
-rw-r--r--core/View/RenderTokenParser.php29
-rw-r--r--core/testMinimumPhpVersion.php2
-rw-r--r--plugins/CoreHome/templates/_dataTableActions.twig4
-rw-r--r--plugins/CoreHome/templates/_dataTableCell.twig4
-rw-r--r--plugins/CoreHome/templates/_topBar.twig4
-rw-r--r--plugins/CorePluginsAdmin/templates/macros.twig6
-rw-r--r--plugins/CorePluginsAdmin/templates/safemode.twig10
-rw-r--r--plugins/CoreVisualizations/templates/_dataTableViz_tagCloud.twig6
-rw-r--r--plugins/CoreVisualizations/templates/macros.twig2
m---------plugins/CustomAlerts0
m---------plugins/CustomDimensions0
-rw-r--r--plugins/Diagnostics/tests/UI/expected-screenshots/Diagnostics_page.png4
-rw-r--r--plugins/Insights/templates/overviewWidget.twig3
-rw-r--r--plugins/Installation/tests/UI/expected-screenshots/Installation_system_check.png4
-rw-r--r--plugins/Live/templates/index.twig6
-rw-r--r--plugins/Marketplace/templates/overview.twig1
-rw-r--r--plugins/Marketplace/templates/plugin-details.twig10
-rw-r--r--plugins/Marketplace/templates/plugin-list.twig4
-rw-r--r--plugins/UserCountry/templates/adminIndex.twig2
-rw-r--r--tests/PHPUnit/Integration/ReleaseCheckListTest.php2
-rw-r--r--tests/resources/trigger-fatal-exception.php2
27 files changed, 233 insertions, 151 deletions
diff --git a/composer.json b/composer.json
index b66bec9c80..cec2176dfc 100644
--- a/composer.json
+++ b/composer.json
@@ -20,13 +20,13 @@
},
"config":{
"platform": {
- "php": "7.2.0"
+ "php": "7.2.5"
},
"prepend-autoloader": false,
"sort-packages": true
},
"require": {
- "php": ">=7.2.0",
+ "php": ">=7.2.5",
"composer/semver": "~1.3.0",
"davaxi/sparkline": "~1.2",
"geoip2/geoip2": "^2.8",
@@ -37,7 +37,7 @@
"matomo/ini": "~2.0",
"matomo/matomo-php-tracker": "dev-4.x-dev",
"matomo/network": "~2.0",
- "matomo/referrer-spam-blacklist": "~3.0",
+ "matomo/referrer-spam-blacklist": "^3.11",
"matomo/searchengine-and-social-list": "~3.0",
"monolog/monolog": "~1.11",
"mustangostang/spyc": "~0.6.0",
@@ -51,7 +51,7 @@
"symfony/monolog-bridge": "~2.6.0",
"szymach/c-pchart": "^2.0",
"tecnickcom/tcpdf": "~6.0",
- "twig/twig": "~1.0"
+ "twig/twig": "^3.0"
},
"require-dev": {
"lox/xhprof": "dev-master",
diff --git a/composer.lock b/composer.lock
index a7776941ef..db9c0c696f 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "a03445c07f2354bce4f64a147a55cdb3",
+ "content-hash": "af2d8862dd5d4cf2d4a8570cb4e5f307",
"packages": [
{
"name": "composer/ca-bundle",
@@ -1696,6 +1696,65 @@
"time": "2019-11-27T13:56:44+00:00"
},
{
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.14.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "34094cfa9abe1f0f14f48f490772db7a775559f2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/34094cfa9abe1f0f14f48f490772db7a775559f2",
+ "reference": "34094cfa9abe1f0f14f48f490772db7a775559f2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.14-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "time": "2020-01-13T11:15:53+00:00"
+ },
+ {
"name": "szymach/c-pchart",
"version": "v2.0.12",
"source": {
@@ -1823,37 +1882,34 @@
},
{
"name": "twig/twig",
- "version": "v1.42.4",
+ "version": "v3.0.3",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
- "reference": "e587180584c3d2d6cb864a0454e777bb6dcb6152"
+ "reference": "3b88ccd180a6b61ebb517aea3b1a8906762a1dc2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/twigphp/Twig/zipball/e587180584c3d2d6cb864a0454e777bb6dcb6152",
- "reference": "e587180584c3d2d6cb864a0454e777bb6dcb6152",
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/3b88ccd180a6b61ebb517aea3b1a8906762a1dc2",
+ "reference": "3b88ccd180a6b61ebb517aea3b1a8906762a1dc2",
"shasum": ""
},
"require": {
- "php": ">=5.5.0",
- "symfony/polyfill-ctype": "^1.8"
+ "php": "^7.2.5",
+ "symfony/polyfill-ctype": "^1.8",
+ "symfony/polyfill-mbstring": "^1.3"
},
"require-dev": {
"psr/container": "^1.0",
- "symfony/debug": "^3.4|^4.2",
- "symfony/phpunit-bridge": "^4.4@dev|^5.0"
+ "symfony/phpunit-bridge": "^4.4|^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.42-dev"
+ "dev-master": "3.0-dev"
}
},
"autoload": {
- "psr-0": {
- "Twig_": "lib/"
- },
"psr-4": {
"Twig\\": "src/"
}
@@ -1871,7 +1927,6 @@
},
{
"name": "Twig Team",
- "homepage": "https://twig.symfony.com/contributors",
"role": "Contributors"
},
{
@@ -1885,7 +1940,7 @@
"keywords": [
"templating"
],
- "time": "2019-11-11T16:49:32+00:00"
+ "time": "2020-02-11T15:33:47+00:00"
}
],
"packages-dev": [
@@ -3508,11 +3563,11 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
- "php": ">=7.2.0"
+ "php": ">=7.2.5"
},
"platform-dev": [],
"platform-overrides": {
- "php": "7.2.0"
+ "php": "7.2.5"
},
"plugin-api-version": "1.1.0"
}
diff --git a/core/FrontController.php b/core/FrontController.php
index 58659da1d1..00b032833e 100644
--- a/core/FrontController.php
+++ b/core/FrontController.php
@@ -176,7 +176,7 @@ class FrontController extends Singleton
* @param \Piwik\NoAccessException $exception The exception that was caught.
*/
Piwik::postEvent('User.isNotAuthorized', array($exception), $pending = true);
- } catch (\Twig_Error_Runtime $e) {
+ } catch (\Twig\Error\RuntimeError $e) {
echo $this->generateSafeModeOutputFromException($e);
exit;
} catch(StylesheetLessCompileException $e) {
diff --git a/core/Twig.php b/core/Twig.php
index 78dec0b19b..1ff38003ab 100644
--- a/core/Twig.php
+++ b/core/Twig.php
@@ -16,13 +16,13 @@ use Piwik\Plugin\Manager;
use Piwik\Tracker\GoalManager;
use Piwik\View\RenderTokenParser;
use Piwik\Visualization\Sparkline;
-use Twig_Environment;
-use Twig_Extension_Debug;
-use Twig_Loader_Chain;
-use Twig_Loader_Filesystem;
-use Twig_SimpleFilter;
-use Twig_SimpleFunction;
-use Twig_SimpleTest;
+use Twig\Environment;
+use Twig\Extension\DebugExtension;
+use Twig\Loader\ChainLoader;
+use Twig\Loader\FilesystemLoader;
+use Twig\TwigFilter;
+use Twig\TwigFunction;
+use Twig\TwigTest;
function piwik_filter_truncate($string, $size)
{
@@ -64,7 +64,7 @@ function piwik_fix_lbrace($string)
return $string;
}
-function piwik_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false) {
+function piwik_escape_filter(Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false) {
$string = twig_escape_filter($env, $string, $strategy, $charset, $autoescape);
@@ -89,13 +89,13 @@ function piwik_format_money($amount, $idSite)
return $numberFormatter->formatCurrency($amount, $currencySymbol, GoalManager::REVENUE_PRECISION);
}
-class PiwikTwigFilterExtension extends \Twig_Extension
+class PiwikTwigFilterExtension extends \Twig\Extension\AbstractExtension
{
public function getFilters()
{
return array(
- new Twig_SimpleFilter('e', '\Piwik\piwik_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
- new Twig_SimpleFilter('escape', '\Piwik\piwik_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe'))
+ 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'))
);
}
@@ -120,7 +120,7 @@ class Twig
<script type="text/javascript">$(function() { piwik.initSparklines(); });</script>';
/**
- * @var Twig_Environment
+ * @var Environment
*/
private $twig;
@@ -150,20 +150,19 @@ class Twig
$loaders[] = $loader;
- $chainLoader = new Twig_Loader_Chain($loaders);
+ $chainLoader = new ChainLoader($loaders);
// Create new Twig Environment and set cache dir
$templatesCompiledPath = StaticContainer::get('path.tmp') . '/templates_c';
- $this->twig = new Twig_Environment($chainLoader,
+ $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' => $templatesCompiledPath,
)
);
- $this->twig->addExtension(new Twig_Extension_Debug());
- $this->twig->clearTemplateCache();
+ $this->twig->addExtension(new DebugExtension());
$this->addFilter_translate();
$this->addFilter_urlRewriteWithParameters();
@@ -181,10 +180,10 @@ class Twig
$this->addFilter_md5();
$this->addFilter_onlyDomain();
$this->addFilter_safelink();
- $this->twig->addFilter(new Twig_SimpleFilter('implode', 'implode'));
- $this->twig->addFilter(new Twig_SimpleFilter('ucwords', 'ucwords'));
- $this->twig->addFilter(new Twig_SimpleFilter('lcfirst', 'lcfirst'));
- $this->twig->addFilter(new Twig_SimpleFilter('ucfirst', 'ucfirst'));
+ $this->twig->addFilter(new TwigFilter('implode', 'implode'));
+ $this->twig->addFilter(new TwigFilter('ucwords', 'ucwords'));
+ $this->twig->addFilter(new TwigFilter('lcfirst', 'lcfirst'));
+ $this->twig->addFilter(new TwigFilter('ucfirst', 'ucfirst'));
$this->addFunction_includeAssets();
$this->addFunction_linkTo();
@@ -205,7 +204,7 @@ class Twig
private function addTest_false()
{
- $test = new Twig_SimpleTest(
+ $test = new TwigTest(
'false',
function ($value) {
return false === $value;
@@ -216,7 +215,7 @@ class Twig
private function addTest_true()
{
- $test = new Twig_SimpleTest(
+ $test = new TwigTest(
'true',
function ($value) {
return true === $value;
@@ -227,7 +226,7 @@ class Twig
private function addTest_emptyString()
{
- $test = new Twig_SimpleTest(
+ $test = new TwigTest(
'emptyString',
function ($value) {
return '' === $value;
@@ -238,7 +237,7 @@ class Twig
protected function addFunction_getJavascriptTranslations()
{
- $getJavascriptTranslations = new Twig_SimpleFunction(
+ $getJavascriptTranslations = new TwigFunction(
'getJavascriptTranslations',
array(StaticContainer::get('Piwik\Translation\Translator'), 'getJavascriptTranslations')
);
@@ -247,7 +246,7 @@ class Twig
protected function addFunction_isPluginLoaded()
{
- $isPluginLoadedFunction = new Twig_SimpleFunction('isPluginLoaded', function ($pluginName) {
+ $isPluginLoadedFunction = new TwigFunction('isPluginLoaded', function ($pluginName) {
return \Piwik\Plugin\Manager::getInstance()->isPluginLoaded($pluginName);
});
$this->twig->addFunction($isPluginLoadedFunction);
@@ -255,7 +254,7 @@ class Twig
protected function addFunction_includeAssets()
{
- $includeAssetsFunction = new Twig_SimpleFunction('includeAssets', function ($params) {
+ $includeAssetsFunction = new TwigFunction('includeAssets', function ($params) {
if (!isset($params['type'])) {
throw new Exception("The function includeAssets needs a 'type' parameter.");
}
@@ -275,7 +274,7 @@ class Twig
protected function addFunction_postEvent()
{
- $postEventFunction = new Twig_SimpleFunction('postEvent', function ($eventName) {
+ $postEventFunction = new TwigFunction('postEvent', function ($eventName) {
// get parameters to twig function
$params = func_get_args();
// remove the first value (event name)
@@ -294,7 +293,7 @@ class Twig
protected function addFunction_sparkline()
{
- $sparklineFunction = new Twig_SimpleFunction('sparkline', function ($src) {
+ $sparklineFunction = new TwigFunction('sparkline', function ($src) {
$width = Sparkline::DEFAULT_WIDTH;
$height = Sparkline::DEFAULT_HEIGHT;
return sprintf(Twig::SPARKLINE_TEMPLATE, $src, $width, $height);
@@ -304,19 +303,19 @@ class Twig
protected function addFunction_linkTo()
{
- $urlFunction = new Twig_SimpleFunction('linkTo', function ($params) {
+ $urlFunction = new TwigFunction('linkTo', function ($params) {
return 'index.php' . Url::getCurrentQueryStringWithParametersModified($params);
});
$this->twig->addFunction($urlFunction);
}
/**
- * @return Twig_Loader_Filesystem
+ * @return FilesystemLoader
*/
private function getDefaultThemeLoader()
{
$themeDir = Manager::getPluginDirectory(\Piwik\Plugin\Manager::DEFAULT_THEME) . '/templates/';
- $themeLoader = new Twig_Loader_Filesystem(array($themeDir), PIWIK_DOCUMENT_ROOT.DIRECTORY_SEPARATOR);
+ $themeLoader = new FilesystemLoader(array($themeDir), PIWIK_DOCUMENT_ROOT.DIRECTORY_SEPARATOR);
return $themeLoader;
}
@@ -324,7 +323,7 @@ class Twig
/**
* create template loader for a custom theme
* @param \Piwik\Plugin $theme
- * @return \Twig_Loader_Filesystem
+ * @return FilesystemLoader|bool
*/
protected function getCustomThemeLoader(Plugin $theme)
{
@@ -334,7 +333,7 @@ class Twig
if (!file_exists($themeDir)) {
return false;
}
- $themeLoader = new Twig_Loader_Filesystem(array($themeDir), PIWIK_DOCUMENT_ROOT.DIRECTORY_SEPARATOR);
+ $themeLoader = new FilesystemLoader(array($themeDir), PIWIK_DOCUMENT_ROOT.DIRECTORY_SEPARATOR);
return $themeLoader;
}
@@ -347,7 +346,7 @@ class Twig
protected function addFilter_notification()
{
$twigEnv = $this->getTwigEnvironment();
- $notificationFunction = new Twig_SimpleFilter('notification', function ($message, $options) use ($twigEnv) {
+ $notificationFunction = new TwigFilter('notification', function ($message, $options) use ($twigEnv) {
$template = '<div style="display:none" data-role="notification" ';
@@ -375,7 +374,7 @@ class Twig
protected function addFilter_safeDecodeRaw()
{
- $rawSafeDecoded = new Twig_SimpleFilter('rawSafeDecoded', function ($string) {
+ $rawSafeDecoded = new TwigFilter('rawSafeDecoded', function ($string) {
$string = str_replace('+', '%2B', $string);
$string = str_replace('&nbsp;', html_entity_decode('&nbsp;', ENT_COMPAT | ENT_HTML401, 'UTF-8'), $string);
@@ -389,7 +388,7 @@ class Twig
protected function addFilter_prettyDate()
{
- $prettyDate = new Twig_SimpleFilter('prettyDate', function ($dateString, $period) {
+ $prettyDate = new TwigFilter('prettyDate', function ($dateString, $period) {
return Period\Factory::build($period, $dateString)->getLocalizedShortString();
});
$this->twig->addFilter($prettyDate);
@@ -397,7 +396,7 @@ class Twig
protected function addFilter_percentage()
{
- $percentage = new Twig_SimpleFilter('percentage', function ($string, $totalValue, $precision = 1) {
+ $percentage = new TwigFilter('percentage', function ($string, $totalValue, $precision = 1) {
$formatter = NumberFormatter::getInstance();
return $formatter->formatPercent(Piwik::getPercentageSafe($string, $totalValue, $precision), $precision);
});
@@ -406,7 +405,7 @@ class Twig
protected function addFilter_percent()
{
- $percentage = new Twig_SimpleFilter('percent', function ($string, $precision = 1) {
+ $percentage = new TwigFilter('percent', function ($string, $precision = 1) {
$formatter = NumberFormatter::getInstance();
return $formatter->formatPercent($string, $precision);
});
@@ -415,7 +414,7 @@ class Twig
protected function addFilter_percentEvolution()
{
- $percentage = new Twig_SimpleFilter('percentEvolution', function ($string) {
+ $percentage = new TwigFilter('percentEvolution', function ($string) {
$formatter = NumberFormatter::getInstance();
return $formatter->formatPercentEvolution($string);
});
@@ -429,7 +428,7 @@ class Twig
protected function addFilter_number()
{
- $formatter = new Twig_SimpleFilter('number', function ($string, $minFractionDigits = 0, $maxFractionDigits = 0) {
+ $formatter = new TwigFilter('number', function ($string, $minFractionDigits = 0, $maxFractionDigits = 0) {
return piwik_format_number($string, $minFractionDigits, $maxFractionDigits);
});
$this->twig->addFilter($formatter);
@@ -437,13 +436,13 @@ class Twig
protected function addFilter_nonce()
{
- $nonce = new Twig_SimpleFilter('nonce', array('Piwik\\Nonce', 'getNonce'));
+ $nonce = new TwigFilter('nonce', array('Piwik\\Nonce', 'getNonce'));
$this->twig->addFilter($nonce);
}
private function addFilter_md5()
{
- $md5 = new \Twig_SimpleFilter('md5', function ($value) {
+ $md5 = new TwigFilter('md5', function ($value) {
return md5($value);
});
$this->twig->addFilter($md5);
@@ -451,7 +450,7 @@ class Twig
private function addFilter_onlyDomain()
{
- $domainOnly = new \Twig_SimpleFilter('domainOnly', function ($url) {
+ $domainOnly = new TwigFilter('domainOnly', function ($url) {
$parsed = parse_url($url);
return $parsed['scheme'] . '://' . $parsed['host'];
});
@@ -460,7 +459,7 @@ class Twig
protected function addFilter_truncate()
{
- $truncateFilter = new Twig_SimpleFilter('truncate', function ($string, $size) {
+ $truncateFilter = new TwigFilter('truncate', function ($string, $size) {
return piwik_filter_truncate($string, $size);
});
$this->twig->addFilter($truncateFilter);
@@ -468,7 +467,7 @@ class Twig
protected function addFilter_money()
{
- $moneyFilter = new Twig_SimpleFilter('money', function ($amount) {
+ $moneyFilter = new TwigFilter('money', function ($amount) {
if (func_num_args() != 2) {
throw new Exception('the money modifier expects one parameter: the idSite.');
}
@@ -482,7 +481,7 @@ class Twig
protected function addFilter_sumTime()
{
$formatter = $this->formatter;
- $sumtimeFilter = new Twig_SimpleFilter('sumtime', function ($numberOfSeconds) use ($formatter) {
+ $sumtimeFilter = new TwigFilter('sumtime', function ($numberOfSeconds) use ($formatter) {
return $formatter->getPrettyTimeFromSeconds($numberOfSeconds, true);
});
$this->twig->addFilter($sumtimeFilter);
@@ -490,7 +489,7 @@ class Twig
protected function addFilter_urlRewriteWithParameters()
{
- $urlRewriteFilter = new Twig_SimpleFilter('urlRewriteWithParameters', function ($parameters) {
+ $urlRewriteFilter = new TwigFilter('urlRewriteWithParameters', function ($parameters) {
$parameters['updated'] = null;
$url = Url::getCurrentQueryStringWithParametersModified($parameters);
return $url;
@@ -500,7 +499,7 @@ class Twig
protected function addFilter_translate()
{
- $translateFilter = new Twig_SimpleFilter('translate', function ($stringToken) {
+ $translateFilter = new TwigFilter('translate', function ($stringToken) {
if (func_num_args() <= 1) {
$aValues = array();
} else {
@@ -518,7 +517,7 @@ class Twig
$this->twig->addFilter($translateFilter);
}
- private function addPluginNamespaces(Twig_Loader_Filesystem $loader)
+ private function addPluginNamespaces(FilesystemLoader $loader)
{
$pluginManager = \Piwik\Plugin\Manager::getInstance();
$plugins = $pluginManager->getAllPluginsNames();
@@ -537,7 +536,7 @@ class Twig
* Plugin-Templates can be overwritten by putting identically named templates in plugins/[theme]/templates/plugins/[plugin]/
*
*/
- private function addCustomPluginNamespaces(Twig_Loader_Filesystem $loader, $pluginName)
+ private function addCustomPluginNamespaces(FilesystemLoader $loader, $pluginName)
{
$pluginManager = \Piwik\Plugin\Manager::getInstance();
$plugins = $pluginManager->getAllPluginsNames();
@@ -568,7 +567,7 @@ class Twig
private function addFilter_safelink()
{
- $safelink = new Twig_SimpleFilter('safelink', function ($url) {
+ $safelink = new TwigFilter('safelink', function ($url) {
if (!UrlHelper::isLookLikeSafeUrl($url)) {
return '';
}
@@ -579,7 +578,7 @@ class Twig
private function addTest_isNumeric()
{
- $test = new Twig_SimpleTest(
+ $test = new TwigTest(
'numeric',
function ($value) {
return is_numeric($value);
diff --git a/core/View.php b/core/View.php
index b4f9bcd453..707030b2c3 100644
--- a/core/View.php
+++ b/core/View.php
@@ -12,7 +12,8 @@ use Exception;
use Piwik\AssetManager\UIAssetCacheBuster;
use Piwik\Container\StaticContainer;
use Piwik\View\ViewInterface;
-use Twig_Environment;
+use Twig\Environment;
+use Twig\Error\Error;
/**
* Transition for pre-Piwik 0.4.4
@@ -111,7 +112,7 @@ class View implements ViewInterface
/**
* Instance
- * @var Twig_Environment
+ * @var Environment
*/
private $twig;
protected $templateVars = array();
@@ -305,7 +306,7 @@ class View implements ViewInterface
/**
* @internal
* @ignore
- * @return Twig_Environment
+ * @return Environment
*/
public function getTwig()
{
@@ -314,15 +315,7 @@ class View implements ViewInterface
protected function renderTwigTemplate()
{
- try {
- $output = $this->twig->render($this->getTemplateFile(), $this->getTemplateVars());
- } catch (Exception $ex) {
- // twig does not rethrow exceptions, it wraps them so we log the cause if we can find it
- $cause = $ex->getPrevious();
- Log::debug($cause === null ? $ex : $cause);
-
- throw $ex;
- }
+ $output = $this->twig->render($this->getTemplateFile(), $this->getTemplateVars());
if ($this->enableCacheBuster) {
$output = $this->applyFilter_cacheBuster($output);
@@ -440,16 +433,8 @@ class View implements ViewInterface
*/
public static function clearCompiledTemplates()
{
- $twig = StaticContainer::get(Twig::class);
- $environment = $twig->getTwigEnvironment();
- $environment->clearTemplateCache();
-
- $cacheDirectory = $environment->getCache();
- if (!empty($cacheDirectory)
- && is_dir($cacheDirectory)
- ) {
- $environment->clearCacheFiles();
- }
+ $templatesCompiledPath = StaticContainer::get('path.tmp') . '/templates_c';
+ Filesystem::unlinkRecursive($templatesCompiledPath, false);
}
/**
diff --git a/core/View/MethodCallExpression.php b/core/View/MethodCallExpression.php
new file mode 100644
index 0000000000..111d4e7a5a
--- /dev/null
+++ b/core/View/MethodCallExpression.php
@@ -0,0 +1,48 @@
+<?php
+/*
+ * This file is a modified file from Twig 1.x.
+ *
+ * (c) Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with it's source code.
+ */
+
+namespace Piwik\View;
+
+use Twig\Compiler;
+use Twig\Node\Expression\AbstractExpression;
+use Twig\Node\Expression\ArrayExpression;
+use Twig\Node\Expression\NameExpression;
+
+class MethodCallExpression extends AbstractExpression
+{
+ public function __construct(AbstractExpression $node, $method, ArrayExpression $arguments, $lineno)
+ {
+ parent::__construct(['node' => $node, 'arguments' => $arguments], ['method' => $method, 'safe' => false], $lineno);
+
+ if ($node instanceof NameExpression) {
+ $node->setAttribute('always_defined', true);
+ }
+ }
+
+ public function compile(Compiler $compiler)
+ {
+ $compiler
+ ->subcompile($this->getNode('node'))
+ ->raw('->')
+ ->raw($this->getAttribute('method'))
+ ->raw('(')
+ ;
+ $first = true;
+ foreach ($this->getNode('arguments')->getKeyValuePairs() as $pair) {
+ if (!$first) {
+ $compiler->raw(', ');
+ }
+ $first = false;
+
+ $compiler->subcompile($pair['value']);
+ }
+ $compiler->raw(')');
+ }
+} \ No newline at end of file
diff --git a/core/View/RenderTokenParser.php b/core/View/RenderTokenParser.php
index bfcbd43057..099c46108d 100644
--- a/core/View/RenderTokenParser.php
+++ b/core/View/RenderTokenParser.php
@@ -8,11 +8,10 @@
*/
namespace Piwik\View;
-use Twig_Node_Expression_Array;
-use Twig_Node_Expression_MethodCall;
-use Twig_Node_Include;
-use Twig_Token;
-use Twig_TokenParser;
+use Twig\Node\Expression\ArrayExpression;
+use Twig\Node\IncludeNode;
+use Twig\Token;
+use Twig\TokenParser\AbstractTokenParser;
/**
* Defines a new Twig tag that will render a Piwik View.
@@ -23,45 +22,45 @@ use Twig_TokenParser;
*
* where `theView` is a variable referencing a View instance.
*/
-class RenderTokenParser extends Twig_TokenParser
+class RenderTokenParser extends AbstractTokenParser
{
/**
* Parses the Twig stream and creates a Twig_Node_Include instance that includes
* the View's template.
*
- * @return Twig_Node_Include
+ * @return \Twig\Node\Node
*/
- public function parse(Twig_Token $token)
+ public function parse(Token $token)
{
$parser = $this->parser;
$stream = $parser->getStream();
$view = $parser->getExpressionParser()->parseExpression();
- $variablesOverride = new Twig_Node_Expression_Array(array(), $token->getLine());
- if ($stream->test(Twig_Token::NAME_TYPE, 'with')) {
+ $variablesOverride = new ArrayExpression(array(), $token->getLine());
+ if ($stream->test(Token::NAME_TYPE, 'with')) {
$stream->next();
$variablesOverride->addElement($this->parser->getExpressionParser()->parseExpression());
}
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
+ $stream->expect(Token::BLOCK_END_TYPE);
- $viewTemplateExpr = new Twig_Node_Expression_MethodCall(
+ $viewTemplateExpr = new MethodCallExpression(
$view,
'getTemplateFile',
- new Twig_Node_Expression_Array(array(), $token->getLine()),
+ new ArrayExpression(array(), $token->getLine()),
$token->getLine()
);
- $variablesExpr = new Twig_Node_Expression_MethodCall(
+ $variablesExpr = new MethodCallExpression(
$view,
'getTemplateVars',
$variablesOverride,
$token->getLine()
);
- return new Twig_Node_Include(
+ return new IncludeNode(
$viewTemplateExpr,
$variablesExpr,
$only = false,
diff --git a/core/testMinimumPhpVersion.php b/core/testMinimumPhpVersion.php
index 9dc1678b37..5bddad6bfd 100644
--- a/core/testMinimumPhpVersion.php
+++ b/core/testMinimumPhpVersion.php
@@ -21,7 +21,7 @@ $piwik_errorMessage = '';
// 2) tests/travis/generator/Generator.php
// 3) composer.json (in two places)
// 4) tests/PHPUnit/Integration/ReleaseCheckListTest.php
-$piwik_minimumPHPVersion = '7.2.0';
+$piwik_minimumPHPVersion = '7.2.5';
$piwik_currentPHPVersion = PHP_VERSION;
$minimumPhpInvalid = version_compare($piwik_minimumPHPVersion, $piwik_currentPHPVersion) > 0;
if ($minimumPhpInvalid) {
diff --git a/plugins/CoreHome/templates/_dataTableActions.twig b/plugins/CoreHome/templates/_dataTableActions.twig
index aa549d84de..7322800fc7 100644
--- a/plugins/CoreHome/templates/_dataTableActions.twig
+++ b/plugins/CoreHome/templates/_dataTableActions.twig
@@ -11,7 +11,7 @@
{% set visualizationIcons %}
<ul id='dropdownVisualizations{{ randomIdForDropdown }}' class='dropdown-content dataTableFooterIcons'>
{% for footerIconGroup in footerIcons %}
- {% for footerIcon in footerIconGroup.buttons if footerIcon.icon %}
+ {% for footerIcon in footerIconGroup.buttons|filter(footerIcon => footerIcon.icon) %}
<li>
{% set numIcons = numIcons + 1 %}
{% set isActiveEcommerceView = clientSideParameters.abandonedCarts is defined and
@@ -152,4 +152,4 @@
</li>
{% endif %}
</ul>
- {% endif %} \ No newline at end of file
+ {% endif %}
diff --git a/plugins/CoreHome/templates/_dataTableCell.twig b/plugins/CoreHome/templates/_dataTableCell.twig
index 7c72b57385..2021a75262 100644
--- a/plugins/CoreHome/templates/_dataTableCell.twig
+++ b/plugins/CoreHome/templates/_dataTableCell.twig
@@ -1,4 +1,4 @@
-{% spaceless %}
+{% apply spaceless %}
{% set tooltipIndex = column ~ '_tooltip' %}
{% if row.getMetadata(tooltipIndex) %}<span class="cell-tooltip" data-tooltip="{{ row.getMetadata(tooltipIndex) }}">{% endif %}
{% if not row.getIdSubDataTable() and column=='label' and row.getMetadata('url') %}
@@ -38,4 +38,4 @@
{% endif %}
{% if row.getMetadata(tooltipIndex) %}</span>{% endif %}
-{% endspaceless %}
+{% endapply %}
diff --git a/plugins/CoreHome/templates/_topBar.twig b/plugins/CoreHome/templates/_topBar.twig
index 5a8acade30..598a511c02 100644
--- a/plugins/CoreHome/templates/_topBar.twig
+++ b/plugins/CoreHome/templates/_topBar.twig
@@ -30,11 +30,11 @@
{% set topMenuAction = currentAction %}
{% endif %}
- {% spaceless %}
+ {% apply spaceless %}
{% for label,menu in topMenu %}
<li role="menuitem" class="{{ _self.isActiveItem(menu, topMenuModule, topMenuAction) }}">{{ _self.topMenuItem(label, menu._icon, menu) }}</li>
{% endfor %}
- {% endspaceless %}
+ {% endapply %}
</ul>
<ul class="side-nav hide-on-large-only" id="mobile-top-menu">
{% for label,menu in topMenu %}
diff --git a/plugins/CorePluginsAdmin/templates/macros.twig b/plugins/CorePluginsAdmin/templates/macros.twig
index db19df33df..eb126d5c2a 100644
--- a/plugins/CorePluginsAdmin/templates/macros.twig
+++ b/plugins/CorePluginsAdmin/templates/macros.twig
@@ -239,8 +239,8 @@
<div class="plugin-author">
By
{% if plugin.info.authors is defined -%}
- {% spaceless %}
- {% for author in plugin.info.authors if author.name %}
+ {% apply spaceless %}
+ {% for author in plugin.info.authors|filter(author => author.name) %}
{% if author.homepage is defined %}
<a title="{{ 'CorePluginsAdmin_AuthorHomepage'|translate }}" href="{{ author.homepage }}" rel="noreferrer noopener" target="_blank">{{ author.name }}</a>
{% else %}
@@ -250,7 +250,7 @@
,
{% endif %}
{% endfor %}
- {% endspaceless %}
+ {% endapply %}
{%- endif %}.
</div>
{% endif %}
diff --git a/plugins/CorePluginsAdmin/templates/safemode.twig b/plugins/CorePluginsAdmin/templates/safemode.twig
index 48f3cc11ee..87853af664 100644
--- a/plugins/CorePluginsAdmin/templates/safemode.twig
+++ b/plugins/CorePluginsAdmin/templates/safemode.twig
@@ -78,8 +78,8 @@
{% endif %}
</p>
<table>
- {% for pluginName, plugin in plugins if plugin.uninstallable and plugin.activated %}
- <tr {% if loop.index is divisibleby(2) %}style="background-color: #eeeeee"{% endif %}>
+ {% for pluginName, plugin in plugins|filter(plugin => plugin.uninstallable and plugin.activated) %}
+ <tr {% if loop.index is divisible by(2) %}style="background-color: #eeeeee"{% endif %}>
<td style="min-width:200px;">
{{ pluginName }}
</td>
@@ -95,7 +95,7 @@
</table>
{% set uninstalledPluginsFound = false %}
- {% for pluginName, plugin in plugins if plugin.uninstallable and not plugin.activated %}
+ {% for pluginName, plugin in plugins|filter(plugin => plugin.uninstallable and not plugin.activated) %}
{% set uninstalledPluginsFound = true %}
{% endfor %}
@@ -107,8 +107,8 @@
</p>
<table>
- {% for pluginName, plugin in plugins if plugin.uninstallable and not plugin.activated %}
- <tr {% if loop.index is divisibleby(2) %}style="background-color: #eeeeee"{% endif %}>
+ {% for pluginName, plugin in plugins|filter(plugin => plugin.uninstallable and not plugin.activated) %}
+ <tr {% if loop.index is divisible by(2) %}style="background-color: #eeeeee"{% endif %}>
<td style="min-width:200px;">
{{ pluginName }}
</td>
diff --git a/plugins/CoreVisualizations/templates/_dataTableViz_tagCloud.twig b/plugins/CoreVisualizations/templates/_dataTableViz_tagCloud.twig
index f9f51397e2..827135ba89 100644
--- a/plugins/CoreVisualizations/templates/_dataTableViz_tagCloud.twig
+++ b/plugins/CoreVisualizations/templates/_dataTableViz_tagCloud.twig
@@ -3,15 +3,15 @@
<span title="{{ value.word|rawSafeDecoded }} ({{ value.value }} {{ properties.translations[cloudColumn]|default(cloudColumn) }})" class="word size{{ value.size }}
{# we strike tags with 0 hits #}
{% if value.value == 0 %}valueIsZero{% endif %}">
- {% if labelMetadata[value.word].url is not sameas(false) %}
+ {% if labelMetadata[value.word].url is not same as(false) %}
<a href="{{ labelMetadata[value.word].url }}" rel="noreferrer noopener" target="_blank">
{% endif %}
- {% if labelMetadata[value.word].logo is not sameas(false) %}
+ {% if labelMetadata[value.word].logo is not same as(false) %}
<img src="{{ labelMetadata[value.word].logo }}" width="{{ value.logoWidth }}" />
{% else %}
{{ value.wordTruncated|rawSafeDecoded }}
{% endif %}
- {% if labelMetadata[value.word].url is not sameas(false) %}</a>{% endif %}
+ {% if labelMetadata[value.word].url is not same as(false) %}</a>{% endif %}
</span>
{% endfor %}
</div>
diff --git a/plugins/CoreVisualizations/templates/macros.twig b/plugins/CoreVisualizations/templates/macros.twig
index 2956f591b0..d6c5ad9f56 100644
--- a/plugins/CoreVisualizations/templates/macros.twig
+++ b/plugins/CoreVisualizations/templates/macros.twig
@@ -5,7 +5,7 @@
{% if evolution.percent < 0 %}
{% set evolutionClass = 'negative-evolution' %}
{% set evolutionIcon = 'arrow_down.png' %}
- {% elseif evolution.percent == 0 %}
+ {% elseif evolution.percent == 0 or evolution.percent == '0%' %}
{% set evolutionClass = 'neutral-evolution' %}
{% set evolutionIcon = 'stop.png' %}
{% else %}
diff --git a/plugins/CustomAlerts b/plugins/CustomAlerts
-Subproject e4407e9668e09befede000cf3869da937fb35dd
+Subproject affcc9db07300506d7e739f4255a15c6cf4f510
diff --git a/plugins/CustomDimensions b/plugins/CustomDimensions
-Subproject 920cb6a38fb652308e0a044d284a05b4372aedf
+Subproject 58b758bc2dc5503207a784918b0167d37eafb08
diff --git a/plugins/Diagnostics/tests/UI/expected-screenshots/Diagnostics_page.png b/plugins/Diagnostics/tests/UI/expected-screenshots/Diagnostics_page.png
index eb8d9abcdd..7e5cbb6d74 100644
--- a/plugins/Diagnostics/tests/UI/expected-screenshots/Diagnostics_page.png
+++ b/plugins/Diagnostics/tests/UI/expected-screenshots/Diagnostics_page.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:16f6eb7a77e36b275e3293d82b29a7c304587ac1dbf0064f641b2aadaa0915f8
-size 206667
+oid sha256:116075bbcf139586a8c65093f40e7f8859bb8971c024ef26e64f14e9a576c253
+size 206665
diff --git a/plugins/Insights/templates/overviewWidget.twig b/plugins/Insights/templates/overviewWidget.twig
index 3c7f07145e..144d7fbe47 100644
--- a/plugins/Insights/templates/overviewWidget.twig
+++ b/plugins/Insights/templates/overviewWidget.twig
@@ -5,7 +5,7 @@
<div class="dataTableScroller">
<table class="dataTable"
title="{{ consideredGrowth|e('html_attr') }} {{ consideredChanges|e('html_attr') }}">
- {% for dataTable in reports.getDataTables() if dataTable.getRowsCount > 0 %}
+ {% for dataTable in reports.getDataTables()|filter(dataTable => dataTable.getRowsCount > 0) %}
{% set metadata = dataTable.getAllTableMetadata %}
<thead>
@@ -17,7 +17,6 @@
{% include "@Insights/table_row.twig" %}
{% endfor %}
</tbody>
-
{% endfor %}
</table>
</div>
diff --git a/plugins/Installation/tests/UI/expected-screenshots/Installation_system_check.png b/plugins/Installation/tests/UI/expected-screenshots/Installation_system_check.png
index 41b6efef59..aeee5034ca 100644
--- a/plugins/Installation/tests/UI/expected-screenshots/Installation_system_check.png
+++ b/plugins/Installation/tests/UI/expected-screenshots/Installation_system_check.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b41beb22c498bcc9fcb7da38a819cdc568db5ad88c4665e2db6cdbdc87abe052
-size 188672
+oid sha256:f9692e2019e911bd5194068ae0699a5b91c65761c6a87b4e1f8394f1c8907320
+size 188686
diff --git a/plugins/Live/templates/index.twig b/plugins/Live/templates/index.twig
index 1670382d21..1b025d2798 100644
--- a/plugins/Live/templates/index.twig
+++ b/plugins/Live/templates/index.twig
@@ -6,7 +6,7 @@
{{ visitors|raw }}
</div>
-{% spaceless %}
+{% apply spaceless %}
<div class="visitsLiveFooter">
<a title="{{ 'Live_OnClickPause'|translate('Live_VisitorsInRealTime'|translate) }}" href="javascript:void(0);" onclick="onClickPause();">
<img id="pauseImage" border="0" src="plugins/Live/images/pause.png" />
@@ -19,6 +19,6 @@
<a class="rightLink" href="#" onclick="this.href=broadcast.buildReportingUrl('category=General_Visitors&subcategory=Live_VisitorLog')">{{ 'Live_LinkVisitorLog'|translate }}</a>
{% endif %}
</div>
-{% endspaceless %}
+{% endapply %}
-{% if not isWidgetized %}</div>{% endif %} \ No newline at end of file
+{% if not isWidgetized %}</div>{% endif %}
diff --git a/plugins/Marketplace/templates/overview.twig b/plugins/Marketplace/templates/overview.twig
index 1eccd5d407..49c26637a3 100644
--- a/plugins/Marketplace/templates/overview.twig
+++ b/plugins/Marketplace/templates/overview.twig
@@ -1,5 +1,4 @@
{% extends inReportingMenu ? "empty.twig" : "admin.twig" %}
-{% import '@CorePluginsAdmin/macros.twig' as pluginsMacro %}
{% set title %}{{ 'Marketplace_Marketplace'|translate }}{% endset %}
diff --git a/plugins/Marketplace/templates/plugin-details.twig b/plugins/Marketplace/templates/plugin-details.twig
index e939f67164..a24cbb3e86 100644
--- a/plugins/Marketplace/templates/plugin-details.twig
+++ b/plugins/Marketplace/templates/plugin-details.twig
@@ -175,7 +175,7 @@
<br />
{% endif %}
</div>
-
+
{% if plugin.specialOffer is defined and plugin.specialOffer %}<p style="color: green;"><br />{{ plugin.specialOffer }}</p>{% endif %}
<p><br /></p>
@@ -213,9 +213,8 @@
</dd>
{% endif %}
<dt>{{ 'Marketplace_Authors'|translate }}</dt>
- <dd>{% for author in plugin.authors if author.name %}
-
- {% spaceless %}
+ <dd>{% for author in plugin.authors|filter(author => author.name) %}
+ {% apply spaceless %}
{% if author.homepage %}
<a target="_blank" rel="noreferrer noopener" href="{{ author.homepage }}">{{ author.name }}</a>
{% elseif author.email %}
@@ -227,8 +226,7 @@
{% if loop.index < plugin.authors|length %}
,
{% endif %}
- {% endspaceless %}
-
+ {% endapply %}
{% endfor %}
</dd>
{% endif %}
diff --git a/plugins/Marketplace/templates/plugin-list.twig b/plugins/Marketplace/templates/plugin-list.twig
index 9577b5c189..a8d13dcb87 100644
--- a/plugins/Marketplace/templates/plugin-list.twig
+++ b/plugins/Marketplace/templates/plugin-list.twig
@@ -1,11 +1,11 @@
-{% import '@Marketplace/macros.twig' as marketplaceMacro %}
-
{% if pluginsToShow|length > 0 %}
<div class="pluginListContainer row">
{% for plugin in pluginsToShow %}
<div class="col s12 m6 l4">
{% embed 'contentBlock.twig' with {'title': ''} %}
{% block content %}
+ {% import '@Marketplace/macros.twig' as marketplaceMacro %}
+ {% import '@CorePluginsAdmin/macros.twig' as pluginsMacro %}
<div class="plugin">
<h3 class="card-title" title="{{ 'General_MoreDetails'|translate }}">
<a href="#" piwik-plugin-name="{{ plugin.name }}">{{ plugin.displayName }}</a>
diff --git a/plugins/UserCountry/templates/adminIndex.twig b/plugins/UserCountry/templates/adminIndex.twig
index ca11eb6d06..3cd2093cb8 100644
--- a/plugins/UserCountry/templates/adminIndex.twig
+++ b/plugins/UserCountry/templates/adminIndex.twig
@@ -22,7 +22,7 @@
<div class="col s12 push-m9 m3">{{ 'General_InfoFor'|translate(thisIP) }}</div>
</div>
- {% for id,provider in locationProviders if provider.isVisible %}
+ {% for id,provider in locationProviders|filter(provider => provider.isVisible) %}
<div class="row form-group provider{{ id|e('html_attr') }}">
<div class="col s12 m4 l2">
<p>
diff --git a/tests/PHPUnit/Integration/ReleaseCheckListTest.php b/tests/PHPUnit/Integration/ReleaseCheckListTest.php
index 74e4886450..730eac8967 100644
--- a/tests/PHPUnit/Integration/ReleaseCheckListTest.php
+++ b/tests/PHPUnit/Integration/ReleaseCheckListTest.php
@@ -27,7 +27,7 @@ class ReleaseCheckListTest extends \PHPUnit\Framework\TestCase
{
private $globalConfig;
- const MINIMUM_PHP_VERSION = '7.2.0';
+ const MINIMUM_PHP_VERSION = '7.2.5';
public function setUp(): void
{
diff --git a/tests/resources/trigger-fatal-exception.php b/tests/resources/trigger-fatal-exception.php
index ba802fb11d..93f90e6f71 100644
--- a/tests/resources/trigger-fatal-exception.php
+++ b/tests/resources/trigger-fatal-exception.php
@@ -20,7 +20,7 @@ $executed = false;
\Piwik\Piwik::addAction('Request.dispatch', function () use (&$executed) {
if (!$executed) {
$executed = true;
- throw new Twig_Error_Runtime('test message');
+ throw new \Twig\Error\RuntimeError('test message');
}
});