Passed
Push — master ( 1c4d89...16aad8 )
by Gabor
03:50
created

AbstractDataCoupler::__construct()   B

Complexity

Conditions 5
Paths 2

Size

Total Lines 26
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 26
ccs 18
cts 18
cp 1
rs 8.439
c 0
b 0
f 0
cc 5
eloc 18
nc 2
nop 3
crap 5
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\Coupler;
13
14
use InvalidArgumentException;
15
use RuntimeException;
16
use WebHemi\Adapter\Data\DataAdapterInterface;
17
use WebHemi\Data\Entity\DataEntityInterface;
18
19
/**
20
 * Class AbstractDataCoupler.
21
 */
22
abstract class AbstractDataCoupler implements DataCouplerInterface
23
{
24
    /** @var DataAdapterInterface */
25
    private $defaultAdapter;
26
    /** @var array<DataEntityInterface> */
27
    protected $dataEntityPrototypes = [];
28
    /** @var string */
29
    protected $connectorIdKey;
30
    /** @var string */
31
    protected $connectorDataGroup;
32
    /** @var array */
33
    protected $dependentDataGroups;
34
35
    /**
36
     * AbstractDataCoupler constructor.
37
     *
38
     * @param DataAdapterInterface $defaultAdapter
39
     * @param DataEntityInterface  $dataEntityPrototypeA
40
     * @param DataEntityInterface  $dataEntityPrototypeB
41
     */
42 6
    public function __construct(
43
        DataAdapterInterface $defaultAdapter,
44
        DataEntityInterface $dataEntityPrototypeA,
45
        DataEntityInterface $dataEntityPrototypeB
46
    ) {
47 6
        $entityClassA = get_class($dataEntityPrototypeA);
48 6
        $entityClassB = get_class($dataEntityPrototypeB);
49
50 6
        if (!isset($this->dependentDataGroups[$entityClassA])
51 6
            || !isset($this->dependentDataGroups[$entityClassB])
52 6
            || (count(array_keys($this->dependentDataGroups)) == 2 && $entityClassA == $entityClassB)
53 6
        ) {
54 4
            throw new InvalidArgumentException(
55 4
                sprintf(
56 4
                    'This coupler requires data entity instances from the following classes: %s; %s and %s are given.',
57 4
                    implode(', ', array_keys($this->dependentDataGroups)),
58 4
                    $entityClassA,
59
                    $entityClassB
60 4
                )
61 4
            );
62
        }
63
64 6
        $this->defaultAdapter = $defaultAdapter;
65 6
        $this->dataEntityPrototypes[$entityClassA] = $dataEntityPrototypeA;
66 6
        $this->dataEntityPrototypes[$entityClassB] = $dataEntityPrototypeB;
67 6
    }
68
69
    /**
70
     * Returns the DataAdapter instance.
71
     *
72
     * @return DataAdapterInterface
73
     */
74 4
    public function getDataAdapter()
75
    {
76 4
        return $this->defaultAdapter;
77
    }
78
79
    /**
80
     * Gets all the entities those are depending from the given entity.
81
     *
82
     * @param DataEntityInterface $entity
83
     * @throws RuntimeException
84
     * @return array<DataEntityInterface>
85
     */
86 4
    public function getEntityDependencies(DataEntityInterface $entity)
87
    {
88 4
        $entityClass = get_class($entity);
89 4
        if (!isset($this->dataEntityPrototypes[$entityClass])) {
90 1
            throw new RuntimeException(
91 1
                sprintf('Cannot use this coupler class to find dependencies for %s.', $entityClass)
92 1
            );
93
        }
94
95 4
        $entityList = [];
96 4
        $dataList = $this->getEntityDataSet($entity);
97
98 4
        foreach ($dataList as $entityData) {
99 4
            $entityList[] = $this->getDependingEntity($entity, $entityData);
100 4
        }
101
102 4
        return $entityList;
103
    }
104
105
    /**
106
     * Gets a DataEntityInterface instance from the provided data according to the reference entity.
107
     *
108
     * @param DataEntityInterface $referenceEntity
109
     * @param array               $entityData
110
     * @return DataEntityInterface
111
     */
112
    abstract protected function getDependingEntity(DataEntityInterface $referenceEntity, array $entityData);
113
114
    /**
115
     * Returns a new instance of the required entity.
116
     *
117
     * @param string $entityClassName
118
     * @throws RuntimeException
119
     * @return DataEntityInterface
120
     */
121 5
    protected function getNewEntityInstance($entityClassName)
122
    {
123 5
        return clone $this->dataEntityPrototypes[$entityClassName];
124
    }
125
126
    /**
127
     * Gets raw depending entity data list for the given entity.
128
     *
129
     * @param DataEntityInterface $entity
130
     * @return array
131
     */
132 3
    protected function getEntityDataSet(DataEntityInterface $entity)
133
    {
134 3
        $entityClassName = get_class($entity);
135 3
        $entityDataSet = [];
136 3
        $identifiers = [];
137
138 3
        $this->getDataAdapter()->setDataGroup($this->connectorDataGroup)
139 3
            ->setIdKey($this->connectorIdKey);
140
141 3
        $dataList = $this->getDataAdapter()->getDataSet([
142 3
            $this->dependentDataGroups[$entityClassName]['source_key'].' = ?' => $entity->getKeyData()
143 3
        ]);
144 3
        foreach ($dataList as $rowData) {
145 3
            $identifiers[] = $rowData[$this->dependentDataGroups[$entityClassName]['connector_key']];
146 3
        }
147
148 3
        if (!empty($identifiers)) {
149 3
            $this->getDataAdapter()->setDataGroup($this->dependentDataGroups[$entityClassName]['depending_group'])
150 3
                ->setIdKey($this->dependentDataGroups[$entityClassName]['depending_id_key']);
151
152 3
            $entityDataSet = $this->getDataAdapter()->getDataSet([
153 3
                $this->dependentDataGroups[$entityClassName]['depending_id_key'].' IN (?)' => $identifiers
154 3
            ]);
155 3
        }
156
157 3
        return $entityDataSet;
158
    }
159
}
160