Files
Ronald Huynen 2547717edb Initial commit
2026-03-23 21:37:59 +01:00

199 lines
7.0 KiB
PHP

<?php
namespace App\Http\Livewire;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Livewire\Component;
class Reports extends Component
{
public function render()
{
return view('livewire.reports');
}
/**
* Decode and validate a base64 chart image string.
* Returns the raw image bytes, or throws if the content is not a PNG or JPEG.
*/
private function decodeChartImage(string $chartImage): string
{
$base64Data = explode(',', $chartImage)[1] ?? $chartImage;
$imageData = base64_decode($base64Data, strict: true);
if ($imageData === false) {
abort(422, 'Invalid chart image data');
}
// Validate magic bytes — must be PNG (\x89PNG) or JPEG (\xFF\xD8\xFF)
$isPng = str_starts_with($imageData, "\x89PNG");
$isJpeg = str_starts_with($imageData, "\xFF\xD8\xFF");
if (!$isPng && !$isJpeg) {
Log::warning('Reports: rejected chart image with invalid magic bytes', [
'guard' => session('activeProfileType'),
'profileId' => session('activeProfileId'),
]);
abort(422, 'Chart image must be a PNG or JPEG');
}
return $imageData;
}
public function exportPdfWithChart($chartImage, $fromDate = null, $toDate = null)
{
abort_unless(Auth::check(), 403);
Log::info('Reports::exportPdfWithChart called', [
'chartImageLength' => strlen($chartImage),
'fromDate' => $fromDate,
'toDate' => $toDate
]);
// Generate unique filename for temporary chart image
$chartImageId = uniqid('chart_', true);
$tempImagePath = storage_path('app/temp/' . $chartImageId . '.png');
// Ensure temp directory exists
if (!file_exists(dirname($tempImagePath))) {
mkdir(dirname($tempImagePath), 0755, true);
}
// Decode and validate image content before writing
$imageData = $this->decodeChartImage($chartImage);
file_put_contents($tempImagePath, $imageData);
Log::info('Chart image saved to temp file', [
'chartImageId' => $chartImageId,
'fileSize' => strlen($imageData)
]);
// Store only the chart image ID in session (much smaller)
session(['chart_image_id' => $chartImageId]);
// Build URL with current report parameters - use passed dates or fallback
$params = [
'fromDate' => $fromDate ?? request()->get('fromDate'),
'toDate' => $toDate ?? request()->get('toDate'),
'with_chart' => 1,
'decimal' => request()->get('decimal', 0),
];
$url = route('reports.pdf', $params);
Log::info('PDF URL generated', ['url' => $url]);
// Use JavaScript to open PDF in new window/tab
$this->dispatch('openPdf', $url);
}
public function exportPdf()
{
Log::info('Reports::exportPdf called - delegating to SingleReport');
// This method should delegate to SingleReport component
// For now, just use basic parameters
$params = [
'fromDate' => request()->get('fromDate'),
'toDate' => request()->get('toDate'),
'decimal' => request()->get('decimal', 0),
];
$url = route('reports.pdf', $params);
Log::info('PDF URL generated from Reports component', ['url' => $url]);
$this->dispatch('openPdf', $url);
}
public function exportReport($type)
{
Log::info('Reports::exportReport called - delegating to SingleReport', ['type' => $type]);
// Delegate to SingleReport for actual export functionality
$params = [
'fromDate' => request()->get('fromDate'),
'toDate' => request()->get('toDate'),
'decimal' => request()->get('decimal', 0),
];
$url = route('reports.pdf', $params);
$this->dispatch('openPdf', $url);
}
/**
* Export report as PDF with both chart images
*/
public function exportPdfWithCharts($returnRatioChartImage = null, $accountBalancesChartImage = null, $fromDate = null, $toDate = null)
{
abort_unless(Auth::check(), 403);
Log::info('Reports::exportPdfWithCharts called', [
'returnRatioChartImageLength' => $returnRatioChartImage ? strlen($returnRatioChartImage) : 0,
'accountBalancesChartImageLength' => $accountBalancesChartImage ? strlen($accountBalancesChartImage) : 0,
'fromDate' => $fromDate,
'toDate' => $toDate
]);
$chartImageIds = [];
// Process Return Ratio Chart image
if ($returnRatioChartImage) {
$returnRatioChartImageId = uniqid('return_ratio_chart_', true);
$tempImagePath = storage_path('app/temp/' . $returnRatioChartImageId . '.png');
// Ensure temp directory exists
if (!file_exists(dirname($tempImagePath))) {
mkdir(dirname($tempImagePath), 0755, true);
}
// Decode and validate image content before writing
$imageData = $this->decodeChartImage($returnRatioChartImage);
file_put_contents($tempImagePath, $imageData);
$chartImageIds['return_ratio_chart_id'] = $returnRatioChartImageId;
Log::info('Return Ratio Chart image saved to temp file', [
'chartImageId' => $returnRatioChartImageId,
'fileSize' => strlen($imageData)
]);
}
// Process Account Balances Chart image
if ($accountBalancesChartImage) {
$accountBalancesChartImageId = uniqid('account_balances_chart_', true);
$tempImagePath = storage_path('app/temp/' . $accountBalancesChartImageId . '.png');
// Ensure temp directory exists
if (!file_exists(dirname($tempImagePath))) {
mkdir(dirname($tempImagePath), 0755, true);
}
// Decode and validate image content before writing
$imageData = $this->decodeChartImage($accountBalancesChartImage);
file_put_contents($tempImagePath, $imageData);
$chartImageIds['account_balances_chart_id'] = $accountBalancesChartImageId;
Log::info('Account Balances Chart image saved to temp file', [
'chartImageId' => $accountBalancesChartImageId,
'fileSize' => strlen($imageData)
]);
}
// Store chart image IDs in session
session(['chart_image_ids' => $chartImageIds]);
// Build URL with current report parameters
$params = [
'fromDate' => $fromDate ?? request()->get('fromDate'),
'toDate' => $toDate ?? request()->get('toDate'),
'with_charts' => 1,
'decimal' => request()->get('decimal', 0),
];
$url = route('reports.pdf', $params);
Log::info('PDF URL generated with charts', ['url' => $url, 'chartImageIds' => $chartImageIds]);
// Use JavaScript to open PDF in new window/tab
$this->dispatch('openPdf', $url);
}
}