|
|
@@ -2207,49 +2207,38 @@ function sendEmail($to, $subject, $message, $isHtml = true, $attachments = [])
|
|
|
);
|
|
|
}
|
|
|
|
|
|
-function buildOrderPdfLines($order)
|
|
|
+function pdfEncodeWinAnsi($text)
|
|
|
{
|
|
|
- $lines = [
|
|
|
- SITE_FULL_NAME,
|
|
|
- SITE_DEPARTMENT_NAME,
|
|
|
- "",
|
|
|
- SITE_SERVICE_HEADER,
|
|
|
- "Bestellnummer: " . $order["id"],
|
|
|
- "Erstellt am: " . formatDate($order["created_at"]),
|
|
|
- "Name: " . $order["customer_name"],
|
|
|
- "E-Mail: " . $order["customer_email"],
|
|
|
- "Organisation: " . $order["organization_label"],
|
|
|
- "",
|
|
|
- "Artikel:",
|
|
|
- ];
|
|
|
+ $text = str_replace("\r", "", (string) $text);
|
|
|
|
|
|
- foreach ($order["items"] as $item) {
|
|
|
- $line = "- " . $item["product_name"];
|
|
|
- if ($item["size"] !== "") {
|
|
|
- $line .= " | Größe: " . $item["size"];
|
|
|
- }
|
|
|
- if ($item["availability_label"] !== "") {
|
|
|
- $line .=
|
|
|
- " | Hinweis: " .
|
|
|
- preg_replace("/\s+/", " ", $item["availability_label"]);
|
|
|
- }
|
|
|
- $lines[] = $line;
|
|
|
+ if (!function_exists("iconv")) {
|
|
|
+ return preg_replace('/[^\x09\x0A\x20-\x7E]/', "?", $text);
|
|
|
+ }
|
|
|
+
|
|
|
+ $chars = preg_split("//u", $text, -1, PREG_SPLIT_NO_EMPTY);
|
|
|
+ if (!is_array($chars)) {
|
|
|
+ $fallback = @iconv("UTF-8", "Windows-1252//TRANSLIT//IGNORE", $text);
|
|
|
+ return is_string($fallback) ? $fallback : $text;
|
|
|
}
|
|
|
|
|
|
- $lines[] = "";
|
|
|
- $lines[] = "Kommentar:";
|
|
|
- if ($order["comment"] !== "") {
|
|
|
- foreach (
|
|
|
- preg_split('/\r\n|\r|\n/', $order["comment"])
|
|
|
- as $commentLine
|
|
|
- ) {
|
|
|
- $lines[] = $commentLine;
|
|
|
+ $result = "";
|
|
|
+ foreach ($chars as $char) {
|
|
|
+ $converted = @iconv("UTF-8", "Windows-1252", $char);
|
|
|
+ if ($converted !== false) {
|
|
|
+ $result .= $converted;
|
|
|
+ continue;
|
|
|
}
|
|
|
- } else {
|
|
|
- $lines[] = "Kein Kommentar";
|
|
|
+
|
|
|
+ $fallback = @iconv("UTF-8", "Windows-1252//TRANSLIT", $char);
|
|
|
+ if ($fallback !== false && $fallback !== "") {
|
|
|
+ $result .= $fallback;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ $result .= "?";
|
|
|
}
|
|
|
|
|
|
- return $lines;
|
|
|
+ return $result;
|
|
|
}
|
|
|
|
|
|
function pdfEscapeText($text)
|
|
|
@@ -2257,65 +2246,317 @@ function pdfEscapeText($text)
|
|
|
$text = str_replace("\\", "\\\\", $text);
|
|
|
$text = str_replace("(", "\(", $text);
|
|
|
$text = str_replace(")", "\)", $text);
|
|
|
- $text = str_replace("\r", "", $text);
|
|
|
+ return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', "", $text);
|
|
|
+}
|
|
|
|
|
|
- if (function_exists("iconv")) {
|
|
|
- $converted = @iconv("UTF-8", "Windows-1252//TRANSLIT//IGNORE", $text);
|
|
|
- if (is_string($converted)) {
|
|
|
- $text = $converted;
|
|
|
+function pdfWrapAnsiText($text, $maxChars)
|
|
|
+{
|
|
|
+ $lines = [];
|
|
|
+ $paragraphs = explode("\n", str_replace("\r", "", (string) $text));
|
|
|
+
|
|
|
+ foreach ($paragraphs as $paragraph) {
|
|
|
+ $normalized = trim(preg_replace("/\s+/", " ", $paragraph));
|
|
|
+ if ($normalized === "") {
|
|
|
+ $lines[] = "";
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ $words = explode(" ", $normalized);
|
|
|
+ $current = "";
|
|
|
+
|
|
|
+ foreach ($words as $word) {
|
|
|
+ if ($word === "") {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (strlen($word) > $maxChars) {
|
|
|
+ if ($current !== "") {
|
|
|
+ $lines[] = $current;
|
|
|
+ $current = "";
|
|
|
+ }
|
|
|
+
|
|
|
+ $parts = str_split($word, $maxChars);
|
|
|
+ $lastIndex = count($parts) - 1;
|
|
|
+ for ($i = 0; $i < $lastIndex; $i++) {
|
|
|
+ $lines[] = $parts[$i];
|
|
|
+ }
|
|
|
+ $current = $parts[$lastIndex];
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ $candidate = $current === "" ? $word : $current . " " . $word;
|
|
|
+ if (strlen($candidate) <= $maxChars) {
|
|
|
+ $current = $candidate;
|
|
|
+ } else {
|
|
|
+ if ($current !== "") {
|
|
|
+ $lines[] = $current;
|
|
|
+ }
|
|
|
+ $current = $word;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($current !== "") {
|
|
|
+ $lines[] = $current;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return $text;
|
|
|
+ if (empty($lines)) {
|
|
|
+ $lines[] = "";
|
|
|
+ }
|
|
|
+
|
|
|
+ return $lines;
|
|
|
}
|
|
|
|
|
|
function generateOrderPdf($order)
|
|
|
{
|
|
|
- $lines = buildOrderPdfLines($order);
|
|
|
- $content = "BT\n/F1 12 Tf\n14 TL\n50 790 Td\n";
|
|
|
- $first = true;
|
|
|
+ $pageWidth = 595;
|
|
|
+ $pageHeight = 842;
|
|
|
+ $leftMargin = 45;
|
|
|
+ $topY = 800;
|
|
|
+ $bottomY = 60;
|
|
|
+ $lineHeight = 14;
|
|
|
|
|
|
- foreach ($lines as $line) {
|
|
|
- if (!$first) {
|
|
|
- $content .= "T*\n";
|
|
|
+ $pages = [];
|
|
|
+ $pageContent = "";
|
|
|
+ $y = $topY;
|
|
|
+ $pageNumber = 0;
|
|
|
+
|
|
|
+ $encodeText = function ($text) {
|
|
|
+ return pdfEncodeWinAnsi((string) $text);
|
|
|
+ };
|
|
|
+
|
|
|
+ $siteName = $encodeText(SITE_FULL_NAME);
|
|
|
+ $orderId = $encodeText($order["id"]);
|
|
|
+ $createdAt = $encodeText(formatDate($order["created_at"]));
|
|
|
+ $customerName = $encodeText($order["customer_name"]);
|
|
|
+ $customerEmail = $encodeText($order["customer_email"]);
|
|
|
+ $organization = $encodeText($order["organization_label"]);
|
|
|
+ $commentRaw = (string) $order["comment"];
|
|
|
+
|
|
|
+ $writeText = function ($x, $y, $encodedText, $fontSize = 12) use (&$pageContent) {
|
|
|
+ $pageContent .=
|
|
|
+ "BT\n/F1 " .
|
|
|
+ $fontSize .
|
|
|
+ " Tf\n1 0 0 1 " .
|
|
|
+ number_format($x, 2, ".", "") .
|
|
|
+ " " .
|
|
|
+ number_format($y, 2, ".", "") .
|
|
|
+ " Tm\n(" .
|
|
|
+ pdfEscapeText($encodedText) .
|
|
|
+ ") Tj\nET\n";
|
|
|
+ };
|
|
|
+
|
|
|
+ $startPage = function () use (
|
|
|
+ &$pages,
|
|
|
+ &$pageContent,
|
|
|
+ &$y,
|
|
|
+ &$pageNumber,
|
|
|
+ $topY,
|
|
|
+ $leftMargin,
|
|
|
+ $lineHeight,
|
|
|
+ $siteName,
|
|
|
+ $orderId,
|
|
|
+ $createdAt,
|
|
|
+ $writeText,
|
|
|
+ $encodeText
|
|
|
+ ) {
|
|
|
+ if ($pageContent !== "") {
|
|
|
+ $pages[] = $pageContent;
|
|
|
}
|
|
|
- $first = false;
|
|
|
- $content .= "(" . pdfEscapeText($line) . ") Tj\n";
|
|
|
+
|
|
|
+ $pageNumber++;
|
|
|
+ $pageContent = "";
|
|
|
+ $y = $topY;
|
|
|
+
|
|
|
+ foreach (pdfWrapAnsiText($siteName, 70) as $index => $line) {
|
|
|
+ $writeText($leftMargin, $y, $line, $index === 0 ? 15 : 11);
|
|
|
+ $y -= $index === 0 ? 19 : $lineHeight;
|
|
|
+ }
|
|
|
+
|
|
|
+ $headerLine = "Bestellung: " . $orderId;
|
|
|
+ if ($pageNumber > 1) {
|
|
|
+ $headerLine .= " | Seite " . $encodeText($pageNumber);
|
|
|
+ }
|
|
|
+ $writeText($leftMargin, $y, $headerLine, 12);
|
|
|
+ $y -= 17;
|
|
|
+ $writeText($leftMargin, $y, "Erstellt am: " . $createdAt, 11);
|
|
|
+ $y -= 20;
|
|
|
+ };
|
|
|
+
|
|
|
+ $ensureSpace = function ($requiredHeight) use (&$y, $bottomY, $startPage) {
|
|
|
+ if ($y - $requiredHeight < $bottomY) {
|
|
|
+ $startPage();
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ $writeWrapped = function (
|
|
|
+ $encodedText,
|
|
|
+ $maxChars,
|
|
|
+ $fontSize = 11,
|
|
|
+ $x = null
|
|
|
+ ) use (&$y, $lineHeight, $leftMargin, $writeText, $ensureSpace) {
|
|
|
+ $targetX = $x === null ? $leftMargin : $x;
|
|
|
+ $lines = pdfWrapAnsiText($encodedText, $maxChars);
|
|
|
+ foreach ($lines as $line) {
|
|
|
+ $ensureSpace($lineHeight);
|
|
|
+ $writeText($targetX, $y, $line, $fontSize);
|
|
|
+ $y -= $lineHeight;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ $writeSectionTitle = function ($titleText) use (
|
|
|
+ &$y,
|
|
|
+ $leftMargin,
|
|
|
+ $writeText,
|
|
|
+ $ensureSpace,
|
|
|
+ $encodeText
|
|
|
+ ) {
|
|
|
+ $ensureSpace(24);
|
|
|
+ $writeText($leftMargin, $y, $encodeText($titleText), 13);
|
|
|
+ $y -= 18;
|
|
|
+ };
|
|
|
+
|
|
|
+ $startPage();
|
|
|
+
|
|
|
+ $writeSectionTitle("Gehört zu");
|
|
|
+ $writeWrapped("Name: " . $customerName, 80);
|
|
|
+ $writeWrapped("Organisation: " . $organization, 80);
|
|
|
+ $writeWrapped("E-Mail: " . $customerEmail, 80);
|
|
|
+ $y -= 6;
|
|
|
+
|
|
|
+ $writeSectionTitle("Artikelliste");
|
|
|
+
|
|
|
+ $itemNumber = 1;
|
|
|
+ if (empty($order["items"])) {
|
|
|
+ $writeWrapped($encodeText("Keine Artikel"), 80);
|
|
|
+ } else {
|
|
|
+ foreach ($order["items"] as $item) {
|
|
|
+ $itemName = $encodeText($item["product_name"]);
|
|
|
+ $sizeLabel = $encodeText($item["size"]);
|
|
|
+ $hintLabel = $encodeText(
|
|
|
+ preg_replace("/\s+/", " ", (string) $item["availability_label"]),
|
|
|
+ );
|
|
|
+
|
|
|
+ $writeWrapped($encodeText($itemNumber . ". ") . $itemName, 78);
|
|
|
+
|
|
|
+ if ($sizeLabel !== "") {
|
|
|
+ $writeWrapped($encodeText(" Größe: ") . $sizeLabel, 76);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($hintLabel !== "") {
|
|
|
+ $writeWrapped($encodeText(" Hinweis: ") . $hintLabel, 76);
|
|
|
+ }
|
|
|
+
|
|
|
+ $y -= 4;
|
|
|
+ $itemNumber++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $y -= 4;
|
|
|
+ $writeSectionTitle("Kommentar");
|
|
|
+
|
|
|
+ if (trim($commentRaw) === "") {
|
|
|
+ $writeWrapped($encodeText("Kein Kommentar"), 80);
|
|
|
+ } else {
|
|
|
+ foreach (preg_split('/\r\n|\r|\n/', $commentRaw) as $commentLine) {
|
|
|
+ $writeWrapped($encodeText($commentLine), 82);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $y -= 6;
|
|
|
+ $writeSectionTitle("Lagerbearbeitung");
|
|
|
+
|
|
|
+ $warehouseLines = [
|
|
|
+ "Ausgegeben am: ________________________",
|
|
|
+ "Ausgegeben durch: _____________________",
|
|
|
+ "Unterschrift: _________________________",
|
|
|
+ "",
|
|
|
+ "[ ] Vollständig ausgegeben",
|
|
|
+ "[ ] Teilweise ausgegeben",
|
|
|
+ ];
|
|
|
+
|
|
|
+ foreach ($warehouseLines as $line) {
|
|
|
+ if ($line === "") {
|
|
|
+ $ensureSpace($lineHeight);
|
|
|
+ $y -= $lineHeight;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $writeWrapped($encodeText($line), 80);
|
|
|
}
|
|
|
|
|
|
- $content .= "ET";
|
|
|
- $length = strlen($content);
|
|
|
+ if ($pageContent !== "") {
|
|
|
+ $pages[] = $pageContent;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (empty($pages)) {
|
|
|
+ $pages[] = "";
|
|
|
+ }
|
|
|
|
|
|
+ $fontObjectNumber = 3;
|
|
|
$objects = [];
|
|
|
- $objects[] = "1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n";
|
|
|
- $objects[] = "2 0 obj\n<< /Type /Pages /Kids [3 0 R] /Count 1 >>\nendobj\n";
|
|
|
- $objects[] =
|
|
|
- "3 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Contents 4 0 R /Resources << /Font << /F1 5 0 R >> >> >>\nendobj\n";
|
|
|
- $objects[] =
|
|
|
- "4 0 obj\n<< /Length " .
|
|
|
- $length .
|
|
|
- " >>\nstream\n" .
|
|
|
- $content .
|
|
|
- "\nendstream\nendobj\n";
|
|
|
- $objects[] =
|
|
|
- "5 0 obj\n<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>\nendobj\n";
|
|
|
+ $objects[1] = "1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n";
|
|
|
+ $objects[
|
|
|
+ $fontObjectNumber
|
|
|
+ ] = "3 0 obj\n<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >>\nendobj\n";
|
|
|
+
|
|
|
+ $kids = [];
|
|
|
+ $nextObjectNumber = 4;
|
|
|
+ foreach ($pages as $pageStream) {
|
|
|
+ $pageObjectNumber = $nextObjectNumber++;
|
|
|
+ $contentObjectNumber = $nextObjectNumber++;
|
|
|
+
|
|
|
+ $kids[] = $pageObjectNumber . " 0 R";
|
|
|
+ $objects[$pageObjectNumber] =
|
|
|
+ $pageObjectNumber .
|
|
|
+ " 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 " .
|
|
|
+ $pageWidth .
|
|
|
+ " " .
|
|
|
+ $pageHeight .
|
|
|
+ "] /Contents " .
|
|
|
+ $contentObjectNumber .
|
|
|
+ " 0 R /Resources << /Font << /F1 " .
|
|
|
+ $fontObjectNumber .
|
|
|
+ " 0 R >> >> >>\nendobj\n";
|
|
|
+
|
|
|
+ $objects[$contentObjectNumber] =
|
|
|
+ $contentObjectNumber .
|
|
|
+ " 0 obj\n<< /Length " .
|
|
|
+ strlen($pageStream) .
|
|
|
+ " >>\nstream\n" .
|
|
|
+ $pageStream .
|
|
|
+ "\nendstream\nendobj\n";
|
|
|
+ }
|
|
|
+
|
|
|
+ $objects[2] =
|
|
|
+ "2 0 obj\n<< /Type /Pages /Kids [" .
|
|
|
+ implode(" ", $kids) .
|
|
|
+ "] /Count " .
|
|
|
+ count($kids) .
|
|
|
+ " >>\nendobj\n";
|
|
|
+
|
|
|
+ ksort($objects);
|
|
|
|
|
|
$pdf = "%PDF-1.4\n";
|
|
|
$offsets = [0];
|
|
|
- foreach ($objects as $object) {
|
|
|
- $offsets[] = strlen($pdf);
|
|
|
- $pdf .= $object;
|
|
|
+ foreach ($objects as $number => $objectContent) {
|
|
|
+ $offsets[$number] = strlen($pdf);
|
|
|
+ $pdf .= $objectContent;
|
|
|
}
|
|
|
|
|
|
+ $lastObjectNumber = (int) max(array_keys($objects));
|
|
|
$xrefOffset = strlen($pdf);
|
|
|
- $pdf .= "xref\n0 " . (count($objects) + 1) . "\n";
|
|
|
+ $pdf .= "xref\n0 " . ($lastObjectNumber + 1) . "\n";
|
|
|
$pdf .= "0000000000 65535 f \n";
|
|
|
|
|
|
- for ($i = 1; $i <= count($objects); $i++) {
|
|
|
- $pdf .= sprintf("%010d 00000 n \n", $offsets[$i]);
|
|
|
+ for ($i = 1; $i <= $lastObjectNumber; $i++) {
|
|
|
+ if (isset($offsets[$i])) {
|
|
|
+ $pdf .= sprintf("%010d 00000 n \n", $offsets[$i]);
|
|
|
+ } else {
|
|
|
+ $pdf .= "0000000000 00000 f \n";
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- $pdf .= "trailer\n<< /Size " . (count($objects) + 1) . " /Root 1 0 R >>\n";
|
|
|
+ $pdf .= "trailer\n<< /Size " . ($lastObjectNumber + 1) . " /Root 1 0 R >>\n";
|
|
|
$pdf .= "startxref\n" . $xrefOffset . "\n%%EOF";
|
|
|
|
|
|
return $pdf;
|