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

klinge / sl-webapp / 19171182574

07 Nov 2025 02:21PM UTC coverage: 75.865%. Remained the same
19171182574

push

github

klinge
Removing kiro folder from SonarCloud analysis

1688 of 2225 relevant lines covered (75.87%)

3.95 hits per line

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

98.59
/App/Services/SeglingService.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace App\Services;
6

7
use Exception;
8
use App\Models\SeglingRepository;
9
use App\Models\BetalningRepository;
10
use App\Models\MedlemRepository;
11
use App\Models\Segling;
12
use App\Models\Roll;
13
use App\Utils\Sanitizer;
14
use App\Utils\Session;
15
use Monolog\Logger;
16
use PDOException;
17

18
class SeglingService
19
{
20
    public function __construct(
21
        private SeglingRepository $seglingRepo,
22
        private BetalningRepository $betalningRepo,
23
        private MedlemRepository $medlemRepo,
24
        private Roll $roll,
25
        private Logger $logger
26
    ) {
27
    }
17✔
28

29
    /**
30
     * Retrieves all seglingar with participants.
31
     *
32
     * @return array<int, Segling> Array of all segling objects with participants
33
     */
34
    public function getAllSeglingar(): array
35
    {
36
        return $this->seglingRepo->getAllWithDeltagare();
1✔
37
    }
38

39
    /**
40
     * Gets all data needed for segling edit form.
41
     *
42
     * @param int $id Segling ID
43
     * @return array<string, mixed> Array containing segling, roles, and member lists
44
     * @throws Exception If segling not found
45
     */
46
    public function getSeglingEditData(int $id): array
47
    {
48
        $segling = $this->seglingRepo->getByIdWithDeltagare($id);
2✔
49
        if (!$segling) {
2✔
50
            throw new Exception('Segling not found');
1✔
51
        }
52

53
        // Get deltagare with payment status
54
        $year = (int) substr($segling->start_dat, 0, 4);
1✔
55
        /** @var array<int, array<string, mixed>> $deltagareWithBetalning */
56
        $deltagareWithBetalning = [];
1✔
57

58
        foreach ($segling->deltagare as $deltagare) {
1✔
59
            $hasPayed = $this->betalningRepo->memberHasPayed($deltagare['medlem_id'], $year);
1✔
60
            $deltagare['har_betalt'] = $hasPayed;
1✔
61
            $deltagareWithBetalning[] = $deltagare;
1✔
62
        }
63

64
        $segling->deltagare = $deltagareWithBetalning;
1✔
65

66
        return [
1✔
67
            'segling' => $segling,
1✔
68
            'roles' => $this->roll->getAll(),
1✔
69
            'allaSkeppare' => $this->medlemRepo->findMembersByRollName('Skeppare'),
1✔
70
            'allaBatsman' => $this->medlemRepo->findMembersByRollName('Båtsman'),
1✔
71
            'allaKockar' => $this->medlemRepo->findMembersByRollName('Kock')
1✔
72
        ];
1✔
73
    }
74

75
    /**
76
     * Updates an existing segling with form data.
77
     *
78
     * @param int $id Segling ID to update
79
     * @param array<string, mixed> $postData Form data from POST request
80
     * @return SeglingServiceResult Result object with success status and redirect info
81
     */
82
    public function updateSegling(int $id, array $postData): SeglingServiceResult
83
    {
84
        $sanitizer = new Sanitizer();
2✔
85
        $rules = [
2✔
86
            'startdat' => ['date', 'Y-m-d'],
2✔
87
            'slutdat' => ['date', 'Y-m-d'],
2✔
88
            'skeppslag' => 'string',
2✔
89
            'kommentar' => 'string',
2✔
90
        ];
2✔
91
        $cleanValues = $sanitizer->sanitize($postData, $rules);
2✔
92

93
        if ($this->seglingRepo->update($id, $cleanValues)) {
2✔
94
            return new SeglingServiceResult(true, 'Segling uppdaterad!', 'segling-list');
1✔
95
        } else {
96
            return new SeglingServiceResult(false, 'Kunde inte uppdatera seglingen. Försök igen.');
1✔
97
        }
98
    }
99

100
    /**
101
     * Deletes a segling by ID.
102
     *
103
     * @param int $id Segling ID to delete
104
     * @return SeglingServiceResult Result object with success status and redirect info
105
     */
106
    public function deleteSegling(int $id): SeglingServiceResult
107
    {
108
        if ($this->seglingRepo->delete($id)) {
2✔
109
            $this->logger->info('Segling was deleted: ' . $id . ' by user: ' . Session::get('user_id'));
1✔
110
            return new SeglingServiceResult(true, 'Seglingen är nu borttagen!', 'segling-list');
1✔
111
        } else {
112
            $this->logger->warning('Failed to delete segling: ' . $id . ' User: ' . Session::get('user_id'));
1✔
113
            return new SeglingServiceResult(false, 'Kunde inte ta bort seglingen. Försök igen.', 'segling-list');
1✔
114
        }
115
    }
116

117
    /**
118
     * Creates a new segling with form data.
119
     *
120
     * @param array<string, mixed> $postData Form data from POST request
121
     * @return SeglingServiceResult Result object with success status and redirect info
122
     */
123
    public function createSegling(array $postData): SeglingServiceResult
124
    {
125
        $sanitizer = new Sanitizer();
3✔
126
        $rules = [
3✔
127
            'startdat' => ['date', 'Y-m-d'],
3✔
128
            'slutdat' => ['date', 'Y-m-d'],
3✔
129
            'skeppslag' => 'string',
3✔
130
            'kommentar' => 'string',
3✔
131
        ];
3✔
132
        $cleanValues = $sanitizer->sanitize($postData, $rules);
3✔
133

134
        // Validate required fields
135
        if (empty($cleanValues['startdat']) || empty($cleanValues['slutdat']) || empty($cleanValues['skeppslag'])) {
3✔
136
            return new SeglingServiceResult(false, 'Indata saknades. Kunde inte spara seglingen. Försök igen.', 'segling-show-create');
1✔
137
        }
138

139
        $result = $this->seglingRepo->create($cleanValues);
2✔
140

141
        if ($result) {
2✔
142
            return new SeglingServiceResult(true, 'Seglingen är nu skapad!', 'segling-edit', $result);
1✔
143
        } else {
144
            return new SeglingServiceResult(false, 'Kunde inte spara till databas. Försök igen.', 'segling-show-create');
1✔
145
        }
146
    }
147

148
    /**
149
     * Adds a member to a segling with optional role.
150
     *
151
     * @param array<string, mixed> $postData Form data containing segling_id, segling_person, and optional segling_roll
152
     * @return SeglingServiceResult Result object with success status and message
153
     */
154
    public function addMemberToSegling(array $postData): SeglingServiceResult
155
    {
156
        if (!isset($postData['segling_id']) || !isset($postData['segling_person'])) {
4✔
157
            return new SeglingServiceResult(false, 'Missing input');
1✔
158
        }
159

160
        $seglingId = (int) $postData['segling_id'];
3✔
161
        $memberId = (int) $postData['segling_person'];
3✔
162
        $roleId = isset($postData['segling_roll']) ? (int) $postData['segling_roll'] : null;
3✔
163

164
        if ($this->seglingRepo->isMemberOnSegling($seglingId, $memberId)) {
3✔
165
            return new SeglingServiceResult(false, 'Medlemmen är redan tillagd på seglingen.');
1✔
166
        }
167

168
        try {
169
            if ($this->seglingRepo->addMemberToSegling($seglingId, $memberId, $roleId)) {
2✔
170
                return new SeglingServiceResult(true, 'Medlem tillagd på segling');
1✔
171
            } else {
172
                return new SeglingServiceResult(false, 'Failed to insert row');
×
173
            }
174
        } catch (PDOException $e) {
1✔
175
            return new SeglingServiceResult(false, 'PDO error: ' . $e->getMessage());
1✔
176
        }
177
    }
178

179
    /**
180
     * Removes a member from a segling.
181
     *
182
     * @param array<string, mixed> $data Data containing segling_id and medlem_id
183
     * @return SeglingServiceResult Result object with success status and message
184
     */
185
    public function removeMemberFromSegling(array $data): SeglingServiceResult
186
    {
187
        $seglingId = $data['segling_id'] ?? null;
3✔
188
        $medlemId = $data['medlem_id'] ?? null;
3✔
189

190
        if (!$seglingId || !$medlemId) {
3✔
191
            $this->logger->warning("Failed to delete medlem from segling. Invalid data. Medlem: " . $medlemId . " Segling: " . $seglingId);
1✔
192
            return new SeglingServiceResult(false, 'Invalid data');
1✔
193
        }
194

195
        if ($this->seglingRepo->removeMemberFromSegling((int) $seglingId, (int) $medlemId)) {
2✔
196
            $this->logger->info("Delete medlem from segling. Medlem: " . $medlemId . " Segling: " . $seglingId . " User: " . Session::get('user_id'));
1✔
197
            return new SeglingServiceResult(true, 'Member removed successfully');
1✔
198
        } else {
199
            $this->logger->warning("Failed to delete medlem from segling. Medlem: " . $medlemId . " Segling: " . $seglingId);
1✔
200
            return new SeglingServiceResult(false, 'Deletion failed');
1✔
201
        }
202
    }
203
}
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