Passed
Push — master ( aabebd...37b412 )
by Gabor
03:36
created

AbstractStorage::getEntityListFromDataSet()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

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