1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-22 17:31:35 +02:00
invoiceninja/app/Services/Template/TemplateService.php

311 lines
8.3 KiB
PHP
Raw Normal View History

2023-09-22 08:14:25 +02:00
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Services\Template;
use App\Models\Design;
2023-09-22 14:35:43 +02:00
use App\Utils\HtmlEngine;
2023-09-22 14:08:57 +02:00
use App\Utils\VendorHtmlEngine;
use App\Utils\PaymentHtmlEngine;
2023-09-22 14:35:43 +02:00
use Illuminate\Support\Collection;
2023-09-22 08:14:25 +02:00
class TemplateService
{
private \DomDocument $document;
private string $compiled_html = '';
2023-09-22 14:08:57 +02:00
private array $standard_excludes = [
'id',
'client_id',
'assigned_user_id',
'project_id',
'vendor_id',
'design_id',
'company_id',
'recurring_id',
'subscription_id'
];
private array $purchase_excludes = [
'id',
'vendor_id',
'assigned_user_id',
'project_id',
'vendor_id',
'design_id',
'company_id',
'recurring_id',
'subscription_id'
];
2023-09-22 14:35:43 +02:00
2023-09-22 08:14:25 +02:00
public function __construct(public Design $template)
{
$this->template = $template;
$this->init();
}
/**
* Boot Dom Document
*
* @return self
*/
private function init(): self
{
$this->document = new \DOMDocument();
$this->document->validateOnParse = true;
return $this;
}
/**
* Iterate through all of the
* ninja nodes
*
* @param array $data - the payload to be passed into the template
* @return self
*/
2023-09-22 14:35:43 +02:00
public function build(array $data): self
2023-09-22 08:14:25 +02:00
{
$this->compose()
->parseNinjaBlocks($data)
2023-09-22 14:08:57 +02:00
->parseVariables($data);
2023-09-22 08:14:25 +02:00
return $this;
}
public function getHtml(): string
{
return $this->compiled_html;
}
/**
* Parses all Ninja tags in the document
*
* @param array $data
*
* @return self
*/
private function parseNinjaBlocks(array $data): self
{
$data = $this->preProcessDataBlocks($data);
$replacements = [];
2023-09-22 14:35:43 +02:00
nlog($data);
2023-09-22 08:14:25 +02:00
$contents = $this->document->getElementsByTagName('ninja');
foreach ($contents as $content) {
$template = $content->ownerDocument->saveHTML($content);
$loader = new \Twig\Loader\FilesystemLoader(storage_path());
$twig = new \Twig\Environment($loader);
$string_extension = new \Twig\Extension\StringLoaderExtension();
$twig->addExtension($string_extension);
$template = $twig->createTemplate(html_entity_decode($template));
$template = $template->render($data);
$f = $this->document->createDocumentFragment();
$f->appendXML($template);
$replacements[] = $f;
}
foreach($contents as $key => $content) {
$content->parentNode->replaceChild($replacements[$key], $content);
}
$this->save();
return $this;
}
/**
* Parses all variables in the document
2023-09-22 14:35:43 +02:00
* @param array $data
2023-09-22 08:14:25 +02:00
* @return self
*/
2023-09-22 14:35:43 +02:00
private function parseVariables(array $data): self
2023-09-22 08:14:25 +02:00
{
2023-09-22 14:35:43 +02:00
$variables = $this->resolveHtmlEngine($data);
$html = $this->getHtml();
2023-09-22 08:14:25 +02:00
2023-09-22 14:08:57 +02:00
foreach($variables as $key => $variable) {
2023-09-22 14:35:43 +02:00
$html = strtr($html, $variable['labels']);
2023-09-22 14:08:57 +02:00
$html = strtr($html, $variable['values']);
}
2023-09-22 08:14:25 +02:00
@$this->document->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$this->save();
return $this;
}
/**
* Saves the document and updates the compiled string.
*
* @return self
*/
private function save(): self
{
$this->compiled_html = str_replace('%24', '$', $this->document->saveHTML());
return $this;
}
/**
* compose
*
* @return self
*/
private function compose(): self
{
$html = '';
$html .= $this->template->design->includes;
$html .= $this->template->design->header;
$html .= $this->template->design->body;
$html .= $this->template->design->footer;
@$this->document->loadHTML($html);
return $this;
}
/**
* Resolves the labels and values needed to replace the string
* holders in the template.
*
* @return array
*/
2023-09-22 14:08:57 +02:00
private function resolveHtmlEngine(array $data): array
2023-09-22 08:14:25 +02:00
{
2023-09-22 14:35:43 +02:00
return collect($data)->map(function ($value, $key) {
$processed = [];
2023-09-22 14:08:57 +02:00
match ($key) {
2023-09-22 14:35:43 +02:00
'invoices' => $processed = (new HtmlEngine($value->first()->invitations()->first()))->generateLabelsAndValues(),
'quotes' => $processed = (new HtmlEngine($value->first()->invitations()->first()))->generateLabelsAndValues(),
'credits' => $processed = (new HtmlEngine($value->first()->invitations()->first()))->generateLabelsAndValues(),
'payments' => $processed = (new PaymentHtmlEngine($value->first(), $value->first()->client->contacts()->first()))->generateLabelsAndValues(),
'tasks' => $processed = [],
'projects' => $processed = [],
'purchase_orders' => $processed = (new VendorHtmlEngine($value->first()->invitations()->first()))->generateLabelsAndValues(),
2023-09-22 14:08:57 +02:00
};
return $processed;
})->toArray();
2023-09-22 08:14:25 +02:00
}
private function preProcessDataBlocks($data): array
{
2023-09-22 14:35:43 +02:00
return collect($data)->map(function ($value, $key){
2023-09-22 08:14:25 +02:00
2023-09-22 14:35:43 +02:00
$processed = [];
2023-09-22 08:14:25 +02:00
match ($key) {
2023-09-22 14:35:43 +02:00
'invoices' => $processed = $this->processInvoices($value),
'quotes' => $processed = $this->processQuotes($value),
'credits' => $processed = $this->processCredits($value),
'payments' => $processed = $this->processPayments($value),
'tasks' => $processed = $this->processTasks($value),
'projects' => $processed = $this->processProjects($value),
'purchase_orders' => $processed = $this->processPurchaseOrders($value),
2023-09-22 08:14:25 +02:00
};
return $processed;
})->toArray();
}
2023-09-22 14:08:57 +02:00
private function processInvoices($invoices): Collection
2023-09-22 08:14:25 +02:00
{
2023-09-22 14:35:43 +02:00
return $invoices->map(function($invoice){
return $invoice->makeHidden($this->standard_excludes);
});
2023-09-22 08:14:25 +02:00
}
2023-09-22 14:08:57 +02:00
private function processQuotes($quotes): Collection
2023-09-22 08:14:25 +02:00
{
2023-09-22 14:08:57 +02:00
return $quotes->makeHidden($this->standard_excludes);
// return $quotes->map(function ($quote){
// })->toArray();
2023-09-22 08:14:25 +02:00
}
2023-09-22 14:08:57 +02:00
private function processCredits($credits): Collection
2023-09-22 08:14:25 +02:00
{
2023-09-22 14:08:57 +02:00
return $credits->makeHidden($this->standard_excludes);
// return $credits->map(function ($credit){
// })->toArray();
2023-09-22 08:14:25 +02:00
}
2023-09-22 14:08:57 +02:00
private function processPayments($payments): Collection
2023-09-22 08:14:25 +02:00
{
2023-09-22 14:08:57 +02:00
return $payments->makeHidden([
'id',
'user_id',
'assigned_user_id',
'client_id',
'company_id',
'project_id',
'vendor_id',
'client_contact_id',
'invitation_id',
'company_gateway_id',
'transaction_id',
]);
// return $payments->map(function ($payment){
// })->toArray();
2023-09-22 08:14:25 +02:00
}
2023-09-22 14:08:57 +02:00
private function processTasks($tasks): Collection
2023-09-22 08:14:25 +02:00
{
2023-09-22 14:35:43 +02:00
return $tasks->makeHidden([
2023-09-22 14:08:57 +02:00
'id',
'user_id',
'assigned_user_id',
'client_id',
'company_id',
'project_id',
'invoice_id'
]);
// return $tasks->map(function ($task){
// })->toArray();
2023-09-22 08:14:25 +02:00
}
2023-09-22 14:08:57 +02:00
private function processProjects($projects): Collection
2023-09-22 08:14:25 +02:00
{
2023-09-22 14:08:57 +02:00
return $projects->makeHidden([
'id',
'client_id',
'company_id',
'user_id',
'assigned_user_id',
]);
// return $projects->map(function ($project){
// })->toArray();
2023-09-22 08:14:25 +02:00
}
private function processPurchaseOrders($purchase_orders): array
{
2023-09-22 14:35:43 +02:00
return $purchase_orders->makeHidden($this->purchase_excludes);
2023-09-22 08:14:25 +02:00
2023-09-22 14:08:57 +02:00
// return $purchase_orders->map(function ($purchase_order){
// })->toArray();
2023-09-22 08:14:25 +02:00
}
}