Test Failed
Push — trunk ( 0d5d14...30e273 )
by SuperNova.WS
11:46
created

RecordV2::replaceFromFieldArray()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 0
loc 8
rs 10
c 1
b 0
f 0
1
<?php
2
/**
3
 * Created by Gorlum 13.11.2018 14:07
4
 */
5
6
namespace DBAL;
7
8
9
use Common\AccessLoggedTranslatedV2;
10
use Core\GlobalContainer;
11
use Exception;
12
use SN;
13
14
/**
15
 * RecordV2 interface for access Storage data
16
 *
17
 * Classes starting from this one and above inheritance tree made for translation DB field names to properties with all bells and whistles
18
 *
19
 * Class itself represents single table where derived object represents single record
20
 * Object  handles insert/delete/update with single ::save() function based on it's internal state
21
 *
22
 *
23
 * @property int|string $id
24
 *
25
 * @package DBAL
26
 */
27
class RecordV2 extends AccessLoggedTranslatedV2 {
28
  const _INDEX_FIELD = 'id';
29
  const _PREFIX1 = 'Record';
30
  const _PREFIX2 = 'RecordV2';
31
32
  /**
33
   * @var StorageSqlV2|null $storage
34
   */
35
  // TODO - replace with IStorage
36
  protected static $storage = null;
37
38
  protected static $_tableName = '';
39
  protected static $_indexField = self::_INDEX_FIELD;
40
41
42
  protected $isNew = true;
43
  protected $toDelete = false;
44
  protected $deleted = false;
45
46
  public static function tableName() {
47
    if (empty(static::$_tableName)) {
48
      if (strpos(static::class, self::_PREFIX1) !== 0) {
49
        static::$_tableName = substr(static::class, strlen(self::_PREFIX1));
50
      } elseif (strpos(static::class, self::_PREFIX2) !== 0) {
51
        static::$_tableName = substr(static::class, strlen(self::_PREFIX2));
52
      } else {
53
        static::$_tableName = static::class;
54
      }
55
    }
56
57
    return static::$_tableName;
58
  }
59
60
  public static function indexField() {
61
    return static::$_indexField;
62
  }
63
64
  public function __construct(GlobalContainer $services = null) {
65
    parent::__construct($services);
66
67
    static::setStorage($services->storageSqlV2);
0 ignored issues
show
Bug Best Practice introduced by
The method DBAL\RecordV2::setStorage() is not static, but was called statically. ( Ignorable by Annotation )

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

67
    static::/** @scrutinizer ignore-call */ 
68
            setStorage($services->storageSqlV2);
Loading history...
68
69
    if (empty(static::$_properties)) {
70
      $fields = static::$storage->fields(static::tableName());
0 ignored issues
show
Bug introduced by
The method fields() does not exist on null. ( Ignorable by Annotation )

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

70
      /** @scrutinizer ignore-call */ 
71
      $fields = static::$storage->fields(static::tableName());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
It seems like static::tableName() can also be of type mixed; however, parameter $tableName of DBAL\StorageSqlV2::fields() does only seem to accept string, 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

70
      $fields = static::$storage->fields(/** @scrutinizer ignore-type */ static::tableName());
Loading history...
71
72
      $this->importFieldDefinitions($fields);
73
    }
74
  }
75
76
  /**
77
   * @param StorageSqlV2 $storage
78
   */
79
  public function setStorage(StorageSqlV2 $storage) {
80
    if (empty(static::$storage)) {
81
      static::$storage = $storage;
82
    }
83
  }
84
85
86
  /**
87
   * Handles saving object to storage
88
   *
89
   * @throws Exception
90
   */
91
  public function save() {
92
    if ($this->toDelete) {
93
      $this->delete();
94
    } elseif ($this->isEmpty()) {
95
      // Object is empty - no valuable info here
96
      if ($this->isNew) {
97
        /*
98
        Do nothing
99
       TODO - Exception ?
100
       Basically it's throw-out instance of class which can be forgotten
101
       May be it's was made for access to some non-static property. Or for something else - it's doesn't matters
102
       What matters that this instance shouldn't (and can't) be stored in Storage
103
        */
104
      } else {
105
        // Deleting empty object
106
        $this->delete();
107
      }
108
    } else {
109
      if ($this->isNew) {
110
        $this->insert();
111
      } else {
112
        $this->update();
113
      }
114
    }
115
  }
116
117
  protected function delete() {
118
    if (!empty($this->id)) {
119
      static::$storage->delete(
120
        static::tableName(),
121
        [static::$_properties[self::_INDEX_FIELD]->field => $this->id]
122
      );
123
    } else {
124
      $this->id = null;
125
    }
126
127
    $this->accept();
128
129
    $this->toDelete = true;
130
    $this->isNew    = true;
131
  }
132
133
  public function toFieldArray($useDefaults = false, $skipId = false) {
134
    $array = parent::toFieldArray($useDefaults);
135
    if ($skipId) {
136
      unset($array[static::$_properties[self::_INDEX_FIELD]->field]);
137
    }
138
139
    return $array;
140
  }
141
142
  /**
143
   * @return int|null|string
144
   *
145
   * @throws Exception
146
   */
147
  protected function insert() {
148
149
    // Filling absent property as default
150
    // TODO - add `mandatory` field that only them was filled with defaults
151
//    foreach (static::$_properties as $name => $description) {
152
//      if (!isset($this->$name)) {
153
//        $this->$name = static::$_defaults[$name];
154
//      }
155
//    }
156
157
    // Inserting records
158
    $fieldValues = $this->toFieldArray(false, true);
159
160
    $id = static::$storage->insert(static::tableName(), $fieldValues);
161
    if (!empty($id)) {
162
      $this->id = $id;
163
      $this->accept();
164
165
      $this->isNew = false;
166
167
      $this->findById($id);
168
    }
169
170
    return $id;
171
  }
172
173
  protected function update() {
174
    static::$storage->update(
175
      static::tableName(),
176
      [static::$_properties[self::_INDEX_FIELD]->field => $this->id],
177
      $this->changesToFields($this->_changes),
178
      $this->changesToFields($this->_deltas)
179
    );
180
181
    $this->accept();
182
183
    $this->isNew = false;
184
185
    $this->findById($this->id);
186
  }
187
188
  /**
189
   * @param int|string $id
190
   *
191
   * @return $this
192
   */
193
  public function findById($id) {
194
    $array = static::$storage->findFirst(static::tableName(), [static::$_properties[self::_INDEX_FIELD]->field => $id]);
195
196
    $this->replaceFromFieldArray($array);
197
198
    return $this;
199
  }
200
201
  protected function replaceFromFieldArray(array $array) {
202
    $this->clear();
203
    if (!empty($array)) {
204
      $this->fromFieldArray($array);
205
206
      $this->accept();
207
208
      $this->isNew = false;
209
    }
210
  }
211
212
  public function clear() {
213
    parent::clear();
214
215
    $this->isNew    = true;
216
    $this->toDelete = false;
217
  }
218
219
  public function isDeleted() {
220
    return $this->toDelete && $this->isNew;
221
  }
222
223
  /**
224
   * Record is empty if one of the mandatory field(s) is empty
225
   *
226
   * @return bool
227
   */
228
  public function isEmpty() {
229
    $isEmpty = false;
230
231
    foreach (static::$_mandatory as $name => $cork) {
232
      if (!isset($this->$name)) {
233
        $isEmpty = true;
234
        break;
235
      }
236
    }
237
238
    return $isEmpty;
239
  }
240
241
242
  public function markDelete($mark = true) {
243
    $this->toDelete = $mark;
244
  }
245
246
247
  /**
248
   * @param $promoCodeId
249
   *
250
   * @return null|static
251
   */
252
  public static function findByIdStatic($promoCodeId) {
253
    $promo = new static(SN::$gc);
254
    $promo->findById($promoCodeId);
255
256
    return $promo->isNew ? null : $promo;
257
  }
258
259
260
  /**
261
   * @param GlobalContainer $services
262
   *
263
   * @return $this[]
264
   */
265
  public static function findAllStatic(GlobalContainer $services) {
266
    $result = [];
267
268
    $iter = static::$storage->findIterator(static::tableName(), []);
269
270
    foreach ($iter as $fields) {
271
      $promo = new static($services);
272
      $promo->fromFieldArray($fields);
0 ignored issues
show
Bug introduced by
It seems like $fields can also be of type null; however, parameter $fieldArray of Common\AccessLoggedTranslatedV2::fromFieldArray() does only seem to accept array, 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

272
      $promo->fromFieldArray(/** @scrutinizer ignore-type */ $fields);
Loading history...
273
      $promo->isNew = false;
274
      $result[]     = $promo;
275
    }
276
277
    return $result;
278
  }
279
280
  /**
281
   * @return bool
282
   */
283
  public function isNew() {
284
    return $this->isNew;
285
  }
286
}
287