getWeeklyTrends()   B
last analyzed

Complexity

Conditions 6
Paths 13

Size

Total Lines 64
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 42
dl 0
loc 64
rs 8.6257
c 1
b 0
f 0
cc 6
nc 13
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace ProjetNormandie\UserBundle\Admin\Extension;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use ProjetNormandie\UserBundle\Entity\SecurityEvent;
7
use ProjetNormandie\UserBundle\Security\Event\SecurityEventTypeEnum;
8
use Sonata\AdminBundle\Admin\AbstractAdminExtension;
9
use Sonata\AdminBundle\Admin\AdminInterface;
10
use Sonata\AdminBundle\Datagrid\ListMapper;
11
use Sonata\AdminBundle\Route\RouteCollectionInterface;
12
13
class SecurityEventStatisticsExtension extends AbstractAdminExtension
14
{
15
    public function __construct(
16
        private readonly EntityManagerInterface $entityManager
17
    ) {
18
    }
19
20
    public function configureRoutes(AdminInterface $admin, RouteCollectionInterface $collection): void
21
    {
22
        $collection->add('statistics', 'statistics');
23
    }
24
25
    public function configureActionButtons(AdminInterface $admin, $list, $action, $object = null): array
26
    {
27
        $list['statistics'] = [
28
            'template' => '@SonataAdmin/CRUD/list__action_statistics.html.twig'
29
        ];
30
        
31
        return $list;
32
    }
33
34
    public function getSecurityStatistics(int $weeks = 4): array
35
    {
36
        $startDate = new \DateTime(sprintf('-%d weeks', $weeks));
37
38
        $eventTypes = [
39
            SecurityEventTypeEnum::PASSWORD_CHANGE->value,
40
            SecurityEventTypeEnum::PASSWORD_RESET_REQUEST->value,
41
            SecurityEventTypeEnum::PASSWORD_RESET_COMPLETE->value,
42
            SecurityEventTypeEnum::EMAIL_CHANGE->value,
43
            SecurityEventTypeEnum::REGISTRATION->value,
44
        ];
45
46
        $qb = $this->entityManager->createQueryBuilder();
47
        $qb->select('se.eventType, COUNT(se.id) as count')
48
           ->from(SecurityEvent::class, 'se')
49
           ->where('se.createdAt >= :startDate')
50
           ->andWhere('se.eventType IN (:eventTypes)')
51
           ->setParameter('startDate', $startDate)
52
           ->setParameter('eventTypes', $eventTypes)
53
           ->groupBy('se.eventType')
54
           ->orderBy('count', 'DESC');
55
56
        $results = $qb->getQuery()->getResult();
57
58
        $statistics = [];
59
        foreach ($results as $result) {
60
            $eventType = SecurityEventTypeEnum::from($result['eventType']);
61
            $statistics[] = [
62
                'type' => $eventType,
63
                'count' => $result['count'],
64
                'label' => $eventType->getLabel(),
65
                'icon' => $eventType->getIcon(),
66
                'severity' => $eventType->getSeverity()
67
            ];
68
        }
69
70
        // Ajouter les types sans événements
71
        foreach ($eventTypes as $type) {
72
            $found = false;
73
            foreach ($statistics as $stat) {
74
                if ($stat['type']->value === $type) {
75
                    $found = true;
76
                    break;
77
                }
78
            }
79
            if (!$found) {
80
                $eventType = SecurityEventTypeEnum::from($type);
81
                $statistics[] = [
82
                    'type' => $eventType,
83
                    'count' => 0,
84
                    'label' => $eventType->getLabel(),
85
                    'icon' => $eventType->getIcon(),
86
                    'severity' => $eventType->getSeverity()
87
                ];
88
            }
89
        }
90
91
        return $statistics;
92
    }
93
94
    public function getWeeklyTrends(int $weeks = 4): array
95
    {
96
        $trends = [];
97
        $eventTypes = [
98
            SecurityEventTypeEnum::PASSWORD_CHANGE->value,
99
            SecurityEventTypeEnum::PASSWORD_RESET_REQUEST->value,
100
            SecurityEventTypeEnum::PASSWORD_RESET_COMPLETE->value,
101
            SecurityEventTypeEnum::EMAIL_CHANGE->value,
102
            SecurityEventTypeEnum::REGISTRATION->value,
103
        ];
104
105
        // Semaine en cours + 4 dernières semaines complètes = 5 semaines au total
106
        for ($i = $weeks; $i >= 0; $i--) {
107
            // Calculer le début de la semaine (lundi)
108
            $weekStart = new \DateTime();
109
            $weekStart->modify(sprintf('-%d weeks', $i));
110
            $weekStart->modify('monday this week');
111
            $weekStart->setTime(0, 0, 0);
112
            
113
            // Calculer la fin de la semaine (dimanche)
114
            $weekEnd = clone $weekStart;
115
            $weekEnd->modify('+6 days');
116
            $weekEnd->setTime(23, 59, 59);
117
            
118
            // Pour la semaine en cours (i = 0), ne pas dépasser aujourd'hui
119
            if ($i === 0) {
120
                $now = new \DateTime();
121
                if ($weekEnd > $now) {
122
                    $weekEnd = $now;
123
                }
124
            }
125
126
            $qb = $this->entityManager->createQueryBuilder();
127
            $qb->select('se.eventType, COUNT(se.id) as count')
128
               ->from(SecurityEvent::class, 'se')
129
               ->where('se.createdAt >= :weekStart')
130
               ->andWhere('se.createdAt < :weekEnd')
131
               ->andWhere('se.eventType IN (:eventTypes)')
132
               ->setParameter('weekStart', $weekStart)
133
               ->setParameter('weekEnd', $weekEnd)
134
               ->setParameter('eventTypes', $eventTypes)
135
               ->groupBy('se.eventType');
136
137
            $weekResults = $qb->getQuery()->getResult();
138
139
            $weekData = [];
140
            foreach ($eventTypes as $type) {
141
                $weekData[$type] = 0;
142
            }
143
144
            foreach ($weekResults as $result) {
145
                $weekData[$result['eventType']] = $result['count'];
146
            }
147
148
            $trends[] = [
149
                'week' => $weekStart->format('W'),
150
                'year' => $weekStart->format('Y'),
151
                'start_date' => $weekStart,
152
                'end_date' => $weekEnd,
153
                'data' => $weekData
154
            ];
155
        }
156
157
        return $trends;
158
    }
159
}
160