<?php
/*
* This file is part of the Symfocal Calendar v1.0.
*
* (c) Symfocal http://www.symfocal.com
* alban@symfocal.com
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Dp\CalendarBundle\Controller;
use App\Util\Util;
use Doctrine\ORM\EntityManagerInterface;
use App\Dp\CalendarBundle\Entity\Item;
use App\Dp\CalendarBundle\Entity\State;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
//use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use App\Dp\CalendarBundle\Entity\Booking;
use Symfony\Component\HttpFoundation\Cookie;
//use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Translation\LocaleSwitcher;
use Symfony\Contracts\Translation\TranslatorInterface;
class DefaultController extends AbstractController
{
private $em;
private $objUtil;
private $translator;
public function __construct(private LocaleSwitcher $localeSwitcher, EntityManagerInterface $em,TranslatorInterface $translator)
{
$this->em = $em;
$this->objUtil = new Util($this->em);
$this->translator = $translator;
}
public function indexAction()
{
return $this->render('DpCalendarBundle:Default:index.html.twig');
}
/**
* @return Response
*/
public function indexAdminAction()
{
//////////////////////////////////////
//all items followed with the calendar
//////////////////////////////////////
$items = $this->em->getRepository(Item::class)->findBy(
array(),
array('position' => 'ASC'));
////////////////////////////////////////
//first item on which calendar will open
////////////////////////////////////////
$objItem = $this->em->getRepository(Item::class)->findOneBy(
array(),
array('position' => 'ASC'), 1, 1);
if (!$objItem)
{
$item = null;
} else {
$item = $objItem->getId();//first item on which calendar will open
}
///////////////////////////////////
//all booking states for the legend
///////////////////////////////////
$states = $this->em->getRepository(State::class)->findBy(
array('item' => $item),
array('position' => 'ASC'));
return $this->render('Dp/CalendarBundle/Default/indexAdmin.html.twig', array(
'items' => $items,
'item' => $item,
'states' => $states,
'util' => $this->objUtil,
));
}
/**
* $admin is a boolean parameter defined in routing.yml set at true for the admin page and false otherwise
*
* @param $admin
* @param $item
* @param Request $request
* @return Response
*/
public function calendarDisplayAction($admin, $item, Request $request)
{
if ($item =='') $item = -1;
$date = new \DateTime();
$year = $date->format('Y'); //to start calendar on current year
$month = $date->format('m'); //to start calendar on current month
$day = $date->format('d');
///////////////////////////////////////
// all items followed with the calendar
/////////////////////////////////////////
$items = $this->em->getRepository(Item::class)->findBy(
array(),
array('position' => 'ASC'));
//$item = $em->getRepository('DpCalendarBundle:Item')->findOneBy(array(), array('position' => 'ASC'), 1, 1)->getId();//first item on which calendar will open
if ($item == -1)
{
/////////////////////////////////////////
// first item on which calendar will open
/////////////////////////////////////////
$objItem = $this->em->getRepository(Item::class)->findOneBy(
array(),
array('position' => 'ASC'), 1, 1);
if (!$objItem)
{
$item = null;
} else {
$item = $objItem->getId();//first item on which calendar will open
}
}
$states = $this->em->getRepository(State::class)->findBy(
array('item' => $item),
array('position' => 'ASC'));//all booking states for the legend
//$statesLellenda = $em->getRepository('DpCalendarBundle:State')->findBy(array(), array('position' => 'ASC'));//all booking states for the legend
if ($admin)
{
$er = $this->em->getRepository(State::class);
$qb = $er->createQueryBuilder('a');
$qb->groupBy('a.class')
->add('orderBy', "a.position ASC");
$statesLellenda = $qb->getQuery()->getResult();
} else {
$statesLellenda = $states;
}
return $this->render('Dp\CalendarBundle\Default\calendar.html.twig', array(
'year' => $year,
'month' => $month,
'day' => $day,
'admin' => $admin,
'items' => $items,
'item' => $item,
'states' => $states,
'statesLellenda' => $statesLellenda,
'locale' => $request->getLocale()
));
}
/**
* controller called via ajax to fill calendar for a specific month, year and item
* @return Response
*/
public function calendarAction(Request $request)
{
$oneday = new \DateInterval('P1D');
$states = $this->em->getRepository(State::class)->findBy(
array(),
array("position" => 'ASC'), 1, 0);
$defaultClass = '';
foreach($states as $state)
{
$defaultClass=$state->getClass();
}
//$request = $this->get('request');
$yearKey=intval($request->request->get('year'));
$monthKey=intval($request->request->get('month'));
$itemId=intval($request->request->get('itemId'));
if ($monthKey==0) $monthKey=12;
$item = $this->em->getRepository(Item::class)->find($itemId);
if (!$item)
{
$return='{"responseCode" : "400", "message" : "the item selected does not exist - please restart the application"}';// if the item is not found, an ajax response is sent with a message to be displayed
return new Response($return,200,array('Content-Type'=>'application/json'));
}
$lowLimit = new \DateTime();//low limit date used to select dates in the booking table
$highLimit = new \DateTime();//high limit date used to select dates in the booking table
$lowLimit->setDate($yearKey, $monthKey, 1);
$lowLimit->sub($oneday);
$highLimit->setDate($yearKey, $monthKey, 31);
$highLimit->add($oneday);
$er = $this->em->getRepository(Booking::class);
$qb = $er->createQueryBuilder('a');
$qb->where('a.theDate BETWEEN :lowLimit AND :highLimit')
->setParameter('lowLimit', $lowLimit)
->setParameter('highLimit', $highLimit)
->andWhere('a.item = :item')
->setParameter('item', $item);
$entities = $qb->getQuery()->getResult();
$bookings = array();
foreach ($entities as $booking)
{
$key = $booking->getTheDate()->format('Y-m-d');
//$bookings[$key]=$booking->getState()->getClass();//for each date found in the query, class to be applied is stored in array $bookings()
$objBookings = $booking->getState();
$sClass = '';
if ($objBookings)
{
$sClass = $objBookings->getClass();//for each date found in the query, class to be applied is stored in array $bookings()
}
$bookings[$key] = $sClass;//for each date found in the query, class to be applied is stored in array $bookings()
}
$return='';
$current_month = $this->getMonth($monthKey);
$title = htmlentities($current_month." ".$yearKey ,ENT_QUOTES);
$return.='"current_month" : "'.$title.'" , ';
$previous_month=$this->getOtherMonth($monthKey,$yearKey,-1);//needed to calculate the number of days of previous month
$days_previous_month = date('t',mktime(0, 0, 0, $previous_month[$monthKey], 1, $previous_month[$yearKey])); //number of days of the previous month, used to populate the calendar cells corresponding to the previous month.
$return.='"days_previous_month" : "'.$days_previous_month.'" , ';
//The following 4 arrays will contain all the information for each cell of the calendar table.
$tab_days = array();
$tab_booked = array();
$tab_class = array();
$tab_dates = array();
$num_day = $this->getFirstDay($monthKey,$yearKey);
$count = 1;
$num_day_current = 1;
$nb_days_prev = 0;
while ($count<43)
{
if ($count<$num_day)
{
$nb_days_prev++;//counts the number of days of previous month appearing on a calendar.
$tab_days[$count]=0;
$tab_booked[$count]=-1;
$tab_class[$count]="";//only actual days of the targeted month will have their class stored here
$tab_dates[$count]="";//only actual days of the targeted month will have their date stored here
} else {
if (checkdate($monthKey,$num_day_current,$yearKey))//if the date is valid
{
$datetime = new \DateTime();
$date=$datetime->setDate($yearKey, $monthKey, $num_day_current)->format('Y-m-d');
$tab_dates[$count]=$date;
if (array_key_exists($date, $bookings))//if the date has been found in the booking table for the targeted item
{
$tab_days[$count]=$num_day_current;
$tab_booked[$count]=1;
$tab_class[$count]=$bookings[$date];
} else {
$tab_days[$count]=$num_day_current;
$tab_booked[$count]=0;
$tab_class[$count]=$defaultClass;//if the date has not been found in the booking table for the targeted item, then we apply the class of the first state
}
$num_day_current++;
} else {
$tab_days[$count]=$count-$num_day_current-$nb_days_prev+1;//used to display the days of the next month displayed on the calendar
$tab_booked[$count]=-2;
$tab_class[$count]="";
$tab_dates[$count]="";
}
}
$count++;
}
$return.='"nb_days_prev" : "'.$nb_days_prev.'" , ';
//now starts the actual building of the JSON response
if (!empty($tab_days))
{
$return.=' "calendar" : [ ';
$count = 1;
while ($count < 43)
{
if ($count == 42)
{
$return.=' { "fill" : "'.$tab_days[$count].'", "booked" : "'.$tab_booked[$count].'", "classe" : "'.$tab_class[$count].'", "dates" : "'.$tab_dates[$count].'" } ';
} else {
$return.=' { "fill" : "'.$tab_days[$count].'", "booked" : "'.$tab_booked[$count].'", "classe" : "'.$tab_class[$count].'", "dates" : "'.$tab_dates[$count].'" } , ';
}
$count++;
}
$return.=' ] ';
}
$return.=' } ';
$return='{"responseCode" : "200", '.$return;
return new Response($return,200,array('Content-Type'=>'application/json'));//make sure it has the correct content type
}
/**
* controller called via ajax when a date is clicked on administration panel
* @return Response
* @throws \Doctrine\ORM\NonUniqueResultException
*/
public function ajaxAdminAction(Request $request)
{
//$request = $this->get('request');
$date=$request->request->get('date');
$id=$request->request->get('id');
$itemId=$request->request->get('itemId');
$clickMethod=$request->request->get('clickMethod');
$item = $this->em->getRepository(Item::class)->find($itemId);
if (!$item)
{
$return='{"responseCode" : "400", "message" : "the item selected does not exist - please restart the application"}';// if the item is not found, an ajax response is sent with a message to be displayed
return new Response($return,200,array('Content-Type'=>'application/json'));
}
if ($clickMethod>0)
{
$stateSelected = $this->em->getRepository(State::class)->find($clickMethod);
if (!$stateSelected)
{
$return='{"responseCode" : "400", "message" : "the state selected does not exist - please restart the application"}';// if the state selected is not found, an ajax response is sent with a message to be displayed
return new Response($return,200,array('Content-Type'=>'application/json'));
}
}
$yearKey = substr($date, 0, 4);
$monthKey = substr($date, 5, 2);
$dayKey = substr($date, 8, 2);
$target = new \DateTime();
$target->setDate($yearKey, $monthKey, $dayKey);
$target->setTime(0, 0, 0);//necessary to be able to test equality between dates in the following query
$er = $this->em->getRepository(Booking::class);
$qb = $er->createQueryBuilder('a');
$qb->where('a.theDate = :theDate')
->setParameter('theDate', $target)
->andWhere('a.item = :item')
->setParameter('item', $item);
$entity = $qb->getQuery()->getOneOrNullResult();
$return='';
$return.='"id_returned" : "'.$id.'" , ';
$return.='"date_returned" : "'.$date.'" , ';
/////////////////////////////////////////////////////////////////////////////////////////
//if the date is not found in the booking table for the targeted item, then it is created
/////////////////////////////////////////////////////////////////////////////////////////
if ($entity==null)
{
if ($clickMethod != 0)
{
$booking = new Booking();
$booking->setTheDate($target);
$booking->setItem($item);
$booking->setState($stateSelected);
$this->em->persist($booking);
$this->em->flush();
$return.='"state" : "'.$booking->getState()->getClass();
} else {
$return.='"state" : "';
}
} else {
////////////////////////////////////////////////////////////////////////////
// click through method is selected, meaning the new state is the next state
///////////////////////////////////////////////////////////////////////////
if ($clickMethod == 0)
{
$this->em->remove($entity);
$this->em->flush();
$return.='"state" : "';
} else {
$entity->setState($stateSelected);
$this->em->persist($entity);
$this->em->flush();
$return.='"state" : "'.$entity->getState()->getClass();
}
}
$return='{"responseCode" : "200", '.$return.'" }';
return new Response($return,200,array('Content-Type'=>'application/json'));//make sure it has the correct content type
}
/**
* controller called via ajax when a date is clicked on administration panel
*
* @return Response
*/
public function ajaxChangeStateAction(Request $request)
{
$return='';
//$request = $this->get('request');
$itemId = $request->request->get('itemId');
// Si fem la crida per fer proves per get
if ($itemId == '') $itemId = $request->query->get('itemId');
$objState = $this->em->getRepository(State::class)->findBy(
array('item' => $itemId),
array('position' => 'ASC')
);
if (!$objState)
{
$return='{"responseCode" : "400", "message" : "the state selected does not exist - please restart the application"}';// if the state selected is not found, an ajax response is sent with a message to be displayed
return new Response($return,200,array('Content-Type'=>'application/json'));
} else {
$return.='"state" : [ ';
foreach ($objState as $states)
{
//echo $states->getName();
//echo '<pre>';
//print_r($states);
//echo '</pre>';
if ($return != '"state" : [ ') $return.=',';
$return.='{"id_returned" : "' . $states->getid() . '" , ';
$return.='"name_returned" : "' . $states->getName() . '" , ';
$return.='"class_returned" : "' . $states->getclass() . '" }';
}
$return.=']';
}
$return='{"responseCode" : "200", ' . $return . ' }';
return new Response($return,200,array('Content-Type'=>'application/json'));//make sure it has the correct content type
}
/**
* Function returning the name of the month based on its number - accents are javascript encoded
*
* @param $monthKey
* @return mixed
*/
function getMonth($monthKey)
{
$monthKey=sprintf("%d",$monthKey);
$tab_mois=array( 1 => $this->translator->trans("Gener"),
$this->translator->trans("Febrer"),
$this->translator->trans("Març"),
$this->translator->trans("Abril"),
$this->translator->trans("Maig"),
$this->translator->trans("Juny"),
$this->translator->trans("Juliol"),
$this->translator->trans("Agost"),
$this->translator->trans("Setembre"),
$this->translator->trans("Octubre"),
$this->translator->trans("Novembre"),
$this->translator->trans("Desembre"));
return $tab_mois[$monthKey];
}
//Function returning following or previous month and year based on $pas
function getOtherMonth($monthKey,$yearKey,$pas)
{
$tmstp_suivant=mktime(0,0,0,($monthKey+$pas),1,$yearKey);
$date_suivante[$monthKey]=date("m",$tmstp_suivant);
$date_suivante[$yearKey]=date("Y",$tmstp_suivant);
return $date_suivante;
}
//Function returning the first day of the month
function getFirstDay($monthKey,$yearKey)
{
$tmstp=mktime(0,0,0,$monthKey,1,$yearKey);
$dayKey=date("w",$tmstp);
$tab_jour=array(0=>7,1=>1,2=>2,3=>3,4=>4,5=>5,6=>6);//This is for calendars with weeks starting on Mondays. Sunday returns a 0 which must be changed to 7
return $tab_jour[$dayKey];//for calendars with weeks starting on Sundays, just return $dayKey.
}
}