TechlistRetriever::getResearchList()   C
last analyzed

Complexity

Conditions 17
Paths 100

Size

Total Lines 87
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 30
CRAP Score 29.1586

Importance

Changes 0
Metric Value
cc 17
eloc 43
nc 100
nop 1
dl 0
loc 87
ccs 30
cts 46
cp 0.6522
crap 29.1586
rs 5.2166
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Research;
6
7
use Stu\Component\Research\ResearchModeEnum;
8
use Stu\Orm\Entity\Researched;
9
use Stu\Orm\Entity\Research;
10
use Stu\Orm\Entity\ResearchDependency;
11
use Stu\Orm\Entity\User;
12
use Stu\Orm\Repository\FactionRepositoryInterface;
13
use Stu\Orm\Repository\ResearchDependencyRepositoryInterface;
14
use Stu\Orm\Repository\ResearchedRepositoryInterface;
15
use Stu\Orm\Repository\ResearchRepositoryInterface;
16
17
final class TechlistRetriever implements TechlistRetrieverInterface
18
{
19 1
    public function __construct(private ResearchRepositoryInterface $researchRepository, private ResearchDependencyRepositoryInterface $researchDependencyRepository, private ResearchedRepositoryInterface $researchedRepository, private FactionRepositoryInterface $factionRepository) {}
20
21 3
    #[\Override]
22
    public function getResearchList(User $user): array
23
    {
24 3
        $researchedList = $this->getResearchedList($user);
25
26 3
        $researchedIdsWithUnfinished = array_map(
27 3
            fn(Researched $researched): int => $researched->getResearch()->getId(),
28 3
            $researchedList
29 3
        );
30
31 3
        $researchedIdsOnlyFinished = array_map(
32 3
            fn(Researched $researched): int => $researched->getResearch()->getId(),
33 3
            array_filter(
34 3
                $researchedList,
35 3
                fn(Researched $researched): bool => $researched->getFinished() > 0
36 3
            )
37 3
        );
38
39 3
        $result = $this->researchRepository->getAvailableResearch($user->getId());
40 3
        $list_result = [];
41
42
        //load dependencies
43 3
        $allDependencies = $this->loadDependencies();
44
45
        //load excludes
46 3
        $excludes = $this->loadExcludes();
47
48
        // calculate possible research items
49 3
        foreach ($result as $research) {
50
            // check for existent user award
51 3
            if ($research->getNeededAwardId() !== null && !$user->hasAward($research->getNeededAwardId())) {
52
                continue;
53
            }
54
55 3
            $researchId = $research->getId();
56
57
            // excludelogic
58 3
            if (isset($excludes[$researchId])) {
59
                foreach ($excludes[$researchId] as $exclude) {
60
                    if (in_array($exclude->getResearchId(), $researchedIdsWithUnfinished)) {
61
                        continue 2;
62
                    }
63
                }
64
            }
65
66
            // dependency logic
67 3
            if (isset($allDependencies[$researchId])) {
68
69
                $dependencies = $allDependencies[$researchId];
70
71
                // check for AND condition
72
                foreach ($dependencies['AND'] as $and_condition) {
73
                    if (!in_array($and_condition, $researchedIdsOnlyFinished)) {
74
                        continue 2;
75
                    }
76
                }
77
78
                // check for OR condition
79
                if (!empty($dependencies['OR'])) {
80
                    $or_condition_met = false;
81
                    foreach ($dependencies['OR'] as $or_condition) {
82
                        if (in_array($or_condition, $researchedIdsOnlyFinished)) {
83
                            $or_condition_met = true;
84
                            break;
85
                        }
86
                    }
87
                    if (!$or_condition_met) {
88
                        continue;
89
                    }
90
                }
91
            }
92
93 3
            $list_result[$researchId] = $research;
94
        }
95
96
97 3
        foreach ($this->factionRepository->findAll() as $faction) {
98 3
            $startResearch = $faction->getStartResearch();
99 3
            if ($startResearch !== null) {
100 3
                $startResearchId = $startResearch->getId();
101 3
                if (isset($list_result[$startResearchId])) {
102 3
                    unset($list_result[$startResearchId]);
103
                }
104
            }
105
        }
106
107 3
        return $list_result;
108
    }
109
110
    #[\Override]
111
    public function canResearch(User $user, int $researchId): ?Research
112
    {
113
        return $this->getResearchList($user)[$researchId] ?? null;
114
    }
115
116
    /** @return array<int, array<string, array<int>>> */
117 3
    private function loadDependencies(): array
118
    {
119 3
        $allDependencies = [];
120
121 3
        $allDependencies_result = $this->researchDependencyRepository->getByMode(
122 3
            [ResearchModeEnum::REQUIRE->value, ResearchModeEnum::REQUIRE_SOME->value]
123 3
        );
124
125 3
        foreach ($allDependencies_result as $dependency) {
126
            $research_id = $dependency->getResearchId();
127
            $mode = $dependency->getMode();
128
129
            if (!isset($allDependencies[$research_id])) {
130
                $allDependencies[$research_id] = [
131
                    'AND' => [],
132
                    'OR' => []
133
                ];
134
            }
135
136
            if ($mode === ResearchModeEnum::REQUIRE) {
137
                $allDependencies[$research_id]['AND'][] = $dependency->getDependsOn();
138
            } elseif ($mode === ResearchModeEnum::REQUIRE_SOME) {
139
                $allDependencies[$research_id]['OR'][] = $dependency->getDependsOn();
140
            }
141
        }
142
143 3
        return $allDependencies;
144
    }
145
146
    /** @return array<int, array<ResearchDependency>> */
147 3
    private function loadExcludes(): array
148
    {
149 3
        $excludes = [];
150 3
        $exclude_result = $this->researchDependencyRepository->getByMode([ResearchModeEnum::EXCLUDE->value]);
151
152 3
        foreach ($exclude_result as $dependency) {
153
            $research_id = $dependency->getDependsOn();
154
            if (array_key_exists($research_id, $excludes) === false) {
155
                $excludes[$research_id] = [];
156
            }
157
            $excludes[$research_id][] = $dependency;
158
        }
159
160 3
        return $excludes;
161
    }
162
163 3
    #[\Override]
164
    public function getResearchedList(User $user): array
165
    {
166 3
        return $this->researchedRepository->getListByUser($user->getId());
167
    }
168
}
169