Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions core/components/pdotools/model/pdotools/_fenom.php
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,42 @@ protected function _addDefaultModifiers()

return preg_split($pattern, $value);
};

$this->_actions['cache'] = [
'type' => self::BLOCK_COMPILER
,'open' =>
function ($tokens, $scope) {
$name = false;
$cname = $scope->tpl->parsePlainArg($tokens, $name);
$params = [
'lifetime'=>0,
'options'=>[],

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

options default

Дефолт 'options' => [] — PHP-массив, а Fenom parseParams обычно ждёт code-string'и. Для пустого дефолта Compiler::toArray([]) ещё ок, но при options=$foo в toArray() попадёт строка выражения и foreach разберёт её по символам.

Лучше: убрать options совсем, либо default как 'options' => 'array()' и явно валидировать значение.

];
$params = $scope->tpl->parseParams($tokens, $params);

if (!$name) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Только static name

parsePlainArg + if (!$name) означает, что {cache $key} не скомпилируется. Ок как ограничение, но стоит явно описать в docs/PR: имя только строковый литерал.

throw new \RuntimeException("Invalid cache name");
}

$scope['name'] = $cname;
$scope['params'] = $params;
$scope['var'] = $scope->tpl->tmpVar();

return "{$scope['var']} = \$var[\"_modx\"]->cacheManager->get({$scope['name']},".Fenom\Compiler::toArray($scope['params']['options']).");\n
if(!{$scope['var']} ) { \n

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cache miss

if (!{$scope['var']}) ломает кэш пустого/нулевого контента ('', '0' и т.п.) — каждый раз будет miss.

Нужно что-то вроде:

if ({$scope['var']} === false || {$scope['var']} === null) {

(как обычно отдаёт miss у MODX cacheManager).

ob_start(); \n
";
}
,'close' =>
function($tokens, $scope){
return "
{$scope['var']} = ob_get_clean(); \n
\$var[\"_modx\"]->cacheManager->set({$scope['name']},{$scope['var']},{$scope['params']['lifetime']},".Fenom\Compiler::toArray($scope['params']['options']).");\n

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set() + options — blocker

microMODXCacheManager::set($key, &$var, $lifetime = 0) принимает только 3 аргумента. Четвёртый options сознательно убран:

// $options is not used due to security reasons
return $this->cacheManager->set($key, $var, $lifetime);

Здесь options снова протаскиваются в set(). Нужно:

\$var[\"_modx\"]->cacheManager->set({$scope['name']}, {$scope['var']}, {$scope['params']['lifetime']});

без 4-го аргумента.

}\n
echo {$scope['var']};
";
}
];

}

Expand Down