App/lib/60_printer.php

445 lines
18 KiB
PHP

<?php #ajax/print.php
class Printer
{
private $db;
private $man;
private $page;
private $responseCode = 500;
private $prints = [];
private $html = "";
public function __construct($db, $man) {
$this->db = $db;
$this->man = $man;
$this->page = $this->man->Route();
$qry = "SELECT l.ID,l.Bezeichnung,l.Hauptblock,b.Css,b.Breite,b.Höhe FROM sys_print_layouts l "
."LEFT JOIN sys_print_blocks b ON l.Hauptblock=b.ID WHERE Seite=? ORDER BY l.Bevorzugt DESC, l.Bezeichnung ASC";
if ($stmt = $this->db->prepare($qry)) {
$stmt->bind_param("s", $this->page);
$stmt->execute();
$res = $stmt->get_result();
while ($row = $res->fetch_assoc()) {
$this->prints[] = [
"ID" => strval($row["ID"]),
"Bezeichnung" => $row["Bezeichnung"],
"Hauptblock" => $row["Hauptblock"],
"Css" => $row["Css"],
"Breite" => $row["Breite"],
"Höhe" => $row["Höhe"],
];
} } }
public function GetPrints() {
return $this->prints;
}
public function CreateHtml($printID) {
// Find requested layout
$layout = null;
foreach ($this->prints as $key => $print) {
if (strval($printID)==$print["ID"]) {
$layout = $print;
break;
} }
// Breakoff if layout doesn't exist
if (null == $layout) {
$this->responseCode = 400;
return;
}
// Get content
$content = $this->man->Output()["content"];
$block = [
"ID" => $layout["Hauptblock"],
"Bezeichnung" => $layout["Bezeichnung"],
"Css" => $layout["Css"],
"Breite" => $layout["Breite"],
"Höhe" => $layout["Höhe"],
"Links" => 0,
"Oben" => 0
];
$entries = $this->prepareEntries($content);
$this->printBlock($block, $entries);
$this->html.= $this->joinHtml($entries);
$this->responseCode = 200;
}
public function GetHtml() {
return $this->html;
}
public function ResponseCode() {
return $this->responseCode;
}
/******************** Private functions *************************/
private function prepareEntries($content) {
$ret = [];
$selectionExists = sizeof($this->man->selected)>0;
foreach ($content as $group) {
foreach ($group["ENTRIES"] as $entry) {
if (!$selectionExists || in_array($entry["ID"], $this->man->selected)) {
$ret[$entry["ID"]] = [
"html" => "",
"floating" => [],
"content" => $entry,
];
} } }
return $ret;
}
private function joinHtml($entries) {
$ret = "";
foreach ($entries as $entry) {
$ret.= $entry["html"];
}
return $ret;
}
private function printBlock($block, &$entries) {
// Initialize block
$div = "<div name='".$block["Bezeichnung"]."' style='".$block["Css"]
."width:".($block["Breite"]/10)."mm;height:".($block["Höhe"]/10)."mm;left:".($block["Links"]/10)."mm;top:".($block["Oben"]/10)."mm;'>";
foreach ($entries as &$entry) {
$entry["html"].= $div;
}
unset($entry); // $entry was used as a reference, so it needs to be unset
// Fetch sub-blocks
$qry = "SELECT spb.*,sph.Links,sph.Oben FROM sys_print_hierarchy sph LEFT JOIN sys_print_blocks spb ON spb.ID=sph.Kindblock WHERE sph.Block=".$block["ID"];
$res = $this->db->query($qry);
while ($subblock = $res->fetch_assoc()) {
$this->printBlock($subblock, $entries);
}
// Fetch block elements
$elements = [];
if ($res = $this->db->query("SELECT * FROM sys_print_elements WHERE Block=".$block["ID"]." ORDER BY Reihenfolge ASC")) {
while ($element = $res->fetch_assoc()) {
$this->printEntryElement($element, $entries);
//$elements[] = $row;
} }
// Finalize block
foreach ($entries as &$entry) {
$entry["html"].= "</div>";
}
unset($entry);
}
private function printEntryElement($element, &$entries) {
foreach ($entries as &$entry) {
$do_print = false;
$cond = explode("|", $element["Bedingung"]);
if ($element["Parameter"]=="") {
$element["Parameter"] = "{}";
}
$params = json_decode($element["Parameter"], true);
switch ($cond[0]) {
case null:
case "":
case "0": //Print always
$do_print = true;
//echo " - Print always";
break;
case "1": //Field has to be NOT null, not false and not empty text
//echo " - Print if NOT null/false/empty";
if (sizeof($cond)>1 && ($this->getContent($entry["content"], $cond[1])!==null && (
$this->getContent($entry["content"], $cond[1])!==false || $this->getContent($entry["content"], $cond[1], true)!=""
) ) ) {
$do_print = true;
}
break;
case "2": //Field has to be null, false or empty text
//echo " - Print if null/false/empty";
if (sizeof($cond)>1 && ($this->getContent($entry["content"], $cond[1])===null || $this->getContent($entry["content"], $cond[1])===false || $this->getContent($entry["content"], $cond[1], true)==""))
$do_print = true;
break;
case "3": //Field has to be value (second parameter) or include value if is link
if (sizeof($cond)>2) {
// UNTESTED
//echo " - Print if has/includes value ".$cond[2];
$result = $this->getContent($entry["content"], $cond[1]);
$arr = is_array($result);
$do_print = ($arr && in_array($cond[2], $result)) || (!$arr && $cond[2]==$result);
}
break;
case "4": //Field has to be NOT value (second parameter) or DONT include value if is link
if (sizeof($cond)>2) {
// UNTESTED
//echo " - Print if has/includes NOT value ".$cond[2];
$result = $this->getContent($entry["content"], $cond[1]);
$arr = is_array($result);
$do_print = ($arr && !in_array($cond[2], $result)) || (!$arr && $cond[2]!=$result);
}
break;
case "5": //Field has to be text (second parameter) or include text if it is link
if (sizeof($cond)>2) {
//echo " - Print if has/includes text ".$cond[2];
$result = $this->getContent($entry["content"], $cond[1], 1);
$testtexts = explode(",", $cond[2]);
if (is_array($result)) {
$do_print = true;
foreach ($testtexts as $testtext) {
if (!in_array($testtext, $result)) {
$do_print = false;
break;
} }
} else {
$do_print = $cond[2]==$result;
} }
break;
case "6": //Field has to be NOT text (second parameter) or DONT include text if it is link
if (sizeof($cond)>2) {
// UNTESTED
//echo " - Print if has/includes NOT text ".$cond[2];
$result = $this->getContent($entry["content"], $cond[1], 1);
$testtexts = explode(",", $cond[2]);
if (is_array($result)) {
$do_print = true;
foreach ($testtexts as $testtext) {
if (in_array($testtext, $result)) {
$do_print = false;
break;
} }
} else {
$do_print = $cond[2]!=$result;
} }
break;
}
$print_count = 0;
if ($do_print) {
$print_count = $params["repeat"] ?? 1;
}
while ($print_count>0) {
//echo " - Printing";
$print_count--;
$border = array();
$border["top"] = isset($params["border-top"]) ? $params["border-top"] : (isset($params["border"]) ? $params["border"] : "0");
$border["bottom"] = isset($params["border-bottom"]) ? $params["border-bottom"] : (isset($params["border"]) ? $params["border"] : "0");
$border["left"] = isset($params["border-left"]) ? $params["border-left"] : (isset($params["border"]) ? $params["border"] : "0");
$border["right"] = isset($params["border-right"]) ? $params["border-right"] : (isset($params["border"]) ? $params["border"] : "0");
$border["color"] = isset($params["border-color"]) ? $params["border-color"] : "#000000";
$border["string"] = "";
if ($border["left"]!="0") {
$border["string"].= "border-left: 1px solid ".$border["color"]."; ";
}
if ($border["right"]!="0") {
$border["string"].= "border-right: 1px solid ".$border["color"]."; ";
}
if ($border["top"]!="0") {
$border["string"].= "border-top: 1px solid ".$border["color"]."; ";
}
if ($border["bottom"]!="0") {
$border["string"].= "border-bottom: 1px solid ".$border["color"]."; ";
}
/*if (isset($params["border"])) {
$border["string"] = "border: 1px solid ".$border["color"].";";
}*/
$cnt = $element["Inhalt"];
$fields = array();
if (preg_match_all("/#([^#\[\]]+)(?:\[(\d*):(\d*)\])?#/", $cnt, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
$replace = "";
$fields[] = $match[1];
$replace = $this->getContent($entry["content"], $match[1], 1);
if (sizeof($match)>3) {
if ($match[3]!="") {
$replace = substr($replace, 0, intval($match[3]));
}
if ($match[2]!="") {
$replace = substr($replace, intval($match[2]));
}
}
$cnt = str_replace($match[0], $replace, $cnt);
}
}
$left = $element["Links"]/10;
$top = $element["Oben"]/10;
$width = $element["Breite"]/10;
if ($width == 0) {
$width = 10;
}
$height = $element["Höhe"]/10;
if ($height == 0) {
$height = 10;
}
$this->moveIfOverlap($entry["floating"], $left, $top, $width, $height, isset($params["float"]) ? $params["float"] : "none");
$position = "position:absolute;";
if (isset($params["position"])) {
$position = "position:".$params["position"].";";
}
$position.= "z-index:".$element["Reihenfolge"].";";
switch ($element["Art"]) {
case "img":
if (isset($params["aspect"]) && $params["aspect"]=="keep") {
$imgsize = "max-width: ".$width."mm; max-height: ".$height."mm; width: auto; height: auto; ";
}
if (isset($params["aspect"]) && $params["aspect"]=="height") {
$imgsize = "height: ".$height."mm; width: auto; ";
} else {
$imgsize = "width: ".$width."mm; height: ".$height."mm; ";
}
$path = $cnt;
if (count($fields)) {
$path = $cnt;
}
//if (file_exists($path)) {
$entry["html"].= "<img src='".$path."' style='".$position." left: ".$left."mm; top: ".$top."mm; ".$imgsize."' />";
//}
break;
case "text":
$rotate = "";
if (isset($params["rotate"]) && $params["rotate"]=="1") {
$rotate = "transform: rotate(-90deg); ";
$left = "calc(".($left + ($height - $width)/2)."mm - ".$border["left"]."px); ";
$top = "calc(".($top + ($width - $height)/2)."mm - ".$border["top"]."px); ";
} else {
$left.= "mm; ";
$top.= "mm; ";
}
$font = "font-family: ".(isset($params["font"]) && $params["font"]=="narrow" ? "Calibri, Carlito, Arial Narrow, Liberation Sans Narrow, Arial, Liberation Sans; " : "Arial, Liberation Sans; ");
$font.= "font-size: ".(isset($params["size"]) ? $params["size"] : $height)."mm; ";
if (isset($params["weight"])) {
$font.= "font-weight: ".$params["weight"]."; ";
}
if (isset($params["align"])) {
$font.= "text-align: ".$params["align"]."; ";
}
if (isset($params["color"])) {
$font.= "color: ".$params["color"]."; ";
}
$entry["html"].= "<span style='".$position."overflow:hidden;white-space:nowrap;left:".$left."top:".$top."width:".$width."mm;height:"
.$height."mm;".$font.$border["string"].$rotate."'>".$cnt."</span>";
break;
case "circle":
$left.= "mm; ";
$top.= "mm; ";
$display = "display: inline-flex; align-items: center; justify-content: space-around; ";
$font = "font-family: ".(isset($params["font"]) && $params["font"]=="narrow" ? "Calibri, Carlito, Arial Narrow, Liberation Sans Narrow, Arial, Liberation Sans; " : "Arial, Liberation Sans; ");
$font.= "font-size: ".(isset($params["size"]) ? $params["size"] : $height)."mm; ";
if (isset($params["weight"])) {
$font.= "font-weight: ".$params["weight"]."; ";
}
if (isset($params["color"])) {
$font.= "color: ".$params["color"]."; ";
}
$font.= "text-align: center; ";
$background = isset($params["background"]) ? "background-color: ".$params["background"].";" : "";
$entry["html"].= "<span style='".$position."left:".$left."top:".$top."width:".$width."mm;height:".$height."mm;".$display.$background.$font
.$border["string"]."border-radius:50%;'>".$cnt."</span>";
break;
case "quartercircle":
$left.= "mm; ";
$top.= "mm; ";
$background = isset($params["background"]) ? "background-color: ".$params["background"].";" : "";
$border_radius = isset($params["corner"]) ? "border-".$params["corner"]."-radius:100%;" : "border-top-left-radius:100%;";
$entry["html"].= "<span style='".$position."left:".$left."top:".$top."width:".$width."mm;height:".$height."mm;"/*.$display*/.$background/*.$font*/
.$border_radius."'>".$cnt."</span>";
break;
} } }
unset($entry);
}
private function getTextFromReference($ref, $getText) {
if (1==$getText && array_key_exists("KÜRZEL", $ref)) {
return $ref["KÜRZEL"];
} elseif (1<=$getText && array_key_exists("NAME", $ref)) {
return $ref["NAME"];
} elseif (array_key_exists("ID", $ref)) {
return $ref["ID"];
}
return "";
}
// $entry Content-array of entry ([ID, MAIN, SUB])
// $key Requested field
// $getText 0 = ID is sufficient, 1 = Kürzel (prio.) or Name desired, 2 = Name desired
private function getContent($entry, $key, $getText = 0) {
// Check if requested field are actually nested keys separated by dots
$dotPos = strpos($key, ".");
if ($dotPos!==false) {
$subkey = substr($key, 0, $dotPos);
if (array_key_exists($subkey, $entry)) {
return $this->getContent($entry[$subkey], substr($key, $dotPos+1, strlen($key)-$dotPos-1));
} }
// Check if requested field exists
if (array_key_exists($key, $entry)) {
// Check if requested field is an array (which means it was selected through a foreign reference or link table)
if (is_array($entry[$key])) {
// Check if array is size 0 -> This means an unset reference, i.e. NULL
if (0==sizeof($entry[$key])) {
return null;
} elseif (array_key_exists("ID", $entry[$key])) { // Check if requested field is a normal foreign reference -> It will have the ID field then.
// Foreign reference with ID, NAME and maybe KÜRZEL
return $this->getTextFromReference($entry[$key], $getText);
} else { // If not, we assume to have an sequential array which means a n:m-link-table
$ret = [];
foreach ($entry[$key] as $i => $ref) {
$ret[] = $this->getTextFromReference($ref, $getText);
}
return $ret;
}
} else { // Requested field is a normal value
return $entry[$key];
}
} elseif (array_key_exists("MAIN", $entry)) { // If we are in the root structure of a content object, we will have sections MAIN and SUB and check those recursively
// Search the MAIN-array for field
$ret = $this->getContent($entry["MAIN"], $key, $getText);
// If only the field name was returned check SUB-array if exists
if ($key==$ret && array_key_exists("SUB", $entry)) {
$ret = $this->getContent($entry["SUB"], $key, $getText);
}
return $ret;
} else {
// Nothing was found, we return the field name
return $key;
} }
private function moveIfOverlap(&$floating, &$left, &$top, $width, $height, $dir = "none", $lastdir = "none") {
$moved = false;
foreach ($floating as $key => $float) {
if (
$left < $float["right"] &&
$left+$width > $float["left"] &&
$top < $float["bottom"] &&
$top+$height > $float["top"]
) {
if ($float["dir"]=="left" && $lastdir!="right") {
$left = $float["right"];
} else if ($float["dir"]=="right" && $lastdir!="left") {
$left = $float["left"] - $width;
} else if ($float["dir"]=="up" && $lastdir!="down") {
$top = $float["bottom"];
} else if ($float["dir"]=="down" && $lastdir!="up") {
$top = $float["top"] - $height;
}
$lastdir = $float["dir"];
$moved = true;
}
}
if ($moved) {
$this->moveIfOverlap($floating, $left, $top, $width, $height, $dir, $lastdir);
} else if ($dir!="none") {
$floating[] = array(
"left" => $left,
"right" => $left + $width,
"top" => $top,
"bottom" => $top + $height,
"dir" => $dir
);
} }
}