File: /var/www/vhost/disk-apps/demo.sports-crowd.com/app/Http/Controllers/PrintTicketController.php
<?php
namespace App\Http\Controllers;
if (!defined('FPDF_FONTPATH')) {
define('FPDF_FONTPATH', public_path('fonts'));
}
use App\Core\Ticket\Application\TicketService;
use App\Core\Ticket\TicketTypesEnum;
use QrCode;
use App\Team;
use App\Ticket;
use App\Parameter;
use App\Services\TicketParametersService;
use Carbon\Carbon;
use App\TokenUserTicket;
use Codedge\Fpdf\Fpdf\Fpdf;
use Illuminate\Support\Facades\Auth;
class PrintTicketController extends Controller
{
private $ticket;
private $main_team;
private $rival_team;
private $url_main_team;
private $url_tournament;
private $url_organizer;
private $url_ticket_background;
private $url_footer_sponsors;
private $__INVALID_ROLE;
private $fpdf;
private $matchEventsController;
private $ticketParametersService;
private $ticketService;
public function __construct()
{
$this->__INVALID_ROLE = [$this->__MESSENGER_ROL, $this->__CLIENT_ROL, $this->__LOGISTICS_ROL]; // De lo contrario es un admin y lo dejará imprimir.
$this->matchEventsController = new MatchEventsController;
$this->ticketParametersService = new TicketParametersService();
$this->ticketService = new TicketService();
}
public function printTicket($code, $user_id = null, $token = null)
{
if ($this->validateUserWhoPrint($code, $user_id)) {
return $this->buildTicket($token);
} else {
return ['status' => 'Unauthorized'];
}
}
public function printTickets($codes, $user_id = null, $token = null)
{
$codes = explode(",", $codes);
$fpdf = new Fpdf('P', 'mm', array(110, 160));
foreach ($codes as $code) {
if ($this->validateUserWhoPrint($code, $user_id)) {
$fpdf = $this->buildPdfTicket($fpdf, false);
} else {
return ['status' => 'Unauthorized'];
}
}
return $this->pdfOutput($token, null, $fpdf);
}
// Metodo para imprimir ticket para correo masivo
public function printTicketForMassMail($code, $type = "base64")
{
$this->getTicketInfo($code);
return $this->buildTicket(null, $type);
}
public function getTicketInfo($code, $user_id = null)
{
$this->ticket = Ticket::where('code_ticket', $code)
->with('seat')
->with('match_event')
->with('user')
->with('ticket_main');
if ($user_id != null) {
$this->ticket->where('user_id', $user_id);
}
$this->ticket = $this->ticket->first();
if (!$this->ticket) {
return false;
}
$this->rival_team = $this->ticket->match_event->team;
$this->main_team = Team::where('is_main', true)->first();
return true;
}
public function validateUserWhoPrint($code, $user_id)
{
try {
if ($user_id) {
return $this->getTicketInfo($code, $user_id);
} else if (Auth::check() && Auth::user()->rol) {
$role_user = Auth::user()->rol->id;
if (!in_array($role_user, $this->__INVALID_ROLE)) {
return $this->getTicketInfo($code);
}
} else {
return $this->getTicketInfo($code);
}
return false;
} catch (\Throwable $th) {
return false;
}
}
public function buildTicket($token, $type = null)
{
$fpdf = $this->buildPdfTicket(new Fpdf('P', 'mm', array(110, 160)));
$data = $this->pdfOutput($token, $type, $fpdf);
return $data;
}
public function pdfOutput($token, $type = null, $fpdf)
{
$code = $this->ticket->code_ticket;
switch ($type) {
case 'base64':
$pdfString = $fpdf->Output('S');
return response($pdfString, 200)
->header('Content-Type', 'application/pdf')
->header('Content-Disposition', 'inline; filename="' . $code . '.pdf"');
case 'file':
$filePath = public_path("tickets_tmp/{$code}.pdf");
$fpdf->Output('F', $filePath);
return "tickets_tmp/{$code}.pdf";
case 'content':
return $fpdf->Output('S');
}
if (!$token) {
$pdfString = $fpdf->Output('S');
return response($pdfString, 200)
->header('Content-Type', 'application/pdf')
->header('Content-Disposition', 'inline; filename="' . $code . '.pdf"');
}
$pdfPath = public_path("tickets_tmp/{$token}.pdf");
$fpdf->Output('F', $pdfPath);
$image = new \Spatie\PdfToImage\Pdf($pdfPath);
$image->setPage(1)
->setOutputFormat('png')
->saveImage(public_path("tickets_tmp/{$token}.png"));
return true;
}
private function buildPdfTicket($fpdf, $cacheFpdf = true)
{
$parameters = Parameter::select('presuscription', 'url_ticket_backgroung', 'url_ticket_sponsor')->first();
$parameters->hideDataSeat = $this->matchEventsController->validateSaleByCapacity($this->ticket->match_event->id);
// Inicio variables
$tournament = $this->ticket->match_event->season->tournament->name;
$tournament = $this->cleanString($tournament);
$tournament = urldecode($tournament);
$date_name = $this->ticket->match_event->date_name;
$date_event = Carbon::parse($this->ticket->match_event->event_start)->format('d-m-Y');
$abbr_local = $this->main_team->abbreviation;
$abbr_visit = $this->rival_team->abbreviation;
$code = $this->ticket->code_ticket;
$time = substr($this->ticket->match_event->event_start, 11, 5);
$tribune = $this->ticket->seat->zone->zone->is_saleable ? $this->ticket->seat->zone->zone->name : $this->ticket->seat->zone->name;
$zones = explode("_", $this->ticket->zone);
$zone = $zones[0];
$zone = str_replace($tribune, "", $zone);
$zone = trim($zone);
$ticketZone = '';
if (count($zones) > 1)
$ticketZone = $zones[1];
else {
$zones = explode(" ", $this->ticket->zone);
if ((count($zones) > 1) && str_contains($zones[0], $tribune)) {
$zone = $zones[1];
} else {
$zone = $zones[0];
}
$ticketZone = count(explode($zone . ' ', $this->ticket->zone)) > 1 ? explode($zone . ' ', $this->ticket->zone)[1] : '';
$zone = substr($zone, 0, 3);
}
$tribune = strtoupper($tribune);
$ticketRow = $this->ticket->letter_seat;
$ticketSeat = $this->ticket->code_seat;
$user = explode(' ', $this->ticket->user->first_name)[0] . ' ' . explode(' ', $this->ticket->user->last_name)[0];
$user = $this->cleanString($user);
$document = $this->ticket->user->document;
$price = $this->ticket->price ?? 0;
$stadium = $this->ticket->match_event->stadium_to_play;
$stadium = $this->cleanString($stadium);
$stadium = urldecode($stadium);
// DYNAMIC IMAGES
$url_main_team = config('filesystems.disks.s3.url') . '/teams/' . $this->main_team->logo;
$url_tournament = $this->ticket->match_event->season->tournament->logo ? config('filesystems.disks.s3.url') . '/tournaments/' . $this->ticket->match_event->season->tournament->logo : null;
$url_organizer = $this->ticket->match_event->season->tournament->tournament_organizer->logo ? config('filesystems.disks.s3.url') . '/organizer/' . $this->ticket->match_event->season->tournament->tournament_organizer->logo : null;
$url_ticket_background = $this->ticket->match_event->season->tournament->ticket_background ? config('filesystems.disks.s3.url') . '/tournaments/' . $this->ticket->match_event->season->tournament->ticket_background : $parameters->url_ticket_backgroung;
$url_footer_sponsors = $this->ticket->match_event->season->tournament->footer_sponsors ? config('filesystems.disks.s3.url') . '/tournaments/' . $this->ticket->match_event->season->tournament->footer_sponsors : $parameters->url_ticket_sponsor;
$qrData = $this->generateQRCode($code);
// Fin variables
// Formato Ticket
$fpdf->AddPage();
$fpdf->SetFillColor(130, 130, 130);
$fpdf->Rect(0, 0, 210, 297, 'F');
if (!$this->url_main_team && $url_main_team) {
$mainTeams = explode("/", $url_main_team);
$this->url_main_team = 'tickets_tmp/main_team_' . end($mainTeams);
if (!file_exists($this->url_main_team) || file_get_contents($this->url_main_team) == '') {
touch($this->url_main_team);
copy($url_main_team, $this->url_main_team);
}
}
if (!$this->url_tournament && $url_tournament) {
$tournaments = explode("/", $url_tournament);
$this->url_tournament = 'tickets_tmp/tournament_' . end($tournaments);
if (!file_exists($this->url_tournament) || file_get_contents($this->url_tournament) == '') {
touch($this->url_tournament);
copy($url_tournament, $this->url_tournament);
}
}
if (!$this->url_organizer && $url_organizer) {
$organizers = explode("/", $url_organizer);
$this->url_organizer = 'tickets_tmp/organizer_' . end($organizers);
if (!file_exists($this->url_organizer) || file_get_contents($this->url_organizer) == '') {
touch($this->url_organizer);
copy($url_organizer, $this->url_organizer);
}
}
if (!$this->url_ticket_background && $url_ticket_background) {
$backgrounds = explode("/", $url_ticket_background);
$this->url_ticket_background = 'tickets_tmp/background_' . end($backgrounds);
if (!file_exists($this->url_ticket_background) || file_get_contents($this->url_ticket_background) == '') {
touch($this->url_ticket_background);
copy($url_ticket_background, $this->url_ticket_background);
}
}
if (!$this->url_footer_sponsors && $url_footer_sponsors) {
$footers = explode("/", $url_footer_sponsors);
$this->url_footer_sponsors = 'tickets_tmp/footer_sponsors_' . end($footers);
if (!file_exists($this->url_footer_sponsors) || file_get_contents($this->url_footer_sponsors) == '') {
touch($this->url_footer_sponsors);
copy($url_footer_sponsors, $this->url_footer_sponsors);
}
}
$fpdf = $this->buildImage($fpdf, $this->url_main_team, $this->url_tournament, $this->url_organizer, $qrData, $this->url_ticket_background, $this->url_footer_sponsors, $cacheFpdf);
$fpdf = $this->addFonts($fpdf);
if ($this->ticket->ticket_type_id != TicketTypesEnum::COMPLIMENTARY) {
$fpdf->SetFont('organetto-regularsemiext', '', 7);
$fpdf->Cell(0, -14, ('NOMBRE: ' . $user . ' - ID: ' . $document), 0, 0, 'C'); // NOMBRE TITULAR
}
$fpdf->SetX(10);
$fpdf->SetFont('organetto-ultraboldsemiext', '', 11);
$fpdf->Cell(0, 32, $tournament, 0, 0, 'C'); // TORNEO
$fpdf->SetX(11.5);
$fpdf->SetFont('organetto-lightsemiext', '', 11);
$fpdf->Cell(0, 42, $date_name, 0, 0, 'C'); // EQUIPOS
if ($this->ticket->match_event->stadium_to_play) {
$fpdf->SetFont('organetto-regularsemiext', '', 9);
$fpdf->SetX(11.5);
$fpdf->Cell(0, 52, ('Estadio: ' . $stadium), 0, 0, 'C'); // ESTADIO
}
$fpdf->SetFont('organetto-regularsemiext', '', 11);
$fpdf->Text(12, 45, 'FECHA DEL PARTIDO:');
$fpdf->SetFont('organetto-ultraboldsemiext', '', 11);
$fpdf->Text(68.5, 45, $date_event);
$fpdf->SetFont('organetto-boldsemiext', '', 30);
$fpdf->Text(15, 58, $abbr_local); // EQUIPO LOCAL
$fpdf->Text(70, 58, $abbr_visit); // EQUIPO VISITANTE
$fpdf->SetFont('organetto-regularsemiext', '', 21);
$fpdf->Text(48, 57, 'VS.');
$specialText = mb_convert_encoding($this->ticket->special_text, 'ISO-8859-1', 'UTF-8');
if (!$parameters->hideDataSeat) {
$fpdf->SetFont('organetto-regularsemiext', '', 9);
$fpdf->Text(4, 68, 'HORA:');
$fpdf->Text(25, 68, 'TRIBUNA:');
$fpdf->Text(50, 68, 'SECTOR:');
$fpdf->Text(75, 68, 'FILA:');
$fpdf->Text(93, 68, 'SILLA');
$fpdf->SetFont('organetto-ultraboldsemiext', '', 12);
// HORA DEL PARTIDO
$fpdf->Text(3, 74, $time);
// TRIBUNA
if ($zone) {
if ($specialText) {
$tribune = substr($tribune, 0, 3);
$fpdf->Text(22, 74, $tribune . '-' . $zone);
} else {
$fpdf->SetFont('organetto-ultraboldsemiext', '', 10);
if (str_contains(strtolower($tribune), strtolower($zone))) {
$fpdf->Text(22, 74, $zone);
} else {
$fpdf->Text(22, 74, $tribune . '-');
$fpdf->Text(22, 78, $zone);
}
}
} else
$fpdf->Text(22, 74, $tribune);
if ($specialText) {
$fpdf->SetFont('organetto-ultraboldsemiext', '', 25);
$fpdf->SetTextColor(255, 0, 0);
$mid_x = (($fpdf->GetPageWidth() / 2) - ($fpdf->GetStringWidth($specialText) / 2));
// TEXTO ESPECIAL BOLETA
$fpdf->Text($mid_x, 84, $specialText);
$fpdf->SetTextColor(0, 0, 0);
$fpdf->SetFont('organetto-ultraboldsemiext', '', 12);
}
// SECTOR
if (strlen($ticketZone) > 9) {
$fpdf->SetFont('organetto-ultraboldsemiext', '', 7);
$ticketZoneWords = explode(" ", $ticketZone);
$chunkSize = ceil(count($ticketZoneWords) / 2);
$chunks = array_chunk($ticketZoneWords, $chunkSize);
$firstArray = $chunks[0]; // First array
$upperTicketZoneText = implode(" ", $firstArray);
$secondArray = $chunks[1] ?? []; // Second array
$lowerTicketZoneText = implode(" ", $secondArray);
$fpdf->Text(50, 72, $upperTicketZoneText);
$fpdf->Text(50, 76, $lowerTicketZoneText);
$fpdf->SetFont('organetto-ultraboldsemiext', '', 12);
} else if (strlen($ticketZone) > 2 && strlen($ticketZone) <= 9) {
$fpdf->SetFont('organetto-ultraboldsemiext', '', 10);
$fpdf->Text(50, 74, $ticketZone);
$fpdf->SetFont('organetto-ultraboldsemiext', '', 12);
} else {
$fpdf->Text(57, 74, $ticketZone);
}
// FILA
$fpdf->Text(78, 74, $ticketRow);
// SILLA
$fpdf->Text(95, 74, $ticketSeat);
} else {
$fpdf->SetFont('organetto-regularsemiext', '', 9);
$fpdf->Text(35, 68, 'HORA:');
$fpdf->Text(57, 68, 'TRIBUNA');
$fpdf->SetFont('organetto-ultraboldsemiext', '', 12);
$fpdf->Text(35, 74, $time); // HORA DEL PARTIDO
if (strlen($tribune) > 18) {
$tribuneWords = explode(" ", $tribune);
$chunkSize = ceil(count($tribuneWords) / 2);
$chunks = array_chunk($tribuneWords, $chunkSize);
$firstArray = $chunks[0]; // First array
$upperTribuneText = implode(" ", $firstArray);
$secondArray = $chunks[1]; // Second array
$lowerTribuneText = implode(" ", $secondArray);
$fpdf->SetFont('organetto-ultraboldsemiext', '', 7);
$fpdf->Text(55, 72, $upperTribuneText); // TRIBUNA PARTE SUPERIOR
$fpdf->Text(55, 75, $lowerTribuneText); // TRIBUNA PARTE INFERIOR
} else if (strlen($tribune) > 10 && strlen($tribune) <= 18) {
$fpdf->SetFont('organetto-ultraboldsemiext', '', 9);
$fpdf->Text(55, 74, $tribune); // TRIBUNA
} else {
$fpdf->SetFont('organetto-ultraboldsemiext', '', 12);
$fpdf->Text(55, 74, $tribune); // TRIBUNA
}
if ($specialText) {
$fpdf->SetFont('organetto-ultraboldsemiext', '', 25);
$fpdf->SetTextColor(255, 0, 0);
$mid_x = (($fpdf->GetPageWidth() / 2) - ($fpdf->GetStringWidth($specialText) / 2));
$fpdf->Text($mid_x, 84, $specialText); // TEXTO ESPECIAL BOLETA
$fpdf->SetTextColor(0, 0, 0);
$fpdf->SetFont('organetto-ultraboldsemiext', '', 12);
}
}
// Codigo boleta
$fpdf->SetY(138);
$fpdf->SetX(30);
$fpdf->SetFont('organetto-ultraboldsemiext', '', 9);
$fpdf->Cell(0, 0, 'COD: ', 0, 0, 'L');
$fpdf->SetX(40);
$fpdf->SetFont('organetto-regularsemiext', '', 9);
$fpdf->Cell(0, 0, $code, 0, 0, 'L'); // CODIGO
// Precio boleta
$fpdf->SetFont('organetto-ultraboldsemiext', '', 12);
$fpdf->Text(35, 145, 'VALOR:');
$fpdf->SetFont('organetto-regularsemiext', '', 12);
$fpdf->Text(55, 145, ('$' . $price)); // PRECIO
// CUFE
if ($this->ticket->ticket_main->cufe) {
$fpdf->SetFont('organetto-regularsemiext', '', 3);
$fpdf->Text(14, 158, 'CUFE: ' . $this->ticket->ticket_main->cufe);
}
return $fpdf;
}
public function buildImage($fpdf, $url_main_team, $url_tournament, $url_organizer, $qrData, $url_ticket_background, $url_footer_sponsors, $cacheFpdf = true)
{
if (!$this->fpdf) {
// Background
if ($url_ticket_background)
$fpdf->Image($url_ticket_background, 1, 1, 107.8, 157.8);
$subtractPositionX = 0;
if (!$url_organizer || !$url_tournament) {
$subtractPositionX = 11;
}
// Tournament Type IMAGE
if ($url_organizer)
$fpdf->Image($url_organizer, 22 - $subtractPositionX, 5, 18, 18, 'png');
// MAIN_TEAM_IMAGE
if ($url_main_team)
$fpdf->Image($url_main_team, 45 - $subtractPositionX, 5, 18, 18);
// TOURNAMENT_IMAGE
if ($url_tournament)
$fpdf->Image($url_tournament, 68 - $subtractPositionX, 5, 18, 18);
// Point line
// $fpdf->Image(public_path('/img/ticket/point-line.png'), 2, 36.3, 105, 0.5, 'png');
// Footer
if ($url_footer_sponsors) {
$fpdf->Image($url_footer_sponsors, 5, 150, 100, 5);
}
if ($cacheFpdf) $this->fpdf = clone $fpdf;
} else {
$fpdf = clone $this->fpdf;
}
// Escalar el tamaño de imagen en el PDF
$scaleFactor = 0.25;
$imageSize = $qrData['size'] * $scaleFactor;
// Calcular posicion dinamica (centrado horizontal)
$pageWidth = $fpdf->GetPageWidth();
$posX = ($pageWidth - $imageSize) / 2;
// 65% de la altura de la pagina
$posY = $fpdf->GetPageHeight() * 0.65 - ($imageSize / 2);
// QR
$qr_base64_png = $qrData['base64'];
$pic = 'data://text/plain;base64,' . $qr_base64_png;
$fpdf->Image($pic, $posX, $posY, $imageSize, $imageSize, 'png');
// Agregar un borde alrededor de la imagen QR
$borderThickness = 0.2; // Grosor del borde en mm
$fpdf->SetLineWidth($borderThickness);
$fpdf->SetDrawColor(255, 255, 255); // Color blanco
$fpdf->Rect($posX, $posY, $imageSize, $imageSize);
return $fpdf;
}
public function addFonts($fpdf)
{
$fpdf->AddFont('organetto-lightsemiext', '');
$fpdf->AddFont('organetto-boldsemiext', '');
$fpdf->AddFont('organetto-regularsemiext', '');
$fpdf->AddFont('organetto-ultraboldsemiext', '');
return $fpdf;
}
public function generateQRCode($code)
{
$qrCodeSize = $this->ticketParametersService->qrCodeSize();
$qrCode = $code;
if ($this->ticketParametersService->isDinamicQRType()) {
$qrCode = $this->ticketService->encryptedQR($code);
}
$qr = QrCode::format('png')
->size($qrCodeSize)
->errorCorrection('M')
->generate($qrCode);
return [
'base64' => base64_encode($qr),
'size' => $qrCodeSize
];
}
public function printTicketValidate($token)
{
$validate = TokenUserTicket::where('token', $token)->first();
if ($validate) {
$code = $validate->code;
$user_id = $validate->user_id;
$validate->delete();
return $this->printTicket($code, $user_id);
}
return ":(";
}
private function cleanString($text)
{
$utf8 = array(
'/[áàâãªä]/u' => 'a',
'/[ÁÀÂÃÄ]/u' => 'A',
'/[ÍÌÎÏ]/u' => 'I',
'/[íìîï]/u' => 'i',
'/[éèêë]/u' => 'e',
'/[ÉÈÊË]/u' => 'E',
'/[óòôõºö]/u' => 'o',
'/[ÓÒÔÕÖ]/u' => 'O',
'/[úùûü]/u' => 'u',
'/[ÚÙÛÜ]/u' => 'U',
'/ç/' => 'c',
'/Ç/' => 'C',
'/ñ/' => 'n',
'/Ñ/' => 'N',
'/–/' => '-', // UTF-8 hyphen to "normal" hyphen
'/[’‘‹›‚]/u' => ' ', // Literally a single quote
'/[“”«»„]/u' => ' ', // Double quote
'/ /' => ' ', // nonbreaking space (equiv. to 0x160)
);
return preg_replace(array_keys($utf8), array_values($utf8), $text);
}
}