src/Controller/StatsController.php line 61

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use Ob\HighchartsBundle\Highcharts\Highchart;
  4. use JMS\DiExtraBundle\Annotation as DI;
  5. //use JMS\Payment\CoreBundle\Entity\Payment;
  6. //use JMS\Payment\CoreBundle\PluginController\Result;
  7. //use JMS\Payment\CoreBundle\Plugin\Exception\ActionRequiredException;
  8. //use JMS\Payment\CoreBundle\Plugin\Exception\Action\VisitUrl;
  9. use Symfony\Component\Routing\Annotation\Route;
  10. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  11. use Symfony\Component\HttpFoundation\RedirectResponse;
  12. use Symfony\Component\HttpFoundation\JsonResponse;
  13. use Symfony\Component\HttpFoundation\Response;
  14. use Symfony\Bundle\FrameworkBundle\Controller\Controller;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Knp\Bundle\SnappyBundle\Snappy\Response\PdfResponse;
  17. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  18. use Doctrine\Common\Collections\ArrayCollection;
  19. use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
  20. use Doctrine\Common\Collections\Criteria;
  21. use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
  22. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  23. use App\Repository\EventsRepository;
  24. use App\Entity\Orders;
  25. use App\Entity\OrderItems;
  26. use App\Entity\OrderTickets;
  27. use App\Entity\Events;
  28. use App\Entity\EventDates;
  29. use App\Entity\EventTickets;
  30. use App\Entity\EventExtra;
  31. use App\Entity\Sites;
  32. use App\Entity\Language;
  33. use App\Entity\Coupons;
  34. use App\Service\EventStats;
  35. /**
  36.  * @Route("/",
  37.  *     name="stats_",
  38.  *     condition="request.headers.get('Host') matches '/stats\./i'"
  39.  * )
  40.  */
  41. class StatsController extends Controller {
  42.     
  43.     private $eventStats;
  44.     private $searchFilter '';
  45.     
  46.     public function __construct(EventStats $eventStats) {        
  47.         $this->eventStats $eventStats;
  48.     }
  49.     
  50.     /**
  51.      * @Route("/", name = "home")
  52.      */
  53.     public function homeAction(Request $request) {
  54.         return $this->redirectToRoute('stats_dashboard');
  55.     }
  56.     
  57.     private function getEvents() {
  58.         //$request = $this->get('request');
  59.         $user $this->getUser();
  60.         $dates = new ArrayCollection();
  61.         //$key = $request->query->get('q');
  62.         
  63.         if($user->isGranted('ROLE_ADMIN')) {
  64.             // Very well... All events are granted!
  65.             $datesObj $this->getDoctrine()->getManager()->getRepository(EventDates::class)->findAll(array(), array('date_start' => 'DESC'));
  66.             foreach($datesObj as $date) {
  67.                 $dates->add($date);
  68.             }
  69.             // All event dates, sorted by start date descending
  70.         } else {
  71.             
  72.             $manager $this->getDoctrine()->getManager();
  73.             
  74.             // Fetch the events from the user object...
  75.            
  76.             $userEvents $this->getUser()->getEvents();
  77.             if($userEvents->count() > 0) {
  78.                 foreach($userEvents as $event) {
  79.                     foreach($event->getDates() as $date) {
  80.                         if(!$dates->contains($date)) {
  81.                             $dates->add($date);
  82.                         }
  83.                     }
  84.                 }
  85.             }
  86.             
  87.             $userOrganisers $this->getUser()->getOrganisers();
  88.             if($userOrganisers->count() > 0) {
  89.                 foreach($userOrganisers as $organiser) {
  90.                     foreach($organiser->getEvents() as $event) {
  91.                         foreach($event->getDates() as $date) {
  92.                             if(!$dates->contains($date)) {
  93.                                 $dates->add($date);
  94.                             }
  95.                         }
  96.                     }
  97.                 }
  98.             }
  99.             
  100.             $userArtists $this->getUser()->getArtists();
  101.             if($userArtists->count() > 0) {
  102.                 foreach($userArtists as $artist) {
  103.                     foreach($artist->getEvents() as $event) {
  104.                         foreach($event->getDates() as $date) {
  105.                             if(!$dates->contains($date)) {
  106.                                 $dates->add($date);
  107.                             }
  108.                         }
  109.                     }
  110.                 }
  111.             }
  112.             
  113.             /*$userLocations = $this->getUser()->getLocations();
  114.             if($userLocations->count() > 0) {
  115.                 foreach($userLocations as $location) {
  116.                     foreach($location->getEvents() as $event) {
  117.                         foreach($event->getEvents()->getDates() as $date) {
  118.                             if(!$dates->contains($date)) {
  119.                                 $dates->add($date);
  120.                             }
  121.                         }
  122.                     }
  123.                 }
  124.             }*/
  125.             
  126.             $userSites $this->getUser()->getSites();
  127.             if($userSites->count() > 0) {
  128.                 foreach($userSites as $site) {
  129.                     // If the site has a location filter active... Do so here too!
  130.                     $locationCriteria false// Preset so no errors will be thrown...
  131.                     if($site->getFilterByVenue()) {
  132.                         $location $site->getLocation();
  133.                         $locationCriteria Criteria::create()->andWhere(Criteria::expr()->eq("location"$location));
  134.                     }
  135.                     foreach($site->getEvents() as $event) {
  136.                         if($locationCriteria instanceof Criteria) {
  137.                             $event_dates $event->getEvents()->getDates()->matching($locationCriteria);
  138.                         } else {
  139.                             $event_dates $event->getEvents()->getDates();
  140.                         }
  141.                         if($event_dates->count() > 0) {
  142.                             foreach($event_dates as $date) {
  143.                                 if(!$dates->contains($date)) {
  144.                                     $dates->add($date);
  145.                                 }
  146.                             }
  147.                         }
  148.                     }
  149.                 }
  150.             }
  151.         }
  152.         return $dates;
  153.     }
  154.     
  155.     private function countTotalTicketsSold(EventDates $date) {
  156.         return $this->getDoctrine()->getManager()->getRepository(EventDates::class)->getAmountTicketsSold($date);
  157.     }
  158.     
  159.     private function countTotalTicketWeight(EventDates $date) {        
  160.         return $this->getDoctrine()->getManager()->getRepository(EventDates::class)->getAmountWeightSold($date);
  161.     }
  162.     
  163.     /**
  164.      * @Route("/stats/list", name = "list")
  165.      */    
  166.     public function listAction(Request $request) {
  167.         
  168.         
  169.         // User has to be logged in to get here by security firewall, no additional checks are done now.
  170.         // No user object means no data...
  171.         
  172.         $data = array();
  173.         $x $y $z 0;
  174.         $sp $request->query->has('start') ? $request->query->get('start') : 0// Start of records
  175.         $pp $request->query->has('length') ? $request->query->get('length') : 10// Amount of records
  176.         $pn $request->query->has('draw') ? $request->query->get('draw') : 1// Which page
  177.         
  178.         $recordsTotal 0;
  179.         $recordsFiltered 0;
  180.         
  181.         if($request->query->has('search')) {
  182.             $sq $request->query->get('search');
  183.             if(isSet($sq['value'])) {
  184.                 if(strlen($sq['value']) > 0) {
  185.                     // Use the filter...
  186.                     $this->searchFilter addslashes($sq['value']);
  187.                 }
  188.             }
  189.         }
  190.         $dates $this->getEvents(); // Now contains the events the user has rights for...        
  191.         // Collect an array iterator.
  192.         $iterator $dates->getIterator();
  193.         // Do sort the new iterator.
  194.         $iterator->uasort(function ($a$b) {
  195.             return ($a->getDateStart() > $b->getDateStart()) ? -1;
  196.         });
  197.         // pass sorted array to a new ArrayCollection.
  198.         $datesSorted = new ArrayCollection(iterator_to_array($iterator));
  199.         // Leave the sorting to datatables now....
  200.         
  201.         foreach($datesSorted as $date) {
  202.             if(isSet($date->getEvents()->getEventDescription()[0])) {
  203.                 $title $date->getEvents()->getEventDescription()[0]->getTitle();
  204.                 $city $date->getLocation()->getCity();
  205.                 // We have at least one object for the description. If not, we won't use it.
  206.                 if((strlen($this->searchFilter) < 1) || stristr($title,$this->searchFilter) || stristr($city,$this->searchFilter)) {
  207.                     if(($x >= $sp) && ($x < ($sp $pp))) {
  208.                         $cnt $cnta 0;
  209.                         $cnt $this->countTotalTicketsSold($date);
  210.                         $cnta $this->countTotalTicketWeight($date);
  211.                         $data[$y] = array(
  212.                             'id' => $date->getId(),
  213.                             'date_id' => $date->getId(),
  214.                             'event_id' => $date->getEvents()->getId(),
  215.                             'start_date' => (string)$date// __toString magic
  216.                             'title' => $title,
  217.                             'city' => $city,
  218.                             'tickets' => $cnt,
  219.                             'attendees' => $cnta,
  220.                             'actions' => array(),
  221.                         );
  222.                         
  223.                         $data[$y]['actions']['stats'] = false;
  224.                         $data[$y]['actions']['export'] = false;
  225.                         $data[$y]['actions']['list'] = false;
  226.                         
  227.                         if($this->getUser()->isGranted('ROLE_STATS') || $this->getUser()->isGranted('ROLE_ADMIN') ) {
  228.                             $data[$y]['actions']['stats'] = $this->generateUrl('stats_details_event_date', array('event'=>$date->getEvents()->getId(),'date'=>$date->getId()));
  229.                         }
  230.                         
  231.                         if($this->getUser()->isGranted('ROLE_EXPORT') || $this->getUser()->isGranted('ROLE_ADMIN') ) {
  232.                             $data[$y]['actions']['export'] = $this->generateUrl('stats_export_event_date', array('event'=>$date->getEvents()->getId(),'date'=>$date->getId()));
  233.                         }
  234.                         if($this->getUser()->isGranted('ROLE_LIST') || $this->getUser()->isGranted('ROLE_ADMIN') ) {
  235.                             $data[$y]['actions']['list'] = $this->generateUrl('stats_list_event_date', array('event'=>$date->getEvents()->getId(),'date'=>$date->getId()));
  236.                         }
  237.                         $y++;
  238.                     }                
  239.                     $x++;
  240.                 }
  241.                 $z++;
  242.             }
  243.         }
  244.         $recordsTotal $z;
  245.         $recordsFiltered $x;
  246.         return new JsonResponse(array('data'=>$data,'draw'=>$pn,'recordsTotal'=>$recordsTotal,'recordsFiltered'=>$recordsFiltered));
  247.     }
  248.     
  249.     /**
  250.      * @Route("/stats/dashboard", name = "dashboard")
  251.      */
  252.     public function dashboardAction(Request $request) {
  253.         $user $this->getUser();
  254.         $tpl 'stats/';
  255.         
  256.         $columns = array(
  257.             'event_id' => 'Evenement ID',
  258.             'date_id' => 'Datum ID',
  259.             'start_date' => 'Startdatum Evenement',
  260.             'title' => 'Titel Evenement',
  261.             'city' => 'Plaats',
  262.             'tickets' => 'Tickets Verkocht',
  263.             'attendees' => 'Deelnemers<br>(Op ticket-gewicht)',
  264.         );
  265.         
  266.         $jsonCol $tblCol = array();
  267.         foreach($columns as $id=>$column) {
  268.             $jsonCol[] = ['data'=>$id,'title'=>$column];
  269.             //$tblCol[] = $column;
  270.         }
  271.         
  272.         return $this->render($tpl.'/dashboard.html.twig',array('jsoncol'=>$jsonCol));        
  273.     }
  274.     
  275.     /**
  276.      * @Route("/stats/details/{event}/{date}", name = "details_event_date")
  277.      */
  278.     public function detailsEventDateAction(Request $requestEvents $eventEventDates $date) {
  279.         
  280.         // User determines access rights. We ignore the domain here.
  281.         if(!$this->getUser()->isGranted('ROLE_STATS') && !$this->getUser()->isGranted('ROLE_ADMIN')) {
  282.             // How the F did he even get here?
  283.             return new Response("Geen rechten om dit te zien.",Response::HTTP_OK);
  284.         }
  285.         
  286.         // We do have to check if the user has the rights to the chosen event, or we're getting problems later on...
  287.         $dates $this->getEvents();
  288.         if(!$dates->contains($date)) {
  289.             // Too bad, no access...
  290.             return new Response("Geen rechten voor het gekozen event.",Response::HTTP_OK);
  291.         }
  292.         
  293.         $eStats $this->eventStats;
  294.         $data $eStats->getEventData($date);
  295.         $prData $eStats->getProvincesByEvent($date);
  296.         $gmData $eStats->getTownshipsByEvent($date);
  297.         $columns = array();
  298.         $columns['title'] = 'Naam';
  299.         $columns['price'] = 'Prijs';
  300.         $columns['total'] = 'Verkocht';
  301.         $columns['paid'] = 'Betaald';
  302.         $columns['pending'] = 'Wacht op betaling';
  303.         $chartData1 $eStats->getTicketCountByDate($date);
  304.         // Chart
  305.         $series = array(
  306.             array("name" => "Tickets",    "data" => $chartData1)
  307.         );
  308.         $ob = new Highchart();
  309.         $ob->chart->renderTo('chart1');  // The #id of the div where to render the chart
  310.         $ob->title->text('Verkoopstatistieken');
  311.         $ob->xAxis->title(array('text'  => "Datum"));
  312.         $ob->yAxis->title(array('text'  => "Aantal"));
  313.         $ob->xAxis->type('datetime');
  314.         $ob->xAxis->tickInterval((28 24 3600 1000));
  315.         $ob->chart->zoomType("x");
  316.         $ob->series($series);
  317.         $ob2 = new Highchart();
  318.         $ob2->chart->renderTo('chart2');
  319.         $ob2->title->text('Verdeling tussen de type\'s tickets');
  320.         $ob2->plotOptions->pie(array(
  321.             'allowPointSelect'  => true,
  322.             'cursor'    => 'pointer',
  323.             'dataLabels'    => array(
  324.                 'enabled' => false,
  325.                 'format' => '{point.name}: {point.y:.1f}%'
  326.             ),
  327.             'showInLegend'  => true
  328.         ));
  329.         $ob2->tooltip->pointFormat('<span style="color:{point.color}">{point.name}</span>: <b>{point.y:.2f}%</b><br/>');
  330.         $tdata = array();
  331.         $total 0;
  332.         foreach($data['tickets'] as $ticket) {
  333.             $total += (int)$ticket['total'];
  334.         }
  335.         foreach($data['tickets'] as $ticket) {
  336.             $perc = ($ticket['total'] / $total) * 100;
  337.             $tdata[] = array($ticket['title'], $perc);
  338.         }
  339.         $ob2->series(array(array('type' => 'pie','name' => 'Ticketverdeling''data' => $tdata)));
  340.         $ob3 = new Highchart();
  341.         $ob3->chart->renderTo('chart3');
  342.         $ob3->title->text('Statistieken per provincie');
  343.         $ob3->plotOptions->pie(array(
  344.             'allowPointSelect'  => true,
  345.             'cursor'    => 'pointer',
  346.             'dataLabels'    => array(
  347.                 'enabled' => false,
  348.                 'format' => '{point.name}: {point.y:.1f}%'
  349.             ),
  350.             'showInLegend'  => true
  351.         ));
  352.         $ob3->tooltip->pointFormat('<span style="color:{point.color}">{point.name}</span>: <b>{point.y:.2f}%</b><br/>');
  353.         $tdata = array();
  354.         $total 0;
  355.         foreach($prData as $aantal) {
  356.             $total += (int)$aantal;
  357.         }
  358.         foreach($prData as $provincie=>$aantal) {
  359.             $perc = ($aantal $total) * 100;
  360.             $tdata[] = array($provincie$perc);
  361.         }
  362.         $ob3->series(array(array('type' => 'pie','name' => 'Provincie''data' => $tdata)));
  363.         $ob4 = new Highchart();
  364.         $ob4->chart->renderTo('chart4');
  365.         $ob4->title->text('Top 10 Gemeentes');
  366.         $ob4->plotOptions->pie(array(
  367.             'allowPointSelect'  => true,
  368.             'cursor'    => 'pointer',
  369.             'dataLabels'    => array(
  370.                 'enabled' => false,
  371.                 'format' => '{point.name}: {point.y:.1f}%'
  372.             ),
  373.             'showInLegend'  => true
  374.         ));
  375.         $ob4->tooltip->pointFormat('<span style="color:{point.color}">{point.name}</span>: <b>{point.y:.2f}%</b><br/>');
  376.         arsort($gmData);
  377.         $tdata = array();
  378.         $total 0;
  379.         foreach($gmData as $aantal) {
  380.             $total += (int)$aantal;
  381.         }
  382.         $i 1;
  383.         foreach($gmData as $gemeente=>$aantal) {
  384.             if($i 10) continue;
  385.             $perc = ($aantal $total) * 100;
  386.             $tdata[] = array($gemeente$perc);
  387.             $i++;
  388.         }
  389.         $ob4->series(array(array('type' => 'pie','name' => 'Gemeente''data' => $tdata)));
  390.         unset($data['ticketmeta']);
  391.         unset($data['globalmeta']);
  392.         return $this->render('stats/detail.html.twig',
  393.             array('event'=>$event,
  394.                   'data'=>$data,
  395.                   'columns'=>$columns,
  396.                   'chart1' => $ob,
  397.                   'chart2' => $ob2,
  398.                   'chart3' => $ob3,
  399.                   'chart4' => $ob4,
  400.                   'modal'=>true
  401.             )
  402.         );
  403.     }
  404.     
  405.     
  406.     
  407.     /**
  408.      * @Route("/stats/export/{event}/{date}", name = "export_event_date")
  409.      */
  410.     public function exportAction(Request $requestEvents $eventEventDates $date) {
  411.         // User determines access rights. We ignore the domain here.
  412.         if(!$this->getUser()->isGranted('ROLE_EXPORT') && !$this->getUser()->isGranted('ROLE_ADMIN')) {
  413.             // How the F did he even get here?
  414.             return new Response("Geen rechten om te exporteren.",Response::HTTP_OK);
  415.         }        
  416.         // We do have to check if the user has the rights to the chosen event, or we're getting problems later on...
  417.         $dates $this->getEvents();
  418.         if(!$dates->contains($date)) {
  419.             // Too bad, no access...
  420.             return new Response("Geen rechten voor het gekozen event.",Response::HTTP_OK);
  421.         }
  422.         
  423.         // OK, so it is allowed?
  424.         return new Response("OK",Response::HTTP_OK);
  425.     }
  426.     
  427.         
  428.     /**
  429.      * @Route("/stats/list/{event}/{date}", name = "list_event_date")
  430.      */
  431.     public function listEventDateAction(Request $requestEvents $eventEventDates $date) {
  432.         
  433.         // User determines access rights. We ignore the domain here.
  434.         
  435.         if(!$this->getUser()->isGranted('ROLE_LIST') && !$this->getUser()->isGranted('ROLE_ADMIN')) {
  436.             // How the F did he even get here?
  437.             return new Response("Geen rechten om te weergeven.",Response::HTTP_OK);
  438.         }        
  439.         // We do have to check if the user has the rights to the chosen event, or we're getting problems later on...
  440.         $dates $this->getEvents();
  441.         if(!$dates->contains($date)) {
  442.             // Too bad, no access...
  443.             return new Response("Geen rechten voor het gekozen event.",Response::HTTP_OK);
  444.         }
  445.         
  446.         $retval $this->getExportData($request,$event,$date);
  447.         
  448.         $retval str_replace("\r\n","</td></tr>\r\n<tr><td>",$retval);
  449.         $retval str_replace(";","</td><td>",$retval);
  450.         $retval "<table><tr><td>".$retval."</td></tr></table>";
  451.         return new Response($retval,Response::HTTP_OK);
  452.     }
  453.     
  454.     /**
  455.      * @Route("/stats/info/{event}/{date}", name = "info_event_date")
  456.      */
  457.     public function infoEventDateAction(Request $requestEvents $eventEventDates $date) {
  458.         
  459.         // User determines access rights. We ignore the domain here.
  460.         
  461.         if(!$this->getUser()->isGranted('ROLE_LIST') && !$this->getUser()->isGranted('ROLE_ADMIN')) {
  462.             // How the F did he even get here?
  463.             return new Response("Geen rechten om te weergeven.",Response::HTTP_OK);
  464.         }        
  465.         // We do have to check if the user has the rights to the chosen event, or we're getting problems later on...
  466.         $dates $this->getEvents();
  467.         if(!$dates->contains($date)) {
  468.             // Too bad, no access...
  469.             return new Response("Geen rechten voor het gekozen event.",Response::HTTP_OK);
  470.         }        
  471.         return new Response($retval,Response::HTTP_OK);
  472.     }
  473.     
  474.     /**
  475.      * @Route("/stats/export/{event}/{date}/download", name = "export_event_date_download")
  476.      * @Route("/stats/export/{event}/{date}/download.{ext}", name = "export_event_date_download")
  477.      */
  478.     public function exportDownloadAction(Request $requestEvents $eventEventDates $date$ext false) {
  479.         // User determines access rights. We ignore the domain here.
  480.         if(!$this->getUser()->isGranted('ROLE_EXPORT') && !$this->getUser()->isGranted('ROLE_ADMIN')) {
  481.             // How the F did he even get here?
  482.             return new Response("Geen rechten om te exporteren.",Response::HTTP_OK);
  483.         }        
  484.         // We do have to check if the user has the rights to the chosen event, or we're getting problems later on...
  485.         $dates $this->getEvents();
  486.         if(!$dates->contains($date)) {
  487.             // Too bad, no access...
  488.             return new Response("Geen rechten voor het gekozen event.",Response::HTTP_OK);
  489.         }
  490.                
  491.         
  492.         $response = new Response();
  493.         $response->headers->set('Content-Type''text/csv');
  494.         $response->headers->set('Content-Disposition''attachment; filename="EventExport '.date("Y-m-d H:i:s").' - '.(string)$event.'.csv"');
  495.         
  496.         $retval $this->getExportData($request,$event,$date);
  497.         
  498.         $response->setContent($retval);
  499.         
  500.         return $response;
  501.     }
  502.     
  503.     private function getExportData(Request $requestEvents $eventEventDates $date) {
  504.         
  505.         $orders $this->getDoctrine()->getManager()->getRepository(Orders::class)->getByEventDate($date);
  506.         $eStats $this->eventStats;        
  507.         $data $eStats->getEventData($date);
  508.         
  509.         $allowedTickets $date->getTickets();
  510.         
  511.         // Determine columns....
  512.         $columns['Id'] = 'Ordernummer';
  513.         $columns['date_created'] = 'Besteldatum';
  514.         $columns['email'] = 'Email';
  515.         $columns['first_name'] = 'Voornaam';
  516.         $columns['lastname'] = 'Achternaam';
  517.         $columns['phone'] = 'Telefoon';
  518.         $columns['address'] = 'Adres';
  519.         $columns['streetnr'] = 'Huisnr';
  520.         $columns['postal_code'] = 'Postcode';
  521.         $columns['city'] = 'Plaats';
  522.         $columns['country'] = 'Land';
  523.         $columns['total'] = 'Bedrag';
  524.                 
  525.         $columns['birthdate'] = 'Geboortedatum';
  526.         $columns['status_text'] = 'Status';
  527.         $columns['sites']['name'] = "Besteld via";
  528.         
  529.         if($this->getUser()->isGranted('ROLE_ADMIN')) {
  530.             $columns['amount_tickets'] = 'Aantal Tickets';
  531.             $columns['ticket_link'] = 'Ticket URL';
  532.             $columns['comments'] = 'Opmerkingen';
  533.         }
  534.         
  535.         $columns['order_extra'] = array();
  536.         $columns['order_meta'] = array();
  537.         $columns['empty1'] = '';
  538.         
  539.         $columns['order_tickets']['Id'] = "Ticketnummer";
  540.         $columns['order_tickets']['product_title'] = "Ticket Type";
  541.         $columns['order_tickets']['weight'] = "Deelnemers";
  542.         $columns['order_tickets']['vak'] = "Vak";
  543.         $columns['order_tickets']['rij'] = "Rij";
  544.         $columns['order_tickets']['stoel'] = "Stoel";
  545.         $columns['order_tickets']['checked_in'] = "Status";
  546.         $columns['ticket_extra'] = array();
  547.         $columns['ticket_meta'] = array();
  548.         $columns['empty2'] = '';
  549.         
  550.         $colIndex = array();
  551.         
  552.         $i 0;
  553.         $y 0;
  554.         
  555.         $ordermeta Orders::getOrderMeta($event->getId());
  556.         
  557.         $ticketMetaColumns = array();
  558.         foreach($data['ticketmeta'] as $prod_id=>$block) {
  559.             foreach($block as $key=>$value) {
  560.                 if(!isSet($columns['ticket_meta'][$key])) {
  561.                     $columns['ticket_meta'][$key] = $value;
  562.                     $ticketMetaColumns[$key] = $value;
  563.                 }
  564.             }            
  565.         }
  566.         
  567.         foreach($data['globalextra'] as $prod_id=>$info) {
  568.             $columns['order_extra'][$prod_id] = $info['title'];
  569.         }
  570.         
  571.         foreach($data['ticketextra'] as $prod_id=>$info) {
  572.             $columns['order_extra'][$prod_id] = $info['title'];
  573.         }
  574.         
  575.         foreach($columns as $k=>$v) {
  576.             if(!is_array($v)) {
  577.                 $retval[$i][] = $v;
  578.                 $colIndex[$y] = $k;
  579.                 $y++;
  580.             } else {
  581.                 foreach($v as $key=>$value) {
  582.                     $retval[$i][] = $value;
  583.                     $colIndex[$y] = $key;
  584.                     $y++;
  585.                 }
  586.             }
  587.         }
  588.         
  589.         
  590.         foreach($orders as $order) {
  591.             $status $order->getStatus();
  592.             if(!in_array($status, array(
  593.                 Orders::ORDER_STATUS_COMPLETE,
  594.                 Orders::ORDER_STATUS_PAID,
  595.                 Orders::ORDER_STATUS_PENDING,
  596.                 Orders::ORDER_STATUS_NEW,
  597.             ))) {
  598.                 continue; // Skip this order, not the correct status.
  599.             }
  600.             foreach($order->getOrderTickets() as $ticket) {
  601.                 if(!$allowedTickets->contains($ticket->getProduct())) continue; // Skip this ticket!
  602.                 //$extra = $ticket->getProduct()->getEvents()->getEventExtra();
  603.                 $i++;
  604.                 foreach($columns as $k=>$v) {
  605.                     if(!is_array($v)) {
  606.                         if(!strstr($k,'empty')) {
  607.                             $value false;
  608.                             if($k == 'amount_tickets') {
  609.                                 $cntTick 0;
  610.                                 foreach($order->getOrderTickets() as $tick) {
  611.                                     if($allowedTickets->contains($tick->getProduct())) {
  612.                                         $cntTick++;
  613.                                     }
  614.                                 }
  615.                                 $value $cntTick;
  616.                             }
  617.                             if($k == 'ticket_link') {
  618.                                 $token md5($order->getEmail().'-Order-Code-'.$order->getId());
  619.                                 $site $order->getSites();
  620.                                 $value 'https://'.$site->getUrl()."/order/".$order->getId()."/pdf/".$token;
  621.                             }
  622.                             if(!$value) {
  623.                                 $value $order->get($k);
  624.                                 if($value instanceof \DateTime) {
  625.                                     $value $value->format("d-m-Y H:i:s");
  626.                                 }
  627.                             }                            
  628.                             $retval[$i][] = $value;
  629.                         } else {
  630.                             $retval[$i][] = '';
  631.                         }
  632.                     } else {
  633.                         if($k == 'order_extra' || $k =='ticket_extra') {
  634.                             foreach($v as $key=>$value) {
  635.                                 $value 0;
  636.                                 foreach($order->getItems() as $item) {
  637.                                     if($item->getType() == 'extra' && $item->getProduct() == $key) {
  638.                                         $value $item->getAmount();
  639.                                     }
  640.                                 }
  641.                                 $retval[$i][] = $value;
  642.                             }
  643.                         }
  644.                         if($k =='ticket_meta') {
  645.                             $meta $ticket->getMeta();
  646.                             foreach($v as $key=>$value) {
  647.                                 $value '';
  648.                                 if(isSet($meta[$key]))  {
  649.                                     $value $meta[$key];
  650.                                 }
  651.                                 $retval[$i][] = $value;
  652.                             }
  653.                         }
  654.                         if($k == 'sites') {
  655.                             $object $order->getSites();
  656.                             foreach($v as $key=>$value) {
  657.                                 $value false;
  658.                                 if(!$value) {
  659.                                     $value $object->get($key);
  660.                                 }
  661.                                 $retval[$i][] = $value;
  662.                             }
  663.                         }
  664.                         if($k == 'order_tickets') {
  665.                             foreach($v as $key=>$value) {
  666.                                 $value false;
  667.                                 if($key == 'product_title') {
  668.                                     $value $ticket->getProduct()->getTitle();
  669.                                 }
  670.                                 if($key == 'checked_in') {
  671.                                     $value  $ticket->getCheckedIn();
  672.                                     $value = ($value == 1) ? 'Ingecheckt' ' ';
  673.                                 }
  674.                                 if($key == 'weight') {
  675.                                     $value  $ticket->getProduct()->getWeight();
  676.                                 }                                
  677.                                 if($key == 'rij' || $key == 'stoel' || $key == 'vak') {
  678.                                     $value =  '-NVT-';
  679.                                 }
  680.                                 if(!$value) {
  681.                                     $value $ticket->get($key);
  682.                                 }
  683.                                 $retval[$i][] = $value;
  684.                             }
  685.                         }                        
  686.                     }
  687.                 }
  688.             }
  689.         }
  690.         
  691.         foreach($retval as $x => $row) {
  692.             $retval[$x] = implode(";",$row);
  693.         }
  694.         
  695.         $retval implode("\r\n",$retval);
  696.         return $retval;
  697.     }
  698.     
  699.     /**
  700.      * @Route("/stats/login", name = "login")
  701.      */
  702.     public function loginAction(Request $requestAuthenticationUtils $authenticationUtils) {
  703.         // get the login error if there is one
  704.         $error $authenticationUtils->getLastAuthenticationError();
  705.     
  706.         // last username entered by the user
  707.         $lastUsername $authenticationUtils->getLastUsername();
  708.     
  709.         return $this->render('stats/login.html.twig', [
  710.             'last_username' => $lastUsername,
  711.             'error'         => $error,
  712.         ]);
  713.     }
  714. }