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

EntityDb::reload()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 11
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 4
c 0
b 0
f 0
nc 4
nop 0
dl 0
loc 11
rs 9.2
ccs 0
cts 6
cp 0
crap 20
1
<?php
2
/**
3
 * Created by Gorlum 08.01.2018 14:46
4
 */
5
6
namespace Core;
7
8
9
use Common\Interfaces\IContainer;
10
use \DBAL\DbQuery;
11
use \DBAL\ActiveRecord;
12
use Common\Traits\TContainer;
13
use Exception;
14
15
/**
16
 * Basic persistent entity class (lives in DB)
17
 *
18
 * Support direct ActiveRecord access
19
 * Support locked reads on transactions
20
 *
21
 * Represents in-game entity which have representation in DB (aka one or more connected ActiveRecords)
22
 *
23
 * @package Core
24
 *
25
 * @method array asArray() Extracts values as array [$propertyName => $propertyValue] (from ActiveRecord)
26
 * @method bool update() Updates DB record(s) in DB (from ActiveRecord)
27
 */
28
class EntityDb extends Entity implements IContainer {
29
  use TContainer;
30
31
  /**
32
   * @var string $_activeClass
33
   */
34
  protected $_activeClass = ''; // \\DBAL\\ActiveRecord
35
36
  /**
37
   * Name translation table
38
   *
39
   * [entityPropertyName => containerPropertyName]
40
   *
41
   * @var string[] $_containerTranslateNames
42
   */
43
  protected $_containerTranslateNames = [];
44
45
46
  /**
47
   * @var ActiveRecord $_container
48
   */
49
  protected $_container;
50
51
  protected $_isNew = true;
52
  protected $_forUpdate = DbQuery::DB_SHARED;
53
54
  /**
55
   * EntityDb constructor.
56
   */
57
  public function __construct() {
58
    if (empty($this->_activeClass)) {
59
      /** @noinspection PhpUnhandledExceptionInspection */
60
      throw new Exception("Class " . get_called_class() . " have no _activeClass property declared!");
61
    }
62
63
    $this->reset();
64
  }
65
66
  /**
67
   * @return $this
68
   */
69
  public function reset() {
70
//    unset($this->_container); // Strange thing - after this string it is not possible to set _container property again!
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
71
    $this->_container = new $this->_activeClass();
72
73
    $this->_isNew = true;
74
    $this->_forUpdate = DbQuery::DB_SHARED;
75
76
    return $this;
77
  }
78
79
  /**
80
   * Reload Entity - if possible
81
   *
82
   * If entity is write-once - this method should decide if any real I/O would be performed
83
   *
84
   * @return static
85
   *
86
   * @throws Exception
87
   */
88
  public function reload() {
89
    // TODO - immutable entities which does not need reload
90
    $dbId = !empty($this->_container) ? $this->_container->id : 0;
91
92
    // If entity is new or no DB ID supplied - throw exception
93
    if ($this->isNew() || !$dbId) {
94
      /** @noinspection PhpUnhandledExceptionInspection */
95
      throw new Exception("Can't reload empty or new Entity: isNew = '{$this->isNew()}', dbId = '{$dbId}', className = " . get_called_class());
96
    }
97
98
    return $this->dbLoadRecord($dbId);
0 ignored issues
show
Bug introduced by
It seems like $dbId 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

98
    return $this->dbLoadRecord(/** @scrutinizer ignore-type */ $dbId);
Loading history...
99
  }
100
101
102
  /**
103
   * Is entity is new
104
   *
105
   * True for newly created and deleted entities
106
   * Code should decide this from context
107
   *
108
   * @return bool
109
   */
110
  public function isNew() {
111
    return $this->_isNew;
112
  }
113
114
  /**
115
   * Load entity from DB
116
   *
117
   * This basic class supports transaction locking
118
   *
119
   * If entity is multi-tabled - this method should care about loading and arrange all necessary information
120
   * If descendant entity is lock-sensitive - this method should issue all necessary locks (including parental locks)
121
   *
122
   * @param int|float $id
123
   *
124
   * @return $this
125
   */
126
  public function dbLoadRecord($id) {
127
    $this->reset();
128
129
    if (sn_db_transaction_check(false)) {
130
      $this->setForUpdate();
131
    }
132
133
    /** @var ActiveRecord $className */
134
    $className = $this->_activeClass;
135
    $container = $className::findById($id);
136
    if (!empty($container)) {
137
      $this->_isNew = false;
138
      $this->_container = $container;
139
    }
140
141
    return $this;
142
  }
143
144
  /**
145
   * Set "for update" flag
146
   *
147
   * @param bool $forUpdate - DbQuery::DB_FOR_UPDATE | DbQuery::DB_SHARED
148
   *
149
   * @return $this
150
   */
151
  public function setForUpdate($forUpdate = DbQuery::DB_FOR_UPDATE) {
152
    /** @var ActiveRecord $className */
153
    $className = $this->_activeClass;
154
    $className::setForUpdate($forUpdate);
155
156
    return $this;
157
  }
158
159
  /**
160
   * @return bool
161
   */
162
  public function dbUpdate() {
163
    return $this->_getContainer()->update();
164
  }
165
166
  /**
167
   * @return ActiveRecord
168
   */
169
  public function _getContainer() {
170
    return $this->_container;
171
  }
172
173
  /**
174
   * Translate entity property name to container property name
175
   *
176
   * Just a little sugar to avoid renaming all and everywhere
177
   *
178
   * @param string $name
179
   *
180
   * @return string
181
   */
182
  protected function _containerTranslatePropertyName($name) {
183
    return !empty($this->_containerTranslateNames[$name]) ? $this->_containerTranslateNames[$name] : $name;
184
  }
185
186
}
187