Passed
Pull Request — master (#1970)
by Janko
22:22 queued 11:55
created

SpacecraftLoader::checkviolations()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 10
nc 6
nop 3
dl 0
loc 15
ccs 10
cts 10
cp 1
crap 6
rs 9.2222
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Spacecraft\Lib;
6
7
use Override;
0 ignored issues
show
Bug introduced by
The type Override was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use RuntimeException;
9
use Stu\Component\Game\SemaphoreConstants;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Game\SemaphoreConstants was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use Stu\Component\Spacecraft\System\SpacecraftSystemTypeEnum;
11
use Stu\Exception\AccessViolation;
12
use Stu\Exception\EntityLockedException;
13
use Stu\Exception\ShipDoesNotExistException;
14
use Stu\Exception\UnallowedUplinkOperation;
15
use Stu\Module\Control\GameControllerInterface;
16
use Stu\Module\Control\SemaphoreUtilInterface;
17
use Stu\Module\Spacecraft\Lib\SpacecraftWrapperFactoryInterface;
18
use Stu\Module\Spacecraft\Lib\SourceAndTargetWrappers;
19
use Stu\Module\Spacecraft\Lib\SourceAndTargetWrappersInterface;
20
use Stu\Module\Tick\Lock\LockManagerInterface;
21
use Stu\Module\Tick\Lock\LockTypeEnum;
22
use Stu\Orm\Entity\SpacecraftInterface;
23
use Stu\Orm\Repository\SpacecraftRepositoryInterface;
24
25
/**
26
 * @implements SpacecraftLoaderInterface<SpacecraftWrapperInterface>
27
 */
28
final class SpacecraftLoader implements SpacecraftLoaderInterface
29
{
30 11
    public function __construct(
31
        private SpacecraftRepositoryInterface $spacecraftRepository,
32
        private SemaphoreUtilInterface $semaphoreUtil,
33
        private GameControllerInterface $game,
34
        private SpacecraftWrapperFactoryInterface $spacecraftWrapperFactory,
35
        private LockManagerInterface $lockManager
36 11
    ) {}
37
38 22
    #[Override]
39
    public function getByIdAndUser(
40
        int $spacecraftId,
41
        int $userId,
42
        bool $allowUplink = false,
43
        bool $checkForEntityLock = true
44
    ): SpacecraftInterface {
45
46 22
        return $this->getByIdAndUserAndTargetIntern(
47 22
            $spacecraftId,
48 22
            $userId,
49 22
            null,
50 22
            $allowUplink,
51 22
            $checkForEntityLock
52 22
        )->getSource()->get();
53
    }
54
55 6
    #[Override]
56
    public function getWrapperByIdAndUser(
57
        int $spacecraftId,
58
        int $userId,
59
        bool $allowUplink = false,
60
        bool $checkForEntityLock = true
61
    ): SpacecraftWrapperInterface {
62
63 6
        return $this->getByIdAndUserAndTargetIntern(
64 6
            $spacecraftId,
65 6
            $userId,
66 6
            null,
67 6
            $allowUplink,
68 6
            $checkForEntityLock
69 6
        )->getSource();
70
    }
71
72 3
    #[Override]
73
    public function getWrappersBySourceAndUserAndTarget(
74
        int $spacecraftId,
75
        int $userId,
76
        int $targetId,
77
        bool $allowUplink = false,
78
        bool $checkForEntityLock = true
79
    ): SourceAndTargetWrappersInterface {
80
81 3
        return $this->getByIdAndUserAndTargetIntern(
82 3
            $spacecraftId,
83 3
            $userId,
84 3
            $targetId,
85 3
            $allowUplink,
86 3
            $checkForEntityLock
87 3
        );
88
    }
89
90
    /**
91
     * @return SourceAndTargetWrappersInterface<SpacecraftWrapperInterface>
92
     */
93 29
    private function getByIdAndUserAndTargetIntern(
94
        int $spacecraftId,
95
        int $userId,
96
        ?int $targetId,
97
        bool $allowUplink,
98
        bool $checkForEntityLock
99
    ): SourceAndTargetWrappersInterface {
100
101 29
        if ($checkForEntityLock) {
102 12
            $this->checkForEntityLock($spacecraftId);
103
        }
104
105 28
        $spacecraft = $this->spacecraftRepository->find($spacecraftId);
106 28
        if ($spacecraft === null) {
107 1
            throw new ShipDoesNotExistException(_('Spacecraft does not exist!'));
108
        }
109 27
        $this->checkviolations($spacecraft, $userId, $allowUplink);
110
111 23
        return $this->acquireSemaphores($spacecraft, $targetId);
112
    }
113
114 25
    private function checkForEntityLock(int $spacecraftId): void
115
    {
116 25
        if ($this->lockManager->isLocked($spacecraftId, LockTypeEnum::SHIP_GROUP)) {
117 1
            throw new EntityLockedException('Tick läuft gerade, Zugriff auf Schiff ist daher blockiert');
118
        }
119
    }
120
121 27
    private function checkviolations(SpacecraftInterface $spacecraft, int $userId, bool $allowUplink): void
122
    {
123 27
        if ($spacecraft->getUser()->getId() !== $userId) {
124 4
            if ($spacecraft->hasCrewmanOfUser($userId)) {
125 3
                if (!$allowUplink) {
126 1
                    throw new UnallowedUplinkOperation(_('This Operation is not allowed via uplink!'));
127
                }
128 2
                if (!$spacecraft->getSystemState(SpacecraftSystemTypeEnum::SYSTEM_UPLINK)) {
129 1
                    throw new UnallowedUplinkOperation(_('Uplink is not activated!'));
130
                }
131 1
                if ($spacecraft->getUser()->isVacationRequestOldEnough()) {
132 1
                    throw new UnallowedUplinkOperation(_('Owner is on vacation!'));
133
                }
134
            } else {
135 1
                throw new AccessViolation(sprintf("Spacecraft owned by another user (%d)! Fool: %d", $spacecraft->getUser()->getId(), $userId));
136
            }
137
        }
138
    }
139
140 13
    #[Override]
141
    public function find(int $spacecraftId, bool $checkForEntityLock = true): ?SpacecraftWrapperInterface
142
    {
143 13
        if ($checkForEntityLock) {
144 13
            $this->checkForEntityLock($spacecraftId);
145
        }
146
147 13
        $spacecraft = $this->spacecraftRepository->find($spacecraftId);
148 13
        if ($spacecraft === null) {
149
            return null;
150
        }
151
152 13
        return $this->acquireSemaphores($spacecraft, null)->getSource();
153
    }
154
155
    #[Override]
156
    public function save(SpacecraftInterface $spacecraft): void
157
    {
158
        $this->spacecraftRepository->save($spacecraft);
159
    }
160
161
    /**
162
     * @return SourceAndTargetWrappersInterface<SpacecraftWrapperInterface>
163
     */
164 36
    private function acquireSemaphores(SpacecraftInterface $spacecraft, ?int $targetId): SourceAndTargetWrappersInterface
165
    {
166 36
        if ($targetId === null && $this->game->isSemaphoreAlreadyAcquired($spacecraft->getUser()->getId())) {
167
            return new SourceAndTargetWrappers($this->spacecraftWrapperFactory->wrapSpacecraft($spacecraft));
168
        }
169
170
        //main spacecraft sema on
171 36
        $mainSema = $this->semaphoreUtil->getSemaphore(SemaphoreConstants::MAIN_SHIP_SEMAPHORE_KEY);
172 36
        $this->semaphoreUtil->acquireMainSemaphore($mainSema);
173
174 36
        $wrapper = $this->acquireSemaphoreForSpacecraft($spacecraft, null);
175 36
        if ($wrapper === null) {
176
            throw new RuntimeException('wrapper should not be null here');
177
        }
178 36
        $result = new SourceAndTargetWrappers($wrapper);
179
180 36
        if ($targetId !== null) {
181 3
            $result->setTarget($this->acquireSemaphoreForSpacecraft(null, $targetId));
182
        }
183
184
        //main spacecraft sema off
185 36
        $this->semaphoreUtil->releaseSemaphore($mainSema);
186
187 36
        return $result;
188
    }
189
190 36
    private function acquireSemaphoreForSpacecraft(?SpacecraftInterface $spacecraft, ?int $spacecraftId): ?SpacecraftWrapperInterface
191
    {
192 36
        if ($spacecraft === null && $spacecraftId === null) {
193
            return null;
194
        }
195
196 36
        if ($spacecraft === null) {
197 3
            $spacecraft = $this->spacecraftRepository->find($spacecraftId);
198
        }
199
200 36
        if ($spacecraft === null) {
201 1
            return null;
202
        }
203
204 36
        $key = $spacecraft->getUser()->getId();
205 36
        $semaphore = $this->semaphoreUtil->getSemaphore($key);
206 36
        $this->semaphoreUtil->acquireSemaphore($key, $semaphore); //prüft ob schon genommen
207 36
        return $this->spacecraftWrapperFactory->wrapSpacecraft($spacecraft);
208
    }
209
}
210