Test Failed
Push — master ( dd2d06...7fea41 )
by Gabor
07:04
created

AbstractDataStorage::getDataEntitySet()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 0
cts 0
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 8
nc 2
nop 3
crap 6
1
<?php
2
/**
3
 * WebHemi.
4
 *
5
 * PHP version 7.1
6
 *
7
 * @copyright 2012 - 2017 Gixx-web (http://www.gixx-web.com)
8
 * @license   https://opensource.org/licenses/MIT The MIT License (MIT)
9
 *
10
 * @link      http://www.gixx-web.com
11
 */
12
declare(strict_types = 1);
13
14
namespace WebHemi\Data\Storage;
15
16
use InvalidArgumentException;
17
use WebHemi\Adapter\Data\DataAdapterInterface;
18
use WebHemi\Data\Entity\DataEntityInterface;
19
20
/**
21
 * Class AbstractDataStorage.
22
 * Suppose to hide DataAdapter and DataEntity instances from children Storage objects.
23
 */
24
abstract class AbstractDataStorage implements DataStorageInterface
25
{
26
    /** @var DataAdapterInterface */
27
    private $defaultAdapter;
28
    /** @var DataEntityInterface */
29
    private $entityPrototype;
30
    /** @var string */
31
    protected $dataGroup;
32
    /** @var string */
33
    protected $idKey;
34
    /** @var bool */
35
    protected $initialized = false;
36
37
    /**
38
     * AbstractDataStorage constructor. The DataEntity SHOULD not be used directly unless it is required to represent
39
     * the same instance all the time.
40
     *
41
     * @param DataAdapterInterface $defaultAdapter
42 27
     * @param DataEntityInterface  $entityPrototype
43
     */
44
    final public function __construct(DataAdapterInterface $defaultAdapter, DataEntityInterface $entityPrototype)
45 27
    {
46 27
        // Every Storage object MUST have unique adapter instance to avoid override private properties like "dataGroup"
47 27
        $this->defaultAdapter = clone $defaultAdapter;
48 27
        $this->entityPrototype = $entityPrototype;
49
        $this->init();
50
    }
51
52
    /**
53
     * Special initialization method. The constructor MUST call it.
54
     *
55 27
     * @return DataStorageInterface
56
     */
57
    public function init() : DataStorageInterface
58 27
    {
59 24
        // They always walk in pair.
60 24
        if (!empty($this->dataGroup) && !empty($this->idKey)) {
61
            $this->defaultAdapter->setDataGroup($this->dataGroup);
62 24
            $this->defaultAdapter->setIdKey($this->idKey);
63
64
            $this->initialized = true;
65 27
        }
66
67
        return $this;
68
    }
69
70
    /**
71
     * Checks if the storage is initialized.
72
     *
73 7
     * @return bool
74
     */
75 7
    final public function initialized() : bool
76
    {
77
        return $this->initialized;
78
    }
79
80
    /**
81
     * Returns the DataAdapter instance.
82
     *
83 24
     * @return DataAdapterInterface
84
     */
85 24
    final public function getDataAdapter() : DataAdapterInterface
86
    {
87
        return $this->defaultAdapter;
88
    }
89
90
    /**
91
     * Creates an empty entity. Should be use by getters.
92
     *
93 24
     * @return DataEntityInterface
94
     */
95 24
    final public function createEntity() : DataEntityInterface
96
    {
97
        return clone $this->entityPrototype;
98
    }
99
100
    /**
101
     * Saves data.
102
     *
103
     * @param DataEntityInterface &$entity
104 1
     * @return DataStorageInterface
105
     */
106 1
    public function saveEntity(DataEntityInterface&$entity) : DataStorageInterface
107 1
    {
108
        $entityClass = get_class($entity);
109 1
        $storageEntityClass = get_class($this->entityPrototype);
110 1
111
        if ($entityClass != $storageEntityClass) {
112 1
            throw new InvalidArgumentException(
113
                sprintf(
114
                    'Cannot use %s with this data storage class. You must use %s.',
115
                    $entityClass,
116 1
                    $storageEntityClass
117
                ),
118
                1000
119
            );
120 1
        }
121
122
        $dataId = $this->getDataAdapter()->saveData($entity->getKeyData(), $this->getEntityData($entity));
123 1
124 1
        // If key data is empty, then it was an insert. Get a new entity with all data.
125 1
        if ($dataId && empty($entity->getKeyData())) {
126
            $entityData = $this->getDataAdapter()->getData($dataId);
127
            $this->populateEntity($entity, $entityData);
128 1
        }
129
130
        return $this;
131
    }
132
133
    /**
134
     * Gets one Entity from the data adapter by expression.
135
     *
136
     * @param array $expression
137
     * @return null|DataEntityInterface
138
     */
139
    protected function getDataEntity(array $expression) : ? DataEntityInterface
140
    {
141
        $entity = null;
142
        $dataList = $this->getDataEntitySet($expression, 1);
143
144
        if (!empty($dataList)) {
145
            $entity = $dataList[0];
146
        }
147
148
        return $entity;
149
    }
150
151
    /**
152
     * Gets a set of Entities from the data adapter by expression.
153
     *
154
     * @param array $expression
155
     * @param int   $limit
156
     * @param int   $offset
157
     * @return array<DataEntityInterface>
158
     */
159
    protected function getDataEntitySet(array $expression, int $limit = PHP_INT_MAX, int $offset = 0) : array
160
    {
161
        $entityList = [];
162
        $dataList = $this->getDataAdapter()->getDataSet($expression, $limit, $offset);
163
164
        foreach ($dataList as $data) {
165
            /** @var DataEntityInterface $entity */
166
            $entity = $this->createEntity();
167
            $this->populateEntity($entity, $data);
168
            $entityList[] = $entity;
169
        }
170
171
        return $entityList;
172
    }
173
174
    /**
175
     * Get data from an entity.
176
     *
177
     * @param DataEntityInterface $entity
178
     * @return array
179
     */
180
    abstract protected function getEntityData(DataEntityInterface $entity) : array;
181
182
    /**
183
     * Populates an entity with storage data.
184
     *
185
     * @param DataEntityInterface $entity
186
     * @param array               $data
187
     * @return void
188
     */
189
    abstract protected function populateEntity(DataEntityInterface&$entity, array $data) : void;
190
}
191