From d7dbde37891671b4a4c9ea2e33c57d9539720d90 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 4 Aug 2020 21:00:19 +1000 Subject: [PATCH] Implement PhantomJS --- .env.example | 3 + app/Http/Controllers/PreviewController.php | 3 +- app/Http/Kernel.php | 2 +- app/Http/Middleware/PhantomSecret.php | 37 +++++++ app/Jobs/Credit/CreateCreditPdf.php | 4 + app/Jobs/Invoice/CreateInvoicePdf.php | 4 + app/Jobs/Quote/CreateQuotePdf.php | 4 + app/Utils/PhantomJS/Phantom.php | 111 +++++++++++++++++++++ config/ninja.php | 2 + resources/views/pdf/html.blade.php | 1 + routes/client.php | 3 + 11 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 app/Http/Middleware/PhantomSecret.php create mode 100644 app/Utils/PhantomJS/Phantom.php create mode 100644 resources/views/pdf/html.blade.php diff --git a/.env.example b/.env.example index 1e13fc0a24c3..83c5abe7471e 100644 --- a/.env.example +++ b/.env.example @@ -51,6 +51,9 @@ ERROR_EMAIL= NINJA_ENVIRONMENT=selfhost +PHANTOMJS_KEY= +PHANTOMJS_SECRET= + SELF_UPDATER_REPO_VENDOR = invoiceninja SELF_UPDATER_REPO_NAME = invoiceninja SELF_UPDATER_USE_BRANCH = v2 diff --git a/app/Http/Controllers/PreviewController.php b/app/Http/Controllers/PreviewController.php index 3a0b4eb845ee..e9f789182245 100644 --- a/app/Http/Controllers/PreviewController.php +++ b/app/Http/Controllers/PreviewController.php @@ -126,14 +126,13 @@ class PreviewController extends BaseController 'company_id' => auth()->user()->company()->id, 'client_id' => $client->id, ]); -info('blank'); + $invitation = factory(\App\Models\InvoiceInvitation::class)->create([ 'user_id' => auth()->user()->id, 'company_id' => auth()->user()->company()->id, 'invoice_id' => $invoice->id, 'client_contact_id' => $contact->id, ]); -info('post invite'); $invoice->setRelation('invitations', $invitation); $invoice->setRelation('client', $client); diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index ca3680122a97..daae0df3cff4 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -115,6 +115,6 @@ class Kernel extends HttpKernel 'locale' => \App\Http\Middleware\Locale::class, 'contact.register' => \App\Http\Middleware\ContactRegister::class, 'shop_token_auth' => \App\Http\Middleware\Shop\ShopTokenAuth::class, - + 'phantom_secret' => \App\Http\Middleware\PhantomSecret::class, ]; } diff --git a/app/Http/Middleware/PhantomSecret.php b/app/Http/Middleware/PhantomSecret.php new file mode 100644 index 000000000000..70180351920a --- /dev/null +++ b/app/Http/Middleware/PhantomSecret.php @@ -0,0 +1,37 @@ +has('phantomjs_secret') && (config('ninja.phantomjs_secret') == $request->input('phantomjs_secret')) ) + { + return $next($request); + } + + return redirect('/'); + + } + +} diff --git a/app/Jobs/Credit/CreateCreditPdf.php b/app/Jobs/Credit/CreateCreditPdf.php index a6f9eeb7a6af..d16aa6b63fd9 100644 --- a/app/Jobs/Credit/CreateCreditPdf.php +++ b/app/Jobs/Credit/CreateCreditPdf.php @@ -20,6 +20,7 @@ use App\Models\Company; use App\Models\Design; use App\Models\Invoice; use App\Utils\HtmlEngine; +use App\Utils\PhantomJS\Phantom; use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesInvoiceHtml; use App\Utils\Traits\NumberFormatter; @@ -67,6 +68,9 @@ class CreateCreditPdf implements ShouldQueue public function handle() { + if(config('ninja.phantomjs_key')) + return (new Phantom)->generate($this->invitation); + $this->credit->load('client'); App::setLocale($this->contact->preferredLocale()); diff --git a/app/Jobs/Invoice/CreateInvoicePdf.php b/app/Jobs/Invoice/CreateInvoicePdf.php index 0b6e878a092f..67a68309bb91 100644 --- a/app/Jobs/Invoice/CreateInvoicePdf.php +++ b/app/Jobs/Invoice/CreateInvoicePdf.php @@ -20,6 +20,7 @@ use App\Models\Company; use App\Models\Design; use App\Models\Invoice; use App\Utils\HtmlEngine; +use App\Utils\PhantomJS\Phantom; use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesInvoiceHtml; use App\Utils\Traits\NumberFormatter; @@ -67,6 +68,9 @@ class CreateInvoicePdf implements ShouldQueue public function handle() { + if(config('ninja.phantomjs_key')) + return (new Phantom)->generate($this->invitation); + App::setLocale($this->contact->preferredLocale()); $path = $this->invoice->client->invoice_filepath(); diff --git a/app/Jobs/Quote/CreateQuotePdf.php b/app/Jobs/Quote/CreateQuotePdf.php index 23580fb6bed0..c3c9f9c298b7 100644 --- a/app/Jobs/Quote/CreateQuotePdf.php +++ b/app/Jobs/Quote/CreateQuotePdf.php @@ -20,6 +20,7 @@ use App\Models\Company; use App\Models\Design; use App\Models\Invoice; use App\Utils\HtmlEngine; +use App\Utils\PhantomJS\Phantom; use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesInvoiceHtml; use App\Utils\Traits\NumberFormatter; @@ -67,6 +68,9 @@ class CreateQuotePdf implements ShouldQueue public function handle() { + if(config('ninja.phantomjs_key')) + return (new Phantom)->generate($this->invitation); + $this->quote->load('client'); App::setLocale($this->contact->preferredLocale()); diff --git a/app/Utils/PhantomJS/Phantom.php b/app/Utils/PhantomJS/Phantom.php new file mode 100644 index 000000000000..a93588ce6d50 --- /dev/null +++ b/app/Utils/PhantomJS/Phantom.php @@ -0,0 +1,111 @@ +{$entity}; + + if($entity == 'invoice') + $path = $entity_obj->client->invoice_filepath(); + + if($entity == 'quote') + $path = $entity_obj->client->quote_filepath(); + + if($entity == 'credit') + $path = $entity_obj->client->credit_filepath(); + + $file_path = $path . $entity_obj->number . '.pdf'; + + $url = rtrim(config('ninja.app_url'), "/") . 'phantom/' . $entity . '/' . $invitation . '?phantomjs_secret='. config('ninja.phantomjs_secret'); + + $json_payload = new \stdClass; + $json_payload->url = $url; + $json_payload->renderType = "pdf"; + + $url = "http://PhantomJScloud.com/api/browser/v2/" . config('ninja.phantomjs_key'); + $payload = json_encode($json_payload); + $options = array( + 'http' => array( + 'header' => "Content-type: application/json\r\n", + 'method' => 'POST', + 'content' => $payload + ) + ); + $context = stream_context_create($options); + $pdf = file_get_contents($url, false, $context); + if ($pdf === FALSE) { /* Handle error */ info("i did not make the PDF from phantom"); } + + Storage::makeDirectory($path, 0755); + + $instance = Storage::disk(config('filesystems.default'))->put($file_path, $pdf); + + return $file_path; + + + } + + public function displayInvitation(string $entity, string $invitation_key) + { + $key = $entity.'_id'; + + $invitation_instance = 'App\Models\\'.ucfirst($entity).'Invitation'; + + $invitation = $invitation_instance::whereRaw("BINARY `key`= ?", [$invitation_key])->first(); + + $entity_obj = $invitation->{$entity}; + + $entity_obj->load('client'); + + App::setLocale($invitation->contact->preferredLocale()); + + $design_id = $entity_obj->design_id ? $entity_obj->design_id : $this->decodePrimaryKey($entity_obj->client->getSetting($entity . '_design_id')); + + $design = Design::find($design_id); + + $designer = new Designer($entity_obj, $design, $entity_obj->client->getSetting('pdf_variables'), $entity); + + $data['html'] = (new HtmlEngine($designer, $invitation, $entity))->build(); + + return view('pdf.html', $data); + } + +} diff --git a/config/ninja.php b/config/ninja.php index b711f0365221..358d25949ab8 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -27,6 +27,8 @@ return [ 'hash_salt' => env('HASH_SALT', ''), 'currency_converter_api_key' => env('OPENEXCHANGE_APP_ID',''), 'enabled_modules' => 32767, + 'phantomjs_key' => env('PHANTOMJS_KEY', false), + 'phantomjs_secret' => env('PHANTOMJS_SECRET', false), 'environment' => env('NINJA_ENVIRONMENT', 'selfhost'), // 'hosted', 'development', 'selfhost', 'reseller' diff --git a/resources/views/pdf/html.blade.php b/resources/views/pdf/html.blade.php new file mode 100644 index 000000000000..46b32073239c --- /dev/null +++ b/resources/views/pdf/html.blade.php @@ -0,0 +1 @@ +{!! $html !!} \ No newline at end of file diff --git a/routes/client.php b/routes/client.php index 5be6c2ad86ca..4d9afff524c5 100644 --- a/routes/client.php +++ b/routes/client.php @@ -73,6 +73,9 @@ Route::group(['middleware' => ['invite_db'], 'prefix' => 'client', 'as' => 'clie Route::get('{entity}/{client_hash}/{invitation_key}', 'ClientPortal\InvitationController@routerForIframe')->name('invoice.client_hash_and_invitation_key'); //should never need this Route::get('payment_hook/{company_gateway_id}/{gateway_type_id}', 'ClientPortal\PaymentHookController@process'); + }); +Route::get('phantom/{entity}/{invitation_key}', '\App\Utils\PhantomJS\Phantom@displayInvitation')->middleware(['invite_db','phantom_secret'])->name('phantom_view'); + Route::fallback('BaseController@notFoundClient');