diff --git a/app/Http/Controllers/BaseController.php b/app/Http/Controllers/BaseController.php index ab3ed18916..535062515c 100644 --- a/app/Http/Controllers/BaseController.php +++ b/app/Http/Controllers/BaseController.php @@ -50,4 +50,21 @@ class BaseController extends Controller return redirect("{$entityTypes}"); } } + + protected function downloadResponse($filename, $contents, $type = 'application/pdf') + { + header('Content-Type: ' . $type); + header('Content-Length: ' . strlen($contents)); + + if (! request()->debug) { + header('Content-disposition: attachment; filename="' . $filename . '"'); + } + + header('Cache-Control: public, must-revalidate, max-age=0'); + header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); + + echo $contents; + + exit; + } } diff --git a/app/Http/Controllers/ClientPortalProposalController.php b/app/Http/Controllers/ClientPortalProposalController.php index 1dd19ab9fc..340b9f1a70 100644 --- a/app/Http/Controllers/ClientPortalProposalController.php +++ b/app/Http/Controllers/ClientPortalProposalController.php @@ -2,11 +2,11 @@ namespace App\Http\Controllers; -use mPDF; use App\Models\Account; use App\Models\Document; use App\Models\Invitation; use App\Ninja\Repositories\ProposalRepository; +use App\Jobs\ConvertProposalToPdf; class ClientPortalProposalController extends BaseController { @@ -39,7 +39,11 @@ class ClientPortalProposalController extends BaseController 'proposalInvitation' => $invitation, ]; - return view('invited.proposal', $data); + if (request()->phantomjs) { + return $proposal->present()->htmlDocument; + } else { + return view('invited.proposal', $data); + } } public function downloadProposal($invitationKey) @@ -50,9 +54,9 @@ class ClientPortalProposalController extends BaseController $proposal = $invitation->proposal; - $mpdf = new mPDF(); - $mpdf->WriteHTML($proposal->present()->htmlDocument); - $mpdf->Output($proposal->present()->filename, 'D'); + $pdf = dispatch(new ConvertProposalToPdf($proposal)); + + $this->downloadResponse($proposal->getFilename(), $pdf); } public function getProposalImage($accountKey, $documentKey) diff --git a/app/Http/Controllers/ProposalController.php b/app/Http/Controllers/ProposalController.php index 299c04f92e..a3f2a3f59b 100644 --- a/app/Http/Controllers/ProposalController.php +++ b/app/Http/Controllers/ProposalController.php @@ -6,6 +6,7 @@ use App\Http\Requests\CreateProposalRequest; use App\Http\Requests\ProposalRequest; use App\Http\Requests\UpdateProposalRequest; use App\Jobs\SendInvoiceEmail; +use App\Jobs\ConvertProposalToPdf; use App\Models\Invoice; use App\Models\Proposal; use App\Models\ProposalTemplate; @@ -17,7 +18,6 @@ use Auth; use Input; use Session; use View; -use mPDF; class ProposalController extends BaseController { @@ -167,14 +167,8 @@ class ProposalController extends BaseController { $proposal = $request->entity(); - $mpdf = new mPDF(); - //$mpdf->showImageErrors = config('app.debug'); - $mpdf->WriteHTML($proposal->present()->htmlDocument); + $pdf = dispatch(new ConvertProposalToPdf($proposal)); - if ($request->debug) { - $mpdf->Output(); - } else { - $mpdf->Output($proposal->present()->filename, 'D'); - } + $this->downloadResponse($proposal->getFilename(), $pdf); } } diff --git a/app/Jobs/ConvertProposalToPdf.php b/app/Jobs/ConvertProposalToPdf.php new file mode 100644 index 0000000000..dc8e27ba7d --- /dev/null +++ b/app/Jobs/ConvertProposalToPdf.php @@ -0,0 +1,25 @@ +proposal = $proposal; + } + + public function handle() + { + $proposal = $this->proposal; + $url = $proposal->getHeadlessLink(); + + $filename = sprintf('%s/storage/app/%s.pdf', base_path(), strtolower(str_random(RANDOM_KEY_LENGTH))); + $pdf = CurlUtils::renderPDF($url, $filename); + + return $pdf; + } +} diff --git a/app/Libraries/CurlUtils.php b/app/Libraries/CurlUtils.php index 7e699c226b..9e1141b4ed 100644 --- a/app/Libraries/CurlUtils.php +++ b/app/Libraries/CurlUtils.php @@ -66,4 +66,32 @@ class CurlUtils return false; } } + + public static function renderPDF($url, $filename) + { + if (! $path = env('PHANTOMJS_BIN_PATH')) { + return false; + } + + $client = Client::getInstance(); + $client->isLazy(); + $client->getEngine()->addOption("--load-images=true"); + $client->getEngine()->setPath($path); + + $request = $client->getMessageFactory()->createPdfRequest($url, 'GET'); + $request->setOutputFile($filename); + //$request->setOrientation('landscape'); + $request->setMargin('0'); + + $response = $client->getMessageFactory()->createResponse(); + $client->send($request, $response); + + if ($response->getStatus() === 200) { + $pdf = file_get_contents($filename); + unlink($filename); + return $pdf; + } else { + return false; + } + } } diff --git a/app/Models/Proposal.php b/app/Models/Proposal.php index 37ffe27b24..b079bf3479 100644 --- a/app/Models/Proposal.php +++ b/app/Models/Proposal.php @@ -96,6 +96,25 @@ class Proposal extends EntityModel { return $this->invoice->invoice_number; } + + public function getLink($forceOnsite = false, $forcePlain = false) + { + $invitation = $this->invitations->first(); + + return $invitation->getLink('proposal', $forceOnsite, $forcePlain); + } + + public function getHeadlessLink() + { + return sprintf('%s?phantomjs=true&phantomjs_secret=%s', $this->getLink(true, true), env('PHANTOMJS_SECRET')); + } + + public function getFilename($extension = 'pdf') + { + $entityType = $this->getEntityType(); + + return trans('texts.proposal') . '_' . $this->invoice->invoice_number . '.' . $extension; + } } Proposal::creating(function ($project) { diff --git a/storage/templates/clean.css b/storage/templates/clean.css index c04e185418..f29644ef12 100755 --- a/storage/templates/clean.css +++ b/storage/templates/clean.css @@ -11,6 +11,7 @@ body { } .blue-upper { + padding-bottom: 8px; font-size: 11px; letter-spacing: 3px; text-transform: uppercase; @@ -94,7 +95,7 @@ a.button:hover { } table td { - padding: 20px 30px; + padding: 20px; } tr.top-header { @@ -122,10 +123,6 @@ tr.top-header p { padding: 0 0 120px 0; } -.card-content { - padding: 80px 30px; -} - tr.block-quote { margin: 50px 0 ; }