Test Failed
Pull Request — dev (#1952)
by Janko
02:59
created

SpacecraftLoader::getByIdAndUser()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

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