Last active
June 8, 2020 20:37
-
-
Save touol/936ae6f2f048ad37219516573129e969 to your computer and use it in GitHub Desktop.
Сниппет генерирующий кеш для любых MODx Element, используя настраиваемый обработчик кеша на основе getCache от Jason Coward.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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