mirror of
https://github.com/processwire/processwire.git
synced 2025-08-09 16:26:59 +02:00
Various improvements to FileLog and WireLog classes. Plus add new deleteAll() and pruneAll() methods to WireLog class.
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Creates and maintains a text-based log file.
|
* Creates and maintains a text-based log file.
|
||||||
*
|
*
|
||||||
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
|
* ProcessWire 3.x, Copyright 2023 by Ryan Cramer
|
||||||
* https://processwire.com
|
* https://processwire.com
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -89,6 +89,7 @@ class FileLog extends Wire {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function __construct($path, $identifier = '') {
|
public function __construct($path, $identifier = '') {
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
if($identifier) {
|
if($identifier) {
|
||||||
$path = rtrim($path, '/') . '/';
|
$path = rtrim($path, '/') . '/';
|
||||||
@@ -98,19 +99,32 @@ class FileLog extends Wire {
|
|||||||
$path = dirname($path) . '/';
|
$path = dirname($path) . '/';
|
||||||
}
|
}
|
||||||
$this->path = $path;
|
$this->path = $path;
|
||||||
if(!is_dir($path)) $this->wire('files')->mkdir($path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __get($key) {
|
/**
|
||||||
if($key == 'delimiter') return $this->delimeter; // @todo learn how to spell
|
* Wired to API
|
||||||
return parent::__get($key);
|
*
|
||||||
|
*/
|
||||||
|
public function wired() {
|
||||||
|
parent::wired();
|
||||||
|
$this->path();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @return mixed
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __get($name) {
|
||||||
|
if($name == 'delimiter') return $this->delimeter; // @todo learn how to spell
|
||||||
|
return parent::__get($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean a string for use in a log file entry
|
* Clean a string for use in a log file entry
|
||||||
*
|
*
|
||||||
* @param $str
|
* @param $str
|
||||||
* @return mixed|string
|
* @return string
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected function cleanStr($str) {
|
protected function cleanStr($str) {
|
||||||
@@ -219,7 +233,7 @@ class FileLog extends Wire {
|
|||||||
|
|
||||||
// if we were creating the file, make sure it has the right permission
|
// if we were creating the file, make sure it has the right permission
|
||||||
if($mode === 'w') {
|
if($mode === 'w') {
|
||||||
$files = $this->wire('files'); /** @var WireFileTools $files */
|
$files = $this->wire()->files;
|
||||||
$files->chmod($this->logFilename);
|
$files->chmod($this->logFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,18 +285,42 @@ class FileLog extends Wire {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get filesize
|
||||||
|
*
|
||||||
|
* @return int|false
|
||||||
|
*
|
||||||
|
*/
|
||||||
public function size() {
|
public function size() {
|
||||||
return filesize($this->logFilename);
|
return filesize($this->logFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get file basename
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
*/
|
||||||
public function filename() {
|
public function filename() {
|
||||||
return basename($this->logFilename);
|
return basename($this->logFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get file pathname
|
||||||
|
*
|
||||||
|
* @return string|bool
|
||||||
|
*
|
||||||
|
*/
|
||||||
public function pathname() {
|
public function pathname() {
|
||||||
return $this->logFilename;
|
return $this->logFilename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get file modification time
|
||||||
|
*
|
||||||
|
* @return int|false
|
||||||
|
*
|
||||||
|
*/
|
||||||
public function mtime() {
|
public function mtime() {
|
||||||
return filemtime($this->logFilename);
|
return filemtime($this->logFilename);
|
||||||
}
|
}
|
||||||
@@ -483,7 +521,7 @@ class FileLog extends Wire {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($options['toFile']) {
|
if($options['toFile']) {
|
||||||
$toFile = $this->path . basename($options['toFile']);
|
$toFile = $this->path() . basename($options['toFile']);
|
||||||
$fp = fopen($toFile, 'w');
|
$fp = fopen($toFile, 'w');
|
||||||
if(!$fp) throw new \Exception("Unable to open file for writing: $toFile");
|
if(!$fp) throw new \Exception("Unable to open file for writing: $toFile");
|
||||||
} else {
|
} else {
|
||||||
@@ -536,7 +574,7 @@ class FileLog extends Wire {
|
|||||||
|
|
||||||
if($fp) {
|
if($fp) {
|
||||||
fclose($fp);
|
fclose($fp);
|
||||||
$this->wire('files')->chmod($toFile);
|
$this->wire()->files->chmod($toFile);
|
||||||
return $cnt;
|
return $cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,8 +591,7 @@ class FileLog extends Wire {
|
|||||||
* @param $line
|
* @param $line
|
||||||
* @param array $options
|
* @param array $options
|
||||||
* @param bool $stopNow Populates this with true when it can determine no more lines are necessary.
|
* @param bool $stopNow Populates this with true when it can determine no more lines are necessary.
|
||||||
* @return bool|int Returns boolean true if valid, false if not.
|
* @return bool Returns boolean true if valid, false if not.
|
||||||
* If valid as a result of a date comparison, the unix timestmap for the line is returned.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected function isValidLine($line, array $options, &$stopNow) {
|
protected function isValidLine($line, array $options, &$stopNow) {
|
||||||
@@ -624,12 +661,14 @@ class FileLog extends Wire {
|
|||||||
fclose($fpw);
|
fclose($fpw);
|
||||||
fclose($fpr);
|
fclose($fpr);
|
||||||
|
|
||||||
|
$files = $this->wire()->files;
|
||||||
|
|
||||||
if($cnt) {
|
if($cnt) {
|
||||||
$this->wire('files')->unlink($filename, true);
|
$files->unlink($filename, true);
|
||||||
$this->wire('files')->rename("$filename.new", $filename, true);
|
$files->rename("$filename.new", $filename, true);
|
||||||
$this->wire('files')->chmod($filename);
|
$files->chmod($filename);
|
||||||
} else {
|
} else {
|
||||||
$this->wire('files')->unlink("$filename.new", true);
|
$files->unlink("$filename.new", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $cnt;
|
return $cnt;
|
||||||
@@ -651,8 +690,9 @@ class FileLog extends Wire {
|
|||||||
'dateTo' => time(),
|
'dateTo' => time(),
|
||||||
));
|
));
|
||||||
if(file_exists($toFile)) {
|
if(file_exists($toFile)) {
|
||||||
$this->wire('files')->unlink($this->logFilename, true);
|
$files = $this->wire()->files;
|
||||||
$this->wire('files')->rename($toFile, $this->logFilename, true);
|
$files->unlink($this->logFilename, true);
|
||||||
|
$files->rename($toFile, $this->logFilename, true);
|
||||||
return $qty;
|
return $qty;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -665,7 +705,7 @@ class FileLog extends Wire {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function delete() {
|
public function delete() {
|
||||||
return $this->wire('files')->unlink($this->logFilename, true);
|
return $this->wire()->files->unlink($this->logFilename, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __toString() {
|
public function __toString() {
|
||||||
@@ -704,6 +744,16 @@ class FileLog extends Wire {
|
|||||||
if($chunkSize > 0) $this->chunkSize = (int) $chunkSize;
|
if($chunkSize > 0) $this->chunkSize = (int) $chunkSize;
|
||||||
return $this->chunkSize;
|
return $this->chunkSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get path where the log is stored (with trailing slash)
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function path() {
|
||||||
|
if(!is_dir($this->path)) $this->wire()->files->mkdir($this->path);
|
||||||
|
return $this->path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
* #pw-summary Enables creation of logs, logging of events, and management of logs.
|
* #pw-summary Enables creation of logs, logging of events, and management of logs.
|
||||||
*
|
*
|
||||||
* ProcessWire 3.x, Copyright 2019 by Ryan Cramer
|
* ProcessWire 3.x, Copyright 2023 by Ryan Cramer
|
||||||
* https://processwire.com
|
* https://processwire.com
|
||||||
*
|
*
|
||||||
* @method bool save($name, $text, $options = array())
|
* @method bool save($name, $text, $options = array())
|
||||||
@@ -139,14 +139,15 @@ class WireLog extends Wire {
|
|||||||
if($options['url']) {
|
if($options['url']) {
|
||||||
$url = $options['url'];
|
$url = $options['url'];
|
||||||
} else {
|
} else {
|
||||||
$input = $this->wire('input');
|
$input = $this->wire()->input;
|
||||||
|
$sanitizer = $this->wire()->sanitizer;
|
||||||
$url = $input ? $input->httpUrl() : '';
|
$url = $input ? $input->httpUrl() : '';
|
||||||
if(strlen($url) && $input) {
|
if(strlen($url) && $input) {
|
||||||
if(count($input->get)) {
|
if(count($input->get)) {
|
||||||
$url .= "?";
|
$url .= "?";
|
||||||
foreach($input->get as $k => $v) {
|
foreach($input->get as $k => $v) {
|
||||||
$k = $this->wire('sanitizer')->name($k);
|
$k = $sanitizer->name($k);
|
||||||
$v = $this->wire('sanitizer')->name($v);
|
$v = $sanitizer->name($v);
|
||||||
$url .= "$k=$v&";
|
$url .= "$k=$v&";
|
||||||
}
|
}
|
||||||
$url = rtrim($url, "&");
|
$url = rtrim($url, "&");
|
||||||
@@ -201,7 +202,8 @@ class WireLog extends Wire {
|
|||||||
/**
|
/**
|
||||||
* Return array of all logs, sorted by name
|
* Return array of all logs, sorted by name
|
||||||
*
|
*
|
||||||
* Each log entry is an array that includes the following:
|
* Each item in returned array is an associative array that includes the following:
|
||||||
|
*
|
||||||
* - `name` (string): Name of log file, excluding extension.
|
* - `name` (string): Name of log file, excluding extension.
|
||||||
* - `file` (string): Full path and filename of log file.
|
* - `file` (string): Full path and filename of log file.
|
||||||
* - `size` (int): Size in bytes
|
* - `size` (int): Size in bytes
|
||||||
@@ -216,13 +218,8 @@ class WireLog extends Wire {
|
|||||||
public function getLogs($sortNewest = false) {
|
public function getLogs($sortNewest = false) {
|
||||||
|
|
||||||
$logs = array();
|
$logs = array();
|
||||||
$dir = new \DirectoryIterator($this->wire('config')->paths->logs);
|
|
||||||
|
|
||||||
foreach($dir as $file) {
|
foreach($this->getFiles() as $name => $file) {
|
||||||
if($file->isDot() || $file->isDir()) continue;
|
|
||||||
if($file->getExtension() != $this->logExtension) continue;
|
|
||||||
$name = basename($file, '.' . $this->logExtension);
|
|
||||||
if($name != $this->wire('sanitizer')->pageName($name)) continue;
|
|
||||||
|
|
||||||
if($sortNewest) {
|
if($sortNewest) {
|
||||||
$sortKey = $file->getMTime();
|
$sortKey = $file->getMTime();
|
||||||
@@ -245,7 +242,7 @@ class WireLog extends Wire {
|
|||||||
ksort($logs);
|
ksort($logs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $logs;
|
return array_values($logs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -260,10 +257,37 @@ class WireLog extends Wire {
|
|||||||
*/
|
*/
|
||||||
public function getFilename($name) {
|
public function getFilename($name) {
|
||||||
$name = strtolower($name);
|
$name = strtolower($name);
|
||||||
if($name !== $this->wire('sanitizer')->pageName($name)) {
|
if($name !== $this->wire()->sanitizer->pageName($name)) {
|
||||||
throw new WireException("Log name must contain only [-_.a-z0-9] with no extension");
|
throw new WireException("Log name must contain only [-_.a-z0-9] with no extension");
|
||||||
}
|
}
|
||||||
return $this->wire('config')->paths->logs . $name . '.' . $this->logExtension;
|
return $this->path() . $name . '.' . $this->logExtension;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get SplFileInfo objects for each log file indexed by log name
|
||||||
|
*
|
||||||
|
* #pw-internal
|
||||||
|
*
|
||||||
|
* @return \SplFileInfo[]
|
||||||
|
* @throws WireException
|
||||||
|
* @since 3.0.214
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function getFiles() {
|
||||||
|
|
||||||
|
$dir = new \DirectoryIterator($this->path());
|
||||||
|
$sanitizer = $this->wire()->sanitizer;
|
||||||
|
$files = array();
|
||||||
|
|
||||||
|
foreach($dir as $file) {
|
||||||
|
if($file->isDot() || $file->isDir()) continue;
|
||||||
|
if($file->getExtension() != $this->logExtension) continue;
|
||||||
|
$name = $file->getBasename(".$this->logExtension");
|
||||||
|
if($name != $sanitizer->pageName($name)) continue;
|
||||||
|
$files[$name] = $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $files;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -299,7 +323,7 @@ class WireLog extends Wire {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function getLines($name, array $options = array()) {
|
public function getLines($name, array $options = array()) {
|
||||||
$pageNum = !empty($options['pageNum']) ? $options['pageNum'] : $this->wire('input')->pageNum;
|
$pageNum = !empty($options['pageNum']) ? $options['pageNum'] : $this->wire()->input->pageNum;
|
||||||
unset($options['pageNum']);
|
unset($options['pageNum']);
|
||||||
$log = $this->getFileLog($name);
|
$log = $this->getFileLog($name);
|
||||||
$limit = isset($options['limit']) ? (int) $options['limit'] : 100;
|
$limit = isset($options['limit']) ? (int) $options['limit'] : 100;
|
||||||
@@ -334,7 +358,7 @@ class WireLog extends Wire {
|
|||||||
|
|
||||||
$log = $this->getFileLog($name);
|
$log = $this->getFileLog($name);
|
||||||
$limit = isset($options['limit']) ? $options['limit'] : 100;
|
$limit = isset($options['limit']) ? $options['limit'] : 100;
|
||||||
$pageNum = !empty($options['pageNum']) ? $options['pageNum'] : $this->wire('input')->pageNum;
|
$pageNum = !empty($options['pageNum']) ? $options['pageNum'] : $this->wire()->input->pageNum;
|
||||||
unset($options['pageNum']);
|
unset($options['pageNum']);
|
||||||
$lines = $log->find($limit, $pageNum, $options);
|
$lines = $log->find($limit, $pageNum, $options);
|
||||||
|
|
||||||
@@ -446,7 +470,7 @@ class WireLog extends Wire {
|
|||||||
*/
|
*/
|
||||||
public function getDate($name, $dateFrom, $dateTo = 0, $limit = 100) {
|
public function getDate($name, $dateFrom, $dateTo = 0, $limit = 100) {
|
||||||
$log = $this->getFileLog($name);
|
$log = $this->getFileLog($name);
|
||||||
$pageNum = $this->wire('input')->pageNum();
|
$pageNum = $this->wire()->input->pageNum();
|
||||||
return $log->getDate($dateFrom, $dateTo, $pageNum, $limit);
|
return $log->getDate($dateFrom, $dateTo, $pageNum, $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,6 +490,35 @@ class WireLog extends Wire {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all log files
|
||||||
|
*
|
||||||
|
* @param bool $throw Throw WireException if any delete fails? (default=false)
|
||||||
|
* @return array Basenames of deleted log files
|
||||||
|
* @since 3.0.214
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function deleteAll($throw = false) {
|
||||||
|
|
||||||
|
$deleted = array();
|
||||||
|
$failed = array();
|
||||||
|
|
||||||
|
foreach($this->getFiles() as $name => $file) {
|
||||||
|
$log = $this->getFileLog($name);
|
||||||
|
if($log && $log->delete()) {
|
||||||
|
$deleted[] = $name;
|
||||||
|
} else {
|
||||||
|
$failed[] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($throw && count($failed)) {
|
||||||
|
throw new WireException("Failed to delete logs: " . implode(', ', $failed));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $deleted;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prune log file to contain only entries from last [n] days
|
* Prune log file to contain only entries from last [n] days
|
||||||
*
|
*
|
||||||
@@ -473,7 +526,7 @@ class WireLog extends Wire {
|
|||||||
*
|
*
|
||||||
* @param string $name Name of log file, excluding path and extension.
|
* @param string $name Name of log file, excluding path and extension.
|
||||||
* @param int $days Number of days
|
* @param int $days Number of days
|
||||||
* @return int Number of items in new log file or boolean false on failure
|
* @return int Number of items in newly pruned log file or boolean false on failure
|
||||||
* @throws WireException
|
* @throws WireException
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -485,6 +538,22 @@ class WireLog extends Wire {
|
|||||||
return $log->pruneDate($oldestDate);
|
return $log->pruneDate($oldestDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prune all log files to given number of days
|
||||||
|
*
|
||||||
|
* @param int $days
|
||||||
|
* @return array
|
||||||
|
* @since 3.0.214
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function pruneAll($days) {
|
||||||
|
$result = array();
|
||||||
|
foreach($this->getFiles() as $name => $filename) {
|
||||||
|
$result[$name] = $this->prune($name, $days);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns instance of FileLog for given log name
|
* Returns instance of FileLog for given log name
|
||||||
*
|
*
|
||||||
@@ -500,6 +569,7 @@ class WireLog extends Wire {
|
|||||||
$filename = $this->getFilename($name);
|
$filename = $this->getFilename($name);
|
||||||
$key = "$filename$delimiter";
|
$key = "$filename$delimiter";
|
||||||
if(isset($this->fileLogs[$key])) return $this->fileLogs[$key];
|
if(isset($this->fileLogs[$key])) return $this->fileLogs[$key];
|
||||||
|
/** @var FileLog $log */
|
||||||
$log = $this->wire(new FileLog($filename));
|
$log = $this->wire(new FileLog($filename));
|
||||||
$log->setDelimiter($delimiter);
|
$log->setDelimiter($delimiter);
|
||||||
$this->fileLogs[$key] = $log;
|
$this->fileLogs[$key] = $log;
|
||||||
@@ -534,4 +604,14 @@ class WireLog extends Wire {
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return disk path to log files
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @since 3.0.214
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function path() {
|
||||||
|
return $this->wire()->config->paths->logs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user