Passed
Push — master ( 411ad7...cc8d44 )
by Tomáš
03:33
created

Importer::createGroups()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 11
nc 5
nop 2
dl 0
loc 19
ccs 12
cts 12
cp 1
crap 4
rs 9.9
c 1
b 0
f 0
1
<?php
2
3
4
namespace TournamentGenerator\Import;
5
6
use Exception;
7
use JsonException;
8
use TournamentGenerator\Base;
9
use TournamentGenerator\Category;
10
use TournamentGenerator\Group;
11
use TournamentGenerator\Interfaces\WithGames;
12
use TournamentGenerator\Interfaces\WithSkipSetters;
13
use TournamentGenerator\Round;
14
use TournamentGenerator\Team;
15
use TournamentGenerator\TeamFilter;
16
use TournamentGenerator\Tournament;
17
18
/**
19
 * Basic importer
20
 *
21
 * Importer uses exported data and creates a new tournament objects from it.
22
 *
23
 * @package TournamentGenerator\Import
24
 * @author  Tomáš Vojík <[email protected]>
25
 * @since   0.5
26
 */
27
class Importer
28
{
29
	/** @var array List of $categoryId => $parent */
30
	protected static array $categories = [];
31
	/** @var array List of $roundId => $parent */
32
	protected static array $rounds = [];
33
	/** @var array List of $groupId => $parent */
34
	protected static array $groups = [];
35
	/** @var array List of $teamId => $parent */
36
	protected static array $teams = [];
37
	/** @var array List of $gameId => $parent */
38
	protected static array $games = [];
39
40
	/** @var Base|null $root Root object - returned from import */
41
	protected static ?Base $root = null;
42
43
	/**
44
	 * Processes a JSON input and creates necessary objects from it
45
	 *
46
	 * @param string $data
47
	 *
48
	 * @return Base
49
	 * @throws JsonException
50
	 * @throws InvalidImportDataException
51
	 * @see Importer::import()
52
	 *
53
	 */
54 33
	public static function importJson(string $data) : ?Base {
55 33
		return self::import(json_decode($data, true, 512, JSON_THROW_ON_ERROR));
0 ignored issues
show
Bug introduced by
Are you sure the usage of self::import(json_decode...t\JSON_THROW_ON_ERROR)) targeting TournamentGenerator\Import\Importer::import() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
56
	}
57
58
	/**
59
	 * Processes an input array of data and creates necessary objects from it
60
	 *
61
	 * @param array $data
62
	 *
63
	 * @return Base Imported root object or null if nothing was created
64
	 *
65
	 * @throws InvalidImportDataException
66
	 * @throws Exception
67
	 */
68 33
	public static function import(array $data) : ?Base {
69
		// Validate data
70 33
		ImportValidator::validate($data);
71
72
		// Groups for parent logging
73
		// This allows setting a parent to other objects. The latest parent in hierarchy.
74 33
		self::$categories = [];
75 33
		self::$rounds = [];
76 33
		self::$groups = [];
77 33
		self::$teams = [];
78 33
		self::$games = [];
79
80
		// Reset root
81 33
		self::$root = null;
82
83
		// Helper array - $id => $object reference
84 33
		$allGroups = [];
85 33
		$allTeams = [];
86
87
		// Try setting up the tournament object
88 33
		self::createTournament((array) ($data['tournament'] ?? []));
89
90
		// Try setting up all category objects
91 33
		self::createCategories($data['categories'] ?? []);
92
93
		// Try setting up all round objects
94 33
		self::createRounds($data['rounds'] ?? []);
95
96
		// Try setting up all group objects
97 33
		self::createGroups($data['groups'] ?? [], $allGroups);
98
99
		// Try setting up all progression objects
100 33
		self::createProgressions($data['progressions'] ?? [], $allGroups);
101
102
		// Try setting up all team objects
103 33
		self::createTeams($data['teams'] ?? [], $allTeams);
104
105
		// Try setting up all game objects
106 33
		self::createGames($data['games'] ?? [], $allTeams);
107
108 33
		return self::$root;
109
	}
110
111
	/**
112
	 * Creates a tournament object
113
	 *
114
	 * @param array $setting
115
	 */
116 33
	protected static function createTournament(array $setting) : void {
117 33
		if (!empty($setting)) {
118
			// Check tournament type (can be a preset)
119 12
			if (empty($setting['type']) || $setting['type'] === 'general') {
120 9
				$tournament = new Tournament();
121
			}
122
			else {
123 3
				$tournament = new $setting['type'];
124
			}
125 12
			self::$root = $tournament; // If set - Tournament is always root
126
127 12
			self::setTournament($tournament, $setting);
128 12
			self::logAllIds($setting, $tournament);
129
		}
130 33
	}
131
132
	/**
133
	 * Setup a tournament with all its settings
134
	 *
135
	 * @param Tournament $tournament
136
	 * @param array      $setting
137
	 */
138 12
	protected static function setTournament(Tournament $tournament, array $setting) : void {
139 12
		foreach ($setting as $key => $value) {
140 12
			switch ($key) {
141 12
				case 'name':
142 12
					$tournament->setName($value);
143 12
					break;
144 12
				case 'skip':
145 8
					$tournament->setSkip($value);
146 8
					break;
147 12
				case 'timing':
148 8
					self::setTiming($tournament, (array) $value);
149 8
					break;
150
			}
151
		}
152 12
	}
153
154
	/**
155
	 * Set timing setting to a tournament object
156
	 *
157
	 * @param Tournament $object
158
	 * @param array      $setting
159
	 */
160 8
	protected static function setTiming(Tournament $object, array $setting) : void {
161 8
		foreach ($setting as $key2 => $value2) {
162 8
			switch ($key2) {
163 8
				case 'play':
164 8
					$object->setPlay($value2);
165 8
					break;
166 7
				case 'gameWait':
167 7
					$object->setGameWait($value2);
168 7
					break;
169 7
				case 'categoryWait':
170 7
					$object->setCategoryWait($value2);
171 7
					break;
172 7
				case 'roundWait':
173 7
					$object->setRoundWait($value2);
174 7
					break;
175
			}
176
		}
177 8
	}
178
179
	/**
180
	 * Log all set ids and objects into helper arrays
181
	 *
182
	 * Adds an $id => $object pair for each id and group. Sets an game autoincrement value to the lowest possible game id if the object is root.
183
	 *
184
	 * @param array $setting Object's settings
185
	 * @param Base  $object  Object that is logged
186
	 *
187
	 * @see Importer::addIds()
188
	 */
189 30
	protected static function logAllIds(array $setting, Base $object) : void {
190 30
		self::addIds(self::$categories, $object, $setting['categories'] ?? []);
191 30
		self::addIds(self::$rounds, $object, $setting['rounds'] ?? []);
192 30
		self::addIds(self::$groups, $object, $setting['groups'] ?? []);
193 30
		self::addIds(self::$teams, $object, $setting['teams'] ?? []);
194 30
		self::addIds(self::$games, $object, $setting['games'] ?? []);
195
		/** @noinspection NotOptimalIfConditionsInspection */
196 30
		if (self::$root === $object && isset($setting['games']) && $object instanceof WithGames) {
197 5
			$object->getGameContainer()->setAutoIncrement(min($setting['games']));
198
		}
199 30
	}
200
201
	/**
202
	 * Log an object as parent to other object
203
	 *
204
	 * Adds an $id => $object pairs for each id into $group.
205
	 *
206
	 * @param array $group  Group to log the object into
207
	 * @param Base  $object Object to log
208
	 * @param array $ids    List of child object ids
209
	 */
210 30
	protected static function addIds(array &$group, Base $object, array $ids) : void {
211 30
		foreach ($ids as $id) {
212 12
			$group[$id] = $object;
213
		}
214 30
	}
215
216
	/**
217
	 * Create category objects
218
	 *
219
	 * @param array $categories
220
	 */
221 33
	protected static function createCategories(array $categories) : void {
222 33
		foreach ($categories as $setting) {
223
			// Typecast settings
224 11
			$setting = (array) $setting;
225 11
			$category = new Category($setting['name'] ?? '', $setting['id'] ?? null);
226
227 11
			if (!isset(self::$root)) {
228 6
				self::$root = $category;
229
			}
230
231 11
			self::setSkip($category, $setting);
232
233
			// Set parent if exists
234 11
			if (isset(self::$categories[$setting['id'] ?? $category->getId()])) {
235 5
				self::$categories[$setting['id'] ?? $category->getId()]->addCategory($category);
236
			}
237
238 11
			self::logAllIds($setting, $category);
239
		}
240 33
	}
241
242
	/**
243
	 * Set skip setting to an object
244
	 *
245
	 * @param WithSkipSetters $category
246
	 * @param array           $setting
247
	 */
248 24
	protected static function setSkip(WithSkipSetters $category, array $setting) : void {
249 24
		if (isset($setting['skip'])) {
250 21
			$category->setSkip($setting['skip']);
251
		}
252 24
	}
253
254
	/**
255
	 * Create round objects
256
	 *
257
	 * @param array $rounds
258
	 */
259 33
	protected static function createRounds(array $rounds) : void {
260 33
		foreach ($rounds as $setting) {
261
			// Typecast settings
262 13
			$setting = (array) $setting;
263 13
			$round = new Round($setting['name'] ?? '', $setting['id'] ?? null);
264
265 13
			if (!isset(self::$root)) {
266 6
				self::$root = $round;
267
			}
268
269 13
			self::setSkip($round, $setting);
270
271
			// Set parent if exists
272 13
			if (isset(self::$rounds[$setting['id'] ?? $round->getId()])) {
273 7
				self::$rounds[$setting['id'] ?? $round->getId()]->addRound($round);
274
			}
275 13
			self::logAllIds($setting, $round);
276
		}
277 33
	}
278
279
	/**
280
	 * Create group objects
281
	 *
282
	 * @param array $groups
283
	 * @param array $allGroups
284
	 *
285
	 * @throws Exception
286
	 */
287 33
	protected static function createGroups(array $groups, array &$allGroups) : void {
288 33
		foreach ($groups as $setting) {
289
			// Typecast settings
290 13
			$setting = (array) $setting;
291 13
			$group = new Group($setting['name'] ?? '', $setting['id'] ?? null);
292 13
			$allGroups[$group->getId()] = $group;
293
294 13
			if (!isset(self::$root)) {
295 6
				self::$root = $group;
296
			}
297
298 13
			self::setSkip($group, $setting);
299 13
			self::setGroup($group, $setting);
300
301
			// Set parent if exists
302 13
			if (isset(self::$groups[$setting['id'] ?? $group->getId()])) {
303 7
				self::$groups[$setting['id'] ?? $group->getId()]->addGroup($group);
304
			}
305 13
			self::logAllIds($setting, $group);
306
		}
307 33
	}
308
309
	/**
310
	 * Setup a group with all its settings
311
	 *
312
	 * @param Group $group
313
	 * @param array $setting
314
	 *
315
	 * @throws Exception
316
	 */
317 13
	protected static function setGroup(Group $group, array $setting) : void {
318 13
		foreach ($setting as $key => $value) {
319 13
			switch ($key) {
320 13
				case 'type':
321 13
					$group->setType($value);
322 13
					break;
323 13
				case 'points':
324 13
					self::setPoints($group, (array) $value);
325 13
					break;
326 13
				case 'inGame':
327 13
					$group->setInGame($value);
328 13
					break;
329 13
				case 'maxSize':
330 13
					$group->setMaxSize($value);
331 13
					break;
332
			}
333
		}
334 13
	}
335
336
	/**
337
	 * Set points setting to an object
338
	 *
339
	 * @param Group $object
340
	 * @param array $setting
341
	 */
342 13
	protected static function setPoints(Group $object, array $setting) : void {
343 13
		foreach ($setting as $key2 => $value2) {
344 13
			switch ($key2) {
345 13
				case 'win':
346 13
					$object->setWinPoints($value2);
347 13
					break;
348 13
				case 'loss':
349 13
					$object->setLostPoints($value2);
350 13
					break;
351 13
				case 'draw':
352 13
					$object->setDrawPoints($value2);
353 13
					break;
354 13
				case 'second':
355 13
					$object->setSecondPoints($value2);
356 13
					break;
357 13
				case 'third':
358 13
					$object->setThirdPoints($value2);
359 13
					break;
360 13
				case 'progression':
361 13
					$object->setProgressPoints($value2);
362 13
					break;
363
			}
364
		}
365 13
	}
366
367
	/**
368
	 * Create all progressions
369
	 *
370
	 * @param array $progressions
371
	 * @param array $allGroups
372
	 */
373 33
	protected static function createProgressions(array $progressions, array $allGroups) : void {
374 33
		foreach ($progressions as $setting) {
375
			// Typecast settings
376
			$setting = (array) $setting;
377
378
			if (isset($setting['from'], $setting['to'], $allGroups[$setting['from']], $allGroups[$setting['to']])) {
379
				$progression = $allGroups[$setting['from']]->progression($allGroups[$setting['to']], $setting['offset'] ?? 0, $setting['length'] ?? null);
380
381
				// Setup filters
382
				foreach ($setting['filters'] ?? [] as $filterSetting) {
383
					// Typecast settings
384
					$filterSetting = (array) $filterSetting;
385
386
					self::$groups = array_map(static function($groupId) use ($allGroups) {
387
						return $allGroups[$groupId] ?? null;
388
					}, $filterSetting['groups'] ?? []);
389
390
					$filter = new TeamFilter($filterSetting['what'] ?? 'points', $filterSetting['how'] ?? '>', $filterSetting['val'] ?? 0, self::$groups);
391
					$progression->addFilter($filter);
392
				}
393
394
				if (isset($setting['progressed'])) {
395
					$progression->setProgressed($setting['progressed']);
396
				}
397
			}
398
		}
399 33
	}
400
401
	/**
402
	 * Create all team objects
403
	 *
404
	 * @param array $teams
405
	 * @param array $allTeams
406
	 */
407 33
	protected static function createTeams(array $teams, array &$allTeams) : void {
408 33
		foreach ($teams as $setting) {
409
			// Typecast settings
410 10
			$setting = (array) $setting;
411 10
			$team = new Team($setting['name'] ?? '', $setting['id'] ?? null);
412 10
			$allTeams[$team->getId()] = $team;
413
414 10
			if (!isset(self::$root)) {
415 3
				self::$root = $team;
416
			}
417
418
			// Set parent if exists
419 10
			if (isset(self::$teams[$setting['id'] ?? $team->getId()])) {
420 7
				self::$teams[$setting['id'] ?? $team->getId()]->addTeam($team);
421
			}
422
		}
423 33
	}
424
425
	/**
426
	 * Create all game objects
427
	 *
428
	 * @param       $games
429
	 * @param array $allTeams
430
	 */
431 33
	protected static function createGames($games, array $allTeams) : void {
432 33
		foreach ($games as $setting) {
433
			// Typecast settings
434 5
			$setting = (array) $setting;
435
436 5
			$gameTeams = array_map(static function($teamId) use ($allTeams) {
437 5
				return $allTeams[$teamId] ?? null;
438 5
			}, $setting['teams'] ?? []);
439
440
			// Check if parent group exists
441 5
			if (isset($setting['id'], self::$games[$setting['id']])) {
442
443 5
				$game = self::$games[$setting['id']]->game($gameTeams);
444
445
				// Set results
446 5
				if (isset($setting['scores'])) {
447 1
					$scores = array_map(static function($info) {
448 1
						return ((array) $info)['score'] ?? 0;
449 1
					}, $setting['scores']);
450 1
					$game->setResults($scores);
451
				}
452
453
			}
454
		}
455 33
	}
456
457
}