Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.83% covered (success)
95.83%
138 / 144
20.00% covered (danger)
20.00%
1 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
SendWeeklySummaryCommand
95.83% covered (success)
95.83%
138 / 144
20.00% covered (danger)
20.00%
1 / 5
28
0.00% covered (danger)
0.00%
0 / 1
 getNotificationSubscriptionType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 autogenerateSubscriptions
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getNotification
97.32% covered (success)
97.32%
109 / 112
0.00% covered (danger)
0.00%
0 / 1
22
 getPrettyDateAndMaybeTime
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
3.03
 getNewsCriteria
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace Olz\Command\Notifications;
4
5use Doctrine\Common\Collections\Criteria;
6use Doctrine\Common\Collections\Order;
7use Olz\Entity\News\NewsEntry;
8use Olz\Entity\NotificationSubscription;
9use Olz\Entity\Termine\Termin;
10use Olz\Utils\WithUtilsTrait;
11use Symfony\Component\Console\Attribute\AsCommand;
12
13#[AsCommand(name: 'olz:send-weekly-summary')]
14class SendWeeklySummaryCommand extends BaseSendNotificationsCommand {
15    use WithUtilsTrait;
16
17    public const CUT_OFF_TIME = '03:00:00';
18
19    protected \DateTime $today;
20    protected \DateTime $lastWeek;
21
22    public function getNotificationSubscriptionType(): string {
23        return NotificationSubscription::TYPE_WEEKLY_SUMMARY;
24    }
25
26    public function autogenerateSubscriptions(): void {
27        // Must be generated by user.
28    }
29
30    /** @param array<string, mixed> $args */
31    public function getNotification(array $args): ?Notification {
32        $current_weekday = intval($this->dateUtils()->getCurrentDateInFormat('N'));
33        $monday = 1;
34        if ($current_weekday != $monday) {
35            return null;
36        }
37
38        $this->today = new \DateTime($this->dateUtils()->getIsoToday());
39        $minus_one_week = \DateInterval::createFromDateString("-7 days");
40        $this->lastWeek = (new \DateTime($this->dateUtils()->getIsoToday()))->add($minus_one_week);
41
42        $today_at_cut_off = new \DateTime($this->today->format('Y-m-d').' '.self::CUT_OFF_TIME);
43        $last_week_at_cut_off = new \DateTime($this->lastWeek->format('Y-m-d').' '.self::CUT_OFF_TIME);
44        $termine_criteria = Criteria::create()
45            ->where(Criteria::expr()->andX(
46                Criteria::expr()->lte('last_modified_at', $today_at_cut_off),
47                Criteria::expr()->gt('last_modified_at', $last_week_at_cut_off),
48                Criteria::expr()->eq('newsletter', true),
49                Criteria::expr()->eq('on_off', 1),
50            ))
51            ->orderBy(['start_date' => Order::Ascending, 'start_time' => Order::Ascending])
52            ->setFirstResult(0)
53            ->setMaxResults(1000)
54        ;
55
56        $notification_text = '';
57        $base_href = $this->envUtils()->getBaseHref();
58        $code_href = $this->envUtils()->getCodeHref();
59
60        if ($args['aktuell'] ?? false) {
61            $news_url = "{$base_href}{$code_href}news";
62            $aktuell_text = '';
63            $news_repo = $this->entityManager()->getRepository(NewsEntry::class);
64            $aktuell_criteria = $this->getNewsCriteria(['aktuell']);
65            $aktuells = $news_repo->matching($aktuell_criteria);
66            foreach ($aktuells as $aktuell) {
67                $id = $aktuell->getId();
68                $pretty_datetime = $this->getPrettyDateAndMaybeTime(
69                    $aktuell->getPublishedDate(),
70                    $aktuell->getPublishedTime()
71                );
72                $title = $aktuell->getTitle();
73                $aktuell_text .= "{$pretty_datetime}: [{$title}]({$news_url}/{$id})\n";
74            }
75            if (strlen($aktuell_text) > 0) {
76                $notification_text .= "\n**Aktuell**\n\n{$aktuell_text}\n";
77            }
78        }
79
80        if ($args['blog'] ?? false) {
81            $news_url = "{$base_href}{$code_href}news";
82            $blog_text = '';
83            $news_repo = $this->entityManager()->getRepository(NewsEntry::class);
84            $blog_criteria = $this->getNewsCriteria(['kaderblog']);
85            $blogs = $news_repo->matching($blog_criteria);
86            foreach ($blogs as $blog) {
87                $id = $blog->getId();
88                $pretty_datetime = $this->getPrettyDateAndMaybeTime(
89                    $blog->getPublishedDate(),
90                    $blog->getPublishedTime()
91                );
92                $title = $blog->getTitle();
93                $blog_text .= "{$pretty_datetime}: [{$title}]({$news_url}/{$id})\n";
94            }
95            if (strlen($blog_text) > 0) {
96                $notification_text .= "\n**Kaderblog**\n\n{$blog_text}\n";
97            }
98        }
99
100        if ($args['forum'] ?? false) {
101            $news_url = "{$base_href}{$code_href}news";
102            $forum_text = '';
103            $news_repo = $this->entityManager()->getRepository(NewsEntry::class);
104            $forum_criteria = $this->getNewsCriteria(['forum']);
105            $forums = $news_repo->matching($forum_criteria);
106            foreach ($forums as $forum) {
107                $id = $forum->getId();
108                $pretty_datetime = $this->getPrettyDateAndMaybeTime(
109                    $forum->getPublishedDate(),
110                    $forum->getPublishedTime()
111                );
112                $title = $forum->getTitle();
113                if (strlen(trim($title)) > 0) {
114                    $forum_text .= "{$pretty_datetime}: [{$title}]({$news_url}/{$id})\n";
115                }
116            }
117            if (strlen($forum_text) > 0) {
118                $notification_text .= "\n**Forum**\n\n{$forum_text}\n";
119            }
120        }
121
122        if ($args['galerie'] ?? false) {
123            $news_url = "{$base_href}{$code_href}news";
124            $galerie_text = '';
125            $news_repo = $this->entityManager()->getRepository(NewsEntry::class);
126            $galerie_criteria = $this->getNewsCriteria(['galerie', 'video']);
127            $galeries = $news_repo->matching($galerie_criteria);
128            foreach ($galeries as $galerie) {
129                $id = $galerie->getId();
130                $pretty_datetime = $this->getPrettyDateAndMaybeTime(
131                    $galerie->getPublishedDate(),
132                    $galerie->getPublishedTime()
133                );
134                $title = $galerie->getTitle();
135                $galerie_text .= "{$pretty_datetime}: [{$title}]({$news_url}/{$id})\n";
136            }
137            if (strlen($galerie_text) > 0) {
138                $notification_text .= "\n**Galerien**\n\n{$galerie_text}\n";
139            }
140        }
141
142        if ($args['termine'] ?? false) {
143            $termine_url = "{$base_href}{$code_href}termine";
144            $termine_text = '';
145            $termin_repo = $this->entityManager()->getRepository(Termin::class);
146            $termine = $termin_repo->matching($termine_criteria);
147            foreach ($termine as $termin) {
148                $id = $termin->getId();
149                $starts_on = $termin->getStartDate();
150                $ends_on = $termin->getEndDate();
151                $pretty_date = ($ends_on && $ends_on > $starts_on)
152                    ? $this->dateUtils()->compactDate($starts_on).' - '.$this->dateUtils()->compactDate($ends_on)
153                    : $this->dateUtils()->compactDate($starts_on);
154                $title = $termin->getTitle();
155                if (strlen(trim($title)) > 0) {
156                    $termine_text .= "{$pretty_date}: [{$title}]({$termine_url}/{$id})\n";
157                }
158            }
159            if (strlen($termine_text) > 0) {
160                $notification_text .= "\n**Aktualisierte Termine**\n\n{$termine_text}\n";
161            }
162        }
163
164        if (strlen($notification_text) == 0) {
165            return null;
166        }
167
168        $title = "Wochenzusammenfassung";
169        $text = "Hallo %%userFirstName%%,\n\nDas lief diese Woche auf [olzimmerberg.ch](https://olzimmerberg.ch):\n\n{$notification_text}";
170
171        return new Notification($title, $text, [
172            'notification_type' => NotificationSubscription::TYPE_WEEKLY_SUMMARY,
173        ]);
174    }
175
176    protected function getPrettyDateAndMaybeTime(?\DateTime $date, ?\DateTime $time = null): string {
177        if (!$date) {
178            return "??";
179        }
180        $pretty_date = $this->dateUtils()->compactDate($date);
181        if (!$time) {
182            return $pretty_date;
183        }
184        $pretty_time = $time->format('H:i');
185        return "{$pretty_date} {$pretty_time}";
186    }
187
188    /** @param array<string> $formats */
189    protected function getNewsCriteria(array $formats): Criteria {
190        return Criteria::create()
191            ->where(Criteria::expr()->andX(
192                Criteria::expr()->in('format', $formats),
193                Criteria::expr()->orX(
194                    Criteria::expr()->andX(
195                        Criteria::expr()->eq('published_date', $this->today),
196                        Criteria::expr()->lte('published_time', new \DateTime(self::CUT_OFF_TIME)),
197                    ),
198                    Criteria::expr()->andX(
199                        Criteria::expr()->lt('published_date', $this->today),
200                        Criteria::expr()->gt('published_date', $this->lastWeek),
201                    ),
202                    Criteria::expr()->andX(
203                        Criteria::expr()->eq('published_date', $this->lastWeek),
204                        Criteria::expr()->gt('published_time', new \DateTime(self::CUT_OFF_TIME)),
205                    ),
206                ),
207                Criteria::expr()->eq('on_off', 1),
208            ))
209            ->orderBy(['published_date' => Order::Ascending, 'published_time' => Order::Ascending])
210            ->setFirstResult(0)
211            ->setMaxResults(1000)
212        ;
213    }
214}