diff --git a/app/Http/Controllers/PreviewController.php b/app/Http/Controllers/PreviewController.php index 27e76dddccc9..0e0e2a420c58 100644 --- a/app/Http/Controllers/PreviewController.php +++ b/app/Http/Controllers/PreviewController.php @@ -28,7 +28,6 @@ use App\Utils\HostedPDF\NinjaPdf; use Illuminate\Support\Facades\DB; use App\Services\PdfMaker\PdfMaker; use Illuminate\Support\Facades\App; -use Illuminate\Support\Facades\Cache; use App\Utils\Traits\MakesInvoiceHtml; use Turbo124\Beacon\Facades\LightLogs; use App\Utils\Traits\Pdf\PageNumbering; @@ -84,141 +83,6 @@ class PreviewController extends BaseController $pdf = $ps->boot()->getPdf(); - - if (Ninja::isHosted()) { - LightLogs::create(new LivePreview()) - ->increment() - ->batch(); - } - - /** Return PDF */ - return response()->streamDownload(function () use ($pdf) { - echo $pdf; - }, 'preview.pdf', [ - 'Content-Disposition' => 'inline', - 'Content-Type' => 'application/pdf', - 'Cache-Control:' => 'no-cache', - 'Server-Timing' => microtime(true)-$start - ]); - - } - - /** - * Refactor - 2023-10-19 - * - * New method does not require Transactions. - * - * @param PreviewInvoiceRequest $request - * @return mixed - */ - public function livexx(PreviewInvoiceRequest $request): mixed - { - - if (Ninja::isHosted() && !in_array($request->getHost(), ['preview.invoicing.co','staging.invoicing.co'])) { - return response()->json(['message' => 'This server cannot handle this request.'], 400); - } - - $start = microtime(true); - - /** Build models */ - $invitation = $request->resolveInvitation(); - $client = $request->getClient(); - $settings = $client->getMergedSettings(); - - /** Set translations */ - App::forgetInstance('translator'); - $t = app('translator'); - App::setLocale($invitation->contact->preferredLocale()); - $t->replace(Ninja::transformTranslations($settings)); - - $entity_prop = str_replace("recurring_", "", $request->entity); - $entity_obj = $invitation->{$request->entity}; - $entity_obj->fill($request->all()); - - /** Update necessary objecty props */ - if(!$entity_obj->id) { - $entity_obj->design_id = intval($this->decodePrimaryKey($settings->{$entity_prop."_design_id"})); - $entity_obj->footer = empty($entity_obj->footer) ? $settings->{$entity_prop."_footer"} : $entity_obj->footer; - $entity_obj->terms = empty($entity_obj->terms) ? $settings->{$entity_prop."_terms"} : $entity_obj->terms; - $entity_obj->public_notes = empty($entity_obj->public_notes) ? $request->getClient()->public_notes : $entity_obj->public_notes; - $invitation->{$request->entity} = $entity_obj; - } - - if(empty($entity_obj->design_id)) { - $entity_obj->design_id = intval($this->decodePrimaryKey($settings->{$entity_prop."_design_id"})); - } - - /** Generate variables */ - $html = new HtmlEngine($invitation); - $html->settings = $settings; - $variables = $html->generateLabelsAndValues(); - - $design = \App\Models\Design::query()->withTrashed()->find($entity_obj->design_id ?? 2); - - if ($design->is_custom) { - $options = [ - 'custom_partials' => json_decode(json_encode($design->design), true), - ]; - $template = new PdfMakerDesign(PdfDesignModel::CUSTOM, $options); - } else { - $template = new PdfMakerDesign(strtolower($design->name)); - } - - $state = [ - 'template' => $template->elements([ - 'client' => $client, - 'entity' => $entity_obj, - 'pdf_variables' => (array) $settings->pdf_variables, - '$product' => $design->design->product, - 'variables' => $variables, - ]), - 'variables' => $variables, - 'options' => [ - 'all_pages_header' => $client->getSetting('all_pages_header'), - 'all_pages_footer' => $client->getSetting('all_pages_footer'), - 'client' => $entity_obj->client ?? [], - 'vendor' => $entity_obj->vendor ?? [], - $request->input('entity')."s" => [$entity_obj], - ], - 'process_markdown' => $client->company->markdown_enabled, - ]; - - $maker = new PdfMaker($state); - - $maker - ->design($template) - ->build(); - - /** Generate HTML */ - $html = $maker->getCompiledHTML(true); - - if (request()->query('html') == 'true') { - return $html; - } - - //if phantom js...... inject here.. - if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') { - return (new Phantom)->convertHtmlToPdf($html); - } - - /** @var \App\Models\User $user */ - $user = auth()->user(); - $company = $user->company(); - - if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') { - - $pdf = (new NinjaPdf())->build($html); - $numbered_pdf = $this->pageNumbering($pdf, $company); - - if ($numbered_pdf) { - $pdf = $numbered_pdf; - } - - return $pdf; - } - - $pdf = (new PreviewPdf($html, $company))->handle(); - if (Ninja::isHosted()) { LightLogs::create(new LivePreview()) ->increment() @@ -429,11 +293,6 @@ class PreviewController extends BaseController } - private function stubTemplateData() - { - - } - private function blankEntity() { diff --git a/app/Jobs/Entity/CreateRawPdf.php b/app/Jobs/Entity/CreateRawPdf.php index 70c5754f9243..57e214784071 100644 --- a/app/Jobs/Entity/CreateRawPdf.php +++ b/app/Jobs/Entity/CreateRawPdf.php @@ -11,34 +11,23 @@ namespace App\Jobs\Entity; -use App\Utils\Ninja; use App\Models\Quote; use App\Models\Credit; -use App\Models\Design; use App\Models\Invoice; -use App\Utils\HtmlEngine; use App\Models\PurchaseOrder; use App\Models\QuoteInvitation; use App\Utils\Traits\MakesHash; use App\Models\CreditInvitation; use App\Models\RecurringInvoice; use App\Services\Pdf\PdfService; -use App\Utils\PhantomJS\Phantom; use App\Models\InvoiceInvitation; -use App\Utils\HostedPDF\NinjaPdf; use App\Utils\Traits\Pdf\PdfMaker; -use Illuminate\Support\Facades\App; -use App\Jobs\Invoice\CreateEInvoice; use App\Utils\Traits\NumberFormatter; use App\Utils\Traits\MakesInvoiceHtml; use App\Models\PurchaseOrderInvitation; use App\Utils\Traits\Pdf\PageNumbering; use App\Exceptions\FilePermissionsFailure; use App\Models\RecurringInvoiceInvitation; -use horstoeko\zugferd\ZugferdDocumentPdfBuilder; -use App\Services\PdfMaker\Design as PdfDesignModel; -use App\Services\PdfMaker\Design as PdfMakerDesign; -use App\Services\PdfMaker\PdfMaker as PdfMakerService; class CreateRawPdf { @@ -79,8 +68,6 @@ class CreateRawPdf $this->entity_string = 'purchase_order'; } - $this->company = $invitation->company; - $this->contact = $invitation->contact; } private function resolveType(): string @@ -112,191 +99,12 @@ class CreateRawPdf ]); $pdf = $ps->boot()->getPdf(); - return $pdf; nlog("pdf timer = ". $ps->execution_time); - - /* Forget the singleton*/ - App::forgetInstance('translator'); - - /* Init a new copy of the translator*/ - $t = app('translator'); - /* Set the locale*/ - App::setLocale($this->contact->preferredLocale()); - - /* Set customized translations _NOW_ */ - $t->replace(Ninja::transformTranslations($this->entity->client->getMergedSettings())); - - if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') { - return (new Phantom)->generate($this->invitation, true); - } - - $entity_design_id = ''; - $path = ''; - - if ($this->entity instanceof Invoice) { - $path = $this->entity->client->invoice_filepath($this->invitation); - $entity_design_id = 'invoice_design_id'; - } elseif ($this->entity instanceof Quote) { - $path = $this->entity->client->quote_filepath($this->invitation); - $entity_design_id = 'quote_design_id'; - } elseif ($this->entity instanceof Credit) { - $path = $this->entity->client->credit_filepath($this->invitation); - $entity_design_id = 'credit_design_id'; - } elseif ($this->entity instanceof RecurringInvoice) { - $path = $this->entity->client->recurring_invoice_filepath($this->invitation); - $entity_design_id = 'invoice_design_id'; - } - - $file_path = $path.$this->entity->numberFormatter().'.pdf'; - - $entity_design_id = $this->entity->design_id ? $this->entity->design_id : $this->decodePrimaryKey($this->entity->client->getSetting($entity_design_id)); - - $design = Design::query()->withTrashed()->find($entity_design_id); - - /* Catch all in case migration doesn't pass back a valid design */ - if (! $design) { - $design = Design::query()->find(2); - } - - $html = new HtmlEngine($this->invitation); - - if ($design->is_custom) { - $options = [ - 'custom_partials' => json_decode(json_encode($design->design), true), - ]; - $template = new PdfMakerDesign(PdfDesignModel::CUSTOM, $options); - } else { - $template = new PdfMakerDesign(strtolower($design->name)); - } - - $variables = $html->generateLabelsAndValues(); - - $state = [ - 'template' => $template->elements([ - 'client' => $this->entity->client, - 'entity' => $this->entity, - 'pdf_variables' => (array) $this->entity->company->settings->pdf_variables, - '$product' => $design->design->product, - 'variables' => $variables, - ]), - 'variables' => $variables, - 'options' => [ - 'all_pages_header' => $this->entity->client->getSetting('all_pages_header'), - 'all_pages_footer' => $this->entity->client->getSetting('all_pages_footer'), - 'client' => $this->entity->client, - 'entity' => $this->entity, - 'variables' => $variables, - ], - 'process_markdown' => $this->entity->client->company->markdown_enabled, - ]; - - $maker = new PdfMakerService($state); - - $maker - ->design($template) - ->build(); - - $pdf = null; - - try { - if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') { - $pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true)); - - $finfo = new \finfo(FILEINFO_MIME); - - //fallback in case hosted PDF fails. - if ($finfo->buffer($pdf) != 'application/pdf; charset=binary') { - $pdf = $this->makePdf(null, null, $maker->getCompiledHTML(true)); - - $numbered_pdf = $this->pageNumbering($pdf, $this->company); - - if ($numbered_pdf) { - $pdf = $numbered_pdf; - } - } - } else { - $pdf = $this->makePdf(null, null, $maker->getCompiledHTML(true)); - - $numbered_pdf = $this->pageNumbering($pdf, $this->company); - - if ($numbered_pdf) { - $pdf = $numbered_pdf; - } - } - } catch (\Exception $e) { - nlog(print_r($e->getMessage(), 1)); - } - - if (config('ninja.log_pdf_html')) { - info($maker->getCompiledHTML()); - } - - if ($pdf) { - $maker =null; - $state = null; - - return $this->checkEInvoice($pdf); - } + return $pdf; throw new FilePermissionsFailure('Unable to generate the raw PDF'); } - /** - * Switch to determine if we need to embed the xml into the PDF itself - * - * @param string $pdf - * @return string - */ - private function checkEInvoice(string $pdf): string - { - if(!$this->entity instanceof Invoice || !$this->company->getSetting('enable_e_invoice')) { - return $pdf; - } - - $e_invoice_type = $this->entity->client->getSetting('e_invoice_type'); - - switch ($e_invoice_type) { - case "EN16931": - case "XInvoice_2_2": - case "XInvoice_2_1": - case "XInvoice_2_0": - case "XInvoice_1_0": - case "XInvoice-Extended": - case "XInvoice-BasicWL": - case "XInvoice-Basic": - return $this->embedEInvoiceZuGFerD($pdf) ?? $pdf; - //case "Facturae_3.2": - //case "Facturae_3.2.1": - //case "Facturae_3.2.2": - // - default: - return $pdf; - } - - } - - /** - * Embed the .xml file into the PDF - * - * @param string $pdf - * @return string - */ - private function embedEInvoiceZuGFerD(string $pdf): string - { - try { - - $e_rechnung = (new CreateEInvoice($this->entity, true))->handle(); - $pdfBuilder = new ZugferdDocumentPdfBuilder($e_rechnung, $pdf); - $pdfBuilder->generateDocument(); - return $pdfBuilder->downloadString(basename($this->entity->getFileName())); - - } catch (\Exception $e) { - nlog("E_Invoice Merge failed - " . $e->getMessage()); - } - - return $pdf; - } - public function failed($e) { } diff --git a/app/Services/Client/Statement.php b/app/Services/Client/Statement.php index 41a2f7127ca6..53c15a736901 100644 --- a/app/Services/Client/Statement.php +++ b/app/Services/Client/Statement.php @@ -158,8 +158,7 @@ class Statement ->where('company_id', $this->client->company_id) ->first(); - $ts = $template->service(); - $ts->build([ + $ts = $template->service()->build([ 'variables' => collect([$variables]), 'invoices' => $this->getInvoices()->get(), 'payments' => $this->options['show_payments_table'] ? $this->getPayments()->get() : collect([]), @@ -167,7 +166,6 @@ class Statement 'aging' => $this->options['show_aging_table'] ? $this->getAging() : collect([]), ]); - // $ts->overrideVariables([$variables]); $html = $ts->getHtml(); return $this->convertToPdf($html); diff --git a/app/Services/Pdf/PdfBuilder.php b/app/Services/Pdf/PdfBuilder.php index ef2328955d56..1ebf44467a45 100644 --- a/app/Services/Pdf/PdfBuilder.php +++ b/app/Services/Pdf/PdfBuilder.php @@ -65,11 +65,11 @@ class PdfBuilder public function build(): self { $this->getTemplate() - ->buildSections() - ->getEmptyElements() - ->updateElementProperties() - ->parseTwigElements() - ->updateVariables(); + ->buildSections() + ->getEmptyElements() + ->updateElementProperties() + ->parseTwigElements() + ->updateVariables(); return $this; } @@ -1680,6 +1680,7 @@ class PdfBuilder } if ($contains_html) { + // If the element contains the HTML, we gonna display it as is. Backend is going to // encode it for us, preventing any errors on the processing stage. // Later, we decode this using Javascript so it looks like it's normal HTML being injected. @@ -1688,9 +1689,11 @@ class PdfBuilder $_child = $this->document->createElement($child['element'], ''); $_child->setAttribute('data-state', 'encoded-html'); $_child->nodeValue = htmlspecialchars($child['content']); + + } else { // .. in case string doesn't contain any HTML, we'll just return - // raw $content. + // raw $content $_child = $this->document->createElement($child['element'], isset($child['content']) ? htmlspecialchars($child['content']) : ''); } diff --git a/app/Services/Pdf/PdfConfiguration.php b/app/Services/Pdf/PdfConfiguration.php index 3b97e841c1ab..a5783fbb4a8c 100644 --- a/app/Services/Pdf/PdfConfiguration.php +++ b/app/Services/Pdf/PdfConfiguration.php @@ -276,7 +276,7 @@ class PdfConfiguration { $design_id = $this->entity->design_id ?: $this->decodePrimaryKey($this->settings_object->getSetting($this->entity_design_id)); - $this->design = Design::withTrashed()->find($design_id ?? 2); + $this->design = Design::withTrashed()->find($design_id) ?? Design::withTrashed()->find(2); return $this; } diff --git a/app/Services/Template/TemplateService.php b/app/Services/Template/TemplateService.php index 84c67de969ee..0528bd133246 100644 --- a/app/Services/Template/TemplateService.php +++ b/app/Services/Template/TemplateService.php @@ -99,7 +99,11 @@ class TemplateService }); $this->twig->addFunction($function); - $filter = new \Twig\TwigFilter('sum', function (array $array, string $column) { + $filter = new \Twig\TwigFilter('sum', function (?array $array, ?string $column) { + + if(!is_array($array)) + return 0; + return array_sum(array_column($array, $column)); }); @@ -1424,11 +1428,11 @@ class TemplateService $_child = $this->document->createElement($child['element'], ''); $_child->setAttribute('data-state', 'encoded-html'); $_child->nodeValue = htmlspecialchars($child['content']); + } else { // .. in case string doesn't contain any HTML, we'll just return // raw $content. - - $_child = $this->document->createElement($child['element'], isset($child['content']) ? htmlspecialchars($child['content']) : ''); + $_child = $this->document->createElement($child['element'], isset($child['content']) ? $child['content'] : ''); } $element->appendChild($_child);