AdminController::showEventsStatisticAction()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 27
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 27
rs 9.6333
c 0
b 0
f 0
cc 4
nc 6
nop 1
1
<?php
2
3
namespace Application\Bundle\DefaultBundle\Controller;
4
5
use Application\Bundle\DefaultBundle\Entity\TicketCost;
6
use Application\Bundle\UserBundle\Entity\User;
7
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
8
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
9
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
10
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
11
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
12
use Stfalcon\Bundle\EventBundle\Entity\Event;
13
use Stfalcon\Bundle\EventBundle\Entity\Ticket;
14
use Stfalcon\Bundle\EventBundle\Entity\Payment;
15
use Symfony\Component\HttpFoundation\JsonResponse;
16
use Symfony\Component\HttpFoundation\Request;
17
use Symfony\Component\HttpFoundation\Response;
18
use Stfalcon\Bundle\EventBundle\Entity\Mail;
19
use Symfony\Component\HttpFoundation\StreamedResponse;
20
21
/**
22
 * Class AdminController.
23
 */
24
class AdminController extends Controller
25
{
26
    /**
27
     * @Route("/admin/event/{slug}/users/add", name="adminusersadd")
28
     *
29
     * @Security("has_role('ROLE_ADMIN')")
30
     *
31
     * @param Event $event
32
     *
33
     * @return Response
34
     */
35
    public function addUsersAction(Event $event)
36
    {
37
        // @todo удалить этот метод. одноразовый харкод
38
        $em = $this->getDoctrine()->getManager();
39
40
        if (isset($_POST['users'])) {
41
            $users = explode("\r\n", $_POST['users']);
42
43
            foreach ($users as $data) {
44
                // данные с формы
45
                $dt = explode(' ', $data);
46
                unset($data);
47
                $data['name'] = $dt[0];
48
                $data['surname'] = $dt[1];
49
                $data['email'] = $dt[2];
50
                $data['discount'] = isset($dt[3]) && 'D' === strtoupper($dt[3]);
51
52
                $user = $this->get('fos_user.user_manager')->findUserBy(['email' => $data['email']]);
53
54
                // создаем нового пользователя
55
                if (!$user) {
56
                    /** @var User $user */
57
                    $user = $this->get('fos_user.user_manager')->createUser();
58
                    $user->setEmail($data['email'])
59
                        ->setName($data['name'])
60
                        ->setSurname($data['surname']);
61
62
                    // генерация временного пароля
63
                    $password = substr(str_shuffle(md5(time())), 5, 8);
64
                    $user->setPlainPassword($password);
65
                    $user->setEnabled(true);
66
67
                    $errors = $this->container->get('validator')->validate($user);
68
                    if ($errors->count() > 0) {
69
                        $this->addFlash('sonata_flash_info', $user->getFullname().' — User create Bad credentials!');
70
                        break;
71
                    }
72
73
                    $this->get('fos_user.user_manager')->updateUser($user);
74
75
                    // отправляем сообщение о регистрации
76
                    $body = $this->container->get('stfalcon_event.mailer_helper')->renderTwigTemplate(
77
                        'ApplicationUserBundle:Registration:automatically.html.twig',
78
                        [
79
                            'user' => $user,
80
                            'plainPassword' => $password,
81
                        ]
82
                    );
83
84
                    $message = \Swift_Message::newInstance()
85
                        ->setSubject('Регистрация на сайте Frameworks Days')
86
                        // @todo refact
87
                        ->setFrom('[email protected]', 'Fwdays')
88
                        ->setTo($user->getEmail())
89
                        ->setBody($body, 'text/html');
90
91
                    // @todo каждый вызов отнимает память
92
                    $this->get('mailer')->send($message);
93
94
                    $this->addFlash('sonata_flash_info', $user->getFullname().' — Create a new user');
95
                } else {
96
                    $this->addFlash('sonata_flash_info', $user->getFullname().' — already registered');
97
                }
98
99
                // обновляем информацию о компании
100
                $user->setCountry('Украина');
101
                if (isset($_POST['city'])) {
102
                    $user->setCity($_POST['city']);
103
                }
104
105
                $user->setCompany($_POST['company']);
106
                $em->persist($user);
107
                $em->flush();
108
109
                // проверяем или у него нет билетов на этот ивент
110
                /** @var Ticket $ticket */
111
                $ticket = $em->getRepository('StfalconEventBundle:Ticket')
112
                    ->findOneBy(array('event' => $event->getId(), 'user' => $user->getId()));
113
114
                if (!$ticket) {
115
                    $ticket = new Ticket();
116
                    $ticket->setEvent($event);
117
                    $ticket->setUser($user);
118
                    $user->addWantsToVisitEvents($event);
119
                    $em->persist($ticket);
120
                }
121
122
                if ($ticket->isPaid()) {
123
                    $this->addFlash('sonata_flash_info', $user->getFullname().' already paid participation in the conference!');
124
                } else {
125
                    // цена участия (с учетом скидки)
126
                    $priceBlockId = $_POST['block_id'];
127
                    $amountWithOutDiscount = $_POST['amount'];
128
                    /** @var TicketCost $ticketCost */
129
                    foreach ($event->getTicketsCost() as $ticketCost) {
130
                        if ($ticketCost->getId() === (int) $priceBlockId) {
131
                            $ticket->setTicketCost($ticketCost);
132
                            break;
133
                        }
134
                    }
135
136
                    $amount = $data['discount'] ? $amountWithOutDiscount * 0.8 : $amountWithOutDiscount;
137
                    $ticket->setAmount($amount);
138
                    $ticket->setHasDiscount($data['discount']);
139
                    $ticket->setAmountWithoutDiscount($amountWithOutDiscount);
140
141
                    $oldPayment = $ticket->getPayment();
142
143
                    if ($oldPayment) {
144
                        $oldPayment->removeTicket($ticket);
145
                        $em->persist($oldPayment);
146
                    }
147
                    $this->addFlash('sonata_flash_info', 'create a new payment');
148
                    $payment = (new Payment())
149
                        ->setUser($user)
150
                        ->setAmount($ticket->getAmount())
151
                        ->setBaseAmount($ticket->getAmountWithoutDiscount())
152
                    ;
153
                    $payment->addTicket($ticket);
154
                    $ticket->setPayment($payment);
155
                    $em->persist($payment);
156
                    $em->flush();
157
158
                    $payment->setPaidWithGate(Payment::ADMIN_GATE);
159
                    $em->flush();
160
161
                    $this->addFlash('sonata_flash_info', 'mark as paid');
162
                }
163
            }
164
165
            $this->addFlash('sonata_flash_info', 'complete');
166
        }
167
168
        $priceBlocks = $event->getTicketsCost();
169
170
        return $this->render(
171
            '@ApplicationDefault/Admin/addUsers.html.twig',
172
            [
173
                'admin_pool' => $this->get('sonata.admin.pool'),
174
                'event' => $event,
175
                'price_blocks' => $priceBlocks,
176
                'event_slug' => $event->getSlug(),
177
            ]
178
        );
179
    }
180
181
    /**
182
     * Widget share contacts.
183
     *
184
     * @return Response
185
     */
186
    public function widgetShareContactsAction()
187
    {
188
        if (null !== ($user = $this->getUser())) {
189
            if ((null === $user->isAllowShareContacts()) && !in_array('ROLE_SUPER_ADMIN', $user->getRoles())) {
190
                return $this->render('ApplicationDefaultBundle:Default:shareContacts.html.twig');
191
            }
192
        }
193
194
        return new Response();
195
    }
196
197
    /**
198
     * Show Statistic.
199
     *
200
     * @Route("/admin/statistic", name="admin_statistic_all")
201
     *
202
     * @Method({"GET", "POST"})
203
     *
204
     * @throws \Doctrine\ORM\Query\QueryException
205
     *
206
     * @return Response
207
     */
208
    public function showStatisticAction()
209
    {
210
//        // беру список активних івентів через івент сервіс чи репозиторій (на морді виводиться, значить має бути готовий)
211
//        $events = $this->getDoctrine()
212
//            ->getRepository('StfalconEventBundle:Event')
213
//            ->findBy(['active' => true], ['date' => 'ASC']);
214
215
//        $dataForDailyStatistics = $this->ticketRepository
216
//            ->getDataForDailyStatisticsOfTicketsSold($dateFrom, $dateTo, $event);
217
//        array_unshift($dataForDailyStatistics, ['Date', 'Number of tickets sold']);
218
219
        $repo = $this->getDoctrine()
220
            ->getManager()
221
            ->getRepository('ApplicationUserBundle:User');
222
223
        $totalUsersCount = $repo->getCountBaseQueryBuilder()->getQuery()->getSingleScalarResult();
224
225
        $qb = $repo->getCountBaseQueryBuilder();
226
        $qb->where('u.enabled = :enabled')
227
        ->setParameter('enabled', 1);
228
        $enabledUsersCount = $qb->getQuery()->getSingleScalarResult();
229
230
        $qb = $repo->getCountBaseQueryBuilder();
231
        $qb->where('u.subscribe = :subscribed')
232
            ->setParameter('subscribed', 1);
233
        $subscribedUsersCount = $qb->getQuery()->getSingleScalarResult();
234
235
        $qb = $repo->getCountBaseQueryBuilder();
236
        $qb->where('u.subscribe = :subscribed')
237
            ->setParameter('subscribed', 0);
238
        $unSubscribedUsersCount = $qb->getQuery()->getSingleScalarResult();
239
240
        //Кол-во людей которые не купили билеты никогда
241
        //Кол-во людей которые купили билеты на одну \ две \ три \ четыре\ пять \ и так далее любых конференций
242
243
        $usersTicketsCount = [];
244
245
        $ticketRepository = $this->getDoctrine()
246
            ->getRepository('StfalconEventBundle:Ticket');
247
248
        $paidTickets = $ticketRepository->getPaidTicketsCount();
249
250
        foreach ($paidTickets as $paidTicket) {
251
            if (isset($usersTicketsCount[$paidTicket[1]])) {
252
                ++$usersTicketsCount[$paidTicket[1]];
253
            } else {
254
                $usersTicketsCount[$paidTicket[1]] = 1;
255
            }
256
        }
257
258
        $haveTickets = 0;
259
        foreach ($usersTicketsCount as $item) {
260
            $haveTickets += $item;
261
        }
262
        $usersTicketsCount[0] = $totalUsersCount - $haveTickets;
263
        ksort($usersTicketsCount);
264
265
        $ticketsByEventGroup = $ticketRepository->getTicketsCountByEventGroup();
266
267
        $countsByGroup = [];
268
269
        foreach ($ticketsByEventGroup as $key => $item) {
270
            if (isset($countsByGroup[$item['name']][$item[1]])) {
271
                ++$countsByGroup[$item['name']][$item[1]];
272
            } else {
273
                $countsByGroup[$item['name']][$item[1]] = 1;
274
            }
275
        }
276
        foreach ($countsByGroup as $key => $item) {
277
            ksort($item);
278
            $countsByGroup[$key] = $item;
279
        }
280
        //сколько людей отказалось предоставлять свои данные партнерам
281
        $qb = $repo->getCountBaseQueryBuilder();
282
        $qb->where('u.allowShareContacts = :allowShareContacts');
283
        $qb->setParameter('allowShareContacts', 0);
284
        $countRefusedProvideData = $qb->getQuery()->getSingleScalarResult();
285
286
        //сколько согласилось
287
        $qb = $repo->getCountBaseQueryBuilder();
288
        $qb->where('u.allowShareContacts = :allowShareContacts');
289
        $qb->setParameter('allowShareContacts', 1);
290
        $countAgreedProvideData = $qb->getQuery()->getSingleScalarResult();
291
292
        //сколько еще не ответило
293
        $qb = $repo->getCountBaseQueryBuilder();
294
        $qb->where($qb->expr()->isNull('u.allowShareContacts'));
295
        $countNotAnswered = $qb->getQuery()->getSingleScalarResult();
296
297
        //сколько было переходов
298
        $qb = $repo->getCountBaseQueryBuilder();
299
        $qb->where($qb->expr()->isNotNull('u.userReferral'));
300
        $countUseReferralProgram = $qb->getQuery()->getSingleScalarResult();
301
302
        $event = $this
303
            ->getDoctrine()
304
            ->getRepository('StfalconEventBundle:Event')
305
            ->findOneBy([], ['date' => 'DESC']);
0 ignored issues
show
Unused Code introduced by
The call to Doctrine\Common\Persiste...Repository::findOneBy() has too many arguments starting with array('date' => 'DESC'). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

305
            ->/** @scrutinizer ignore-call */ findOneBy([], ['date' => 'DESC']);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
306
307
        $eventStatisticSlug = '';
308
        if ($event instanceof Event) {
309
            $eventStatisticSlug = $event->getSlug();
310
        }
311
312
        return $this->render('@ApplicationDefault/Statistic/statistic.html.twig', [
313
            'admin_pool' => $this->get('sonata.admin.pool'),
314
            'data' => [
315
                'countRefusedProvideData' => $countRefusedProvideData,
316
                'countAgreedProvideData' => $countAgreedProvideData,
317
                'countNotAnswered' => $countNotAnswered,
318
                'countUseReferralProgram' => $countUseReferralProgram,
319
                'totalUsersCount' => $totalUsersCount,
320
                'enabledUsersCount' => $enabledUsersCount,
321
                'subscribedUsersCount' => $subscribedUsersCount,
322
                'unSubscribedUsersCount' => $unSubscribedUsersCount,
323
                'haveTicketsCount' => $haveTickets,
324
                'usersTicketsCount' => $usersTicketsCount,
325
                'countsByGroup' => $countsByGroup,
326
                'event_statistic_slug' => $eventStatisticSlug,
327
            ],
328
        ]);
329
    }
330
331
    /**
332
     * Start mail action.
333
     *
334
     * @Route("/mail/{id}/start/{value}", name="admin_start_mail")
335
     *
336
     * @param Request $request Request
337
     * @param Mail    $mail    Mail
338
     * @param int     $value   Value
339
     *
340
     * @return JsonResponse
341
     */
342
    public function startMailAction(Request $request, Mail $mail, $value)
343
    {
344
        if (!$request->isXmlHttpRequest()) {
345
            throw $this->createNotFoundException();
346
        }
347
348
        $em = $this->getDoctrine()->getManager();
349
350
        $mail->setStart((bool) $value);
351
        $em->persist($mail);
352
        $em->flush();
353
354
        return new JsonResponse([
355
            'status' => true,
356
            'value' => $value,
357
        ]);
358
    }
359
360
    /**
361
     * @ParamConverter("event", options={"mapping": {"slug": "slug"}})
362
     *
363
     * @param Event $event
364
     *
365
     * @Route("/admin/event_statistic/{slug}", name="admin_event_statistic")
366
     * @Route("/admin/event_statistic", name="admin_event_without_slug_statistic")
367
     *
368
     * @Security("has_role('ROLE_ADMIN')")
369
     *
370
     * @return Response
371
     */
372
    public function showEventStatisticAction(Event $event)
373
    {
374
        $events = $this
375
            ->getDoctrine()
376
            ->getRepository('StfalconEventBundle:Event')
377
            ->findBy([], ['date' => 'DESC']);
378
379
        $eventStatisticHtml = $this->getEventStatistic($event);
380
381
        return $this->render('@ApplicationDefault/Statistic/event_statistic_page.html.twig', [
382
            'admin_pool' => $this->get('sonata.admin.pool'),
383
            'events' => $events,
384
            'event' => $event,
385
            'event_statistic_html' => $eventStatisticHtml,
386
            'current_event_slug' => $event->getSlug(),
387
        ]);
388
    }
389
390
    /**
391
     * @Route("/admin/events_statistic/{checkedEvents}", name="admin_events_statistic")
392
     * @Route("/admin/events_statistic", name="admin_events_statistic_all")
393
     *
394
     * @param string $checkedEvents
395
     *
396
     * @Security("has_role('ROLE_ADMIN')")
397
     *
398
     * @return Response
399
     */
400
    public function showEventsStatisticAction($checkedEvents = '')
401
    {
402
        $ticketRepository = $this->getDoctrine()->getRepository('StfalconEventBundle:Ticket');
403
404
        $events = $ticketRepository->getEventWithTicketsCount();
405
        if (empty($checkedEvents)) {
406
            $checkedEventsArr = null;
407
        } else {
408
            $checkedEventsArr = explode(';', $checkedEvents);
409
            array_pop($checkedEventsArr);
410
            $checkedEventsArr = array_flip($checkedEventsArr);
411
        }
412
        foreach ($events as $key => $event) {
413
            if (empty($checkedEventsArr)) {
414
                $events[$key]['checked'] = (int) $event['cnt'] > 90;
415
            } else {
416
                $events[$key]['checked'] = isset($checkedEventsArr[$event['id']]);
417
            }
418
            $events[$key]['slug'] = $event['slug'].' ('.$event['cnt'].')';
419
        }
420
421
        $tableHtml = $this->getEventsTable($events);
422
423
        return $this->render('@ApplicationDefault/Statistic/events_statistic_page.html.twig', [
424
            'admin_pool' => $this->get('sonata.admin.pool'),
425
            'events' => $events,
426
            'table_html' => $tableHtml,
427
        ]);
428
    }
429
430
    /**
431
     * @Route("/admin/users_not_buy_tickets", name="admin_user_tickets")
432
     *
433
     * @param Request $request
434
     *
435
     * @Security("has_role('ROLE_ADMIN')")
436
     *
437
     * @return Response|StreamedResponse
438
     */
439
    public function usersNotBuyTicketAction(Request $request)
440
    {
441
        $checkEventId = $request->request->getInt('check_event');
442
        $checkType = $request->request->get('check_type', 'event');
443
        $hasTicketObjectId = 'event' === $checkType ? $request->request->getInt('has_ticket_event')
444
            : $request->request->getInt('has_ticket_group');
445
446
        $events = $this->getDoctrine()->getRepository('StfalconEventBundle:Event')
447
            ->findBy([], ['date' => 'DESC']);
448
        $groups = $this->getDoctrine()->getRepository('StfalconEventBundle:EventGroup')
449
            ->findAll();
450
451
        if ($checkEventId > 0 && $hasTicketObjectId > 0) {
452
            $users = $this->getDoctrine()->getRepository('ApplicationUserBundle:User')
453
                ->getUsersNotBuyTicket($checkEventId, $hasTicketObjectId, $checkType);
454
            if (\count($users)) {
455
                return $this->getCsvResponse($users);
456
            }
457
        }
458
459
        return $this->render('@ApplicationDefault/Statistic/user_ticket_statistic.html.twig', [
460
            'admin_pool' => $this->get('sonata.admin.pool'),
461
            'events' => $events,
462
            'groups' => $groups,
463
        ]);
464
    }
465
466
    /**
467
     * @param Event $event
468
     *
469
     * @return string
470
     */
471
    private function getEventStatistic(Event $event)
472
    {
473
        $wannaVisitEvent = $event->getWantsToVisitCount();
474
        $ticketBlocks = $event->getTicketsCost();
475
        $totalTicketCount = 0;
476
        $totalSoldTicketCount = 0;
477
        /** @var TicketCost $ticketBlock */
478
        foreach ($ticketBlocks as $ticketBlock) {
479
            $blockSold = $ticketBlock->recalculateSoldCount();
480
            $totalTicketCount += $ticketBlock->getCount();
481
            $totalSoldTicketCount += $blockSold;
482
        }
483
484
        $ticketsWithoutCostsCount = (int) $this->getDoctrine()->getRepository('StfalconEventBundle:Ticket')->getEventTicketsWithoutTicketCostCount($event);
485
        $totalSoldTicketCount += $ticketsWithoutCostsCount;
486
        $totalTicketCount += $ticketsWithoutCostsCount;
487
488
        $html = $this->renderView('@ApplicationDefault/Statistic/event_statistic.html.twig', [
489
            'wannaVisitEvent' => $wannaVisitEvent,
490
            'ticketBlocks' => $ticketBlocks,
491
            'totalTicketCount' => $totalTicketCount,
492
            'totalSoldTicketCount' => $totalSoldTicketCount,
493
            'totalTicketsWithoutCostsCount' => $ticketsWithoutCostsCount,
494
        ]);
495
496
        return $html;
497
    }
498
499
    /**
500
     * @param array $events
501
     *
502
     * @return string
503
     */
504
    private function getEventsTable($events)
505
    {
506
        $ticketRepository = $this->getDoctrine()->getRepository('StfalconEventBundle:Ticket');
507
508
        $minGreen = 127;
509
        $maxGreen = 255;
510
        $deltaGreen = $maxGreen - $minGreen;
511
512
        foreach ($events as $key => $event) {
513
            if (!$event['checked']) {
514
                continue;
515
            }
516
            foreach ($events as $subEvent) {
517
                if (!$subEvent['checked']) {
518
                    continue;
519
                }
520
                if ($event !== $subEvent) {
521
                    $result['cnt'] = $ticketRepository->getUserVisitsEventCount($event['id'], $subEvent['id']);
522
                    if ($subEvent['cnt'] > 0) {
523
                        $result['percent'] = round($result['cnt'] * 100 / $subEvent['cnt'], 2);
524
                    } else {
525
                        $result['percent'] = 0;
526
                    }
527
                    $result['text'] = $result['cnt'].'&nbsp;('.$result['percent'].'&nbsp;%)';
528
529
                    $green = $maxGreen - round($deltaGreen * $result['percent'] / 100);
530
                    $otherColor = (int) round($green / ($maxGreen / $green));
531
                    $otherColor = dechex($otherColor);
532
                    $result['color'] = '#'.$otherColor.dechex((int) $green).$otherColor;
533
                } else {
534
                    $result = [
535
                        'cnt' => 0,
536
                        'percent' => 0,
537
                        'text' => '',
538
                        'color' => '#FFFFFF',
539
                    ];
540
                }
541
                $events[$key]['events'][$subEvent['slug']] = $result;
542
            }
543
        }
544
545
        $html = $this->renderView('@ApplicationDefault/Statistic/events_statistic_table.html.twig', [
546
            'events' => $events,
547
        ]);
548
549
        return $html;
550
    }
551
552
    /**
553
     * @param array  $users
554
     * @param string $filename
555
     *
556
     * @return Response
557
     */
558
    private function getCsvResponse($users, $filename = 'users.csv')
559
    {
560
        \array_unshift($users, ['Fullname', 'email']);
561
562
        $headers = [
563
            'Content-Disposition' => sprintf('attachment; filename="%s"', $filename),
564
            'Content-Type' => 'text/csv',
565
        ];
566
        $callback = function() use ($users) {
567
            $usersFile = \fopen('php://output', 'w');
568
            foreach ($users as $fields) {
569
                \fputcsv($usersFile, $fields);
0 ignored issues
show
Bug introduced by
It seems like $usersFile can also be of type false; however, parameter $handle of fputcsv() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

569
                \fputcsv(/** @scrutinizer ignore-type */ $usersFile, $fields);
Loading history...
570
            }
571
572
            return $usersFile;
573
        };
574
575
        $response = new StreamedResponse($callback, 200, $headers);
576
577
        return $response;
578
    }
579
}
580