Template scaffold

This commit is contained in:
David Bomba 2023-09-25 15:56:32 +10:00
parent 909d9ed9df
commit ae7915353f
7 changed files with 240 additions and 80 deletions

View File

@ -11,42 +11,47 @@
namespace App\Http\Controllers;
use App\DataMapper\Analytics\LivePreview;
use App\Factory\CreditFactory;
use App\Factory\InvoiceFactory;
use App\Factory\QuoteFactory;
use App\Factory\RecurringInvoiceFactory;
use App\Http\Requests\Preview\DesignPreviewRequest;
use App\Http\Requests\Preview\PreviewInvoiceRequest;
use App\Jobs\Util\PreviewPdf;
use App\Libraries\MultiDB;
use App\Models\Task;
use App\Utils\Ninja;
use App\Models\Quote;
use App\Models\Client;
use App\Models\ClientContact;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\InvoiceInvitation;
use App\Models\Quote;
use App\Models\RecurringInvoice;
use App\Repositories\CreditRepository;
use App\Repositories\InvoiceRepository;
use App\Repositories\QuoteRepository;
use App\Repositories\RecurringInvoiceRepository;
use App\Models\Payment;
use App\Models\Project;
use App\Utils\HtmlEngine;
use App\Libraries\MultiDB;
use App\Factory\QuoteFactory;
use App\Jobs\Util\PreviewPdf;
use App\Models\ClientContact;
use App\Services\Pdf\PdfMock;
use App\Factory\CreditFactory;
use App\Factory\InvoiceFactory;
use App\Utils\Traits\MakesHash;
use App\Models\RecurringInvoice;
use App\Utils\PhantomJS\Phantom;
use App\Models\InvoiceInvitation;
use App\Services\PdfMaker\Design;
use App\Utils\HostedPDF\NinjaPdf;
use Illuminate\Support\Facades\DB;
use App\Services\PdfMaker\PdfMaker;
use Illuminate\Support\Facades\App;
use App\Repositories\QuoteRepository;
use App\Repositories\CreditRepository;
use App\Utils\Traits\MakesInvoiceHtml;
use Turbo124\Beacon\Facades\LightLogs;
use App\Repositories\InvoiceRepository;
use App\Utils\Traits\Pdf\PageNumbering;
use App\Factory\RecurringInvoiceFactory;
use Illuminate\Support\Facades\Response;
use App\DataMapper\Analytics\LivePreview;
use App\Services\Template\TemplateService;
use App\Repositories\RecurringInvoiceRepository;
use App\Http\Requests\Preview\DesignPreviewRequest;
use App\Services\PdfMaker\Design as PdfDesignModel;
use App\Services\PdfMaker\Design as PdfMakerDesign;
use App\Services\PdfMaker\PdfMaker;
use App\Utils\HostedPDF\NinjaPdf;
use App\Utils\HtmlEngine;
use App\Utils\Ninja;
use App\Utils\PhantomJS\Phantom;
use App\Utils\Traits\MakesHash;
use App\Utils\Traits\MakesInvoiceHtml;
use App\Utils\Traits\Pdf\PageNumbering;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Response;
use Turbo124\Beacon\Facades\LightLogs;
use App\Http\Requests\Preview\PreviewInvoiceRequest;
use App\Models\PurchaseOrder;
class PreviewController extends BaseController
{
@ -67,6 +72,11 @@ class PreviewController extends BaseController
public function show()
{
// if(request()->has('template')){
return $this->template();
// }
nlog("wooops");
if (request()->has('entity') &&
request()->has('entity_id') &&
! empty(request()->input('entity')) &&
@ -132,7 +142,6 @@ class PreviewController extends BaseController
return (new Phantom)->convertHtmlToPdf($maker->getCompiledHTML(true));
}
/** @var \App\Models\User $user */
$user = auth()->user();
@ -342,6 +351,64 @@ class PreviewController extends BaseController
return $response;
}
private function template()
{
/** @var \App\Models\User $user */
$user = auth()->user();
/** @var \App\Models\Company $company */
$company = $user->company();
// $template = request()->input('design');
$design_object = json_decode(json_encode(request()->input('design')),1);
$data = [
'invoices' => Invoice::whereHas('payments')->with('client','payments')->company()->orderBy('id','desc')->take(5)->get(),
'quotes' => Quote::query()->company()->with('client')->orderBy('id','desc')->take(5)->get(),
'credits' => Credit::query()->company()->with('client')->orderBy('id','desc')->take(5)->get(),
'payments' => Payment::query()->company()->with('client')->orderBy('id','desc')->take(5)->get(),
'purchase_orders' => PurchaseOrder::query()->with('vendor')->company()->orderBy('id','desc')->take(5)->get(),
'tasks' => Task::query()->with('client','invoice')->company()->orderBy('id','desc')->take(5)->get(),
'projects' => Project::query()->with('tasks','client')->company()->orderBy('id','desc')->take(5)->get(),
];
nlog($design_object);
$ts = (new TemplateService());
$ts->setTemplate($design_object)
->build($data);
$html = $ts->getHtml();
if (request()->query('html') == 'true') {
return $html;
}
if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') {
return (new Phantom)->convertHtmlToPdf($html);
}
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;
}
$file_path = (new PreviewPdf($html, $company))->handle();
$response = Response::make($file_path, 200);
$response->header('Content-Type', 'application/pdf');
return $response;
}
private function blankEntity()
{

View File

@ -12,6 +12,7 @@
namespace App\Services\PdfMaker;
use App\Services\Template\TemplateService;
use League\CommonMark\CommonMarkConverter;
class PdfMaker
@ -78,17 +79,13 @@ class PdfMaker
$replacements = [];
$contents = $this->document->getElementsByTagName('ninja');
$twig = (new TemplateService())->twig;
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($this->options);

View File

@ -15,7 +15,6 @@ use App\Models\Task;
use App\Models\Quote;
use App\Models\Credit;
use App\Models\Design;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\Project;
use App\Utils\HtmlEngine;
@ -24,7 +23,6 @@ use App\Models\ClientContact;
use App\Models\PurchaseOrder;
use App\Utils\VendorHtmlEngine;
use App\Utils\PaymentHtmlEngine;
use Illuminate\Support\Collection;
use Twig\Extra\Intl\IntlExtension;
use App\Transformers\TaskTransformer;
use App\Transformers\QuoteTransformer;
@ -41,9 +39,11 @@ class TemplateService
private \DomDocument $document;
public \Twig\Environment $twig;
private string $compiled_html = '';
public function __construct(public Design $template)
public function __construct(public ?Design $template = null)
{
$this->template = $template;
$this->init();
@ -59,6 +59,12 @@ class TemplateService
$this->document = new \DOMDocument();
$this->document->validateOnParse = true;
$loader = new \Twig\Loader\FilesystemLoader(storage_path());
$this->twig = new \Twig\Environment($loader);
$string_extension = new \Twig\Extension\StringLoaderExtension();
$this->twig->addExtension($string_extension);
$this->twig->addExtension(new IntlExtension());
return $this;
}
@ -93,24 +99,19 @@ class TemplateService
{
$data = $this->preProcessDataBlocks($data);
$replacements = [];
nlog($data);
// nlog($data);
$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);
$twig->addExtension(new IntlExtension());
$template = $twig->createTemplate(html_entity_decode($template));
$template = $this->twig->createTemplate(html_entity_decode($template));
$template = $template->render($data);
nlog($template);
// nlog($template);
$f = $this->document->createDocumentFragment();
$f->appendXML($template);
@ -140,8 +141,12 @@ nlog($data);
$html = $this->getHtml();
foreach($variables as $key => $variable) {
$html = strtr($html, $variable['labels']);
$html = strtr($html, $variable['values']);
if(isset($variable['labels']) && isset($variable['values']))
{
$html = strtr($html, $variable['labels']);
$html = strtr($html, $variable['values']);
}
}
@$this->document->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
@ -169,6 +174,9 @@ nlog($data);
*/
private function compose(): self
{
if(!$this->template)
return $this;
$html = '';
$html .= $this->template->design->includes;
$html .= $this->template->design->header;
@ -181,6 +189,27 @@ nlog($data);
}
/**
* Inject the template components
* manually
*
* @return self
*/
public function setTemplate(array $partials): self
{nlog($partials);
$html = '';
$html .= $partials['design']['includes'];
$html .= $partials['design']['header'];
$html .= $partials['design']['body'];
$html .= $partials['design']['footer'];
@$this->document->loadHTML($html);
return $this;
}
/**
* Resolves the labels and values needed to replace the string
* holders in the template.
@ -200,7 +229,7 @@ nlog($data);
'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(),
'purchase_orders' => $processed = $value->first() && $value->first()->invitations()->first() ? (new VendorHtmlEngine($value->first()->invitations()->first()))->generateLabelsAndValues() : [],
};
return $processed;
@ -251,6 +280,7 @@ nlog($data);
if($invoice['payments']['data'] ?? false) {
foreach($invoice['payments']['data'] as $keyx => $payment) {
$invoices['data'][$key]['payments'][$keyx]['paymentables']= $payment['paymentables']['data'] ?? [];
$invoices['data'][$key]['payments'][$keyx]['type']= $payment['type']['data'] ?? [];
}
}
@ -264,12 +294,22 @@ nlog($data);
$it = new QuoteTransformer();
$it->setDefaultIncludes(['client']);
$manager = new Manager();
$manager->setSerializer(new ArraySerializer());
$resource = new \League\Fractal\Resource\Collection($quotes, $it, Quote::class);
$i = $manager->createData($resource)->toArray();
$manager->parseIncludes(['client']);
$resource = new \League\Fractal\Resource\Collection($quotes, $it, null);
$resources = $manager->createData($resource)->toArray();
foreach($resources['data'] as $key => $resource) {
$resources['data'][$key]['client'] = $resource['client']['data'] ?? [];
$resources['data'][$key]['client']['contacts'] = $resource['client']['data']['contacts']['data'] ?? [];
}
return $resources['data'];
$i['client']['contacts'] = $i['client']['contacts'][ClientContact::class];
return $i[Quote::class];
}
@ -278,10 +318,18 @@ nlog($data);
$it = new CreditTransformer();
$it->setDefaultIncludes(['client']);
$manager = new Manager();
$manager->setSerializer(new ArraySerializer());
$resource = new \League\Fractal\Resource\Collection($credits, $it, Credit::class);
$i = $manager->createData($resource)->toArray();
return $i[Credit::class];
$resources = $manager->createData($resource)->toArray();
foreach($resources['data'] as $key => $resource) {
$resources['data'][$key]['client'] = $resource['client']['data'] ?? [];
$resources['data'][$key]['client']['contacts'] = $resource['client']['data']['contacts']['data'] ?? [];
}
return $resources['data'];
}
@ -290,22 +338,40 @@ nlog($data);
$it = new PaymentTransformer();
$it->setDefaultIncludes(['client','invoices','paymentables']);
$manager = new Manager();
$manager->setSerializer(new ArraySerializer());
$resource = new \League\Fractal\Resource\Collection($payments, $it, Payment::class);
$i = $manager->createData($resource)->toArray();
return $i[Payment::class];
$resource = new \League\Fractal\Resource\Collection($payments, $it, null);
$resources = $manager->createData($resource)->toArray();
foreach($resources['data'] as $key => $resource) {
$resources['data'][$key]['client'] = $resource['client']['data'] ?? [];
$resources['data'][$key]['client']['contacts'] = $resource['client']['data']['contacts']['data'] ?? [];
$resources['data'][$key]['invoices'] = $invoice['invoices']['data'] ?? [];
}
return $resources['data'];
}
private function processTasks($tasks): array
{
$it = new TaskTransformer();
$it->setDefaultIncludes(['client','tasks','project','invoice']);
$it->setDefaultIncludes(['client','project','invoice']);
$manager = new Manager();
$manager->setSerializer(new ArraySerializer());
$resource = new \League\Fractal\Resource\Collection($tasks, $it, Task::class);
$i = $manager->createData($resource)->toArray();
return $i[Task::class];
$resource = new \League\Fractal\Resource\Collection($tasks, $it, null);
$resources = $manager->createData($resource)->toArray();
foreach($resources['data'] as $key => $resource) {
$resources['data'][$key]['client'] = $resource['client']['data'] ?? [];
$resources['data'][$key]['client']['contacts'] = $resource['client']['data']['contacts']['data'] ?? [];
$resources['data'][$key]['project'] = $resource['project']['data'] ?? [];
$resources['data'][$key]['invoice'] = $resource['invoice'] ?? [];
}
return $resources['data'];
}

View File

@ -12,10 +12,11 @@
namespace App\Transformers;
use App\Models\Client;
use App\Models\Document;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\Document;
use App\Models\Paymentable;
use App\Models\PaymentType;
use App\Utils\Traits\MakesHash;
class PaymentTransformer extends EntityTransformer
@ -72,9 +73,7 @@ class PaymentTransformer extends EntityTransformer
public function includeType(Payment $payment)
{
return [
'type' => $payment->type->translatedType() ?? '',
];
return $this->includeItem($payment, new PaymentTypeTransformer, PaymentType::class);
}
public function transform(Payment $payment)

View File

@ -0,0 +1,25 @@
<?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\Transformers;
use App\Models\Payment;
class PaymentTypeTransformer extends EntityTransformer
{
public function transform(Payment $payment)
{
return [
'name' => $payment->translatedType()
];
}
}

View File

@ -55,7 +55,7 @@ class TaskTransformer extends EntityTransformer
{
$transformer = new InvoiceTransformer($this->serializer);
if (!$task->user) {
if (!$task->invoice) {
return null;
}

View File

@ -102,7 +102,13 @@ class TemplateTest extends TestCase
';
private string $payments_body = '
<ninja>
CoName: $company.name
ClName: $client.name
InNumber: $invoice.number
<ninja>
CoName: $company.name
ClName: $client.name
InNumber: $invoice.number
<table class="min-w-full text-left text-sm font-light">
<thead class="border-b font-medium dark:border-neutral-500">
<tr class="text-sm leading-normal">
@ -129,7 +135,7 @@ class TemplateTest extends TestCase
{% for payment in invoice.payments|filter(payment => payment.is_deleted == false) %}
{% for pivot in payment.paymentables %}
<tr class="border-b dark:border-neutral-500">
<td class="whitespace-nowrap px-6 py-4 font-medium">{{ payment.number }}</td>
<td class="whitespace-nowrap px-6 py-4 font-medium">{{ payment.date }}</td>
@ -221,8 +227,8 @@ class TemplateTest extends TestCase
$data['invoices'] = $invoices;
$ts = $replicated_design->service()->build($data);
nlog("results = ");
nlog($ts->getHtml());
// nlog("results = ");
// nlog($ts->getHtml());
$this->assertNotNull($ts->getHtml());
}
@ -253,8 +259,8 @@ class TemplateTest extends TestCase
$ts = $replicated_design->service()->build($data);
nlog("results = ");
nlog($ts->getHtml());
// nlog("results = ");
// nlog($ts->getHtml());
$this->assertNotNull($ts->getHtml());
}