<?PHP /** * Generic collection of functions used in CSVXML. * * @file * * @author */ declare(strict_types = 1); // Set autoloader # \error_reporting(E_ALL); # \ini_set('display_errors', "1"); \spl_autoload_register("mdCsvxmlAutoloader"); \set_exception_handler("mdExceptionHandler"); \set_error_handler("mdErrorHandler", E_ALL); require_once __DIR__ . '/../inc/constants.php'; require_once __DIR__ . '/../vendor/autoload.php'; /** * Autoloader for museum-digital.org. * * @param string $className Name of the class to load. * * @return void */ function mdCsvxmlAutoloader(string $className):void { // Try using class map as defined through /scripts/buildClassMap.php if (isset(AUTOLOAD_CLASS_MAP[$className])) { include AUTOLOAD_CLASS_MAP[$className]; return; } // Fallback: Load classes by autoload directories foreach (AUTOLOAD_DIRS as $classDir) { if (\file_exists("$classDir/$className.php")) { include "$classDir/$className.php"; return; } } } /** * Own error handler: Set to enforce exit on any error. * * @param integer $errno Error number. * @param string $string Error message. * @param string $file File in which the error occured. * @param integer $line Line number. * * @return void */ function mdErrorHandler(int $errno, string $string, string $file, int $line):void { $getStr = []; foreach ($_GET as $key => $value) { if (is_array($value)) continue; $getStr[] = $key . "=" . $value; } $userMsg = ""; if (isset($_SESSION['anmnam'])) $userMsg .= " User: " . $_SESSION["anmnam"]; if (isset($_SESSION['username'])) $userMsg .= " (" . $_SESSION["username"] . ")"; if ($userMsg) $userMsg = " |--" . $userMsg; $errorMsg = ""; if (!empty($_SERVER) && !empty($_SERVER["HTTP_HOST"])) { $errorPage = $_SERVER['PHP_SELF'] . "?" . implode("&", $getStr); $errorPageFull = "https://" . $_SERVER["HTTP_HOST"] . $errorPage; $errorMsg = "*$errno (<a href='https://www.google.de/search?q=php+" . str_replace(" ", "+", $string) . "'>$string</a>) at $file: line_ $line _"; $errorMsg .= $userMsg; $errorMsg .= " |-- Error generating page: <a href='$errorPageFull'>$errorPage</a>"; $errorMsg .= " |-- Used RAM / Peak RAM / Allowed: " . MD_STD::human_filesize(memory_get_usage()) . " / " . MD_STD::human_filesize(memory_get_peak_usage()) . " / " . ini_get("memory_limit"); $errorMsg = str_replace(PHP_EOL, " ", $errorMsg); error_log($errorMsg); } if ($errno == E_ERROR) exit; } /** * Exception handler to also be able to handle custom exceptions. * * @param Throwable $exception Exception. * * @return void */ function mdExceptionHandler(Throwable $exception):void { $formatErrorPage = function(string $errorMsg = "", string $versionName = "") :string { if (PHP_SAPI === "cli") { return $errorMsg . PHP_EOL; } $output = '<!DOCTYPE html> <html id="errorPage"> <head> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> <meta name="description" content="Validate import CSV files for museum-digital" /> <link rel="manifest" href="./manifest.webmanifest" /> <link rel="stylesheet" type="text/css" href="assets/css/csvxml.min.css" /> <meta name="theme-color" content="#aa4400" /> <meta name="robots" content="noindex" /> <link rel="shortcut icon" sizes="128x128" href="assets/img/mdlogo-csvxml.svg" />'; $output .= ' <title>Error :: '; $output .= $versionName; $output .= '</title> </head> <body> <main> <img src="/assets/img/mdlogo-csvxml.svg" alt="" /> <p>' . $errorMsg . '</p> <nav> <a href="index.php?t=home">Home</a> <a href="index.php?t=museum">Museum</a> <a href="index.php?t=collection">Collection</a> <a href="index.php?t=exhibitions_overview">Exhibition</a> <a href="index.php?t=events">Event</a> <a href="index.php?t=topics">Topics</a> <a href="index.php?t=listen&sv=+&done=yes">Objects</a> </nav> <nav> <a href="index.php?t=kontakt">Contact</a> <a href="index.php?t=impressum">Impressum</a> <a href="index.php?t=privacy">Privacy Policy</a> </nav> </main> </body> </html>'; return $output; }; $errorReporter = new MDErrorReporter("md:csvxml", "bugs-csvxml@museum-digital.de"); $errorCategory = MDErrorReporter::categorizeError($exception); http_response_code(404); switch ($errorCategory) { case MDErrorReporter::MD_ERROR_KNOWN: if (isset($_GET["output"]) and $_GET['output'] === "json") { header('Content-type: application/json'); $output = [ "status" => "Error", "msg" => $exception->getMessage(), ]; echo MD_STD::json_encode($output); exit; } echo $formatErrorPage($exception->getMessage(), ""); exit; default: $errorReporter->sendErrorReport($exception, "joshua@museum-digital.de"); echo $formatErrorPage("Uncaught exception ...<br />Our team has been notified and will get to fixing this error shortly.", ""); exit; } } /** * Function for generating the HTML head. * * @param string $injected Additional code to inject into the head, e.g. a * reference to JS files. * * @return string */ function printHTMLHead(string $injected = ""):string { $output = '<!DOCTYPE HTML> <html lang="en"> <head> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> <meta name="description" content="Validate import CSV files for museum-digital" /> <link rel="stylesheet" type="text/css" href="assets/css/csvxml.min.css" /> <meta name="theme-color" content="#aa4400" /> <link rel="shortcut icon" sizes="128x128" href="assets/img/mdlogo-csvxml.svg" /> <script src="assets/js/csvxml-overview.min.js" type="text/javascript" defer></script> <meta name="robots" content="noindex" /> <title>CSVXML :: museum-digital</title> <meta name="keywords" content="Imports, museum-digital" /> '; $output .= $injected; $output .= ' </head> <body> <h1> <img src="assets/img/mdlogo-csvxml.svg" alt="" /> <span>museum-digital:csvxml</span> </h1> '; return $output; } /** * Function generateHelpTooltip returns a tooltip for hovering over using the common settings. * * @param string $identifier ID attribute of the tooltip. * @param string $title Title of the tooltip. * @param string $explica More in-depth explanation: body of the tooltip. * @param boolean $setParagraph If set to true (default), the content of the tooltip will be put into a <p> element. Optional. * * @return array */ function generateHelpTooltip(string $identifier, string $title, string $explica, bool $setParagraph = true):array { $outputTag = '<a class="newToolTipTag icons iconsHelp" data-for="' . $identifier . '" title="Help"></a>'; $output = '<span class="newToolTip" id="tooltip_' . $identifier . '" data-title="' . $title . '">'; if ($setParagraph) $output .= '<p class="toolTipCont">'; $output .= $explica; if ($setParagraph) $output .= '</p>'; $output .= '</span>'; return [$output, $outputTag]; } /** * Outputs a DOMDocument with correct header and then aborts. * Used mainly for debugging. * * @param DOMDocument $xmlDoc XML object. * * @return string */ function printDOMDocToXML(DOMDocument $xmlDoc):string { return '<?xml version="1.0" encoding="UTF-8"?>' . $xmlDoc->saveXML($xmlDoc->documentElement); } /** * Function for creating a DOMElement with a text node inside. * * @param DOMDocument $xmlDoc XML document. * @param string $tag Tag. * @param string $content Text content. * * @return DOMElement */ function createTextDomElement(DOMDocument $xmlDoc, string $tag, string $content):DOMElement { try { $element = $xmlDoc->createElement($tag); } catch (DOMException $e) { echo "Error at " . __FILE__ . ", line #" . __LINE__ . PHP_EOL . "<br/>"; echo "Cannot create DOM element for $tag / $content"; exit; } $element->appendChild($xmlDoc->createTextNode($content)); return $element; } /** * Function for creating a DOMDocument record channel. * * @return array */ function getBlankRecordChannel():array { $xmlDoc = new DOMDocument("1.0", "UTF-8"); $xmlMainElem = $xmlDoc->createElement("record"); $record_node = $xmlDoc->appendChild($xmlMainElem); //add RSS element to XML node return [$xmlDoc, $record_node]; } /** * Function for removing a directory with all its contents. * * @param string $dir File path of the directory to remove. * * @return void */ function rrmdir(string $dir):void { if (is_dir($dir)) { $objects = scandir($dir); foreach ($objects as $object) { if ($object != "." && $object != "..") { if (filetype($dir . "/" . $object) == "dir") rrmdir($dir . "/" . $object); else unlink($dir . "/" . $object); } } reset($objects); rmdir($dir); } } /** * Function for checking if two arrays have identical values / contents. * * @param array $arrayA First array to compare. * @param array $arrayB Second array to compare. * * @return boolean */ function identical_values(array $arrayA, array $arrayB):bool { sort($arrayA); sort($arrayB); return $arrayA == $arrayB; }