Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Failed Conditions
Push — main ( 5797ad...3faf69 )
by Dan
29s queued 24s
created

EditGalaxiesProcessor::build()   F

Complexity

Conditions 38
Paths > 20000

Size

Total Lines 201
Code Lines 108

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 38
eloc 108
nc 3742848
nop 1
dl 0
loc 201
rs 0
c 1
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 declare(strict_types=1);
2
3
namespace Smr\Pages\Admin\UniGen;
4
5
use Smr\Database;
6
use Smr\Page\AccountPageProcessor;
7
use Smr\Request;
8
use SmrAccount;
9
use SmrGalaxy;
10
use SmrGame;
11
use SmrLocation;
12
use SmrPlanet;
13
use SmrPort;
14
use SmrSector;
15
16
class EditGalaxiesProcessor extends AccountPageProcessor {
17
18
	public function __construct(
19
		private readonly int $gameID,
20
		private readonly int $galaxyID
21
	) {}
22
23
	public function build(SmrAccount $account): never {
24
		$db = Database::getInstance();
25
26
		$gameID = $this->gameID;
27
		$game = SmrGame::getGame($gameID);
28
		$galaxies = $game->getGalaxies();
29
30
		// Save the original sizes for later processing
31
		$origGals = [];
32
		foreach ($galaxies as $i => $galaxy) {
33
			$origGals[$i] = [
34
				'Width' => $galaxy->getWidth(),
35
				'Height' => $galaxy->getHeight(),
36
			];
37
		}
38
39
		// Modify the galaxy properties
40
		foreach ($galaxies as $i => $galaxy) {
41
			$galaxy->setName(Request::get('gal' . $i));
42
			$galaxy->setGalaxyType(Request::get('type' . $i));
43
			$galaxy->setMaxForceTime(IFloor(Request::getFloat('forces' . $i) * 3600));
0 ignored issues
show
Bug introduced by
The function IFloor was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

43
			$galaxy->setMaxForceTime(/** @scrutinizer ignore-call */ IFloor(Request::getFloat('forces' . $i) * 3600));
Loading history...
44
			if (!$game->isEnabled()) {
45
				$galaxy->setWidth(Request::getInt('width' . $i));
46
				$galaxy->setHeight(Request::getInt('height' . $i));
47
			}
48
		}
49
50
		// Early return if no galaxy dimensions are modified
51
		$galaxySizesUnchanged = true;
52
		foreach ($galaxies as $i => $galaxy) {
53
			if ($galaxy->getWidth() != $origGals[$i]['Width'] || $galaxy->getHeight() != $origGals[$i]['Height']) {
54
				$galaxySizesUnchanged = false;
55
				break;
56
			}
57
		}
58
		if ($galaxySizesUnchanged) {
59
			SmrGalaxy::saveGalaxies();
60
			$message = '<span class="green">SUCCESS: </span>Edited galaxies (sizes unchanged).';
61
			$container = new EditGalaxy($this->gameID, $this->galaxyID, $message);
62
			$container->go();
63
		}
64
65
		// *** BEGIN GALAXY DIMENSION MODIFICATION! ***
66
		// Warning: This changes primary keys for several tables, which needs to be
67
		// done carefully. It also interacts with the caches in unexpected ways.
68
		// *** BEGIN GALAXY DIMENSION MODIFICATION! ***
69
70
		// Efficiently construct the caches before proceeding
71
		// NOTE: these will be associated with the old sector IDs, so the caches
72
		// will need to be cleared afterwards.
73
		foreach ($galaxies as $galaxy) {
74
			$galaxy->getSectors();
75
			$galaxy->getPorts();
76
			$galaxy->getLocations();
77
			$galaxy->getPlanets();
78
		}
79
80
		// Determine the mapping from old to new sector IDs
81
		$newID = 0;
82
		$oldID = 0;
83
		$sectorMap = [];
84
		foreach ($galaxies as $i => $galaxy) {
85
			$maxRows = max($galaxy->getHeight(), $origGals[$i]['Height']);
86
			$maxCols = max($galaxy->getWidth(), $origGals[$i]['Width']);
87
			for ($row = 0; $row < $maxRows; $row++) {
88
				for ($col = 0; $col < $maxCols; $col++) {
89
					$oldExists = ($row < $origGals[$i]['Height'] && $col < $origGals[$i]['Width']);
90
					$newExists = ($row < $galaxy->getHeight() && $col < $galaxy->getWidth());
91
92
					if ($oldExists && $newExists) {
93
						$oldID++;
94
						$newID++;
95
						$sectorMap[$newID] = $oldID;
96
					} elseif ($newExists) {
97
						$newID++;
98
						$sectorMap[$newID] = false;
99
					} elseif ($oldExists) {
100
						$oldID++;
101
						// Remove this sector and everything in it
102
						$delSector = SmrSector::getSector($gameID, $oldID);
103
						$delSector->removeAllFixtures();
104
						$db->write('DELETE FROM sector WHERE ' . $delSector->getSQL());
105
					}
106
				}
107
			}
108
		}
109
110
		// Save remaining old warps to re-add later, then clear all warp data.
111
		// This is necessary because we will be manually modifying sector IDs.
112
		$oldWarps = [];
113
		foreach ($galaxies as $galaxy) {
114
			foreach ($galaxy->getSectors() as $galSector) {
115
				if ($galSector->hasWarp()) {
116
					$oldWarps[$galSector->getSectorID()] = $galSector->getWarp();
117
				}
118
			}
119
		}
120
		$db->write('UPDATE sector SET warp = 0 WHERE game_id = ' . $db->escapeNumber($gameID));
121
122
		// Many sectors will have their IDs shifted up or down, so we need to modify
123
		// the primary keys for the sector table as well as planets, ports, etc.
124
		// We have to do this in a loop to ensure that the new sector ID will not
125
		// collide with an old sector ID that hasn't been shifted yet (because we
126
		// may be both adding and removing sectors).
127
		//
128
		// NOTE: We have already accounted for collisions from removing sectors by
129
		// deleting all fixtures from sectors that will no longer exist.
130
		$needsUpdate = $sectorMap;
131
		while ($needsUpdate) {
132
			foreach ($needsUpdate as $newID => $oldID) {
133
				// If sector is new or has the same ID, then no shifting is necessary
134
				if ($oldID === false || $oldID == $newID) {
135
					unset($needsUpdate[$newID]);
136
					continue;
137
				}
138
139
				// If the oldID still exists, then we have to defer shifting until
140
				// this destination has been vacated.
141
				if (array_search($newID, $needsUpdate)) {
142
					continue;
143
				}
144
145
				// Else we are ready to shift from oldID to newID
146
				$oldSector = SmrSector::getSector($gameID, $oldID);
147
				$SQL = 'SET sector_id = ' . $db->escapeNumber($newID) . ' WHERE ' . $oldSector->getSQL();
148
149
				if ($oldSector->hasPlanet()) {
150
					$db->write('UPDATE planet ' . $SQL);
151
					$db->write('UPDATE planet_has_building ' . $SQL);
152
					$db->write('UPDATE planet_has_cargo ' . $SQL);
153
					$db->write('UPDATE planet_has_weapon ' . $SQL);
154
				}
155
156
				if ($oldSector->hasPort()) {
157
					$db->write('UPDATE port ' . $SQL);
158
					$db->write('UPDATE port_has_goods ' . $SQL);
159
				}
160
161
				if ($oldSector->hasLocation()) {
162
					$db->write('UPDATE location ' . $SQL);
163
				}
164
165
				$db->write('UPDATE sector ' . $SQL);
166
				unset($needsUpdate[$newID]);
167
			}
168
		}
169
170
		// Clear all the caches, since they are associated with the old IDs.
171
		// NOTE: We can't re-initialize the cache here because the sectors
172
		// still have the wrong galaxy ID at this point.
173
		SmrSector::clearCache();
174
		SmrPort::clearCache();
175
		SmrPlanet::clearCache();
176
		SmrLocation::clearCache();
177
178
		// Create any new sectors that need to be made
179
		foreach ($sectorMap as $newID => $oldID) {
180
			if ($oldID === false) {
181
				SmrSector::createSector($gameID, $newID);
182
			}
183
		}
184
185
		// Finally, modify sector properties (galaxy ID, links, and warps)
186
		foreach ($sectorMap as $newID => $oldID) {
187
			$newSector = SmrSector::getSector($gameID, $newID);
188
189
			// Update the galaxy ID
190
			// NOTE: this must be done before SmrGalaxy::getSectors is called
191
			foreach ($galaxies as $galaxy) {
192
				if ($galaxy->contains($newID)) {
193
					$newSector->setGalaxyID($galaxy->getGalaxyID());
194
				}
195
			}
196
197
			// Update the sector connections
198
			foreach (['Up', 'Down', 'Left', 'Right'] as $dir) {
199
				if ($oldID === false) {
200
					// No sector walls for newly added sectors
201
					$newSector->enableLink($dir);
202
				} else {
203
					// Toggle links twice to reset them (since this internally handles
204
					// the calculation of the neighboring sector IDs).
205
					$newSector->toggleLink($dir);
206
					$newSector->toggleLink($dir);
207
				}
208
			}
209
210
			// Update the warp
211
			if ($oldID !== false && isset($oldWarps[$oldID])) {
212
				$oldWarpID = $oldWarps[$oldID];
213
				$newWarpID = array_search($oldWarpID, $sectorMap);
214
				$newSector->setWarp(SmrSector::getSector($gameID, $newWarpID));
0 ignored issues
show
Bug introduced by
It seems like $newWarpID can also be of type string; however, parameter $sectorID of SmrSector::getSector() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

214
				$newSector->setWarp(SmrSector::getSector($gameID, /** @scrutinizer ignore-type */ $newWarpID));
Loading history...
215
			}
216
		}
217
218
		SmrGalaxy::saveGalaxies();
219
		SmrSector::saveSectors();
220
221
		$message = '<span class="green">SUCCESS: </span>Edited galaxies (sizes have changed).';
222
		$container = new EditGalaxy($this->gameID, $this->galaxyID, $message);
223
		$container->go();
224
	}
225
226
}
227