mirror of
https://github.com/processwire/processwire.git
synced 2025-08-16 19:54:24 +02:00
Refactoring of WireShutdown class and related minor updates to some other classes
This commit is contained in:
@@ -1538,7 +1538,8 @@ class Page extends WireData implements \Countable, WireMatchable {
|
||||
*/
|
||||
public function getText($key, $oneLine = false, $entities = null) {
|
||||
$value = $this->getMarkup($key);
|
||||
if(!strlen($value)) return '';
|
||||
$length = strlen($value);
|
||||
if(!$length) return '';
|
||||
$options = array(
|
||||
'entities' => (is_null($entities) ? $this->outputFormatting() : (bool) $entities)
|
||||
);
|
||||
@@ -1547,6 +1548,8 @@ class Page extends WireData implements \Countable, WireMatchable {
|
||||
} else {
|
||||
$value = $this->wire('sanitizer')->markupToText($value, $options);
|
||||
}
|
||||
// if stripping tags from non-empty value made it empty, just indicate that it was markup and length
|
||||
if(!strlen(trim($value))) $value = "markup($length)";
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
@@ -204,8 +204,9 @@ class ProcessWire extends Wire {
|
||||
|
||||
$this->wire('hooks', new WireHooks($this, $config), true);
|
||||
|
||||
$this->shutdown = $this->wire(new WireShutdown());
|
||||
$this->setConfig($config);
|
||||
$this->shutdown = $this->wire(new WireShutdown($config));
|
||||
$this->setStatus(self::statusBoot);
|
||||
$this->load($config);
|
||||
|
||||
if(self::getNumInstances() > 1) {
|
||||
@@ -274,13 +275,6 @@ class ProcessWire extends Wire {
|
||||
$config->debug = $debugIf;
|
||||
}
|
||||
|
||||
// If script is being called externally, add an extra shutdown function
|
||||
if(!$config->internal) register_shutdown_function(function() {
|
||||
if(error_get_last()) return;
|
||||
$process = isset($this) ? $this->wire('process') : wire('process');
|
||||
if($process == 'ProcessPageView') $process->finished();
|
||||
});
|
||||
|
||||
if($config->useFunctionsAPI) {
|
||||
$file = $config->paths->core . 'FunctionsAPI.php';
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
@@ -302,9 +296,6 @@ class ProcessWire extends Wire {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$this->setStatus(self::statusBoot);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -750,6 +741,41 @@ class ProcessWire extends Wire {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get root path, check it, and optionally auto-detect it if not provided
|
||||
*
|
||||
* @param bool|string $rootPath Root path if already known, in which case we’ll just modify as needed
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
protected static function getRootPath($rootPath = '') {
|
||||
|
||||
if(strpos($rootPath, '..') !== false) {
|
||||
$rootPath = realpath($rootPath);
|
||||
}
|
||||
|
||||
if(empty($rootPath) && !empty($_SERVER['SCRIPT_FILENAME'])) {
|
||||
// first try to determine from the script filename
|
||||
$parts = explode(DIRECTORY_SEPARATOR, $_SERVER['SCRIPT_FILENAME']);
|
||||
array_pop($parts); // most likely: index.php
|
||||
$rootPath = implode('/', $parts) . '/';
|
||||
if(!file_exists($rootPath . 'wire/core/ProcessWire.php')) $rootPath = '';
|
||||
}
|
||||
|
||||
if(empty($rootPath)) {
|
||||
// if unable to determine from script filename, attempt to determine from current file
|
||||
$parts = explode(DIRECTORY_SEPARATOR, __FILE__);
|
||||
$parts = array_slice($parts, 0, -3); // removes "ProcessWire.php", "core" and "wire"
|
||||
$rootPath = implode('/', $parts) . '/';
|
||||
}
|
||||
|
||||
if(DIRECTORY_SEPARATOR != '/') {
|
||||
$rootPath = str_replace(DIRECTORY_SEPARATOR, '/', $rootPath);
|
||||
}
|
||||
|
||||
return $rootPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static method to build a Config object for booting ProcessWire
|
||||
*
|
||||
@@ -762,17 +788,9 @@ class ProcessWire extends Wire {
|
||||
* @throws WireException
|
||||
*
|
||||
*/
|
||||
public static function buildConfig($rootPath, $rootURL = null, array $options = array()) {
|
||||
|
||||
if(strpos($rootPath, '..') !== false) {
|
||||
$rootPath = realpath($rootPath);
|
||||
if($rootPath === false) throw new WireException("Path not found");
|
||||
}
|
||||
|
||||
if(DIRECTORY_SEPARATOR != '/') {
|
||||
$rootPath = str_replace(DIRECTORY_SEPARATOR, '/', $rootPath);
|
||||
}
|
||||
|
||||
public static function buildConfig($rootPath = '', $rootURL = null, array $options = array()) {
|
||||
|
||||
$rootPath = self::getRootPath($rootPath);
|
||||
$httpHost = '';
|
||||
$scheme = '';
|
||||
$siteDir = isset($options['siteDir']) ? $options['siteDir'] : 'site';
|
||||
|
@@ -577,7 +577,7 @@ class WireInput extends Wire {
|
||||
// page not yet available, attempt to pull URL from request uri
|
||||
$info = parse_url($_SERVER['REQUEST_URI']);
|
||||
$parts = explode('/', $info['path']);
|
||||
$charset = $config->pageNameCharset;
|
||||
$charset = $config ? $config->pageNameCharset : '';
|
||||
foreach($parts as $i => $part) {
|
||||
if($i > 0) $url .= "/";
|
||||
$url .= ($charset === 'UTF8' ? $sanitizer->pageNameUTF8($part) : $sanitizer->pageName($part, false));
|
||||
|
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* ProcessWire shutdown handler
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
|
||||
* ProcessWire 3.x, Copyright 2018 by Ryan Cramer
|
||||
*
|
||||
* Look for errors at shutdown and log them, plus echo the error if the page is editable
|
||||
*
|
||||
@@ -12,26 +12,80 @@
|
||||
*/
|
||||
|
||||
class WireShutdown extends Wire {
|
||||
|
||||
|
||||
/**
|
||||
* Associative array of [ PHP E_* constants (i.e. E_ERROR) => Translated description ]
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $types = array();
|
||||
protected $fatalTypes = array();
|
||||
|
||||
/**
|
||||
* Regular array of PHP E_* constants that are considered fatal (i.e. E_ERROR)
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $fatalTypes = array(
|
||||
E_ERROR,
|
||||
E_CORE_ERROR,
|
||||
E_COMPILE_ERROR,
|
||||
E_USER_ERROR,
|
||||
E_PARSE,
|
||||
E_RECOVERABLE_ERROR,
|
||||
);
|
||||
|
||||
/**
|
||||
* Associative array of phrase translations for this module
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $labels = array();
|
||||
|
||||
public function __construct() {
|
||||
|
||||
/**
|
||||
* @var Config
|
||||
*
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Contents of last error_get_last() call
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $error = array();
|
||||
|
||||
/**
|
||||
* Default HTML to use for error message
|
||||
*
|
||||
* Can be overridden with $config->fatalErrorHTML in /site/config.php
|
||||
*
|
||||
*/
|
||||
const defaultFatalErrorHTML = '<p><b>{message}</b><br /><small>{why}</small></p>';
|
||||
|
||||
/**
|
||||
* Construct and register shutdown function
|
||||
*
|
||||
* @param Config $config
|
||||
*
|
||||
*/
|
||||
public function __construct(Config $config) {
|
||||
$this->config = $config;
|
||||
register_shutdown_function(array($this, 'shutdown'));
|
||||
$this->fatalTypes = array(
|
||||
E_ERROR,
|
||||
E_CORE_ERROR,
|
||||
E_COMPILE_ERROR,
|
||||
E_USER_ERROR,
|
||||
E_PARSE,
|
||||
E_RECOVERABLE_ERROR,
|
||||
);
|
||||
// If script is being called externally, add an extra shutdown function
|
||||
if(!$config->internal) register_shutdown_function(array($this, 'shutdownExternal'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Setup our translation labels
|
||||
*
|
||||
*/
|
||||
protected function prepareLabels() {
|
||||
$this->types = array(
|
||||
E_ERROR => $this->_('Error'),
|
||||
E_ERROR => $this->_('Fatal Error'),
|
||||
E_WARNING => $this->_('Warning'),
|
||||
E_PARSE => $this->_('Parse Error'),
|
||||
E_NOTICE => $this->_('Notice'),
|
||||
@@ -62,62 +116,246 @@ class WireShutdown extends Wire {
|
||||
|
||||
}
|
||||
|
||||
public function shutdown() {
|
||||
$error = error_get_last();
|
||||
if(!$error) return true;
|
||||
$type = $error['type'];
|
||||
if(!in_array($type, $this->fatalTypes)) return true;
|
||||
/**
|
||||
* Create more informative error message from $error array
|
||||
*
|
||||
* @param array $error Error array from PHP’s error_get_last()
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
protected function getErrorMessage(array $error) {
|
||||
|
||||
$this->prepareLabels();
|
||||
$http = isset($_SERVER['HTTP_HOST']);
|
||||
$config = $this->wire('config');
|
||||
$user = $this->wire('user');
|
||||
$userName = $user ? $user->name : '?';
|
||||
if($config && $config->logIP && isset($_SERVER['REMOTE_ADDR'])) $userName .= " ($_SERVER[REMOTE_ADDR])";
|
||||
$page = $this->wire('page');
|
||||
$path = ($config ? $config->httpHost : '') . ($page ? $page->url : '/?/');
|
||||
if($config && $http) $path = ($config->https ? 'https://' : 'http://') . $path;
|
||||
$line = $error['line'];
|
||||
$file = $error['file'];
|
||||
$message = isset($this->types[$type]) ? $this->types[$type] : $this->types[E_ERROR];
|
||||
if(strpos($error['message'], "\t") !== false) $error['message'] = str_replace("\t", ' ', $error['message']);
|
||||
$message .= ": \t$error[message]";
|
||||
if($type != E_USER_ERROR) $message .= ' ' . sprintf($this->labels['line-of-file'], $line, $file) . ' ';
|
||||
$debug = false;
|
||||
$log = null;
|
||||
$why = '';
|
||||
$who = '';
|
||||
$sendOutput = true;
|
||||
$type = $error['type'];
|
||||
|
||||
if(isset($this->types[$type])) {
|
||||
$errorType = $this->types[$type];
|
||||
} else {
|
||||
$errorType = $this->types[E_USER_ERROR];
|
||||
}
|
||||
|
||||
$message = str_replace("\t", ' ', $error['message']);
|
||||
|
||||
if($type != E_USER_ERROR) {
|
||||
$detail = sprintf($this->labels['line-of-file'], $error['line'], $error['file']) . ' ';
|
||||
} else {
|
||||
$detail = '';
|
||||
}
|
||||
|
||||
return "$errorType: \t$message $detail ";
|
||||
}
|
||||
|
||||
if($config) {
|
||||
$debug = $config->debug;
|
||||
$sendOutput = $config->allowExceptions !== true;
|
||||
if($config->ajax) $http = false;
|
||||
if((function_exists("\\ProcessWire\\wireMail") || function_exists("wireMail")) && $config->adminEmail && $sendOutput) {
|
||||
$logMessage = "Page: $path\nUser: $userName\n\n" . str_replace("\t", "\n", $message);
|
||||
wireMail($config->adminEmail, $config->adminEmail, $this->labels['email-subject'], $logMessage);
|
||||
}
|
||||
if($config->paths->logs) {
|
||||
$logMessage = "$userName\t$path\t" . str_replace("\n", " ", $message);
|
||||
$log = $this->wire(new FileLog($config->paths->logs . 'errors.txt'));
|
||||
$log->setDelimeter("\t");
|
||||
$log->save($logMessage);
|
||||
}
|
||||
/**
|
||||
* Get WireInput instance and create it if not already present in the API
|
||||
*
|
||||
* @return WireInput
|
||||
*
|
||||
*/
|
||||
protected function getWireInput() {
|
||||
/** @var WireInput $input */
|
||||
$input = $this->wire('input');
|
||||
if($input) return $input;
|
||||
$input = $this->wire(new WireInput());
|
||||
return $input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current request URL or "/?/" if it cannot be determined
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
protected function getCurrentUrl() {
|
||||
|
||||
/** @var Page|null $page */
|
||||
$page = $this->wire('page');
|
||||
$input = $this->getWireInput();
|
||||
$http = isset($_SERVER['HTTP_HOST']) || isset($_SERVER['REQUEST_URI']);
|
||||
|
||||
if($http) {
|
||||
// best case, everything available. getting httpUrl requires that $config API var is available...
|
||||
$url = $input->httpUrl();
|
||||
} else if($page) {
|
||||
// this can occur for non-http request like command line
|
||||
$url = $page->url();
|
||||
} else {
|
||||
// unable to determine url
|
||||
$url = '/?/';
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render an error message and reason why
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $why
|
||||
* @param bool $useHTML
|
||||
*
|
||||
*/
|
||||
protected function sendErrorMessage($message, $why, $useHTML) {
|
||||
|
||||
$this->sendExistingOutput();
|
||||
|
||||
// return text-only error
|
||||
if(!$useHTML) {
|
||||
echo "\n\n$message\n\n$why\n\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// output HTML error
|
||||
$html = $this->config->fatalErrorHTML ? $this->config->fatalErrorHTML : self::defaultFatalErrorHTML;
|
||||
$html = str_replace(array(
|
||||
'{message}',
|
||||
'{why}'
|
||||
), array(
|
||||
nl2br(htmlspecialchars($message, ENT_QUOTES, "UTF-8", false)),
|
||||
htmlspecialchars($why, ENT_QUOTES, "UTF-8", false)
|
||||
), $html);
|
||||
|
||||
// make a prettier looking debug backtrace, when applicable
|
||||
$html = preg_replace('!(<br[^>]*>\s*)(#\d+\s+[^<]+)!is', '$1<code>$2</code>', $html);
|
||||
|
||||
// reference original file rather than compiled version, when applicable
|
||||
$html = str_replace('assets/cache/FileCompiler/site/', '', $html);
|
||||
|
||||
// output the error message
|
||||
echo "\n\n$html\n\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a 500 internal server error
|
||||
*
|
||||
* This is a public fatal error that doesn’t reveal anything specific.
|
||||
*
|
||||
* @param string $message Message to indicate who error was also sent to
|
||||
* @param bool $useHTML Output for a web browser?
|
||||
*
|
||||
*/
|
||||
protected function sendError500($message, $useHTML) {
|
||||
|
||||
if($useHTML) {
|
||||
header("HTTP/1.1 500 Internal Server Error");
|
||||
$message = htmlspecialchars($message, ENT_QUOTES, 'UTF-8');
|
||||
// file that error message will be output in, when available
|
||||
$file = $this->config->paths->templates . 'errors/500.html';
|
||||
} else {
|
||||
$file = '';
|
||||
}
|
||||
|
||||
$this->sendExistingOutput();
|
||||
|
||||
if($file && is_file($file)) {
|
||||
// use defined /site/templates/errors/500.html file
|
||||
echo str_replace('{message}', $message, file_get_contents($file));
|
||||
} else {
|
||||
// use generic error message, since no 500.html available
|
||||
echo "\n\n" . $this->labels['unable-complete'] . ($message ? " - $message" : "") . "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send any existing output while removing PHP’s error message from it (to avoid duplication)
|
||||
*
|
||||
*/
|
||||
protected function sendExistingOutput() {
|
||||
|
||||
$files = TemplateFile::getRenderStack();
|
||||
if(!count($files)) return;
|
||||
|
||||
$out = ob_get_clean();
|
||||
if(!strlen($out)) return;
|
||||
|
||||
// if error message isn't in existing output, then reutrn as-is
|
||||
if(empty($this->error['message']) || strpos($out, $this->error['message']) === false) {
|
||||
echo $out;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!$sendOutput) return true;
|
||||
$token = '';
|
||||
do {
|
||||
$token .= 'xPW' . mt_rand() . 'SD';
|
||||
} while(strpos($out, $token) !== false);
|
||||
|
||||
// replace error message with token
|
||||
$out = str_replace($this->error['message'], $token, $out);
|
||||
|
||||
// replace anything else on the same line as the PHP error (error type, file, line-number)
|
||||
$out = preg_replace('/([\r\n]|^)[^\r\n]+' . $token . '[^\r\n]*/', '', $out);
|
||||
|
||||
echo $out;
|
||||
}
|
||||
|
||||
// we populate $who to give an ambiguous indication where the full error message has been sent
|
||||
if($log) $who .= $this->labels['error-logged'] . ' ';
|
||||
if($config && $config->adminEmail) $who .= $this->labels['admin-notified'];
|
||||
/**
|
||||
* Shutdown function registered with PHP
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
public function shutdown() {
|
||||
|
||||
/** @var Config|null $config */
|
||||
/** @var User|null $user */
|
||||
/** @var Page|null $page */
|
||||
|
||||
$error = error_get_last();
|
||||
|
||||
if(!$error) return true;
|
||||
if(!in_array($error['type'], $this->fatalTypes)) return true;
|
||||
|
||||
$this->error = $error;
|
||||
$this->prepareLabels();
|
||||
$config = $this->config;
|
||||
$user = $this->wire('user'); // current user, if present
|
||||
$useHTML = isset($_SERVER['HTTP_HOST']); // is this an HTTP request where we can output HTML?
|
||||
$name = $user ? $user->name : '?'; // user name
|
||||
$why = ''; // reason why error is being shown, when access allows
|
||||
$who = ''; // who/where the error message has been sent
|
||||
$message = $this->getErrorMessage($error);
|
||||
$url = $this->getCurrentUrl();
|
||||
$sendOutput = $config->allowExceptions !== true;
|
||||
|
||||
// use text-only output if an http request that is ajax
|
||||
if($useHTML && $config->ajax) $useHTML = false;
|
||||
|
||||
// include IP address is user name if configured to do so
|
||||
if($config->logIP && isset($_SERVER['REMOTE_ADDR'])) {
|
||||
$ip = $this->wire('session') ? $this->wire('session')->getIP() : $_SERVER['REMOTE_ADDR'];
|
||||
$name = "$name ($ip)";
|
||||
}
|
||||
|
||||
// send error email if applicable
|
||||
if($config->adminEmail && $sendOutput && $this->wire('mail')) {
|
||||
$n = $this->wire('mail')->new()
|
||||
->to($config->adminEmail)
|
||||
->from($config->adminEmail)
|
||||
->subject($this->labels['email-subject'])
|
||||
->body("Page: $url\nUser: $name\n\n" . str_replace("\t", "\n", $message));
|
||||
if($n) $who .= $this->labels['admin-notified'];
|
||||
}
|
||||
|
||||
// save to errors.txt log file if applicable
|
||||
if($config->paths->logs) {
|
||||
$log = $this->wire(new FileLog($config->paths->logs . 'errors.txt'));
|
||||
$log->setDelimeter("\t");
|
||||
$log->save("$name\t$url\t" . str_replace("\n", " ", $message));
|
||||
$who .= ($who ? ' ' : '') . $this->labels['error-logged'];
|
||||
}
|
||||
|
||||
// if not allowed to send output, then do nothing further
|
||||
if(!$sendOutput) return true;
|
||||
|
||||
// we populate $why if we're going to show error details for any of the following reasons:
|
||||
// otherwise $why will NOT be populated with anything
|
||||
if($debug) $why = $this->labels['debug-mode'] . " (\$config->debug = true; => /site/config.php).";
|
||||
else if(!$http) $why = $this->labels['cli-mode'];
|
||||
else if($user && $user->isSuperuser()) $why = $this->labels['you-superuser'];
|
||||
else if($config && is_file($config->paths->root . "install.php")) $why = $this->labels['install-php'];
|
||||
else if($config && !is_file($config->paths->assets . "active.php")) {
|
||||
if($config->debug) {
|
||||
$why = $this->labels['debug-mode'] . " (\$config->debug = true; => /site/config.php).";
|
||||
} else if(!$useHTML) {
|
||||
$why = $this->labels['cli-mode'];
|
||||
} else if($user && $user->isSuperuser()) {
|
||||
$why = $this->labels['you-superuser'];
|
||||
} else if($config && is_file($config->paths->root . "install.php")) {
|
||||
$why = $this->labels['install-php'];
|
||||
} else if($config && $config->paths->assets && !is_file($config->paths->assets . "active.php")) {
|
||||
// no login has ever occurred or user hasn't logged in since upgrade before this check was in place
|
||||
// check the date the site was installed to ensure we're not dealing with an upgrade
|
||||
$installed = $config->paths->assets . "installed.php";
|
||||
@@ -125,40 +363,26 @@ class WireShutdown extends Wire {
|
||||
// site was installed within the last 6 hours, safe to assume it's a new install
|
||||
$why = $this->labels['superuser-never'];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if($why) {
|
||||
// when in debug mode, we can assume the message was already shown, so we just say why.
|
||||
// when not in debug mode, we display the full error message since error_reporting and display_errors are off.
|
||||
$why = $this->labels['shown-because'] . " $why $who";
|
||||
$html = "<p><b>{message}</b><br /><small>{why}</small></p>";
|
||||
if($http) {
|
||||
if($config && $config->fatalErrorHTML) $html = $config->fatalErrorHTML;
|
||||
$html = str_replace(array('{message}', '{why}'), array(
|
||||
nl2br(htmlspecialchars($message, ENT_QUOTES, "UTF-8", false)),
|
||||
htmlspecialchars($why, ENT_QUOTES, "UTF-8", false)), $html);
|
||||
// make a prettier looking debug backtrace, when applicable
|
||||
$html = preg_replace('!(<br[^>]*>\s*)(#\d+\s+[^<]+)!is', '$1<code>$2</code>', $html);
|
||||
$html = str_replace('assets/cache/FileCompiler/site/', '', $html);
|
||||
echo "\n\n$html\n\n";
|
||||
} else {
|
||||
echo "\n\n$message\n\n$why\n\n";
|
||||
}
|
||||
$this->sendErrorMessage($message, $why, $useHTML);
|
||||
} else {
|
||||
// public fatal error that doesn't reveal anything specific
|
||||
if($http) header("HTTP/1.1 500 Internal Server Error");
|
||||
// file that error message will be output in, when available
|
||||
$file = $config && $http ? $config->paths->templates . 'errors/500.html' : '';
|
||||
if($file && is_file($file)) {
|
||||
// use defined /site/templates/errors/500.html file
|
||||
echo str_replace('{message}', $who, file_get_contents($file));
|
||||
} else {
|
||||
// use generic error message, since no 500.html available
|
||||
echo "\n\n" . $this->labels['unable-complete'] . ($who ? " - $who" : "") . "\n\n";
|
||||
}
|
||||
$this->sendError500($who, $useHTML);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Secondary shutdown call when ProcessWire booted externally
|
||||
*
|
||||
*/
|
||||
public function shutdownExternal() {
|
||||
if(error_get_last()) return;
|
||||
$process = $this->wire('process');
|
||||
if($process == 'ProcessPageView') $process->finished();
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user