Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
75.64% covered (warning)
75.64%
59 / 78
40.00% covered (danger)
40.00%
2 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
ImageUtils
75.64% covered (warning)
75.64%
59 / 78
40.00% covered (danger)
40.00%
2 / 5
50.71
0.00% covered (danger)
0.00%
0 / 1
 olzImage
77.78% covered (warning)
77.78%
28 / 36
0.00% covered (danger)
0.00%
0 / 1
11.10
 getThumbSize
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 generateThumbnails
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 getThumbFile
68.75% covered (warning)
68.75%
22 / 32
0.00% covered (danger)
0.00%
0 / 1
23.81
 fromEnv
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace Olz\Utils;
4
5class ImageUtils {
6    use WithUtilsTrait;
7
8    public const TABLES_IMG_DIRS = [
9        'karten' => 'img/karten/',
10        'news' => 'img/news/',
11        'questions' => 'img/questions/',
12        'roles' => 'img/roles/',
13        'snippets' => 'img/snippets/',
14        'termine' => 'img/termine/',
15        'termin_labels' => 'img/termin_labels/',
16        'termin_locations' => 'img/termin_locations/',
17        'termin_templates' => 'img/termin_templates/',
18        'users' => 'img/users/',
19        'weekly_picture' => 'img/weekly_picture/',
20    ];
21
22    public function olzImage(
23        string $db_table,
24        int|string|null $id,
25        ?string $index,
26        int $dim,
27        ?string $lightview = 'image',
28        string $attrs = '',
29    ): string {
30        $data_href = $this->envUtils()->getDataHref();
31        $data_path = $this->envUtils()->getDataPath();
32        if (!isset($this::TABLES_IMG_DIRS[$db_table])) {
33            $message = "Ungültige db_table: {$db_table} (in olzImage)";
34            $this->log()->error($message);
35            return "<span style='color:#ff0000; font-style:italic;'>{$message}</span>";
36        }
37        $db_imgpath = $this::TABLES_IMG_DIRS[$db_table];
38        $imgfile = "{$db_imgpath}{$id}/img/{$index}";
39        if (!$id || !$index || !is_file("{$data_path}{$imgfile}")) {
40            $message = "Bild nicht vorhanden (in olzImage): {$imgfile}";
41            $this->log()->error($message);
42            return "<span style='color:#ff0000; font-style:italic;'>{$message}</span>";
43        }
44        $info = getimagesize("{$data_path}{$imgfile}");
45        $swid = $info[0] ?? 0;
46        $shei = $info[1] ?? 0;
47        if ($shei < $swid) {
48            $wid = $dim;
49            $hei = intval($wid * $shei / $swid);
50        } else {
51            $hei = $dim;
52            $wid = intval($hei * $swid / $shei);
53        }
54        $span_before = $lightview === 'image' ? "<span class='lightgallery'>" : "";
55        $span_after = $lightview === 'image' ? "</span>" : "";
56        $a_before = $lightview ? "<a href='{$data_href}{$imgfile}' aria-label='Bild vergrössern' data-src='{$data_href}{$imgfile}' onclick='event.stopPropagation()'>" : "";
57        $a_after = $lightview ? "</a>" : "";
58
59        $url_without_dim = "{$data_href}img/{$db_table}/{$id}/thumb/{$index}";
60        $thumbdim = $this->getThumbSize($dim);
61        $thumbdim2x = $thumbdim * 2;
62        return <<<ZZZZZZZZZZ
63            {$span_before}{$a_before}
64            <img
65                src='{$url_without_dim}\${$thumbdim}.jpg'
66                srcset='{$url_without_dim}\${$thumbdim2x}.jpg 2x, {$url_without_dim}\${$thumbdim}.jpg 1x'
67                alt=''
68                width='{$wid}'
69                height='{$hei}'
70                {$attrs}
71            />
72            {$a_after}{$span_after}
73            ZZZZZZZZZZ;
74    }
75
76    public function getThumbSize(int $size): int {
77        $ndim = $size - 1;
78        for ($i = 1; $i < 9 && ($ndim >> $i) > 0; $i++) {
79        }
80        return 1 << $i;
81    }
82
83    /** @param array<string> $image_ids */
84    public function generateThumbnails(array $image_ids, string $entity_img_path): void {
85        foreach ($image_ids as $image_id) {
86            for ($i = 5; $i < 9; $i++) {
87                $size = (1 << $i);
88                if (!is_file("{$entity_img_path}thumb/{$image_id}\${$size}.jpg")) {
89                    $this->log()->info("Generate {$entity_img_path}thumb/{$image_id}\${$size}.jpg...");
90                    $this->getThumbFile($image_id, $entity_img_path, $size);
91                }
92            }
93        }
94    }
95
96    public function getThumbFile(string $image_id, string $entity_img_path, int $size): string {
97        if ($size !== 32 && $size !== 64 && $size !== 128 && $size !== 256 && $size !== 512) {
98            throw new \Exception("Size must be a power of two (32,64,128,256,512), was: {$size}");
99        }
100        $imgfile = "{$entity_img_path}img/{$image_id}";
101        $info = getimagesize($imgfile);
102        $swid = $info[0] ?? 0;
103        $shei = $info[1] ?? 0;
104        if ($shei < $swid) {
105            $wid = $size;
106            $hei = intval($wid * $shei / $swid);
107        } else {
108            $hei = $size;
109            $wid = intval($hei * $swid / $shei);
110        }
111        if ($wid <= 0 || $hei <= 0 || $wid > 800 || $hei > 800) {
112            $message = "getThumbFile: Invalid dimension: {$size}";
113            $this->log()->warning($message);
114            throw new \Exception($message);
115        }
116        if ($wid > 256 || $hei > 256) {
117            $thumbfile = $imgfile;
118        } else {
119            $thumbfile = "{$entity_img_path}thumb/{$image_id}\${$size}.jpg";
120        }
121        if (!is_file($thumbfile)) {
122            if (!is_dir(dirname($thumbfile))) {
123                mkdir(dirname($thumbfile), 0o777, true);
124            }
125            $img = imagecreatefromjpeg($imgfile);
126            if (!$img) {
127                $message = "getThumbFile: Could not open image {$imgfile}";
128                $this->log()->warning($message);
129                throw new \Exception($message);
130            }
131            $thumb = imagecreatetruecolor($wid, $hei);
132            imagesavealpha($thumb, true);
133            imagecopyresampled($thumb, $img, 0, 0, 0, 0, $wid, $hei, $swid, $shei);
134            imagejpeg($thumb, $thumbfile, 90);
135            imagedestroy($thumb);
136        }
137        return $thumbfile;
138    }
139
140    public static function fromEnv(): self {
141        return new self();
142    }
143}