From 6ceb940517032e832dde20e4bf1e7162a2c63d82 Mon Sep 17 00:00:00 2001 From: Skylar Ittner Date: Fri, 25 Sep 2020 16:16:37 -0600 Subject: [PATCH] Add label PDF generation API --- api/actions/label.php | 35 ++++++++++ api/apisettings.php | 11 ++++ lib/DeviceLabelPrinter.lib.php | 117 +++++++++++++++++++++++++++++++++ lib/Label.lib.php | 88 +++++++++++++++++++++++++ print/print.php | 95 ++------------------------ 5 files changed, 257 insertions(+), 89 deletions(-) create mode 100644 api/actions/label.php create mode 100644 lib/DeviceLabelPrinter.lib.php create mode 100644 lib/Label.lib.php diff --git a/api/actions/label.php b/api/actions/label.php new file mode 100644 index 0000000..ca6cf6a --- /dev/null +++ b/api/actions/label.php @@ -0,0 +1,35 @@ + $templates]); +} + +if (Machine::exists($VARS["id"])) { + $machine = new Machine($VARS['id']); +} else if (Machine::serialExists($VARS["id"])) { + $machine = new Machine(Machine::getIDFromSerial($VARS['id'])); +} else { + http_response_code(404); + sendJsonResp("Requested ID does not exist.", "ERROR"); +} + +$templates = DeviceLabelPrinter::getLabelTemplates(); + +$labeltype = array_keys($templates)[0]; + +if (array_key_exists($VARS["type"], $templates)) { + $labeltype = $VARS["type"]; +} + +$printer = new DeviceLabelPrinter($labeltype, $machine); + +$printer->servePDF(); diff --git a/api/apisettings.php b/api/apisettings.php index fbe0d1a..e5f0450 100644 --- a/api/apisettings.php +++ b/api/apisettings.php @@ -18,6 +18,17 @@ $APIS = [ "id" => "/^[0-9a-zA-Z]+$/" ] ], + "getlabel" => [ + "load" => "label.php", + "vars" => [ + "id" => "/^[0-9a-zA-Z]+$/", + "type" => "string" + ] + ], + "listlabels" => [ + "load" => "label.php", + "vars" => [] + ], "editmachine" => [ "load" => "machine.php", "vars" => [ diff --git a/lib/DeviceLabelPrinter.lib.php b/lib/DeviceLabelPrinter.lib.php new file mode 100644 index 0000000..fce315f --- /dev/null +++ b/lib/DeviceLabelPrinter.lib.php @@ -0,0 +1,117 @@ +labeltype = $labeltype; + + if (!file_exists($this->getLabelPath())) { + throw new InvalidArgumentException("Label " . $this->getLabelPath() . " does not exist."); + } + + $this->machine = $machine; + } + + public static function getLabelTemplates(): array { + global $SETTINGS; + return $SETTINGS["labels"]["templates"]; + } + + public function getLabelPath(): string { + return __DIR__ . "/../print/templates/$this->labeltype.glabels"; + } + + public function servePDF() { + $this->buildMergeData(); + $label = new Label($this->getLabelPath(), "$this->labeltype (ID " . $this->mergedata['id'] . ")"); + + $label->setFields($this->mergedata); + $label->servePDF(); + } + + /** + * https://stackoverflow.com/a/14167216 + */ + public static function formatPhoneNumber($phoneNumber) { + $phoneNumber = preg_replace('/[^0-9]/', '', $phoneNumber); + + if (strlen($phoneNumber) > 10) { + $countryCode = substr($phoneNumber, 0, strlen($phoneNumber) - 10); + $areaCode = substr($phoneNumber, -10, 3); + $nextThree = substr($phoneNumber, -7, 3); + $lastFour = substr($phoneNumber, -4, 4); + + $phoneNumber = '+' . $countryCode . ' (' . $areaCode . ') ' . $nextThree . '-' . $lastFour; + } else if (strlen($phoneNumber) == 10) { + $areaCode = substr($phoneNumber, 0, 3); + $nextThree = substr($phoneNumber, 3, 3); + $lastFour = substr($phoneNumber, 6, 4); + + $phoneNumber = '(' . $areaCode . ') ' . $nextThree . '-' . $lastFour; + } else if (strlen($phoneNumber) == 7) { + $nextThree = substr($phoneNumber, 0, 3); + $lastFour = substr($phoneNumber, 3, 4); + + $phoneNumber = $nextThree . '-' . $lastFour; + } + + return $phoneNumber; + } + + private function buildMergeData() { + global $SETTINGS; + + $this->mergedata = [ + "id" => $this->machine->getID(), + "price" => number_format($this->machine->getPrice(), 2), + "devicetype" => $this->machine->getTypeLabel(), + "devicetype_lowercase" => strtolower($this->machine->getTypeLabel()), + "serial" => $this->machine->getSerial(), + "model" => $this->machine->getModel(), + "os" => $this->machine->getOS(), + "manufacturer" => $this->machine->getManufacturer(), + "publicnotes" => $this->machine->getPublicNotes(), + "privatenotes" => $this->machine->getPrivateNotes(), + "date" => date($SETTINGS["date_format"]), + "date_time" => date($SETTINGS["datetime_format"]), + "clientid" => "", + "clientname" => "", + "clientphone" => "", + "clientphoneformatted" => "", + "clientemail" => "", + "clientbillingaddress" => "", + "clientshippingaddress" => "", + "clientpublicnotes" => "", + "clientprivatenotes" => "" + ]; + + foreach ($SETTINGS["labels"]["fields"] as $id => $val) { + $this->mergedata[$id] = str_replace("{{id}}", $this->machine->getID(), $val); + } + + if (!empty($this->machine->getClientID())) { + $client = Clients::getClient($this->machine->getClientID()); + $this->mergedata["clientid"] = $client->getID(); + $this->mergedata["clientname"] = $client->getName(); + $this->mergedata["clientphone"] = $client->getPhone(); + $this->mergedata["clientphoneformatted"] = $this->formatPhoneNumber($client->getPhone()); + $this->mergedata["clientemail"] = $client->getEmail(); + $this->mergedata["clientbillingaddress"] = $client->getBillingAddress(); + $this->mergedata["clientshippingaddress"] = $client->getMailingAddress(); + $this->mergedata["clientpublicnotes"] = $client->getPublicNotes(); + $this->mergedata["clientprivatenotes"] = $client->getPrivateNotes(); + } + } + +} diff --git a/lib/Label.lib.php b/lib/Label.lib.php new file mode 100644 index 0000000..4c9d1a1 --- /dev/null +++ b/lib/Label.lib.php @@ -0,0 +1,88 @@ +labelpath = $labelpath; + } else { + throw new InvalidArgumentException("Label $labelpath does not exist."); + } + $this->title = $labeltitle; + } + + /** + * Set the value of a mail merge field. + * @param string $name + * @param string $value + */ + public function setField(string $name, string $value) { + $this->fields[$name] = $value; + } + + /** + * Set multiple mail merge fields at once. + * @param array $fields key => value string array + */ + public function setFields(array $fields) { + foreach ($fields as $name => $value) { + $this->fields[$name] = $value; + } + } + + public function setTitle(string $title) { + $this->title = $title; + } + + private function writeCSVFileAndReturnFilePath(): string { + $csvfile = tempnam(sys_get_temp_dir(), "GLABELS_MERGE_CSV"); + + $fp = fopen($csvfile, 'w'); + fputcsv($fp, array_keys($this->fields)); + fputcsv($fp, array_values($this->fields)); + fclose($fp); + + return $csvfile; + } + + private function toPDFFilePath() { + $csvfile = $this->writeCSVFileAndReturnFilePath(); + $pdffile = tempnam(sys_get_temp_dir(), "GLABELS_MERGE_PDF"); + + shell_exec("glabels-3-batch --input=$csvfile --output=$pdffile " . $this->labelpath); + + unlink($csvfile); + + return $pdffile; + } + + public function servePDF() { + $pdfpath = $this->toPDFFilePath(); + $pdfsize = filesize($pdfpath); + + header('Content-Type: application/pdf'); + header("Content-Length: $pdfsize"); + header("Content-Disposition: inline; filename=\"$this->title\""); + header('Content-Transfer-Encoding: binary'); + header('Accept-Ranges: bytes'); + + echo file_get_contents($pdfpath); + unlink($pdfpath); + } + +} diff --git a/print/print.php b/print/print.php index db8901a..9d35c2c 100644 --- a/print/print.php +++ b/print/print.php @@ -24,99 +24,16 @@ if (!Machine::exists($machineid)) { exit("No such machine."); } -$labeltype = array_keys($SETTINGS["labels"]["templates"])[0]; +$templates = DeviceLabelPrinter::getLabelTemplates(); -if (array_key_exists($VARS["labeltype"], $SETTINGS["labels"]["templates"])) { +$labeltype = array_keys($templates)[0]; + +if (array_key_exists($VARS["labeltype"], $templates)) { $labeltype = $VARS["labeltype"]; } $machine = new Machine($machineid); -$mergedata = [ - "id" => $machine->getID(), - "price" => number_format($machine->getPrice(), 2), - "devicetype" => $machine->getTypeLabel(), - "devicetype_lowercase" => strtolower($machine->getTypeLabel()), - "serial" => $machine->getSerial(), - "model" => $machine->getModel(), - "os" => $machine->getOS(), - "manufacturer" => $machine->getManufacturer(), - "publicnotes" => $machine->getPublicNotes(), - "privatenotes" => $machine->getPrivateNotes(), - "clientid" => "", - "clientname" => "", - "clientphone" => "", - "clientphoneformatted" => "", - "clientemail" => "", - "clientbillingaddress" => "", - "clientshippingaddress" => "", - "clientpublicnotes" => "", - "clientprivatenotes" => "" -]; - -foreach ($SETTINGS["labels"]["fields"] as $id => $val) { - $mergedata[$id] = str_replace("{{id}}", $machine->getID(), $val); -} - -/** - * https://stackoverflow.com/a/14167216 - */ -function formatPhoneNumber($phoneNumber) { - $phoneNumber = preg_replace('/[^0-9]/', '', $phoneNumber); - - if (strlen($phoneNumber) > 10) { - $countryCode = substr($phoneNumber, 0, strlen($phoneNumber) - 10); - $areaCode = substr($phoneNumber, -10, 3); - $nextThree = substr($phoneNumber, -7, 3); - $lastFour = substr($phoneNumber, -4, 4); - - $phoneNumber = '+' . $countryCode . ' (' . $areaCode . ') ' . $nextThree . '-' . $lastFour; - } else if (strlen($phoneNumber) == 10) { - $areaCode = substr($phoneNumber, 0, 3); - $nextThree = substr($phoneNumber, 3, 3); - $lastFour = substr($phoneNumber, 6, 4); - - $phoneNumber = '(' . $areaCode . ') ' . $nextThree . '-' . $lastFour; - } else if (strlen($phoneNumber) == 7) { - $nextThree = substr($phoneNumber, 0, 3); - $lastFour = substr($phoneNumber, 3, 4); - - $phoneNumber = $nextThree . '-' . $lastFour; - } - - return $phoneNumber; -} - -if (!empty($machine->getClientID())) { - $client = Clients::getClient($machine->getClientID()); - $mergedata["clientid"] = $client->getID(); - $mergedata["clientname"] = $client->getName(); - $mergedata["clientphone"] = $client->getPhone(); - $mergedata["clientphoneformatted"] = formatPhoneNumber($client->getPhone()); - $mergedata["clientemail"] = $client->getEmail(); - $mergedata["clientbillingaddress"] = $client->getBillingAddress(); - $mergedata["clientshippingaddress"] = $client->getMailingAddress(); - $mergedata["clientpublicnotes"] = $client->getPublicNotes(); - $mergedata["clientprivatenotes"] = $client->getPrivateNotes(); -} - -$csvfile = tempnam("/tmp", "MCHMGR_CSV"); - -$fp = fopen($csvfile, 'w'); -fputcsv($fp, array_keys($mergedata)); -fputcsv($fp, array_values($mergedata)); -fclose($fp); - -$pdffile = tempnam("/tmp", "MCHMGR_PDF"); - -shell_exec("glabels-3-batch --input=$csvfile --output=$pdffile " . __DIR__ . "/templates/$labeltype.glabels"); - -header('Content-type: application/pdf'); -header("Content-Disposition: inline; filename=\"$labeltype (ID $mergedata[id])\""); -header('Content-Transfer-Encoding: binary'); -header('Accept-Ranges: bytes'); - -echo file_get_contents($pdffile); +$printer = new DeviceLabelPrinter($labeltype, $machine); -unlink($csvfile); -unlink($pdffile); +$printer->servePDF(); \ No newline at end of file