<?php
declare(strict_types=1);
/*
* This file is part of contao-weinanlieferung-bundle.
*
* (c) vonRotenberg
*
* @license commercial
*/
namespace vonRotenberg\WeinanlieferungBundle\Controller\Frontend\Ajax;
use Contao\Controller;
use Contao\CoreBundle\Controller\AbstractController;
use Contao\CoreBundle\Exception\PageNotFoundException;
use Contao\CoreBundle\Framework\ContaoFramework;
use Contao\CoreBundle\Security\Authentication\Token\TokenChecker;
use Contao\Environment;
use Contao\File;
use Contao\FilesModel;
use Contao\FormFileUpload;
use Contao\Frontend;
use Contao\FrontendUser;
use Contao\Input;
use Contao\StringUtil;
use Contao\System;
use Doctrine\DBAL\Connection;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungLeseartModel;
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungRebsorteModel;
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungReservationModel;
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungSlotsModel;
/**
* @Route("/_ajax/vr_wa/v1/slot", name="vr_wa_slot_ajax", defaults={"_scope" = "frontend", "_token_check" = false})
*/
class SlotAjaxController extends AbstractController
{
private $tokenChecker;
private $translator;
private $framework;
public function __construct(ContaoFramework $framework, TokenChecker $tokenChecker, TranslatorInterface $translator)
{
$this->framework = $framework;
$this->tokenChecker = $tokenChecker;
$this->translator = $translator;
}
public function __invoke(Request $request)
{
System::loadLanguageFile('default');
if (!$this->tokenChecker->hasFrontendUser())
{
return $this->renderUnauthorized();
}
if (empty($_REQUEST['do']))
{
return new Response('Required parameter missing',412);
}
$blnModal = true;
if (!empty($_REQUEST['modal']))
{
$blnModal = !(strtolower($_REQUEST['modal']) == 'false');
}
switch ($_REQUEST['do'])
{
case 'details':
return $this->renderDetails($blnModal);
case 'annotation':
return $this->renderAnnotation($blnModal);
case 'booking':
return $this->renderBooking($blnModal);
case 'reservate':
return $this->reservate();
case 'updateReservation':
return $this->updateReservation();
case 'delete':
return $this->deleteReservation();
}
return new Response('',500);
}
protected function renderDetails(bool $blnModal=true,string $error=null)
{
if (empty($_REQUEST['id']))
{
return new Response('Required parameter missing',412);
}
if (($Slot = WeinanlieferungSlotsModel::findPublishedById($_REQUEST['id'])) === null)
{
return new Response('Could not load slot data',500);
}
// Get slot reservations from user
$arrReservations = [];
if (($Reservations = WeinanlieferungReservationModel::findBy(["uid = ?","pid = ?"],[FrontendUser::getInstance()->id,$Slot->id])) !== null)
{
foreach ($Reservations as $reservation)
{
$arrSortenBooked = [];
$SortenLeseart = explode(';',$reservation->sorten);
foreach($SortenLeseart as $sorteLeseart)
{
list($sorte,$leseart) = explode(',',$sorteLeseart);
$objSorte = WeinanlieferungRebsorteModel::findByPk($sorte);
$objLeseart = WeinanlieferungLeseartModel::findByPk($leseart);
$arrSortenBooked[$objSorte->id.','.$objLeseart->id] = ($objSorte !== null ? $objSorte->title : '') . ' ' . ($objLeseart !== null ? $objLeseart->title : '');
}
/*if (($Sorten = $reservation->getRelated('sorten')) !== null)
{
$arrSortenBooked = $Sorten->fetchEach('title');
}*/
$arrReservations[] = array_merge($reservation->row(),[
'sorten' => $arrSortenBooked
]);
}
}
// Build data
$arrSorten = [];
$Sorten = StringUtil::deserialize($Slot->sorten,true);
foreach($Sorten as $sorte)
{
$objSorte = WeinanlieferungRebsorteModel::findByPk($sorte['sorte']);
$objLeseart = WeinanlieferungLeseartModel::findByPk($sorte['leseart']);
$arrSorten[$objSorte->id.','.$objLeseart->id] = ($objSorte !== null ? $objSorte->title : '') . ' ' . ($objLeseart !== null ? $objLeseart->title : '');
}
/*if (($Sorten = $Slot->getRelated('sorte')) !== null)
{
$arrSorten = array_combine($Sorten->fetchEach('id'),$Sorten->fetchEach('title'));
}*/
$arrErnteart = [];
if ($Slot->ernteart !== null)
{
foreach (explode(',', $Slot->ernteart) as $ernteart)
{
$arrErnteart[] = $GLOBALS['TL_LANG']['REF']['wa_ernteart'][$ernteart] ?? $ernteart;
}
}
$intAvailableBehaelter = $Slot->getAvailableBehaelter();
$arrData = [
'modal' => $blnModal,
'id' => $Slot->id,
'slot' => array_merge($Slot->row(),[
'sorte' => $arrSorten,
'behaelterAvailable' => $intAvailableBehaelter
]),
'standort' => $Slot->getRelated('pid'),
'lage' => $Slot->getRelated('lage'),
'ernteart' => $arrErnteart,
'buchen' => [
'buchbar' => (boolean) $intAvailableBehaelter,
'behaelter' => range(min($intAvailableBehaelter,1),$intAvailableBehaelter),
'sorten' => $arrSorten
],
'reservations' => $arrReservations
];
if (!empty($error))
{
$arrData['toast'] = $error;
}
return $this->render('@Contao/modal_slot_details.html.twig',$arrData);
}
protected function renderAnnotation(bool $blnModal=true,string $error=null)
{
if (empty($_REQUEST['id']))
{
return new Response('Required parameter missing',412);
}
if (($Slot = WeinanlieferungSlotsModel::findPublishedById($_REQUEST['id'])) === null)
{
return new Response('Could not load slot data',500);
}
// Build data
$arrSorten = [];
$Sorten = StringUtil::deserialize($Slot->sorten,true);
foreach($Sorten as $sorte)
{
$objSorte = WeinanlieferungRebsorteModel::findByPk($sorte['sorte']);
$objLeseart = WeinanlieferungLeseartModel::findByPk($sorte['leseart']);
$arrSorten[$objSorte->id.','.$objLeseart->id] = ($objSorte !== null ? $objSorte->title : '') . ' ' . ($objLeseart !== null ? $objLeseart->title : '');
}
$arrErnteart = [];
if ($Slot->ernteart !== null)
{
foreach (explode(',', $Slot->ernteart) as $ernteart)
{
$arrErnteart[] = $GLOBALS['TL_LANG']['REF']['wa_ernteart'][$ernteart] ?? $ernteart;
}
}
$intAvailableBehaelter = $Slot->getAvailableBehaelter();
$arrData = [
'modal' => $blnModal,
'id' => $Slot->id,
'slot' => array_merge($Slot->row(),[
'sorte' => $arrSorten,
'behaelterAvailable' => $intAvailableBehaelter
]),
'standort' => $Slot->getRelated('pid'),
'lage' => $Slot->getRelated('lage'),
'ernteart' => $arrErnteart,
'buchen' => [
'buchbar' => (boolean) $intAvailableBehaelter,
'behaelter' => range(min($intAvailableBehaelter,1),$intAvailableBehaelter),
'sorten' => $arrSorten
],
];
return $this->render('@Contao/modal_slot_annotation.html.twig',$arrData);
}
protected function renderBooking(bool $blnModal=true)
{
$arrData = [];
if (empty($_REQUEST['id']))
{
return new Response('Required parameter missing',412);
}
/** @var WeinanlieferungSlotsModel $Slot */
if (($Booking = WeinanlieferungReservationModel::findById($_REQUEST['id'])) === null || ($Slot = $Booking->getRelated('pid')) === null)
{
return new Response('Could not load booking data',500);
}
$objFile = FilesModel::findByUuid($Booking->upload);
if (!empty($_REQUEST['deleteFile']) && $_REQUEST['deleteFile'] && $objFile !== null)
{
$File = new File($objFile->path);
if ($File->delete())
{
$objFile->delete();
$objFile = null;
}
}
if (!empty($Booking->upload) && $objFile !== null)
{
$File = new File($objFile->path);
$strHref = Environment::get('request');
// Remove an existing file parameter (see #5683)
if (isset($_GET['file']))
{
$strHref = preg_replace('/(&(amp;)?|\?)file=[^&]+/', '', $strHref);
}
$strHref .= (strpos($strHref, '?') !== false ? '&' : '?') . 'file=' . System::urlEncode($File->value);
$arrData['file'] = [
'link' => $strHref,
'filename' => $File->filename,
'extension' => $File->extension,
'name' => $File->name,
'path' => $File->dirname
];
}
// Send the file to the browser (see #4632 and #8375)
if ($objFile !== null && ($file = Input::get('file', true)))
{
if ($file == $objFile->path)
{
Controller::sendFileToBrowser($file);
}
}
$arrSortenAvailable = [];
$Sorten = StringUtil::deserialize($Slot->sorten,true);
foreach($Sorten as $sorte)
{
$objSorte = WeinanlieferungRebsorteModel::findByPk($sorte['sorte']);
$objLeseart = WeinanlieferungLeseartModel::findByPk($sorte['leseart']);
$arrSortenAvailable[$objSorte->id.','.$objLeseart->id] = ($objSorte !== null ? $objSorte->title : '') . ' ' . ($objLeseart !== null ? $objLeseart->title : '');
}
$arrSortenBooked = [];
$SortenLeseart = explode(';',$Booking->sorten);
foreach($SortenLeseart as $sorteLeseart)
{
list($sorte,$leseart) = explode(',',$sorteLeseart);
$objSorte = WeinanlieferungRebsorteModel::findByPk($sorte);
$objLeseart = WeinanlieferungLeseartModel::findByPk($leseart);
$arrSortenBooked[$objSorte->id.','.$objLeseart->id] = ($objSorte !== null ? $objSorte->title : '') . ' ' . ($objLeseart !== null ? $objLeseart->title : '');
}
$intAvailableBehaelter = $Slot->getAvailableBehaelter();
$arrData = array_merge($arrData,[
'modal' => $blnModal,
'id' => $Booking->id,
'slot' => array_merge($Slot->row(),[
'sorte' => $arrSortenAvailable,
'behaelterAvailable' => $intAvailableBehaelter
]),
'buchung' => array_merge($Booking->row(),[
'sorten' => $arrSortenBooked
]),
'standort' => $Slot->getRelated('pid'),
'buchen' => [
'buchbar' => (boolean) $intAvailableBehaelter,
'behaelter' => range(min($intAvailableBehaelter,1),$intAvailableBehaelter+$Booking->behaelter),
'sorten' => $arrSortenAvailable
]
]);
return $this->render('@Contao/modal_booking_details.html.twig',$arrData);
}
protected function reservate()
{
Controller::loadDataContainer('tl_vr_wa_reservation');
$arrData = [];
if (($rootPage = Frontend::getRootPageFromUrl()) !== null && !empty($rootPage->vr_wa_uploadFolderSRC))
{
$File = new FormFileUpload(\Contao\Widget::getAttributesFromDca($GLOBALS['TL_DCA']['tl_vr_wa_reservation']['fields']['upload'], 'upload'));
$File->storeFile = true;
$File->doNotOverwrite = true;
$File->uploadFolder = $rootPage->vr_wa_uploadFolderSRC;
$File->validate();
if ($File->hasErrors())
{
return $this->renderDetails(false,'<div class="toast toast--danger mx-0">' . $File->getErrorAsHTML() . '</div>');
}
if (!empty($_SESSION['FILES'][$File->name]))
{
$arrData['filename'] = $_SESSION['FILES'][$File->name]['name'] ?? '';
$arrData['upload'] = $_SESSION['FILES'][$File->name]['uuid'] ? StringUtil::uuidToBin($_SESSION['FILES'][$File->name]['uuid']) : null;
}
}
if (empty($_REQUEST['id']) || empty(Input::post('behaelter')) || empty(Input::post('sorten')))
{
return new Response('Missing parameter',412);
}
$arrSorten = [];
if (!is_array(Input::post('sorten')))
{
$arrSorten[] = Input::post('sorten');
} else {
$arrSorten = implode(';', Input::post('sorten'));
}
$Reservation = new WeinanlieferungReservationModel();
$arrData = array_merge($arrData,[
'pid' => $_REQUEST['id'],
'tstamp' => time(),
'uid' => FrontendUser::getInstance()->id,
'behaelter' => Input::post('behaelter'),
'sorten' => $arrSorten
]);
$Reservation->setRow($arrData);
$Reservation->save();
return new Response('<div class="toast toast--success mx-0"><p>Reservierung erfolgreich</p></div>',200,['HX-Trigger'=> 'updateWaList']);
}
protected function updateReservation()
{
Controller::loadDataContainer('tl_vr_wa_reservation');
if (empty($_REQUEST['id']) || empty(Input::post('behaelter')) || empty(Input::post('sorten')))
{
return new Response('Missing parameter',412);
}
if (($Reservation = WeinanlieferungReservationModel::findById($_REQUEST['id'])) === null)
{
return new Response('Could not load booking data',500);
}
if (($rootPage = Frontend::getRootPageFromUrl()) !== null && !empty($rootPage->vr_wa_uploadFolderSRC))
{
$File = new FormFileUpload(\Contao\Widget::getAttributesFromDca($GLOBALS['TL_DCA']['tl_vr_wa_reservation']['fields']['upload'], 'upload'));
$File->storeFile = true;
$File->doNotOverwrite = true;
$File->uploadFolder = $rootPage->vr_wa_uploadFolderSRC;
$File->validate();
if ($File->hasErrors())
{
return $this->renderDetails(false,'<div class="toast toast--danger mx-0">' . $File->getErrorAsHTML() . '</div>');
}
if (!empty($_SESSION['FILES'][$File->name]))
{
$Reservation->filename = $_SESSION['FILES'][$File->name]['name'] ?? '';
$Reservation->upload = $_SESSION['FILES'][$File->name]['uuid'] ? StringUtil::uuidToBin($_SESSION['FILES'][$File->name]['uuid']) : null;
}
}
$arrSorten = [];
if (!is_array(Input::post('sorten')))
{
$arrSorten[] = Input::post('sorten');
} else {
$arrSorten = implode(';', Input::post('sorten'));
}
$Reservation->tstamp = time();
$Reservation->behaelter = Input::post('behaelter');
$Reservation->sorten = $arrSorten;
$Reservation->save();
return new Response('<div class="toast toast--success mx-0"><p>Reservierung erfolgreich geändert</p></div>',200,['HX-Trigger'=> 'updateWaBooking']);
}
protected function deleteReservation()
{
if (empty($_REQUEST['id']))
{
return new Response('Missing parameter',412);
}
/** @var Connection $db */
$db = Controller::getContainer()->get('database_connection');
$arrCriteria = [
'uid' => FrontendUser::getInstance()->id,
'id' => $_REQUEST['id']
];
if ($db->delete('tl_vr_wa_reservation',$arrCriteria))
{
return new Response(null,203,['HX-Trigger'=> 'updateWaBooking']);
}
return new Response('Could not delete',500);
}
protected function renderUnauthorized()
{
return $this->render('@Contao/modal_unauthorized.html.twig');
}
}