Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
23.03% covered (danger)
23.03%
41 / 178
22.22% covered (danger)
22.22%
6 / 27
CRAP
0.00% covered (danger)
0.00%
0 / 1
TwigExtension
23.03% covered (danger)
23.03%
41 / 178
22.22% covered (danger)
22.22%
6 / 27
1931.50
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFunctions
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
2
 dump
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 currentRoute
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
30
 getD115Enabeld
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getD115OpeningTimes
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getD115Text
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getBobbiChatButtonEnabeld
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getOSMAccessToken
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getOSMOptions
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 formatPhoneNumber
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 convertOpeningTimes
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
 dateToTS
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 tsToDate
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 formatDateTime
94.44% covered (success)
94.44%
17 / 18
0.00% covered (danger)
0.00%
0 / 1
4.00
 kindOfPayment
50.00% covered (danger)
50.00%
6 / 12
0.00% covered (danger)
0.00%
0 / 1
10.50
 azPrefixList
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
30
 sortFirstChar
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 sortByName
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 toSortableString
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
2
 csvProperty
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
20
 csvAppointmentLocations
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
56
 getAppointmentForLocationFromServiceAppointmentLocations
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 getAppointmentForService
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
30
 getLocationHintByServiceId
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
20
 dayIsBookable
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3/**
4 * @copyright BerlinOnline Stadtportal GmbH & Co. KG
5 **/
6
7namespace BO\Zmsdldb;
8
9/**
10 * Extension for Twig
11 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
12 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
13 * @SuppressWarnings(PHPMD.TooManyMethods)
14 */
15class TwigExtension extends \Twig\Extension\AbstractExtension
16{
17    private $container;
18
19    public function __construct(mixed $container = null)
20    {
21        $this->container = $container;
22    }
23
24    public function getName(): string
25    {
26        return 'dldb';
27    }
28
29    /** @psalm-suppress InvalidArgument */
30    #[\Override]
31    public function getFunctions()
32    {
33        return array(
34            new \Twig\TwigFunction('convertOpeningTimes', array($this, 'convertOpeningTimes')),
35            new \Twig\TwigFunction('csvProperty', array($this, 'csvProperty')),
36            new \Twig\TwigFunction('csvAppointmentLocations', array($this, 'csvAppointmentLocations')),
37            new \Twig\TwigFunction('getAppointmentForService', array($this, 'getAppointmentForService')),
38            new \Twig\TwigFunction('getLocationHintByServiceId', array($this, 'getLocationHintByServiceId')),
39            new \Twig\TwigFunction('isAppointmentBookable', array($this, 'isAppointmentBookable')),
40            new \Twig\TwigFunction('kindOfPayment', array($this, 'kindOfPayment')),
41            new \Twig\TwigFunction('formatDateTime', array($this, 'formatDateTime')),
42            new \Twig\TwigFunction('dateToTS', array($this, 'dateToTS')),
43            new \Twig\TwigFunction('tsToDate', array($this, 'tsToDate')),
44            new \Twig\TwigFunction('dayIsBookable', array($this, 'dayIsBookable')),
45            new \Twig\TwigFunction('azPrefixList', array($this, 'azPrefixList')),
46            new \Twig\TwigFunction('formatPhoneNumber', array($this, 'formatPhoneNumber')),
47            new \Twig\TwigFunction('getOSMOptions', array($this, 'getOSMOptions')),
48            new \Twig\TwigFunction('getOSMAccessToken', array($this, 'getOSMAccessToken')),
49            new \Twig\TwigFunction('getD115Enabeld', array($this, 'getD115Enabeld')),
50            new \Twig\TwigFunction('getD115OpeningTimes', array($this, 'getD115OpeningTimes')),
51            new \Twig\TwigFunction('getD115Text', array($this, 'getD115Text')),
52            new \Twig\TwigFunction('getBobbiChatButtonEnabeld', array($this, 'getBobbiChatButtonEnabeld')),
53            new \Twig\TwigFunction('currentRoute', array($this, 'currentRoute')),
54            new \Twig\TwigFunction('dump', array($this, 'dump')),
55            new \Twig\TwigFunction(
56                'getAppointmentForLocationFromServiceAppointmentLocations',
57                array($this, 'getAppointmentForLocationFromServiceAppointmentLocations')
58            ),
59        );
60    }
61
62    public function dump(mixed $item): string
63    {
64        return '<pre>' . print_r($item, true) . '</pre>';
65    }
66
67    /**
68     * @return (array|mixed|string)[]
69     *
70     */
71    public function currentRoute(mixed $lang = null): array
72    {
73        if ($this->container->has('currentRoute')) {
74            $routeParams = $this->container->get('currentRouteParams');
75
76            if (null !== $lang && 'de' == $lang) {
77                unset($routeParams['lang']);
78            } else {
79                $routeParams['lang'] = ($lang !== null) ? $lang : \App::$language->getCurrentLanguage();
80            }
81
82
83            $routeName = $this->container->get('currentRoute');
84            $route = array(
85                'name' => $routeName,
86                'params' => $routeParams
87            );
88        } else {
89            $route = array(
90                'name' => 'noroute',
91                'params' => []
92            );
93        }
94        return $route;
95    }
96
97
98    public function getD115Enabeld(): bool
99    {
100        /** @psalm-suppress UndefinedPropertyFetch */
101        $settingsRepository = \App::$repository->fromSetting();
102        $active = (bool)($settingsRepository->fetchName('d115.active') ?? true);
103
104
105        return $active;
106    }
107
108    public function getD115OpeningTimes(): mixed
109    {
110        /** @psalm-suppress UndefinedPropertyFetch */
111        $settingsRepository = \App::$repository->fromSetting();
112        $openinTimes = $settingsRepository->fetchName('d115.openingTime') ?? \App::D115_DEFAULT_OPENINGTIME;
113
114        return $openinTimes;
115    }
116
117    public function getD115Text(): mixed
118    {
119        /** @psalm-suppress UndefinedPropertyFetch */
120        $settingsRepository = \App::$repository->fromSetting();
121        $text = $settingsRepository->fetchName('d115.messageHtml') ?? \App::D115_DEFAULT_TEXT;
122
123        return $text;
124    }
125
126    public function getBobbiChatButtonEnabeld(): bool
127    {
128        /** @psalm-suppress UndefinedPropertyFetch */
129        $settingsRepository = \App::$repository->fromSetting();
130        $buttonEnabled = (bool)($settingsRepository->fetchName('frontend.bobbi.chatbutton.enabled') ?? false);
131
132        return $buttonEnabled;
133    }
134
135    public function getOSMAccessToken(): string
136    {
137        return \App::OSM_ACCESS_TOKEN;
138    }
139
140    public function getOSMOptions(): string
141    {
142        return 'gestureHandling: ' . \App::OSM_GESTURE_HANDLING;
143    }
144
145    public function formatPhoneNumber(mixed $phoneNumber): string|null
146    {
147        preg_match_all('/(^\+)?[\d]+/', $phoneNumber, $matches);
148        $number = implode($matches[0]);
149        $phonenumber = preg_replace('/^030/', '+4930', $number);
150        return $phonenumber;
151    }
152
153    public function convertOpeningTimes(mixed $name): string
154    {
155        $days = array(
156            'monday' => 'Montag',
157            'tuesday' => 'Dienstag',
158            'wednesday' => 'Mittwoch',
159            'thursday' => 'Donnerstag',
160            'friday' => 'Freitag',
161            'saturday' => 'Samstag',
162            'sunday' => 'Sonntag',
163            'special' => ''
164        );
165        return $days[$name];
166    }
167
168    /**
169     * @return false|int
170     */
171    public function dateToTS(mixed $datetime): int|false
172    {
173        $timestamp = ($datetime === (int)$datetime) ? $datetime : strtotime($datetime);
174        return $timestamp;
175    }
176
177    public function tsToDate(mixed $timestamp): string
178    {
179        $date =  date('Y-m-d', $timestamp);
180        return $date;
181    }
182
183    /**
184     * @return (false|float|int|mixed|string)[]
185     *
186     */
187    public function formatDateTime(mixed $dateString): array
188    {
189        $dateTime = new \DateTimeImmutable($dateString, new \DateTimeZone('Europe/Berlin'));
190        $formatDate = [];
191        $formatDate['date']     = Helper\DateTime::getFormatedDates($dateTime, "EE, dd. MMMM yyyy");
192        $formatDate['fulldate'] = Helper\DateTime::getFormatedDates($dateTime, "EEEE, 'den' dd. MMMM yyyy");
193        $weekdayNumber = (int) $dateTime->format('N');
194        $formatDate['weekday']  = ($weekdayNumber == 0) ?
195            $weekdayNumber + 6 :
196            $weekdayNumber - 1;
197        $formatDate['weekdayfull'] = Helper\DateTime::getFormatedDates($dateTime, "EEEE");
198
199        $time = $dateTime->format('H:i');
200        $formatDate['time']     = ($time != '00:00') ?
201            Helper\DateTime::getFormatedDates($dateTime, "HH:mm 'Uhr'") :
202            false;
203        $formatDate['timeId']   = ($time != '00:00') ? $time : false;
204        $formatDate['ts']       = $dateTime->getTimestamp();
205        $formatDate['dateId']   = $dateTime->format('Y-m-d');
206        $formatDate['ym']      = $dateTime->format('Y-m');
207
208        return $formatDate;
209    }
210
211    public function kindOfPayment(mixed $code): string
212    {
213        $result = '';
214        if ($code == 0) {
215            $result = 'eccash';
216        } elseif ($code == 1) {
217            $result = 'nocash';
218        } elseif ($code == 2) {
219            $result = 'ec';
220        } elseif ($code == 3) {
221            $result = 'cash';
222        } elseif ($code == 4) {
223            $result = 'subscribecash';
224        }
225        return $result;
226    }
227
228    /**
229     * @return (array|mixed)[][]
230     *
231     */
232    public function azPrefixList(mixed $list, mixed $property): array
233    {
234        $azList = array();
235        foreach ((array)$list as $item) {
236            if (!is_scalar($item) && Entity\Base::hasValidOffset($item, $property)) {
237                $currentPrefix = self::sortFirstChar($item[$property]);
238                if (!array_key_exists($currentPrefix, $azList)) {
239                    $azList[$currentPrefix] = array(
240                        'prefix' => $currentPrefix,
241                        'sublist' => array(),
242                    );
243                }
244                $azList[$currentPrefix]['sublist'][] = $item;
245                uasort($azList[$currentPrefix]['sublist'], array($this,'sortByName'));
246                ksort($azList);
247            }
248        }
249        return $azList;
250    }
251
252    protected static function sortFirstChar(mixed $string): string
253    {
254        $firstChar = mb_substr($string, 0, 1);
255        $firstChar = mb_strtoupper($firstChar);
256        $firstChar = strtr($firstChar, array('Ä' => 'A', 'Ö' => 'O', 'Ü' => 'U'));
257        return $firstChar;
258    }
259
260    protected static function sortByName(mixed $left, mixed $right): int
261    {
262        return strcmp(
263            self::toSortableString(strtolower($left['name'])),
264            strtolower(self::toSortableString($right['name']))
265        );
266    }
267
268    protected static function toSortableString(string $string): string
269    {
270        $string = strtr($string, array(
271            'Ä' => 'Ae',
272            'Ö' => 'Oe',
273            'Ü' => 'Ue',
274            'ä' => 'ae',
275            'ö' => 'oe',
276            'ü' => 'ue',
277            'ß' => 'ss',
278            '€' => 'E',
279        ));
280        return $string;
281    }
282
283    public function csvProperty(mixed $list, mixed $property): string
284    {
285        $propertylist = array();
286        foreach ($list as $item) {
287            if (!is_scalar($item) && Entity\Base::hasValidOffset($item, $property)) {
288                $propertylist[] = $item[$property];
289            }
290        }
291        return implode(',', array_unique($propertylist));
292    }
293
294    public function csvAppointmentLocations(mixed $list, string $service_id = ''): string
295    {
296        $propertylist = array();
297        foreach ($list as $item) {
298            if (!is_scalar($item) && Entity\Base::hasValidOffset($item, 'services')) {
299                $appointment = $this->getAppointmentForService($item, $service_id);
300                if ($appointment === false) {
301                    continue;
302                }
303                if (false === $appointment['external'] && true === $appointment['allowed']) {
304                    $propertylist[] = $item['id'];
305                }
306            }
307        }
308        return implode(',', array_unique($propertylist));
309    }
310
311    /**
312     * @SuppressWarnings(PHPMD.LongVariable)
313     */
314    public function getAppointmentForLocationFromServiceAppointmentLocations(
315        array $serviceAppointmentLocationList,
316        mixed $locationId
317    ): mixed {
318        if (isset($serviceAppointmentLocationList[$locationId])) {
319            $appointment = $serviceAppointmentLocationList[$locationId]['appointment'];
320            $appointment['responsibility_hint'] = $serviceAppointmentLocationList[$locationId]['responsibility_hint'];
321            $appointment['responsibility'] = $serviceAppointmentLocationList[$locationId]['responsibility'];
322            return $appointment;
323        }
324        return false;
325    }
326
327    public function getAppointmentForService(mixed $location, mixed $service_id): mixed
328    {
329        $servicecompare = explode(',', $service_id);
330        foreach ($location['services'] as $service) {
331            if (in_array($service['service'], $servicecompare)) {
332                $appointment = $service['appointment'];
333                if ($appointment['allowed'] === true || $appointment['external'] === true) {
334                    return $appointment;
335                }
336            }
337        }
338        return false;
339    }
340
341    public function getLocationHintByServiceId(mixed $location, mixed $service_id): mixed
342    {
343        if (isset($location['services'])) {
344            foreach ($location['services'] as $service) {
345                if ($service['service'] == $service_id) {
346                    return $service['hint'];
347                }
348            }
349        }
350        return false;
351    }
352
353    public function dayIsBookable(mixed $dateList, mixed $day): mixed
354    {
355        $result = false;
356        if (count($dateList)) {
357            foreach ($dateList as $date) {
358                if ($date['datum'] == $day) {
359                    $result = $date;
360                }
361            }
362        }
363        return $result;
364    }
365}