226 lines
7.4 KiB
PHP
226 lines
7.4 KiB
PHP
<?php
|
|
|
|
namespace App\Traits\Controllers;
|
|
|
|
use App\Enums\Claims\ClaimExportFormat;
|
|
use App\Lib\Helpers\FileHelper;
|
|
use Barryvdh\DomPDF\Facade\Pdf;
|
|
use Illuminate\Support\Facades\File;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
|
use ZipArchive;
|
|
|
|
trait ExportDatas
|
|
{
|
|
/**
|
|
* Check if the export needs to be in a .zip file.
|
|
* .zip is needed for :
|
|
* - csv with any files
|
|
* - pdf with files other than pictures
|
|
*
|
|
* @param ClaimExportFormat $format Requested format.
|
|
* @param \Illuminate\Database\Eloquent\Collection $collection Collection of models to export.
|
|
* @param string $fileFieldName Name of the field containing the file.
|
|
* @return boolean
|
|
*/
|
|
public function needsZip(
|
|
ClaimExportFormat $format,
|
|
\Illuminate\Database\Eloquent\Collection $collection,
|
|
string $fileFieldName = 'file'
|
|
): bool {
|
|
if ($format->equals(ClaimExportFormat::csv)) {
|
|
return $collection->whereNotNull($fileFieldName)->pluck($fileFieldName)->isNotEmpty();
|
|
} elseif ($format->equals(ClaimExportFormat::pdf)) {
|
|
return $collection
|
|
->whereNotNull($fileFieldName)
|
|
->whereNotIn('file_extension', ['jpg', 'jpeg', 'png'])
|
|
->isNotEmpty();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Return a StreamedResponse with a zip file.
|
|
*
|
|
* @param ClaimExportFormat $format
|
|
* @param \Illuminate\Database\Eloquent\Collection $claims
|
|
* @param string $file
|
|
* @return \Symfony\Component\HttpFoundation\StreamedResponse
|
|
*/
|
|
public function returnExportZip(
|
|
ClaimExportFormat $format,
|
|
\Illuminate\Database\Eloquent\Collection $claims,
|
|
string $file
|
|
): \Symfony\Component\HttpFoundation\StreamedResponse {
|
|
return new StreamedResponse(function () use ($file, $claims, $format) {
|
|
// Create zip.
|
|
$zip = new ZipArchive();
|
|
$zipName = $this->createExportZip($zip, $file, $format);
|
|
|
|
// Add attachments.
|
|
$this->addAttachmentsToZip($zip, $claims, $format);
|
|
|
|
$zip->close();
|
|
readfile($zipName);
|
|
unlink($zipName);
|
|
}, 200, $this->getFileHeaders($format, true));
|
|
}
|
|
|
|
/**
|
|
* Create the zip folder for the export with the main file inside.
|
|
*
|
|
* @param ZipArchive $zip
|
|
* @param string $file
|
|
* @param ClaimExportFormat $format
|
|
* @return string|false
|
|
*
|
|
* @throws \Exception If the zip opening failed.
|
|
*/
|
|
private function createExportZip(ZipArchive &$zip, string $file, ClaimExportFormat $format): string|false
|
|
{
|
|
$zipName = tempnam(Storage::disk('private')->path('export'), 'zip');
|
|
if (!$zip->open($zipName, ZipArchive::OVERWRITE)) {
|
|
throw new \Exception(__('Couldn\'t open zip file.'));
|
|
};
|
|
$zip->addFromString($format->fileName(), $file);
|
|
|
|
return $zipName;
|
|
}
|
|
|
|
/**
|
|
* Add attachments to zip
|
|
*
|
|
* @param ZipArchive $zip
|
|
* @param \Illuminate\Database\Eloquent\Collection $claims
|
|
* @param ClaimExportFormat $format
|
|
* @param string $fileFieldName Name of the field containing the file.
|
|
* @return void
|
|
*/
|
|
private function addAttachmentsToZip(
|
|
ZipArchive &$zip,
|
|
\Illuminate\Database\Eloquent\Collection $claims,
|
|
ClaimExportFormat $format,
|
|
string $fileFieldName = 'file'
|
|
) {
|
|
$claimsWithFilesToZip = $claims->whereNotNull($fileFieldName)
|
|
->when($format->equals(ClaimExportFormat::pdf), function ($collection) {
|
|
return $collection->whereNotIn('file_extension', ['jpg', 'jpeg', 'png']);
|
|
});
|
|
foreach ($claimsWithFilesToZip as $claim) {
|
|
$filePath = FileHelper::getPrivateFilePath($claim->file);
|
|
if (Storage::disk('private')->exists($filePath)) {
|
|
$zip->addFile(
|
|
Storage::disk('private')->path($filePath),
|
|
$claim->export_file_name
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get file headers to use with StreamedResponse.
|
|
*
|
|
* @param ClaimExportFormat $format
|
|
* @param boolean $isZip
|
|
* @return array
|
|
*/
|
|
public function getFileHeaders(ClaimExportFormat $format, bool $isZip = false): array
|
|
{
|
|
if ($isZip) {
|
|
return [
|
|
'Content-Type' => 'application/zip',
|
|
'Content-Disposition' => 'attachment; filename="export.zip"',
|
|
];
|
|
};
|
|
return $format->fileHeaders();
|
|
}
|
|
|
|
/**
|
|
* Transform Array into CSV.
|
|
*
|
|
* @param array $lines
|
|
* @param string $delimiter
|
|
* @param string $enclosure
|
|
* @param string $escape_char
|
|
* @return string|false
|
|
*/
|
|
private function array2csv(
|
|
array $lines,
|
|
string $delimiter = ',',
|
|
string $enclosure = '"',
|
|
string $escape_char = "\\"
|
|
) {
|
|
$f = fopen('php://temp', 'r+');
|
|
|
|
// UTF-8 BOM.
|
|
$BOM = "\xEF\xBB\xBF";
|
|
fwrite($f, $BOM);
|
|
|
|
foreach ($lines as $item) {
|
|
fputcsv($f, $item, $delimiter, $enclosure, $escape_char);
|
|
}
|
|
|
|
rewind($f);
|
|
$csvContent = stream_get_contents($f);
|
|
fclose($f);
|
|
|
|
return $csvContent;
|
|
}
|
|
|
|
/**
|
|
* Generate claims CSV
|
|
*
|
|
* @param \Illuminate\Database\Eloquent\Collection $models
|
|
* @return string|false
|
|
*/
|
|
private function generateCsv(\Illuminate\Database\Eloquent\Collection $models)
|
|
{
|
|
// CSV Header.
|
|
$class = get_class($models->first());
|
|
$csvlines[] = $class::getCsvHeaders();
|
|
|
|
foreach ($models as $model) {
|
|
$csvlines[] = $model->getFormattedCsvLine();
|
|
}
|
|
|
|
return $this->array2csv($csvlines, ';');
|
|
}
|
|
|
|
/**
|
|
* Generate PDF with models datas.
|
|
*
|
|
* @param \Illuminate\Database\Eloquent\Collection $models
|
|
* @return \Barryvdh\DomPDF\PDF
|
|
*/
|
|
private function generatePdf(\Illuminate\Database\Eloquent\Collection $models): \Barryvdh\DomPDF\PDF
|
|
{
|
|
// Convert pictures to base64.
|
|
foreach ($models->whereIn('file_extension', ['jpg', 'jpeg', 'png']) as $claim) {
|
|
$filePath = FileHelper::getPrivateFilePath($claim->file);
|
|
$claim->fileBase64 = sprintf(
|
|
'data:%s;base64,%s',
|
|
File::mimeType(Storage::disk('private')->path($filePath)),
|
|
base64_encode(Storage::disk('private')->get($filePath))
|
|
);
|
|
}
|
|
|
|
// Create temp folder if it doesn't exists. Needed to allow base64 pictures to be displayed in pdf.
|
|
if (!Storage::disk('private')->exists('temp')) {
|
|
Storage::disk('private')->makeDirectory('temp');
|
|
}
|
|
|
|
$modelClassName = class_basename($models->first());
|
|
return Pdf::setOptions(['tempDir' => Storage::disk('private')->path('temp')])
|
|
->loadView(
|
|
sprintf(
|
|
'export.pdf',
|
|
str($modelClassName)->lower()->plural()
|
|
),
|
|
[
|
|
'models' => $models,
|
|
'modelName' => str($modelClassName)->lower()
|
|
]
|
|
);
|
|
}
|
|
}
|