Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@touol
Last active June 8, 2020 20:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save touol/936ae6f2f048ad37219516573129e969 to your computer and use it in GitHub Desktop.
Save touol/936ae6f2f048ad37219516573129e969 to your computer and use it in GitHub Desktop.
Сниппет генерирующий кеш для любых MODx Element, используя настраиваемый обработчик кеша на основе getCache от Jason Coward.
<?php
/**
* Cache the output of any MODx Element using a configurable cacheHandler
* Сниппет генерирующий кеш для любых MODx Element, используя настраиваемый обработчик кеша на основе getCache от Jason Coward.
* Добавлены перехват и кеширование js, стилей и изменения $_GET, $_POST.
* Добавлены параметры лога:
* &loged выводить лог в журнал ошибок MODx.
* &noCache не кешировать Element для проверки его работы.
* &logedResource id ресурса для которого выводить лог. При его использовании &loged должен быть 0 или не определен.
* Добавлен preHooks. Это сниппеты, через ;, которые будут выполнены, если кеш элемента пуст, до выполнения элемента.
* Например Для &preHooks=`getFilterValueMain;getCurrentCategoryID?{"hook_properties":"categoryId,parents"}`, если кеша еще нет, то будут
* выполнятся сниппеты getFilterValueMain и getCurrentCategoryID с параметрами заданными в json.
* Если параметрах хука задан hook_properties, то для кешуруемого элемента будут добавлены параметры его выполнения. То есть,
* [[!getCacheSensitive?
* &element=`tmFilters`
* &preHooks=`getCurrentCategoryID?{"hook_properties":"categoryId,parents"}`
* ]]
* эквивалентно
* [[!tmFilters?
* &categoryId=`[[!getCurrentCategoryID]]`
* &parents=`[[!getCurrentCategoryID]]`
* ]]
* только при загрузке из кеша сниппеты из &preHooks уже не выполняются и не грузят страницу.
* 10.12.2019
* Добавил убираем параметры getCacheSensitive. С element=`tmCatalog` возникает рекурсия. tmCatalog сам себя много раз вызывает.
* Добавил if(empty($elementClass)) $elementClass = 'modSnippet';
*
* @author Alexsandr Tuniekov <touols@yandex.ru>
* @since 08.12.2019
* Use example
* [[!getCacheSensitive?
* &preHooks=`getFilterValueMain;getCurrentCategoryID?{"hook_properties":"categoryId,parents"}`
* &element=`tmFilters`
* &cacheKey=`tmFilters`
* &cacheExpires=`0`
*
* &filterOuterTpl=`public. tm2_filterOuterTpl`
* &filterTpl=`public. tm2_filterTpl`
* &filterNumericOuterTpl=`public. tm2_filterOuterTpl`
* &filterNumericTpl=`public. tm2_filterNumericTpl`
* &jsMap=`1`
* &jsScript=`1`
* &style=`0`
* &toPlaceholder=`filters`
* &loged=`0`
* &noCache=`0`
* &logedResource=`0`
* ]]
*/
$output = '';
if($logedResource and $modx->resource->id == $logedResource) $loged = true;
if(empty($elementClass)) $elementClass = 'modSnippet';
if (empty($element)) {
$modx->log(modX::LOG_LEVEL_ERROR, "getClass requires an element and elementClass property to be set");
return $output;
}
$properties = $scriptProperties;
/* Unset these to prevent filters from being applied to the element being processed
* See http://bugs.modx.com/issues/2609
*/
unset($properties['filter_commands']);
unset($properties['filter_modifiers']);
if (empty($cacheKey)) $cacheKey = $modx->getOption('cache_resource_key', null, 'resource');
if (empty($cacheHandler)) $cacheHandler = $modx->getOption('cache_resource_handler', null, $modx->getOption(xPDO::OPT_CACHE_HANDLER, null, 'xPDOFileCache'));
if (!isset($cacheExpires)) $cacheExpires = (integer) $modx->getOption('cache_resource_expires', null, $modx->getOption(xPDO::OPT_CACHE_EXPIRES, null, 0));
$request = $modx->request->getParameters();
if(isset($request['debug'])){
unset($request['debug']);unset($request['cache']);unset($request['top']);unset($request['add']);
}
$properties2 = $properties; unset($properties2['loged']); unset($properties2['logedResource']);
if (empty($cacheElementKey)) $cacheElementKey = $modx->resource->getCacheKey() . '/' . md5($modx->toJSON($properties2) . $modx->toJSON($request));
unset($properties2);
$cacheOptions = array(
xPDO::OPT_CACHE_KEY => $cacheKey,
xPDO::OPT_CACHE_HANDLER => $cacheHandler,
xPDO::OPT_CACHE_EXPIRES => $cacheExpires,
);
$cached = $modx->cacheManager->get($cacheElementKey, $cacheOptions);
if($noCache) $cached = false;
if (!isset($cached['properties']) || !isset($cached['output'])) {
if($preHooks){
$Hooks = explode(";", $preHooks);
foreach($Hooks as $h){
$h = explode("?",$h);
$sp = array();
if(isset($h[1])){
$json = json_decode($h[1],1);
if(is_array($json)){
$sp = $json;
}
}
if($loged) $modx->log(modX::LOG_LEVEL_ERROR, "getCacheSensitive preHooks {$h[0]} {$h[1]} ".print_r($sp,1));
$out = $modx->runSnippet(trim($h[0]), $sp);
if(isset($sp['hook_properties'])){
$hook_propertys = explode(",",$sp['hook_properties']);
foreach($hook_propertys as $hp){
$properties[$hp] = $out;
}
}
}
}
if($loged) $modx->log(modX::LOG_LEVEL_ERROR, "getCacheSensitive properties ".print_r($properties,1));
$elementObj = $modx->getObject($elementClass, array('name' => $element));
if ($elementObj) {
//loadscript
$sjscripts = $modx->sjscripts;
$jscripts = $modx->jscripts;
//get
$get = $_GET;
$post = $_POST;
//убираем параметры getCacheSensitive. С element=`tmCatalog` возникает рекурсия. tmCatalog сам себя много раз вызывает.
unset($properties['preHooks']);unset($properties['element']);unset($properties['cacheKey']);unset($properties['cacheExpires']);
$elementObj->setCacheable(false);
if (!empty($properties['toPlaceholder'])) {
$elementObj->process($properties);
$output = $modx->getPlaceholder($properties['toPlaceholder']);
} else {
$output = $elementObj->process($properties);
}
$sjscripts = array_diff($modx->sjscripts,$sjscripts);
$jscripts = array_diff($modx->jscripts,$jscripts);
$get = array_diff($_GET,$get);
$post = array_diff($_POST,$get);
if ($modx->getCacheManager()) {
$cached = array('properties' => $properties, 'output' => $output, 'sjscripts' => $sjscripts, 'jscripts' => $jscripts, 'get' => $get, 'post' => $post);
$modx->cacheManager->set($cacheElementKey, $cached, $cacheExpires, $cacheOptions);
if($loged) $modx->log(modX::LOG_LEVEL_ERROR, "getCacheSensitive run {$element} of cacheElementKey {$cacheElementKey} on {$modx->resource->pagetitle} request ".print_r($request,1)." get ".print_r($get,1));
}
} else {
$modx->log(modX::LOG_LEVEL_ERROR, "getCache could not find requested element {$element} of class {$elementClass}");
}
} else {
$properties = $cached['properties'];
$output = $cached['output'];
if(!empty($cached['sjscripts'])){
foreach($cached['sjscripts'] as $sj){
if (strpos(strtolower($sj), "<style") !== false || strpos(strtolower($sj), "<link") !== false) {
$modx->regClientCSS($sj);
}else{
$modx->regClientStartupScript($sj);
}
}
}
if(!empty($cached['jscripts'])){
foreach($cached['jscripts'] as $j){
$modx->regClientScript($j);
}
}
if(!empty($cached['get'])){
$_GET = array_merge($_GET,$cached['get']);
}
if(!empty($cached['post'])){
$_POST = array_merge($_POST,$cached['post']);
}
if($loged) $modx->log(modX::LOG_LEVEL_ERROR, "getCacheSensitive load from cache {$element} of cacheElementKey {$cacheElementKey} on {$modx->resource->pagetitle} request ".print_r($request,1));
}
$modx->setPlaceholders($properties, $properties['namespace']);
if (!empty($properties['toPlaceholder'])) {
$modx->setPlaceholder($properties['toPlaceholder'], $output);
$output = '';
}
return $output;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment