Passed
Push — master ( 37b412...8220b9 )
by Gabor
03:10
created

AbstractStorage::getEntitySetFromDataSet()   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 31
    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 31
        $this->connector = clone $connector;
49 31
        $this->dataEntityPrototype = $dataEntityPrototype;
50 31
        $this->init();
51 31
    }
52
53
    /**
54
     * Special initialization method. The constructor MUST call it.
55
     *
56
     * @return StorageInterface
57
     */
58 31
    public function init() : StorageInterface
59
    {
60
        // They always walk in pair.
61 31
        if (!empty($this->dataGroup) && !empty($this->idKey)) {
62 28
            $this->connector->setDataGroup($this->dataGroup);
63 28
            $this->connector->setIdKey($this->idKey);
64
65 28
            $this->initialized = true;
66
        }
67
68 31
        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 28
    public function getConnector() : ConnectorInterface
87
    {
88 28
        return $this->connector;
89
    }
90
91
    /**
92
     * Creates an empty entity. Should be use by getters.
93
     *
94
     * @return DataEntityInterface
95
     */
96 28
    public function createEntity() : DataEntityInterface
97
    {
98 28
        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
        $entityList = $this->getDataEntitySet($expression, [ConnectorInterface::OPTION_LIMIT => 1]);
144
145 13
        if (!empty($entityList)) {
146 13
            $entity = $entityList[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 array $options
157
     * @return DataEntityInterface[]
158
     */
159 20
    protected function getDataEntitySet(array $expression, array $options = []) : array
160
    {
161 20
        $dataList = $this->getConnector()->getDataSet($expression, $options);
162
163 20
        return $this->getEntitySetFromDataSet($dataList);
164
    }
165
166
    /**
167
     * Gets entity list from data storage set.
168
     *
169
     * @param array $dataList
170
     * @return DataEntityInterface[]
171
     */
172 20
    protected function getEntitySetFromDataSet(array $dataList) : array
173
    {
174 20
        $entityList = [];
175
176 20
        foreach ($dataList as $entityData) {
177
            /** @var DataEntityInterface $entity */
178 20
            $entity = $this->createEntity();
179 20
            $this->populateEntity($entity, $entityData);
180 20
            $entityList[] = $entity;
181
        }
182
183 20
        return $entityList;
184
    }
185
186
    /**
187
     * Get data from an entity.
188
     *
189
     * @param DataEntityInterface $dataEntity
190
     * @return array
191
     */
192
    abstract protected function getEntityData(DataEntityInterface $dataEntity) : array;
193
194
    /**
195
     * Populates an entity with storage data.
196
     *
197
     * @param DataEntityInterface $dataEntity
198
     * @param array               $data
199
     * @return void
200
     */
201
    abstract protected function populateEntity(DataEntityInterface&$dataEntity, array $data) : void;
202
}
203