Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
52.22% covered (warning)
52.22%
47 / 90
46.15% covered (danger)
46.15%
6 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
BaseController
52.22% covered (warning)
52.22%
47 / 90
46.15% covered (danger)
46.15%
6 / 13
195.49
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getLogList
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 clearLogList
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSpendTime
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getNow
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
2.06
 getHttp
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
2.06
 sendMailer
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
6
 removeEntityOlderThanOneHour
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 deleteEntityFromQueue
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 testEntity
36.36% covered (danger)
36.36%
8 / 22
0.00% covered (danger)
0.00%
0 / 1
19.63
 monitorProcesses
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
90
 log
90.91% covered (success)
90.91%
10 / 11
0.00% covered (danger)
0.00%
0 / 1
2.00
 convertCollectionToArray
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3/**
4 *
5 * @package Zmsmessaging
6 *
7 */
8
9namespace BO\Zmsmessaging;
10
11use BO\Zmsentities\Mail;
12use BO\Zmsentities\Mimepart;
13use BO\Zmsentities\Schema\Entity;
14use BO\Mellon\Validator;
15use BO\Zmsclient\Http;
16
17class BaseController
18{
19    protected mixed $verbose = false;
20    protected static array $logList = [];
21    protected mixed $workstation = null;
22    protected float $startTime;
23    protected mixed $maxRunTime = 50;
24
25    public function __construct(mixed $verbose = false, mixed $maxRunTime = 50)
26    {
27        $this->verbose = $verbose;
28        $this->startTime = microtime(true);
29        $this->maxRunTime = $maxRunTime;
30    }
31
32    public static function getLogList(): array
33    {
34        return static::$logList;
35    }
36
37    public static function clearLogList(): void
38    {
39        static::$logList = [];
40    }
41
42    protected function getSpendTime(): float
43    {
44        $time = round(microtime(true) - $this->startTime, 3);
45        return $time;
46    }
47
48    protected function getNow(): \DateTimeInterface
49    {
50        $now = \App::$now;
51        if ($now instanceof \DateTimeInterface) {
52            return $now;
53        }
54        throw new \RuntimeException('Current time is not initialized');
55    }
56
57    protected function getHttp(): Http
58    {
59        $http = \App::$http;
60        if ($http instanceof Http) {
61            return $http;
62        }
63        throw new \RuntimeException('HTTP client is not initialized');
64    }
65
66    protected function sendMailer(Entity $entity, mixed $mailer = null, mixed $action = false): mixed
67    {
68        // @codeCoverageIgnoreStart
69        $hasSendSuccess = ($action) ? $mailer->Send() : $action;
70        if (false !== $action && null !== $mailer && ! $hasSendSuccess) {
71            $this->log("Exception: SendingFailed  - " . $this->getNow()->format('c'));
72            throw new Exception\SendingFailed();
73        }
74        // @codeCoverageIgnoreEnd
75        $log = new Mimepart(['mime' => 'text/plain']);
76        $log['content'] = ($entity instanceof Mail) ? $entity['subject'] : $entity['message'];
77        $this->getHttp()->readPostResult('/log/process/' . $entity['process']['id'] . '/', $log);
78        return $mailer;
79    }
80
81    /**
82     * @return false|null
83     */
84    protected function removeEntityOlderThanOneHour(Mail $entity)
85    {
86        if (3600 < $this->getNow()->getTimestamp() - $entity['createTimestamp']) {
87            $this->deleteEntityFromQueue($entity);
88            $log = new Mimepart(['mime' => 'text/plain']);
89            $log['content'] = 'Zmsmessaging Failure: Queue entry older than 1 hour has been removed';
90            $this->getHttp()->readPostResult('/log/process/' . $entity['process']['id'] . '/', $log, ['error' => 1]);
91            \App::$log->warning($log['content']);
92            return false;
93        }
94    }
95
96    public function deleteEntityFromQueue(Mail $entity): bool
97    {
98        try {
99            $entity = $this->getHttp()
100                ->readDeleteResult('/mails/' . $entity['id'] . '/')
101                ->getEntity();
102        } catch (\BO\Zmsclient\Exception $exception) {
103            throw $exception;
104        }
105
106        return (bool) $entity;
107    }
108
109    /**
110     * @return void
111     */
112    public function testEntity(Mail $entity)
113    {
114        if (!isset($entity['department'])) {
115            throw new \Exception("Could not resolve department for message " . $entity['id']);
116        }
117        if (!isset($entity['department']['email'])) {
118            throw new \Exception(
119                "No mail address for department "
120                . $entity['department']['name']
121                . " (departmentID="
122                . $entity['department']['id']
123                . " Vorgang="
124                . $entity['process']['id']
125                . ") "
126                . $entity['id']
127            );
128        }
129        if (! $entity->hasContent()) {
130            throw new \BO\Zmsmessaging\Exception\MailWithoutContent();
131        }
132        $isMail = Validator::value($entity->getRecipient())->isMail()->getValue();
133        if (!$isMail) {
134            throw new \BO\Zmsmessaging\Exception\InvalidMailAddress();
135        }
136        if (\App::$verify_dns_enabled) {
137            $hasDns = Validator::value($entity->getRecipient())->isMail()->hasDNS()->getValue();
138            if (!$hasDns) {
139                throw new \BO\Zmsmessaging\Exception\InvalidMailAddress();
140            }
141        }
142    }
143
144    protected function monitorProcesses(array $processHandles): void
145    {
146        $running = true;
147        while ($running) {
148            $running = false;
149            foreach ($processHandles as &$handle) {
150                if (is_resource($handle['process'])) {
151                    $status = proc_get_status($handle['process']);
152                    if ($status['running']) {
153                        $running = true;
154                    } else {
155                        $output = stream_get_contents($handle['pipes'][1]);  // stdout
156                        $errorOutput = stream_get_contents($handle['pipes'][2]);  // stderr
157                        fclose($handle['pipes'][1]);
158                        fclose($handle['pipes'][2]);
159                        if (is_string($output) && trim($output)) {
160                            $this->log("\nProcess stdout: " . trim($output) . "\n");
161                        }
162                        if (is_string($errorOutput) && trim($errorOutput)) {
163                            $this->log("\nProcess stderr: " . trim($errorOutput) . "\n");
164                        }
165
166                        proc_close($handle['process']);
167                        $handle['process'] = null;
168                    }
169                }
170            }
171            usleep(500000);
172        }
173    }
174
175
176
177
178    public function log(string $message): void
179    {
180        $time = $this->getSpendTime();
181        $memory = memory_get_usage() / (1024 * 1024);
182        static::$logList[] = $message;
183
184        $context = [
185            'component' => 'zmsmessaging',
186            'elapsed' => $time,
187            'memory_mb' => $memory,
188        ];
189        if ($this->verbose) {
190            \App::$log->debug($message, $context);
191        } else {
192            \App::$log->info($message, $context);
193        }
194    }
195
196    protected function convertCollectionToArray(mixed $collection): array
197    {
198        $this->log("Converting collection to array");
199        $array = [];
200        foreach ($collection as $item) {
201            $array[] = $item;
202        }
203        $this->log("Conversion complete, array size: " . count($array));
204        return $array;
205    }
206}