*/ /** * Class for handling outputs and logs for museum-digital's background tools. */ class MDOutputHandler { /* * Variables */ /** @var integer */ private $_verbosity; /** @var string */ private $_context; /** @var string */ private $_logfile; /** @var integer */ private $_counter; /** @var boolean */ private $_file_logging; /** @var float */ private $_startTime; /** * Function human_filesize translates byte-level filesizes to human readable ones. * Thanks to Jeffrey Sambells http://jeffreysambells.com/2012/10/25/human-readable-filesize-php * * @param integer $bytes A file size, e.g. returned from filesize(). * @param integer $decimals Number of decimal digits to allow. * * @return string */ final private function _human_filesize(int $bytes, int $decimals = 2):string { $size = ['B','kB','MB','GB','TB','PB','EB','ZB','YB']; $factor = floor((strlen((string)$bytes) - 1) / 3); return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . $size[$factor]; } /** * Setter function for the verbosity option. * * @param integer $input New value of boolean value verbosity. * * @return void */ final public function setVerbosity(int $input = 0):void { $this->_verbosity = $input; } /** * Setter function for the additional context description. * * @param string $input New value. * * @return void */ final public function setContext(string $input = ""):void { $this->_context = $input; } /** * Setter function for file logging. * * @param boolean $input New value. * * @return void */ final public function setFileLogging(bool $input = false):void { $this->_file_logging = $input; if ($this->_file_logging === true) { if (!is_dir(__DIR__ . "/../logs")) mkdir(__DIR__ . "/../logs", 0755); touch($this->_logfile); } } /** * Main function of this class. * Formats a message uniformly and writes it to the log, maybe also to stdout. * * @param string $msg Message to log. * @param integer $statusCode Status code. * 0: Note * 1: Skipped * 2: Update * 3: Error. * * @return void */ final public function toLog(string $msg, int $statusCode = 0):void { // Get parts for generating the message to log. $this->_counter++; // Increment counter $date = date("Y-m-d H:i:s"); // Get current date & time. switch ($statusCode) { case MDConsole::STATUS_SKIPPED: $statusSymbol = "-"; break; case MDConsole::STATUS_UPDATE: $statusSymbol = "U"; break; case MDConsole::STATUS_ERROR: $statusSymbol = "E"; break; case MDConsole::STATUS_DELETION: $statusSymbol = "D"; break; case MDConsole::STATUS_NOTICE: default: $statusSymbol = "N"; break; } if (!empty($this->_context)) $contextStr = "{$this->_context} │ "; else $contextStr = ""; // Generate the message to log. $message = "$statusSymbol │ {$contextStr}#" . sprintf("%1$07s", $this->_counter) . " │ " . sprintf("%1$7s", $this->_human_filesize(memory_get_usage())) . " │ {$date} │ {$msg}" . PHP_EOL; if ($this->_file_logging === true) { file_put_contents($this->_logfile, $message, FILE_APPEND); } if (($this->_verbosity > 0 && in_array($statusCode, [MDConsole::STATUS_UPDATE, MDConsole::STATUS_DELETION, MDConsole::STATUS_ERROR])) || $this->_verbosity === 2) echo $message; if ($this->_counter % 250 === 0) { echo '―――> ' . sprintf("%1$07d", $this->_counter) . " operations processed" . PHP_EOL; echo str_replace("_", "―", sprintf("%'_80s", "_")) . PHP_EOL; } } /** * Constructor function that sets defaults and ensures the logfile exists. */ public function __construct() { $this->_startTime = microtime(true); $this->_counter = 0; $this->setVerbosity(); $this->setContext(); $this->setFileLogging(); $this->_logfile = __DIR__ . "/../logs/" . date("Ymd_His") . ".txt"; // Ensure the log directory exists $this->toLog("Activated logger."); } /** * Destructor. * * @return void */ function __destruct() { $endtime = microtime(true); $this->toLog("Finished operation. Processing duration: " . strval($endtime - $this->_startTime)); } }