1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-10 16:54:44 +02:00

Minor refactoring/updates in PageRender, plus remove the template!=admin exclusion for the field rendering

This commit is contained in:
Ryan Cramer
2021-09-10 12:00:08 -04:00
parent 429e43506c
commit 5fc01ef102

View File

@@ -7,7 +7,7 @@
* This module is also able to cache page renders. * This module is also able to cache page renders.
* It hooks into Pages and Fieldtypes to ensure cache files are cleaned/deleted when pages are saved/deleted. * It hooks into Pages and Fieldtypes to ensure cache files are cleaned/deleted when pages are saved/deleted.
* *
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer * ProcessWire 3.x, Copyright 2021 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
* @method renderPage(HookEvent $event) * @method renderPage(HookEvent $event)
@@ -29,7 +29,7 @@ class PageRender extends WireData implements Module, ConfigurableModule {
'permanent' => true, 'permanent' => true,
'singular' => true, 'singular' => true,
'autoload' => true, 'autoload' => true,
); );
} }
/** /**
@@ -68,11 +68,11 @@ class PageRender extends WireData implements Module, ConfigurableModule {
*/ */
public function init() { public function init() {
$this->useFuel(false); $this->useFuel(false);
$this->config = $this->wire('config'); $this->config = $this->wire()->config;
$this->addHook('Page::render', $this, 'renderPage'); $this->addHook('Page::render', $this, 'renderPage');
// $this->addHook('Page::renderField', $this, 'renderField'); $pages = $this->wire()->pages;
$this->wire('pages')->addHookAfter('save', $this, 'clearCacheFile'); $pages->addHookAfter('save', $this, 'clearCacheFile');
$this->wire('pages')->addHookAfter('delete', $this, 'clearCacheFile'); $pages->addHookAfter('delete', $this, 'clearCacheFile');
// $this->addHookAfter('Fieldtype::savePageField', $this, 'savePageField'); // removed, see note in commented function // $this->addHookAfter('Fieldtype::savePageField', $this, 'savePageField'); // removed, see note in commented function
} }
@@ -81,10 +81,7 @@ class PageRender extends WireData implements Module, ConfigurableModule {
* *
*/ */
public function ready() { public function ready() {
// todo 3.0.190: remove template!=admin condition: https://github.com/processwire/processwire-issues/issues/1424 $this->addHookBefore('Page::render', $this, 'beforeRenderPage', array('priority' => 1));
if($this->wire()->page->template != 'admin') {
$this->addHookBefore('Page::render', $this, 'beforeRenderPage', array('priority' => 1));
}
} }
/** /**
@@ -120,36 +117,42 @@ class PageRender extends WireData implements Module, ConfigurableModule {
*/ */
public function isCacheAllowed($page) { public function isCacheAllowed($page) {
if(!$page->template || ((int) $page->template->cache_time) < 1) return false; $template = $page->template;
if(!$template || ((int) $template->cache_time) < 1) return false;
if(!$this->wire('user')->isGuest()) { if(!$this->wire()->user->isGuest()) {
if(!$page->template->useCacheForUsers) return false; if(!$template->useCacheForUsers) return false;
if($page->editable()) return false; if($page->editable()) return false;
} }
$allowed = true; $allowed = true;
$noCacheGetVars = $template->noCacheGetVars;
$noCachePostVars = $template->noCachePostVars;
if(count($_GET) && $page->template->noCacheGetVars) { if($noCacheGetVars && count($_GET)) {
if(strpos($page->template->noCacheGetVars, '*') !== false) { if(strpos($noCacheGetVars, '*') !== false) {
$allowed = false; $allowed = false;
} else { } else {
$vars = explode(' ', $page->template->noCacheGetVars); $vars = explode(' ', $noCacheGetVars);
foreach($vars as $name) if($name && isset($_GET[$name])) $allowed = false; foreach($vars as $name) if($name && isset($_GET[$name])) $allowed = false;
} }
} }
if($allowed && count($_POST) && $page->template->noCachePostVars) { if($allowed && $noCachePostVars && count($_POST)) {
if(strpos($page->template->noCachePostVars, '*') !== false) { if(strpos($noCachePostVars, '*') !== false) {
$allowed = false; $allowed = false;
} else { } else {
$vars = explode(' ', $page->template->noCachePostVars); $vars = explode(' ', $noCachePostVars);
foreach($vars as $name) if($name && isset($_POST[$name])) $allowed = false; foreach($vars as $name) if($name && isset($_POST[$name])) $allowed = false;
} }
} }
// NOTE: other modules may set a session var of PageRenderNoCachePage containing a page ID to temporarily if($allowed) {
// remove caching for some page, if necessary. // NOTE: other modules may set a session var of PageRenderNoCachePage containing a page ID to temporarily
if($this->wire('session')->PageRenderNoCachePage && $this->wire('session')->PageRenderNoCachePage == $page->id) $allowed = false; // remove caching for some page, if necessary.
$id = (int) $this->wire()->session->get('PageRenderNoCachePage');
if($id && $id === $page->id) $allowed = false;
}
return $allowed; return $allowed;
} }
@@ -172,7 +175,7 @@ class PageRender extends WireData implements Module, ConfigurableModule {
'prependFile' => '', 'prependFile' => '',
'appendFile' => '', 'appendFile' => '',
'filename' => '', 'filename' => '',
); );
$options = array_merge($defaults, $options); $options = array_merge($defaults, $options);
$path = $config->paths->cache . self::cacheDirName . "/"; $path = $config->paths->cache . self::cacheDirName . "/";
@@ -185,21 +188,23 @@ class PageRender extends WireData implements Module, ConfigurableModule {
} }
if(!is_dir($path)) { if(!is_dir($path)) {
if(!$this->wire('files')->mkdir($path, true)) throw new WireException("Cache path does not exist: $path"); if(!$this->wire()->files->mkdir($path, true)) throw new WireException("Cache path does not exist: $path");
if($config->chmodDir) chmod($path, octdec($config->chmodDir));
} }
$cacheFile = new CacheFile($path, $id, $cacheTime); $cacheFile = new CacheFile($path, $id, $cacheTime);
$this->wire($cacheFile);
if($this->wire('page') === $page) { if($this->wire()->page === $page) {
// this part is skipped if arguments provided an id (int) rather than a Page object // this part is skipped if arguments provided an id (int) rather than a Page object
$secondaryID = ''; $secondaryID = '';
$pageNum = $this->wire('input')->pageNum; $input = $this->wire()->input;
$urlSegments = $this->wire('input')->urlSegments; $sanitizer = $this->wire()->sanitizer;
$pageNum = $input->pageNum;
$urlSegments = $input->urlSegments;
if(count($urlSegments)) { if(count($urlSegments)) {
foreach($urlSegments as $urlSegment) { foreach($urlSegments as $urlSegment) {
$secondaryID .= $this->wire('sanitizer')->pageName($urlSegment) . '+'; $secondaryID .= $sanitizer->pageName($urlSegment) . '+';
} }
} }
@@ -210,8 +215,8 @@ class PageRender extends WireData implements Module, ConfigurableModule {
if($config->https) $secondaryID .= 'https+'; if($config->https) $secondaryID .= 'https+';
if($pageNum > 1) $secondaryID .= "page{$pageNum}"; if($pageNum > 1) $secondaryID .= "page{$pageNum}";
$secondaryID = rtrim($secondaryID, '+'); $secondaryID = rtrim($secondaryID, '+');
if($this->wire('languages')) { if($this->wire()->languages) {
$language = $this->wire('user')->language; $language = $this->wire()->user->language;
if($language && $language->id && !$language->isDefault()) $secondaryID .= "_" . $language->id; if($language && $language->id && !$language->isDefault()) $secondaryID .= "_" . $language->id;
} }
if($secondaryID) $cacheFile->setSecondaryID($secondaryID); if($secondaryID) $cacheFile->setSecondaryID($secondaryID);
@@ -252,7 +257,6 @@ class PageRender extends WireData implements Module, ConfigurableModule {
if(((int) $p->template->cache_time) < 1) continue; if(((int) $p->template->cache_time) < 1) continue;
$cf = $this->getCacheFile($p); $cf = $this->getCacheFile($p);
if($cf->exists()) $cf->remove(); if($cf->exists()) $cf->remove();
// if($this->config->debug) $this->message(sprintf($this->_('Cleared cache file: %s'), $cf));
} }
} }
@@ -263,14 +267,21 @@ class PageRender extends WireData implements Module, ConfigurableModule {
* *
*/ */
public function clearCacheFile($event) { public function clearCacheFile($event) {
/** @var Page $page */
$page = $event->arguments[0]; $page = $event->arguments[0];
if(((int) $page->template->cache_time) == 0) return; $template = $page->template;
$cacheExpire = $page->template->cacheExpire;
if(((int) $template->cache_time) == 0) return;
$cacheExpire = $template->cacheExpire;
if($cacheExpire == Template::cacheExpireNone) { if($cacheExpire == Template::cacheExpireNone) {
if($event->method == 'delete') $cacheExpire = Template::cacheExpirePage; if($event->method == 'delete') {
else return; $cacheExpire = Template::cacheExpirePage;
} else {
return;
}
} }
if($cacheExpire == Template::cacheExpireSite) { if($cacheExpire == Template::cacheExpireSite) {
@@ -280,7 +291,7 @@ class PageRender extends WireData implements Module, ConfigurableModule {
} else { } else {
// clear the page that was saved // clear the page that was saved
if($page->template->cache_time > 0) { if($template->cache_time > 0) {
$cacheFile = $this->getCacheFile($page); $cacheFile = $this->getCacheFile($page);
if($cacheFile->exists()) { if($cacheFile->exists()) {
$cacheFile->remove(); $cacheFile->remove();
@@ -293,16 +304,20 @@ class PageRender extends WireData implements Module, ConfigurableModule {
if($cacheExpire == Template::cacheExpireParents || $cacheExpire == Template::cacheExpireSpecific) { if($cacheExpire == Template::cacheExpireParents || $cacheExpire == Template::cacheExpireSpecific) {
// expire specific pages or parents // expire specific pages or parents
if($cacheExpire == Template::cacheExpireParents) { if($cacheExpire == Template::cacheExpireParents) {
foreach($page->parents as $parent) $pageIDs[] = $parent->id; foreach($page->parents as $parent) {
$pageIDs[] = $parent->id;
}
} else if(is_array($page->template->cacheExpirePages) && count($page->template->cacheExpirePages)) { } else if(is_array($template->cacheExpirePages) && count($template->cacheExpirePages)) {
$pageIDs = $page->template->cacheExpirePages; $pageIDs = $template->cacheExpirePages;
} }
} else if($cacheExpire == Template::cacheExpireSelector && $page->template->cacheExpireSelector) { } else if($cacheExpire == Template::cacheExpireSelector && $template->cacheExpireSelector) {
// expire pages matching a selector // expire pages matching a selector
/** @var PageFinder $finder */
$finder = $this->wire(new PageFinder()); $finder = $this->wire(new PageFinder());
$selectors = new Selectors(); $selectors = new Selectors();
$selectors->init($page->template->cacheExpireSelector); $this->wire($selectors);
$selectors->init($template->cacheExpireSelector);
$pageIDs = $finder->findIDs($selectors, array( $pageIDs = $finder->findIDs($selectors, array(
'getTotal' => false, 'getTotal' => false,
'findHidden' => true 'findHidden' => true
@@ -310,7 +325,7 @@ class PageRender extends WireData implements Module, ConfigurableModule {
} }
if(count($pageIDs)) { if(count($pageIDs)) {
$items = $this->wire('pages')->getById($pageIDs, array( $items = $this->wire()->pages->getById($pageIDs, array(
'cache' => false, 'cache' => false,
'getNumChildren' => false, 'getNumChildren' => false,
'autojoin' => false, 'autojoin' => false,
@@ -320,6 +335,7 @@ class PageRender extends WireData implements Module, ConfigurableModule {
if(!$items->has($page)) $items->add($page); if(!$items->has($page)) $items->add($page);
} else { } else {
$items = new PageArray(); $items = new PageArray();
$this->wire($items);
$items->add($page); $items->add($page);
} }
if(count($items)) { if(count($items)) {
@@ -355,7 +371,7 @@ class PageRender extends WireData implements Module, ConfigurableModule {
*/ */
public function beforeRenderPage(HookEvent $event) { public function beforeRenderPage(HookEvent $event) {
$fieldName = $event->arguments(0); $fieldName = $event->arguments(0);
if($fieldName && is_string($fieldName) && $this->wire('sanitizer')->fieldName($fieldName) === $fieldName) { if($fieldName && is_string($fieldName) && $this->wire()->sanitizer->fieldName($fieldName) === $fieldName) {
// render field requested, cancel page render and hooks, and delegate to renderField // render field requested, cancel page render and hooks, and delegate to renderField
$file = $event->arguments(1); // optional basename of file to use for render $file = $event->arguments(1); // optional basename of file to use for render
if(!is_string($file)) $file = null; if(!is_string($file)) $file = null;
@@ -422,16 +438,17 @@ class PageRender extends WireData implements Module, ConfigurableModule {
/** @var Template $template */ /** @var Template $template */
$template = $page->template; $template = $page->template;
$this->wire('pages')->setOutputFormatting(true); $this->wire()->pages->setOutputFormatting(true);
if($page->status >= Page::statusUnpublished && !$page->viewable()) { if($page->status >= Page::statusUnpublished && !$page->viewable()) {
throw new WirePermissionException("Page '{$page->url}' is not currently viewable."); throw new WirePermissionException("Page '{$page->url}' is not currently viewable.");
} }
$_page = $this->wire('page'); // just in case one page is rendering another, save the previous $_page = $this->wire()->page; // just in case one page is rendering another, save the previous
$config = $this->wire('config'); $config = $this->wire()->config;
$compiler = null; $compiler = null; /** @var FileCompiler|null $compiler */
$compilerOptions = array(); $compilerOptions = array();
if($config->templateCompile && $template->compile) { if($config->templateCompile && $template->compile) {
$compilerOptions = array( $compilerOptions = array(
'namespace' => strlen(__NAMESPACE__) > 0, 'namespace' => strlen(__NAMESPACE__) > 0,
@@ -466,7 +483,7 @@ class PageRender extends WireData implements Module, ConfigurableModule {
'allowCache' => true, 'allowCache' => true,
'forceBuildCache' => false, 'forceBuildCache' => false,
'pageStack' => array(), // set after array_merge 'pageStack' => array(), // set after array_merge
); );
$options = array_merge($defaultOptions, $options); $options = array_merge($defaultOptions, $options);
$options['pageStack'] = $this->pageStack; $options['pageStack'] = $this->pageStack;
@@ -558,7 +575,7 @@ class PageRender extends WireData implements Module, ConfigurableModule {
} }
} }
if($this->wire('config')->useMarkupRegions) { if($config->useMarkupRegions) {
$contentType = $template->contentType; $contentType = $template->contentType;
if(empty($contentType) || stripos($contentType, 'html') !== false) { if(empty($contentType) || stripos($contentType, 'html') !== false) {
$this->populateMarkupRegions($data); $this->populateMarkupRegions($data);
@@ -610,7 +627,7 @@ class PageRender extends WireData implements Module, ConfigurableModule {
$htmlBefore = substr($html, 0, $pos); $htmlBefore = substr($html, 0, $pos);
$html = substr($html, $pos); $html = substr($html, $pos);
$options = array('useClassActions' => true); $options = array('useClassActions' => true);
$config = $this->wire('config'); $config = $this->wire()->config;
$version = (int) $config->useMarkupRegions; $version = (int) $config->useMarkupRegions;
if($config->installed >= 1498132609 || $version >= 2) { if($config->installed >= 1498132609 || $version >= 2) {
@@ -636,15 +653,12 @@ class PageRender extends WireData implements Module, ConfigurableModule {
* *
*/ */
public function renderField(Page $page, $fieldName, $file = '', $value = null) { public function renderField(Page $page, $fieldName, $file = '', $value = null) {
$sanitizer = $this->wire()->sanitizer;
$config = $this->wire()->config;
/*
if(strpos($fieldName, '/') && empty($file)) {
$file = $fieldName;
$fieldName = '';
}
*/
if(strlen($fieldName)) { if(strlen($fieldName)) {
$fieldName = $this->wire('sanitizer')->fieldName($fieldName); $fieldName = $sanitizer->fieldName($fieldName);
} }
if(is_null($value) && $fieldName) $value = $page->getFormatted($fieldName); if(is_null($value) && $fieldName) $value = $page->getFormatted($fieldName);
@@ -652,14 +666,14 @@ class PageRender extends WireData implements Module, ConfigurableModule {
if($fieldName) { if($fieldName) {
$field = $page->getField($fieldName); $field = $page->getField($fieldName);
if(!$field) $field = $this->wire('fields')->get($fieldName); if(!$field) $field = $this->wire()->fields->get($fieldName);
$fieldtypeName = $field && $field->type ? $field->type->className() : ''; $fieldtypeName = $field && $field->type ? $field->type->className() : '';
} else { } else {
$field = null; $field = null;
$fieldtypeName = ''; $fieldtypeName = '';
} }
$path = $this->wire('config')->paths->fieldTemplates; $path = $config->paths->fieldTemplates;
$files = array(); $files = array();
if($file) { if($file) {
@@ -680,7 +694,7 @@ class PageRender extends WireData implements Module, ConfigurableModule {
// file includes a directory off of fields/[dir] // file includes a directory off of fields/[dir]
$parts = explode('/', $file); $parts = explode('/', $file);
foreach($parts as $key => $part) { foreach($parts as $key => $part) {
$parts[$key] = $this->wire('sanitizer')->name($part); $parts[$key] = $sanitizer->name($part);
} }
$file = implode('/', $parts); $file = implode('/', $parts);
$file = str_replace('..', '', $file); $file = str_replace('..', '', $file);
@@ -749,10 +763,11 @@ class PageRender extends WireData implements Module, ConfigurableModule {
} }
} }
if($this->wire('config')->templateCompile) { if($config->templateCompile) {
$renderFile = $this->wire('files')->compile($renderFile, array('skipIfNamespace' => true)); $renderFile = $this->wire()->files->compile($renderFile, array('skipIfNamespace' => true));
} }
/** @var TemplateFile $tpl */
$tpl = $this->wire(new TemplateFile($renderFile)); $tpl = $this->wire(new TemplateFile($renderFile));
$tpl->set('page', $page); $tpl->set('page', $page);
$tpl->set('value', $value); $tpl->set('value', $value);
@@ -769,14 +784,19 @@ class PageRender extends WireData implements Module, ConfigurableModule {
* *
*/ */
public function getModuleConfigInputfields(array $data) { public function getModuleConfigInputfields(array $data) {
$config = $this->wire()->config;
$input = $this->wire()->input;
$files = $this->wire()->files;
$modules = $this->wire()->modules;
if($data) {} if($data) {}
$path = $this->wire('config')->paths->cache . self::cacheDirName . '/'; $path = $config->paths->cache . self::cacheDirName . '/';
$numPages = 0; $numPages = 0;
$numFiles = 0; $numFiles = 0;
$inputfields = $this->wire(new InputfieldWrapper()); $inputfields = $this->wire(new InputfieldWrapper());
$dir = null; $dir = null;
$clearNow = $this->wire('input')->post->clearCache ? true : false; $clearNow = $input->post('_clearCache') ? true : false;
try { $dir = new \DirectoryIterator($path); } catch(\Exception $e) { } try { $dir = new \DirectoryIterator($path); } catch(\Exception $e) { }
@@ -788,10 +808,10 @@ class PageRender extends WireData implements Module, ConfigurableModule {
foreach($d as $f) { foreach($d as $f) {
if(!$f->isDir() && preg_match('/\.cache$/D', $f->getFilename())) { if(!$f->isDir() && preg_match('/\.cache$/D', $f->getFilename())) {
$numFiles++; $numFiles++;
$this->wire('files')->unlink($f->getPathname()); $files->unlink($f->getPathname());
} }
} }
$this->wire('files')->rmdir($file->getPathname()); $files->rmdir($file->getPathname());
} }
if($clearNow) { if($clearNow) {
@@ -799,9 +819,9 @@ class PageRender extends WireData implements Module, ConfigurableModule {
$numPages = 0; $numPages = 0;
} }
$name = "clearCache"; /** @var InputfieldCheckbox $f */
$f = $this->wire('modules')->get('InputfieldCheckbox'); $f = $modules->get('InputfieldCheckbox');
$f->attr('name', $name); $f->attr('name', '_clearCache');
$f->attr('value', 1); $f->attr('value', 1);
$f->label = $this->_('Clear the Page Render Disk Cache?'); $f->label = $this->_('Clear the Page Render Disk Cache?');
$f->description = sprintf($this->_('There are currently %d pages cached in %s'), $numPages, $path); $f->description = sprintf($this->_('There are currently %d pages cached in %s'), $numPages, $path);
@@ -809,7 +829,6 @@ class PageRender extends WireData implements Module, ConfigurableModule {
$inputfields->append($f); $inputfields->append($f);
return $inputfields; return $inputfields;
} }
} }