Passed
Push — trunk ( 338765...433e05 )
by SuperNova.WS
04:23
created

RepoV2::getFleet()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 2
rs 10
ccs 0
cts 2
cp 0
crap 2
1
<?php
2
/**
3
 * Created by Gorlum 21.04.2018 16:13
4
 */
5
6
namespace Core;
7
8
use Common\Interfaces\IContainer;
9
use Exception;
10
use Fleet\Fleet;
11
use Planet\Planet;
12
use SN;
13
14
/**
15
 * Entity repository
16
 *
17
 * Caches Entities for further use
18
 *
19
 * Support synonyms to hold class parents along with a children
20
 * Support transactions
21
 * DOES NOT support locking
22
 *
23
 * @package Core
24
 */
25
class RepoV2 implements IContainer {
26
27
  /**
28
   * List of synonyms
29
   *
30
   * @var string[] $synonyms
31
   */
32
  protected $synonyms = [];
33
34
  /**
35
   * @var EntityDb[][] $repo
36
   */
37
  protected $repo = [];
38
39
  /**
40
   * @var int[][] $versionId
41
   */
42
  protected $versionId = [];
43
44
  /**
45
   * Core\Repository constructor.
46
   *
47
   * @param GlobalContainer $gc
48
   */
49
  public function __construct(GlobalContainer $gc) { }
0 ignored issues
show
Unused Code introduced by
The parameter $gc is not used and could be removed. ( Ignorable by Annotation )

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

49
  public function __construct(/** @scrutinizer ignore-unused */ GlobalContainer $gc) { }

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
50
51
  /**
52
   * @param string $className
53
   * @param string $synonym
54
   *
55
   * @return $this
56
   */
57
  public function addSynonym($className, $synonym) {
58
    $this->synonyms[$className] = $synonym;
59
60
    return $this;
61
  }
62
63
  /**
64
   * @param array $name - [entityClassName, dbId]
65
   *
66
   * @return EntityDb|null
67
   */
68
  public function __get($name) {
69
    return $this->__isset($name) ? $this->repo[reset($name)][end($name)] : null;
70
  }
71
72
  /**
73
   * Get entity verion
74
   *
75
   * @param array $name - [entityClassName, dbId]
76
   *
77
   * @return int
78
   */
79
  protected function version($name) {
80
    return !empty($version = $this->versionId[$this->getClassName($name)][$this->getDbId($name)]) ? $version : -1;
81
  }
82
83
  /**
84
   * Retrieve entity from repository or load it from DB (by entity's own load method)
85
   *
86
   * Supports transactions and version tracking (between transactions)
87
   *
88
   * @param array $name - [entityClassName, dbId]
89
   *
90
   * @return EntityDb|null
91
   *
92
   * @throws Exception
93
   */
94
  public function getOrLoad($name) {
95
    $className = $this->getClassName($name);
96
    $dbId = $this->getDbId($name);
97
98
    if ($this->__isset($name)) {
99
      // If entity exists in repo - getting it
100
      $entity = $this->__get($name);
101
102
      // If in transaction and version missmatch - record should be refreshed just for a case
103
      if (sn_db_transaction_check(false) && $this->version($name) < SN::$transaction_id) {
104
        // Entity will care by itself - should it be really reloaded or not
105
        $entity->reload();
106
      }
107
108
      if ($entity->isNew()) {
109
        $this->__unset($name);
110
      }
111
    } else {
112
      /**
113
       * @var EntityDb $entity
114
       */
115
      $entity = new $className();
116
      $entity->dbLoadRecord($dbId);
117
118
      if (!$entity->isNew()) {
119
        $this->__set($name, $entity);
120
      }
121
    }
122
123
    if ($entity->isNew()) {
124
      unset($entity);
125
      $entity = null;
126
    }
127
128
    return $entity;
129
  }
130
131
  /**
132
   * @param int|string $planetId
133
   *
134
   * @return Planet|EntityDb|null
135
   *
136
   * @throws Exception
137
   */
138
  public function getPlanet($planetId) {
139
    return $this->getOrLoad([Planet::class, $planetId]);
140
  }
141
142
  /**
143
   * @param int|string $fleetId
144
   *
145
   * @return Fleet|EntityDb|null
146
   *
147
   * @throws Exception
148
   */
149
  public function getFleet($fleetId) {
150
    return $this->getOrLoad([Fleet::class, $fleetId]);
151
  }
152
153
  /**
154
   * Writes entity to repository
155
   *
156
   * Entity should not be already set - otherwise exception raised
157
   *
158
   * @param array    $name - [entityClassName, dbId]
159
   * @param EntityDb $value
160
   *
161
   * @return void
162
   * @throws Exception
163
   */
164
  public function __set($name, $value) {
165
    if (!($className = $this->getClassName($name))) {
166
      throw new Exception("Mallformed name " . var_export($name, true) . " in RepoV2::__set(). ");
167
    }
168
169
    if ($this->__isset($name) && $this->__get($name) !== $value) {
170
      throw new Exception("Trying to overwrite entity [" . implode(',', $name) . "] which already set. Unset it first!");
171
    }
172
173
    $dbId = $this->getDbId($name);
174
    $this->repo[$className][$dbId] = $value;
175
    $this->versionId[$className][$dbId] = SN::$transaction_id;
176
  }
177
178
  /**
179
   * @param array $name - [entityClassName, dbId]
180
   *
181
   * @return string
182
   */
183
  protected function getClassName($name) {
184
    if (!$this->isNameValid($name)) {
185
      return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
186
    }
187
188
    $className = reset($name);
189
    if (!empty($this->synonyms[$className])) {
190
      $className = $this->synonyms[$className];
191
    }
192
193
    return $className;
194
  }
195
196
  /**
197
   * @param array $name - [entityClassName, dbId]
198
   *
199
   * @return mixed
200
   */
201
  protected function getDbId($name) {
202
    $dbId = end($name);
203
204
    return $dbId;
205
  }
206
207
  /**
208
   * @param array $name - [entityClassName, dbId]
209
   *
210
   * @return bool
211
   */
212
  protected function isNameValid($name) {
213
    return is_array($name) && count($name) == 2;
214
  }
215
216
  /**
217
   * Checks if entity with specified DB ID registered in repository
218
   *
219
   * Repository also holds entity current version (for transaction support)
220
   * Repository stores ONLY EXISTING OBJECTS - so it's not caches unsuccessful data retrieves
221
   *
222
   * @param array $name - [entityClassName, dbId]
223
   *
224
   * @return bool
225
   */
226
  public function __isset($name) {
227
    if (!($className = $this->getClassName($name))) {
228
      return false;
229
    }
230
    $dbId = $this->getDbId($name);
231
232
    return is_array($this->repo[$className]) && isset($this->repo[$className][$dbId]);
233
  }
234
235
  /**
236
   * @param array $name - [entityClassName, dbId]
237
   *
238
   * @return void
239
   */
240
  public function __unset($name) {
241
    if (!($className = $this->getClassName($name))) {
242
      return;
243
    }
244
245
    $dbId = $this->getDbId($name);
246
    unset($this->repo[$className][$dbId]);
247
    unset($this->versionId[$className][$dbId]);
248
  }
249
250
  /**
251
   * Is container contains no data
252
   *
253
   * @return bool
254
   */
255
  public function isEmpty() {
256
    return empty($this->repo) && empty($this->versionId);
257
  }
258
259
  /**
260
   * Clears container contents
261
   */
262
  public function clear() {
263
    $this->repo = [];
264
    $this->versionId = [];
265
  }
266
267
}
268