Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
71.23% covered (warning)
71.23%
52 / 73
28.57% covered (danger)
28.57%
2 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
Log
71.23% covered (warning)
71.23%
52 / 73
28.57% covered (danger)
28.57%
2 / 7
23.88
0.00% covered (danger)
0.00%
0 / 1
 writeLogEntry
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
1
 writeProcessLog
93.10% covered (success)
93.10%
27 / 29
0.00% covered (danger)
0.00%
0 / 1
6.01
 readByProcessId
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 readByProcessData
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 delete
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 backtraceLogEntry
87.50% covered (warning)
87.50%
7 / 8
0.00% covered (danger)
0.00%
0 / 1
5.05
 clearLogsOlderThan
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace BO\Zmsdb;
4
5use BO\Zmsentities\Collection\RequestList;
6use BO\Zmsentities\Log as Entity;
7
8/**
9 * Logging for actions
10 *
11 */
12class Log extends Base
13{
14    const PROCESS = 'buerger';
15    const MIGRATION = 'migration';
16    const ERROR = 'error';
17
18    const ACTION_MAIL_SUCCESS = 'E-Mail-Versand erfolgreich';
19    const ACTION_MAIL_FAIL = 'E-Mail-Versand ist fehlgeschlagen';
20    const ACTION_STATUS_CHANGE = 'Terminstatus wurde geändert';
21    const ACTION_SEND_REMINDER = 'Erinnerungsmail wurde gesendet';
22    const ACTION_REMOVED = 'Termin aus der Warteschlange entfernt';
23    const ACTION_CALLED = 'Termin wurde aufgerufen';
24    const ACTION_ARCHIVED = 'Termin wurde archiviert';
25    const ACTION_EDITED = 'Termin wurde geändert';
26    const ACTION_NEW_PICKUP = 'Abholtermin wurde erstellt';
27    const ACTION_REDIRECTED = 'Termin wurde weitergeleitet';
28    const ACTION_NEW = 'Neuer Termin wurde erstellt';
29    const ACTION_DELETED = 'Termin wurde gelöscht';
30    const ACTION_CANCELED = 'Termin wurde abgesagt';
31
32    public static $operator = 'lib';
33
34    public static function writeLogEntry(
35        $message,
36        $referenceId,
37        $type = self::PROCESS,
38        ?int $scopeId = null,
39        ?string $userId = null,
40        ?string $data = null
41    ) {
42        $message .= " [" . static::$operator . "]";
43        $log = new static();
44        $sql = "INSERT INTO `log` SET 
45`message`=:message, 
46`reference_id`=:referenceId, 
47`type`=:type, 
48`scope_id`=:scopeId,
49`user_id`=:userId,
50`data`=:dataString";
51
52        $parameters = [
53            "message" => $message . static::backtraceLogEntry(),
54            "referenceId" => $referenceId,
55            "type" => $type,
56            "scopeId" => $scopeId,
57            "userId" => $userId,
58            "dataString" => $data
59        ];
60
61        return $log->perform($sql, $parameters);
62    }
63
64    public static function writeProcessLog(
65        string $method,
66        string $action,
67        ?\BO\Zmsentities\Process $process,
68        ?\BO\Zmsentities\Useraccount $userAccount = null
69    ) {
70        if (empty($process) || empty($process->getId()) || empty($userAccount)) {
71            return;
72        }
73
74        $requests = new RequestList();
75        if (! empty($process->getRequestIds())) {
76            $requests = (new Request())->readRequestsByIds($process->getRequestIds());
77        }
78
79        $data = json_encode(array_filter([
80            'Aktion' => $action,
81            "Sachbearbeiter*in" => $userAccount ? $userAccount->getId() : '',
82            "Terminnummer" => $process->getDisplayNumber(),
83            "Wartenummer" => $process->getQueueNumber(),
84            "Terminzeit" => $process->getFirstAppointment()->toDateTime()->format('d.m.Y H:i:s'),
85            "Bürger*in" => $process->getFirstClient()->familyName,
86            "Dienstleistung/en" => implode(', ', array_map(function ($request) {
87                return $request->getName();
88            }, $requests->getAsArray())),
89            "Anmerkung" => $process->getAmendment(),
90            "E-Mail" => $process->getFirstClient()->email,
91            "Telefon" => $process->getFirstClient()->telephone,
92            "Status" => $process->getStatus(),
93            "DB Status" => $process->dbstatus,
94        ]), JSON_UNESCAPED_UNICODE);
95
96        Log::writeLogEntry(
97            $method,
98            $process->getId(),
99            self::PROCESS,
100            $process->getScopeId(),
101            $userAccount->getId(),
102            $data
103        );
104    }
105
106    public function readByProcessId($processId)
107    {
108        $query = new Query\Log(Query\Base::SELECT);
109        $query->addEntityMapping();
110        $query->addConditionProcessId($processId);
111        $logList = new \BO\Zmsentities\Collection\LogList($this->fetchList($query, new Entity()));
112        return $logList;
113    }
114
115    public function readByProcessData($search, $page = 1, $perPage = 100)
116    {
117        $query = new Query\Log(Query\Base::SELECT);
118        $query->addEntityMapping();
119        $query->addConditionDataSearch($search);
120        $query->addLimit($perPage, ($page - 1)  * $perPage);
121
122        return new \BO\Zmsentities\Collection\LogList($this->fetchList($query, new Entity()));
123    }
124
125    public function delete($processId)
126    {
127        $query = new Query\Log(Query\Base::SELECT);
128        $query->addEntityMapping();
129        $query->addConditionProcessId($processId);
130        $logList = new \BO\Zmsentities\Collection\LogList($this->fetchList($query, new Entity()));
131        return $logList;
132    }
133
134    protected static function backtraceLogEntry()
135    {
136        $trace = debug_backtrace();
137        $short = '';
138        foreach ($trace as $step) {
139            if (
140                isset($step['file'])
141                && isset($step['line'])
142                && !strpos($step['file'], 'Zmsdb')
143            ) {
144                return ' (' . basename($step['file'], '.php') . ')';
145            }
146        }
147        return $short;
148    }
149
150    public function clearLogsOlderThan(int $olderThan): bool
151    {
152        try {
153            $olderThanDate = (new \DateTime())->modify('-' . $olderThan . ' days');
154
155            $query = new Query\Log(Query\Base::DELETE);
156            $query->addConditionOlderThan($olderThanDate);
157
158            $result = $this->writeItem($query);
159            return $result !== false;
160        } catch (\Exception $e) {
161            error_log("Error during log cleanup: " . $e->getMessage());
162            return false;
163        }
164    }
165}