• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

klinge / sl-webapp / 18972011891

31 Oct 2025 12:06PM UTC coverage: 74.73% (+11.1%) from 63.602%
18972011891

push

github

klinge
Fixed phpcs errors

1662 of 2224 relevant lines covered (74.73%)

3.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.03
/App/Models/MedlemRepository.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace App\Models;
6

7
use PDO;
8
use Exception;
9
use Psr\Log\LoggerInterface;
10

11
class MedlemRepository extends BaseModel
12
{
13
    public $medlemmar;
14

15
    public function __construct(PDO $db, LoggerInterface $logger)
16
    {
17
        parent::__construct($db, $logger);
39✔
18
    }
19

20

21
    /**
22
     * Retrieves all members from the database.
23
     *
24
     * Fetches member and creates Medlem objects for each,
25
     * and returns them in an array sorted by last name.
26
     *
27
     * @return array Medlem[] An array of Medlem objects
28
     */
29
    public function getAll(): array
30
    {
31
        $medlemmar = [];
×
32

33
        $query = "SELECT id FROM Medlem ORDER BY efternamn ASC";
×
34
        $stmt = $this->conn->prepare($query);
×
35
        $stmt->execute();
×
36
        $members =  $stmt->fetchAll(PDO::FETCH_ASSOC);
×
37

38
        foreach ($members as $member) {
×
39
            try {
40
                $medlem = $this->createMedlem($member['id']);
×
41
                $medlemmar[] = $medlem;
×
42
            } catch (Exception $e) {
×
43
                //Do nothing right now..
44
            }
45
        }
46
        return $medlemmar;
×
47
    }
48

49
    // Find all Medlemmar in a role by querying Medlem, Roll, and Medlem_Roll tables
50
    // to find members with a specified roll_namn
51
    public function getMembersByRollName(string $rollName): array
52
    {
53
        $query = "SELECT m.id,m.fornamn, m.efternamn, r.roll_namn
1✔
54
            FROM  Medlem m
55
            INNER JOIN Medlem_Roll mr ON mr.medlem_id = m.id
56
            INNER JOIN Roll r ON r.id = mr.roll_id
57
            WHERE r.roll_namn = :rollnamn
58
            ORDER BY m.efternamn ASC;";
1✔
59
        $stmt = $this->conn->prepare($query);
1✔
60
        $stmt->bindParam(':rollnamn', $rollName);
1✔
61
        $stmt->execute();
1✔
62
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
1✔
63
    }
64

65
    // Query Medlem, Roll, and Medlem_Roll tables
66
    // to find members with a specified roll_namn
67
    public function getMembersByRollId(int $rollId): array
68
    {
69
        $query = "SELECT m.id,m.fornamn, m.efternamn, r.id AS roll_id, r.roll_namn
1✔
70
            FROM  Medlem m
71
            INNER JOIN Medlem_Roll mr ON mr.medlem_id = m.id
72
            INNER JOIN Roll r ON r.id = mr.roll_id
73
            WHERE r.id = :id
74
            ORDER BY m.fornamn ASC;";
1✔
75
        $stmt = $this->conn->prepare($query);
1✔
76
        $stmt->bindParam(':id', $rollId);
1✔
77
        $stmt->execute();
1✔
78
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
1✔
79
    }
80

81
    /**
82
     * Retrieves member data by email.
83
     *
84
     * @param string $email The email address of the member
85
     * @return array|bool Member data array or false if not found
86
     */
87
    public function getMemberByEmail(string $email): array|bool
88
    {
89
        $stmt = $this->conn->prepare("SELECT * FROM medlem WHERE email = :email");
12✔
90
        $stmt->bindParam(':email', $email);
12✔
91
        $stmt->execute();
12✔
92

93
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
12✔
94
        return $result ?: false;
12✔
95
    }
96

97
    /**
98
     * Retrieves member email addresses.
99
     *
100
     * @return array An array of member email addresses
101
     */
102
    public function getEmailForActiveMembers(): array
103
    {
104
        $query = "SELECT email FROM medlem WHERE pref_kommunikation = 1";
1✔
105
        $stmt = $this->conn->prepare($query);
1✔
106
        $stmt->execute();
1✔
107
        $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
1✔
108
        //Remove rows with empty emails
109
        return array_filter($result, fn($item) => !empty($item['email']));
1✔
110
    }
111

112
    /**
113
     * Finds member data by ID.
114
     *
115
     * @param int $id The member ID
116
     * @return array|null Member data array or null if not found
117
     */
118
    public function findById(int $id): ?array
119
    {
120
        $query = "SELECT * FROM Medlem WHERE id = :id LIMIT 1";
6✔
121
        $stmt = $this->conn->prepare($query);
6✔
122
        $stmt->bindParam(':id', $id);
6✔
123
        $stmt->execute();
6✔
124
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
6✔
125
        return $row ?: null;
6✔
126
    }
127

128
    /**
129
     * Retrieves a member by ID.
130
     *
131
     * @param int $id The member ID
132
     * @return Medlem|null The Medlem object or null if not found
133
     */
134
    public function getById(int $id): ?Medlem
135
    {
136
        $data = $this->findById($id);
4✔
137
        if (!$data) {
4✔
138
            return null;
×
139
        }
140

141
        $medlem = new Medlem();
4✔
142
        $this->populateMedlem($medlem, $data);
4✔
143
        $medlem->roller = $this->getRolesByMemberId($id);
4✔
144
        return $medlem;
4✔
145
    }
146

147
    /**
148
     * Creates a new empty Medlem object for data entry.
149
     *
150
     * @return Medlem New Medlem object
151
     */
152
    public function createNew(): Medlem
153
    {
154
        return new Medlem();
1✔
155
    }
156

157
    /**
158
     * Inserts a new member.
159
     *
160
     * @param array $data Member data
161
     * @return int The new member ID
162
     */
163
    public function insert(array $data): int
164
    {
165
        $params = [
1✔
166
            "fodelsedatum", "fornamn", "efternamn", "email", "gatuadress",
1✔
167
            "postnummer", "postort", "mobil", "telefon", "kommentar",
1✔
168
            "godkant_gdpr", "pref_kommunikation", "isAdmin", "foretag",
1✔
169
            "standig_medlem", "skickat_valkomstbrev"
1✔
170
        ];
1✔
171

172
        $sql = "INSERT INTO Medlem (" . implode(', ', $params) . ") VALUES (" .
1✔
173
               implode(', ', array_map(fn($p) => ":$p", $params)) . ")";
1✔
174

175
        $stmt = $this->conn->prepare($sql);
1✔
176
        $this->bindMemberParams($stmt, $data);
1✔
177
        $stmt->execute();
1✔
178

179
        return (int) $this->conn->lastInsertId();
1✔
180
    }
181

182
    /**
183
     * Updates an existing member.
184
     *
185
     * @param int $id Member ID
186
     * @param array $data Member data
187
     * @return bool Success status
188
     */
189
    public function update(int $id, array $data): bool
190
    {
191
        $params = [
1✔
192
            "fodelsedatum", "fornamn", "efternamn", "email", "gatuadress",
1✔
193
            "postnummer", "postort", "mobil", "telefon", "kommentar",
1✔
194
            "godkant_gdpr", "pref_kommunikation", "isAdmin", "foretag",
1✔
195
            "standig_medlem", "skickat_valkomstbrev"
1✔
196
        ];
1✔
197

198
        $sql = "UPDATE Medlem SET " . implode(', ', array_map(fn($p) => "$p = :$p", $params)) .
1✔
199
               " WHERE id = :id";
1✔
200

201
        $stmt = $this->conn->prepare($sql);
1✔
202
        $this->bindMemberParams($stmt, $data);
1✔
203
        $stmt->bindParam(':id', $id, PDO::PARAM_INT);
1✔
204
        $stmt->execute();
1✔
205

206
        return true;
1✔
207
    }
208

209
    /**
210
     * Saves a member (create or update).
211
     *
212
     * @param Medlem $medlem The member to save
213
     * @return bool Success status
214
     */
215
    public function save(Medlem $medlem): bool
216
    {
217
        try {
218
            $data = $this->medlemToArray($medlem);
×
219

220
            if (isset($medlem->id) && $medlem->id > 0) {
×
221
                $this->update($medlem->id, $data);
×
222
            } else {
223
                $medlem->id = $this->insert($data);
×
224
            }
225

226
            $this->saveRolesForMember($medlem->id, $medlem->roller);
×
227
            return true;
×
228
        } catch (Exception $e) {
×
229
            $this->logger->error('Failed to save medlem: ' . $e->getMessage());
×
230
            return false;
×
231
        }
232
    }
233

234
    /**
235
     * Deletes a member by ID.
236
     *
237
     * @param int $id Member ID
238
     * @return bool Success status
239
     */
240
    public function deleteById(int $id): bool
241
    {
242
        try {
243
            $this->conn->beginTransaction();
2✔
244

245
            // Remove roles first
246
            $stmt = $this->conn->prepare('DELETE FROM Medlem_Roll WHERE medlem_id = ?');
2✔
247
            $stmt->execute([$id]);
2✔
248

249
            // Remove member
250
            $stmt = $this->conn->prepare('DELETE FROM Medlem WHERE id = ?');
1✔
251
            $stmt->execute([$id]);
1✔
252

253
            $this->conn->commit();
1✔
254
            return true;
1✔
255
        } catch (Exception $e) {
1✔
256
            $this->conn->rollBack();
1✔
257
            $this->logger->error('Failed to delete medlem: ' . $e->getMessage());
1✔
258
            return false;
1✔
259
        }
260
    }
261

262
    /**
263
     * Deletes a member.
264
     *
265
     * @param Medlem $medlem The member to delete
266
     * @return bool Success status
267
     */
268
    public function delete(Medlem $medlem): bool
269
    {
270
        return $this->deleteById($medlem->id);
×
271
    }
272

273
    /**
274
     * Gets roles for a member.
275
     *
276
     * @param int $memberId Member ID
277
     * @return array Array of roles
278
     */
279
    public function getRolesByMemberId(int $memberId): array
280
    {
281
        $query = "SELECT mr.roll_id, r.roll_namn 
5✔
282
                  FROM Medlem_Roll mr
283
                  INNER JOIN Roll r ON mr.roll_id = r.id
284
                  WHERE mr.medlem_id = :id";
5✔
285

286
        $stmt = $this->conn->prepare($query);
5✔
287
        $stmt->bindParam(':id', $memberId);
5✔
288
        $stmt->execute();
5✔
289
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
5✔
290
    }
291

292
    /**
293
     * Saves roles for a member.
294
     *
295
     * @param int $memberId Member ID
296
     * @param array $roles Array of roles
297
     * @return void
298
     */
299
    public function saveRolesForMember(int $memberId, array $roles): void
300
    {
301
        try {
302
            $this->conn->beginTransaction();
1✔
303

304
            // Get current roles
305
            $stmt = $this->conn->prepare("SELECT roll_id FROM Medlem_Roll WHERE medlem_id = :medlem_id");
1✔
306
            $stmt->execute(['medlem_id' => $memberId]);
1✔
307
            $currentRoles = $stmt->fetchAll(PDO::FETCH_COLUMN);
1✔
308

309
            $newRoles = array_map(fn($role) => (int) $role['roll_id'], $roles);
1✔
310

311
            // Add new roles
312
            $rolesToAdd = array_diff($newRoles, $currentRoles);
1✔
313
            if (!empty($rolesToAdd)) {
1✔
314
                $stmt = $this->conn->prepare("INSERT INTO Medlem_Roll (medlem_id, roll_id) VALUES (:medlem_id, :roll_id)");
1✔
315
                foreach ($rolesToAdd as $rollId) {
1✔
316
                    $stmt->execute(['medlem_id' => $memberId, 'roll_id' => $rollId]);
1✔
317
                }
318
            }
319

320
            // Remove old roles
321
            $rolesToRemove = array_diff($currentRoles, $newRoles);
1✔
322
            if (!empty($rolesToRemove)) {
1✔
323
                $stmt = $this->conn->prepare("DELETE FROM Medlem_Roll WHERE medlem_id = :medlem_id AND roll_id = :roll_id");
×
324
                foreach ($rolesToRemove as $rollId) {
×
325
                    $stmt->execute(['medlem_id' => $memberId, 'roll_id' => $rollId]);
×
326
                }
327
            }
328

329
            $this->conn->commit();
1✔
330
        } catch (Exception $e) {
×
331
            $this->conn->rollBack();
×
332
            $this->logger->error("Error updating roles for medlem ID $memberId: " . $e->getMessage());
×
333
            throw $e;
×
334
        }
335
    }
336

337
    /**
338
     * Gets seglingar for a member.
339
     *
340
     * @param int $memberId Member ID
341
     * @return array Array of seglingar
342
     */
343
    public function getSeglingarByMemberId(int $memberId): array
344
    {
345
        $query = 'SELECT smr.medlem_id, s.id as segling_id, r.roll_namn, s.skeppslag, s.startdatum
1✔
346
            FROM Segling_Medlem_Roll smr
347
            INNER JOIN Segling s ON s.id = smr.segling_id
348
            LEFT JOIN Roll r ON r.id = smr.roll_id
349
            WHERE smr.medlem_id = :id
350
            ORDER BY s.startdatum DESC
351
            LIMIT 10';
1✔
352

353
        $stmt = $this->conn->prepare($query);
1✔
354
        $stmt->bindParam(':id', $memberId);
1✔
355
        $stmt->execute();
1✔
356
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
1✔
357
    }
358

359
    private function bindMemberParams($stmt, array $data): void
360
    {
361
        $stmt->bindParam(':fodelsedatum', $data['fodelsedatum'], PDO::PARAM_STR);
2✔
362
        $stmt->bindParam(':fornamn', $data['fornamn'], PDO::PARAM_STR);
2✔
363
        $stmt->bindParam(':efternamn', $data['efternamn'], PDO::PARAM_STR);
2✔
364
        $email = $data['email'] ?: null;
2✔
365
        $stmt->bindParam(':email', $email, PDO::PARAM_STR);
2✔
366
        $stmt->bindParam(':gatuadress', $data['adress'], PDO::PARAM_STR);
2✔
367
        $stmt->bindParam(':postnummer', $data['postnummer'], PDO::PARAM_STR);
2✔
368
        $stmt->bindParam(':postort', $data['postort'], PDO::PARAM_STR);
2✔
369
        $stmt->bindParam(':mobil', $data['mobil'], PDO::PARAM_STR);
2✔
370
        $stmt->bindParam(':telefon', $data['telefon'], PDO::PARAM_STR);
2✔
371
        $stmt->bindParam(':kommentar', $data['kommentar'], PDO::PARAM_STR);
2✔
372
        $stmt->bindParam(':godkant_gdpr', $data['godkant_gdpr'], PDO::PARAM_BOOL);
2✔
373
        $stmt->bindParam(':pref_kommunikation', $data['pref_kommunikation'], PDO::PARAM_BOOL);
2✔
374
        $stmt->bindParam(':isAdmin', $data['isAdmin'], PDO::PARAM_BOOL);
2✔
375
        $stmt->bindParam(':foretag', $data['foretag'], PDO::PARAM_BOOL);
2✔
376
        $stmt->bindParam(':standig_medlem', $data['standig_medlem'], PDO::PARAM_BOOL);
2✔
377
        $stmt->bindParam(':skickat_valkomstbrev', $data['skickat_valkomstbrev'], PDO::PARAM_BOOL);
2✔
378
    }
379

380
    private function populateMedlem(Medlem $medlem, array $data): void
381
    {
382
        $medlem->id = (int) $data['id'];
4✔
383
        $medlem->fodelsedatum = $data['fodelsedatum'] ?? null;
4✔
384
        $medlem->fornamn = $data['fornamn'] ?? null;
4✔
385
        $medlem->efternamn = $data['efternamn'];
4✔
386
        $medlem->email = $data['email'] ?? null;
4✔
387
        $medlem->mobil = $data['mobil'] ?? null;
4✔
388
        $medlem->telefon = $data['telefon'] ?? null;
4✔
389
        $medlem->adress = $data['gatuadress'] ?? null;
4✔
390
        $medlem->postnummer = $data['postnummer'] ?? null;
4✔
391
        $medlem->postort = $data['postort'] ?? null;
4✔
392
        $medlem->kommentar = $data['kommentar'] ?? null;
4✔
393
        $medlem->godkant_gdpr = (bool) $data['godkant_gdpr'];
4✔
394
        $medlem->pref_kommunikation = (bool) $data['pref_kommunikation'];
4✔
395
        $medlem->foretag = (bool) $data['foretag'];
4✔
396
        $medlem->standig_medlem = (bool) $data['standig_medlem'];
4✔
397
        $medlem->skickat_valkomstbrev = (bool) $data['skickat_valkomstbrev'];
4✔
398
        $medlem->isAdmin = (bool) $data['isAdmin'];
4✔
399
        $medlem->password = $data['password'] ?? null;
4✔
400
        $medlem->created_at = $data['created_at'];
4✔
401
        $medlem->updated_at = $data['updated_at'];
4✔
402
    }
403

404
    private function medlemToArray(Medlem $medlem): array
405
    {
406
        return [
×
407
            'fodelsedatum' => $medlem->fodelsedatum,
×
408
            'fornamn' => $medlem->fornamn,
×
409
            'efternamn' => $medlem->efternamn,
×
410
            'email' => $medlem->email,
×
411
            'adress' => $medlem->adress,
×
412
            'postnummer' => $medlem->postnummer,
×
413
            'postort' => $medlem->postort,
×
414
            'mobil' => $medlem->mobil,
×
415
            'telefon' => $medlem->telefon,
×
416
            'kommentar' => $medlem->kommentar,
×
417
            'godkant_gdpr' => $medlem->godkant_gdpr,
×
418
            'pref_kommunikation' => $medlem->pref_kommunikation,
×
419
            'isAdmin' => $medlem->isAdmin,
×
420
            'foretag' => $medlem->foretag,
×
421
            'standig_medlem' => $medlem->standig_medlem,
×
422
            'skickat_valkomstbrev' => $medlem->skickat_valkomstbrev
×
423
        ];
×
424
    }
425

426
    protected function createMedlem(int $id): Medlem
427
    {
428
        return $this->getById($id);
×
429
    }
430
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc