Passed
Push — master ( 4b954d...b01812 )
by Gabor
03:38
created

AbstractDataStorage::saveEntity()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 25
ccs 16
cts 16
cp 1
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 14
nc 3
nop 1
crap 4
1
<?php
2
/**
3
 * WebHemi.
4
 *
5
 * PHP version 5.6
6
 *
7
 * @copyright 2012 - 2016 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
namespace WebHemi\Data\Storage;
13
14
use InvalidArgumentException;
15
use WebHemi\Adapter\Data\DataAdapterInterface;
16
use WebHemi\Data\Entity\DataEntityInterface;
17
18
/**
19
 * Class AbstractDataStorage.
20
 * Suppose to hide DataAdapter and DataEntity instances from children Storage objects.
21
 */
22
abstract class AbstractDataStorage implements DataStorageInterface
23
{
24
    /** @var DataAdapterInterface */
25
    private $defaultAdapter;
26
    /** @var DataEntityInterface */
27
    private $entityPrototype;
28
    /** @var string */
29
    protected $dataGroup;
30
    /** @var string */
31
    protected $idKey;
32
    /** @var bool */
33
    protected $initialized = false;
34
35
    /**
36
     * AbstractDataStorage constructor. The DataEntity SHOULD not be used directly unless it is required to represent
37
     * the same instance all the time.
38
     *
39
     * @param DataAdapterInterface $defaultAdapter
40
     * @param DataEntityInterface  $entityPrototype
41
     */
42 25
    final public function __construct(DataAdapterInterface $defaultAdapter, DataEntityInterface $entityPrototype)
43
    {
44
        // Every Storage object MUST have unique adapter instance to avoid override private properties like "dataGroup"
45 25
        $this->defaultAdapter = clone $defaultAdapter;
46 25
        $this->entityPrototype = $entityPrototype;
47 25
        $this->init();
48 25
    }
49
50
    /**
51
     * Special initialization method. The constructor MUST call it.
52
     *
53
     * @return DataStorageInterface
54
     */
55 25
    public function init()
56
    {
57
        // They always walk in pair.
58 25
        if (!empty($this->dataGroup) && !empty($this->idKey)) {
59 22
            $this->defaultAdapter->setDataGroup($this->dataGroup);
60 22
            $this->defaultAdapter->setIdKey($this->idKey);
61
62 22
            $this->initialized = true;
63 22
        }
64
65 25
        return $this;
66
    }
67
68
    /**
69
     * Checks if the storage is initialized.
70
     *
71
     * @return bool
72
     */
73 7
    final public function initialized()
74
    {
75 7
        return $this->initialized;
76
    }
77
78
    /**
79
     * Returns the DataAdapter instance.
80
     *
81
     * @return DataAdapterInterface
82
     */
83 22
    final public function getDataAdapter()
84
    {
85 22
        return $this->defaultAdapter;
86
    }
87
88
    /**
89
     * Creates an empty entity. Should be use by getters.
90
     *
91
     * @return DataEntityInterface
92
     */
93 22
    final public function createEntity()
94
    {
95 22
        return clone $this->entityPrototype;
96
    }
97
98
    /**
99
     * Saves data.
100
     *
101
     * @param DataEntityInterface &$entity
102
     * @return mixed The ID of the saved entity in the storage
103
     */
104 1
    public function saveEntity(DataEntityInterface &$entity)
105
    {
106 1
        $entityClass = get_class($entity);
107 1
        $storageEntityClass = get_class($this->entityPrototype);
108
109 1
        if ($entityClass != $storageEntityClass) {
110 1
            throw new InvalidArgumentException(
111 1
                sprintf(
112 1
                    'Cannot use %s with this data storage class. You must use %s.',
113 1
                    $entityClass,
114
                    $storageEntityClass
115 1
                )
116 1
            );
117
        }
118
119 1
        $dataId = $this->getDataAdapter()->saveData($entity->getKeyData(), $this->getEntityData($entity));
120
121
        // If key data is empty, then it was an insert. Get a new entity with all data.
122 1
        if ($dataId && empty($entity->getKeyData())) {
123 1
            $entityData = $this->getDataAdapter()->getData($dataId);
124 1
            $this->populateEntity($entity, $entityData);
125 1
        }
126
127 1
        return $dataId;
128
    }
129
130
    /**
131
     * Get data from an entity.
132
     *
133
     * @param DataEntityInterface $entity
134
     * @return array
135
     */
136
    abstract protected function getEntityData(DataEntityInterface $entity);
137
138
    /**
139
     * Populates an entity with storage data.
140
     *
141
     * @param DataEntityInterface $entity
142
     * @param array               $data
143
     */
144
    abstract protected function populateEntity(DataEntityInterface &$entity, array $data);
145
}
146