Completed
Push — trunk ( 76e427...0e7f64 )
by SuperNova.WS
05:41
created

RepoV2::unsetByEntity()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 6
ccs 0
cts 5
cp 0
crap 2
rs 9.4285
c 0
b 0
f 0
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) { }
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
  /**
65
   * @param string     $className
66
   * @param int|string $objectId
67
   *
68
   * @return EntityDb|null
69
   */
70
  public function get($className, $objectId) {
71
    return $this->is_set($className, $objectId) ? $this->repo[$className][$objectId] : null;
72
  }
73
74
  /**
75
   * Get entity version
76
   *
77
   * @param $className
78
   * @param $objectId
79
   *
80
   * @return int
81
   */
82
  protected function version($className, $objectId) {
83
    return !empty($version = $this->versionId[$className][$objectId]) ? $version : -1;
84
  }
85
86
  /**
87
   * Retrieve entity from repository or load it from DB (by entity's own load method)
88
   *
89
   * Supports transactions and version tracking (between transactions)
90
   *
91
   * @param string     $className - fully qualified class name
92
   * @param int|string $objectId  - entity ID
93
   *
94
   * @return EntityDb|null
95
   *
96
   * @throws Exception
97
   */
98
  public function getOrLoad($className, $objectId) {
99
    if ($this->is_set($className, $objectId)) {
100
      // If entity exists in repo - getting it
101
      $entity = $this->get($className, $objectId);
102
103
      // If in transaction and version missmatch - record should be refreshed just for a case
104
      if (sn_db_transaction_check(false) && $this->version($className, $objectId) < SN::$transaction_id) {
105
        // Entity will care by itself - should it be really reloaded or not
106
        $entity->reload();
107
      }
108
109
      if ($entity->isNew()) {
110
        $this->un_set($className, $objectId);
111
      }
112
    } else {
113
      /**
114
       * @var EntityDb $entity
115
       */
116
      $entity = new $className();
117
      $entity->dbLoadRecord($objectId);
0 ignored issues
show
Bug introduced by
It seems like $objectId can also be of type string; however, parameter $id of Core\EntityDb::dbLoadRecord() does only seem to accept integer|double, 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

117
      $entity->dbLoadRecord(/** @scrutinizer ignore-type */ $objectId);
Loading history...
118
119
      if (!$entity->isNew()) {
120
        $this->set($entity);
121
      }
122
    }
123
124
    if ($entity->isNew()) {
125
      unset($entity);
126
      $entity = null;
127
    }
128
129
    return $entity;
130
  }
131
132
  /**
133
   * @param int|string $planetId
134
   *
135
   * @return Planet|EntityDb|null
136
   *
137
   * @throws Exception
138
   */
139
  public function getPlanet($planetId) {
140
    return $this->getOrLoad(Planet::class, $planetId);
141
  }
142
143
  /**
144
   * @param int|string $fleetId
145
   *
146
   * @return Fleet|EntityDb|null
147
   *
148
   * @throws Exception
149
   */
150
  public function getFleet($fleetId) {
151
    return $this->getOrLoad(Fleet::class, $fleetId);
152
  }
153
154
155
  /**
156
   * Writes entity to repository
157
   *
158
   * Entity should not be already in registry - otherwise exception raised
159
   *
160
   * @param EntityDb $value
161
   *
162
   * @return bool
163
   * @throws Exception
164
   */
165
  public function set($value) {
166
    $className = $this->getClassStoreName(get_class($value));
167
    $objectId = $value->id;
168
169
    if (empty($value->id)) {
170
      throw new Exception("Trying to add in registry entity [" . implode(',', [$className, $objectId]) . "] with zero objectId");
171
    }
172
173
    if ($this->is_set($className, $objectId) && $this->get($className, $objectId) !== $value) {
174
      throw new Exception("Trying to overwrite entity [" . implode(',', [$className, $objectId]) . "] which already set. Unset it first!");
175
    }
176
177
    $this->repo[$className][$objectId] = $value;
178
    $this->versionId[$className][$objectId] = SN::$transaction_id;
179
180
    return true;
181
  }
182
183
184
  /**
185
   * @param string $className
186
   *
187
   * @return string
188
   */
189
  protected function getClassStoreName($className) {
190
    return !empty($this->synonyms[$className]) ? $this->synonyms[$className] : $className;
191
  }
192
193
  /**
194
   * @param string     $className
195
   * @param int|string $objectId
196
   *
197
   * @return bool
198
   */
199
  public function is_set($className, $objectId) {
200
    return is_array($this->repo[$className]) && isset($this->repo[$className][$objectId]);
201
  }
202
203
  /**
204
   * @param string     $className
205
   * @param int|string $objectId
206
   *
207
   * @return void
208
   */
209
  public function un_set($className, $objectId) {
210
    unset($this->repo[$className][$objectId]);
211
    unset($this->versionId[$className][$objectId]);
212
  }
213
214
  /**
215
   * @param EntityDb $entity
216
   *
217
   * @return void
218
   */
219
  public function unsetByEntity($entity) {
220
    $className = $this->getClassStoreName($entity);
0 ignored issues
show
Bug introduced by
$entity of type Core\EntityDb is incompatible with the type string expected by parameter $className of Core\RepoV2::getClassStoreName(). ( Ignorable by Annotation )

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

220
    $className = $this->getClassStoreName(/** @scrutinizer ignore-type */ $entity);
Loading history...
221
    $objectId = $entity->id;
222
223
    unset($this->repo[$className][$objectId]);
224
    unset($this->versionId[$className][$objectId]);
225
  }
226
227
  /**
228
   * Is container contains no data
229
   *
230
   * @return bool
231
   */
232
  public function isEmpty() {
233
    return empty($this->repo) && empty($this->versionId);
234
  }
235
236
  /**
237
   * Clears container contents
238
   */
239
  public function clear() {
240
    $this->repo = [];
241
    $this->versionId = [];
242
  }
243
244
  /**
245
   * @param array    $name - [entityClassName, objectId]
246
   * @param EntityDb $value
247
   *
248
   * @return void
249
   * @throws Exception
250
   *
251
   * @deprecated
252
   * @see RepoV2::set()
253
   */
254
  public function __set($name, $value) {
255
    throw new Exception("DEPRECATED! Method RepoV2::__set() is DEPRECATED! Use RepoV2::set() instead!");
256
  }
257
258
  /**
259
   * @param array $name - [entityClassName, objectId]
260
   *
261
   * @return void
262
   * @throws Exception
263
   * @deprecated
264
   */
265
  public function __get($name) {
266
    throw new Exception("DEPRECATED! Method RepoV2::__get() is DEPRECATED! Use RepoV2::get() instead!");
267
  }
268
269
  /**
270
   * Checks if entity with specified DB ID registered in repository
271
   *
272
   * Repository also holds entity current version (for transaction support)
273
   * Repository stores ONLY EXISTING OBJECTS - so it's not caches unsuccessful data retrieves
274
   *
275
   * @param array $name - [entityClassName, objectId]
276
   *
277
   * @return void
278
   * @throws Exception
279
   * @deprecated
280
   */
281
  public function __isset($name) {
282
    throw new Exception("DEPRECATED! Method RepoV2::__isset() is DEPRECATED! Use RepoV2::is_set() instead!");
283
  }
284
285
  /**
286
   * @param array $name - [entityClassName, objectId]
287
   *
288
   * @return void
289
   * @throws Exception
290
   * @deprecated
291
   */
292
  public function __unset($name) {
293
    throw new Exception("DEPRECATED! Method RepoV2::__unset() is DEPRECATED! Use RepoV2::un_set() instead!");
294
  }
295
296
}
297