Completed
Push — master ( f960a1...9f1a25 )
by De Cramer
02:44
created

RuleTransformOperation::getColumnVariables()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3.0175

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 3
nop 1
dl 0
loc 14
ccs 7
cts 8
cp 0.875
crap 3.0175
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Oliverde8\Component\PhpEtl\ChainOperation\Transformer;
4
5
use oliverde8\AssociativeArraySimplified\AssociativeArray;
6
use Oliverde8\Component\PhpEtl\ChainOperation\AbstractChainOperation;
7
use Oliverde8\Component\PhpEtl\ChainOperation\DataChainOperationInterface;
8
use Oliverde8\Component\PhpEtl\Item\DataItem;
9
use Oliverde8\Component\PhpEtl\Item\DataItemInterface;
10
use Oliverde8\Component\PhpEtl\Item\ItemInterface;
11
use Oliverde8\Component\RuleEngine\RuleApplier;
12
13
/**
14
 * Class RuleTransformOperation
15
 *
16
 * @author    de Cramer Oliver<[email protected]>
17
 * @copyright 2018 Oliverde8
18
 * @package Oliverde8\Component\PhpEtl\ChainOperation\Transformer
19
 */
20
class RuleTransformOperation extends AbstractChainOperation implements DataChainOperationInterface
21
{
22
    const VARIABLE_MATCH_REGEX = '/{(?<variables>[^{}]+)}/';
23
24
    /** @var string */
25
    protected $parsedColums = [];
26
27
    /** @var RuleApplier */
28
    protected $ruleApplier;
29
30
    /** @var array */
31
    protected $rules;
32
33
    /** @var boolean */
34
    protected $add;
35
36
    /**
37
     * RuleTransformOperation constructor.
38
     *
39
     * @param RuleApplier $ruleApplier
40
     * @param array $rules
41
     * @param boolean $add
42
     */
43 5
    public function __construct(RuleApplier $ruleApplier, array $rules, $add)
44
    {
45 5
        $this->ruleApplier = $ruleApplier;
46 5
        $this->rules = $rules;
47 5
        $this->add = $add;
48 5
    }
49
50
    /**
51
     * @param DataItemInterface $item
52
     * @param array $context
53
     *
54
     * @return ItemInterface
55
     * @throws \Oliverde8\Component\RuleEngine\Exceptions\RuleException
56
     * @throws \Oliverde8\Component\RuleEngine\Exceptions\UnknownRuleException
57
     */
58 5
    public function processData(DataItemInterface $item, array &$context)
59
    {
60 5
        $data = $item->getData();
61 5
        $newData = [];
62
63
        // We add data and don't send new data.
64 5
        if ($this->add) {
65 1
            $newData = $data;
66
        }
67
68 5
        foreach ($this->rules as $column => $rule) {
69
            // Add context to the data.
70 5
            $data['@context'] = array_merge($context, isset($rule['context']) ? $rule['context'] : []);
71
72 5
            $columnsValues = $this->resolveColumnVariables($column, $data, $newData);
73 5
            $possibleColumns = [];
74 5
            $this->getColumnPosssibleValues($column, $columnsValues, [], $possibleColumns);
75
76 5
            foreach ($possibleColumns as $column => $values) {
0 ignored issues
show
Comprehensibility Bug introduced by
$column is overwriting a variable from outer foreach loop.
Loading history...
77 5
                $data['@column'] = $values;
78 5
                AssociativeArray::setFromKey($newData, $column, $this->ruleApplier->apply($data, $newData, $rule['rules'], []));
79
            }
80
        }
81
82 5
        return new DataItem($newData);
83
    }
84
85
    /**
86
     * Resolve list of variables.
87
     *
88
     * @param $columnString
89
     * @param $data
90
     * @param $newData
91
     *
92
     * @return array
93
     */
94 5
    protected function resolveColumnVariables($columnString, $data, $newData)
95
    {
96 5
        $variables = $this->getColumnVariables($columnString);
97 5
        $variableValues = [];
98
99 5
        foreach ($variables as $variable) {
100 3
            $data['@new'] = $newData;
101 3
            $variableValues[] = ['variable' => $variable,  'value' => AssociativeArray::getFromKey($data, $variable, "")];
102
        }
103
104 5
        return $variableValues;
105
    }
106
107
    /**
108
     * Get all possible values for the column.
109
     *
110
     * @param $columnString
111
     * @param $variableValues
112
     * @param $preparedValues
113
     * @param $valueCombinations
114
     */
115 5
    protected function getColumnPosssibleValues($columnString, $variableValues, $preparedValues, &$valueCombinations)
116
    {
117 5
        if (empty($variableValues)) {
118 5
            $key = $this->getColumnName($columnString, $preparedValues);
119 5
            $valueCombinations[$key] = $preparedValues;
120 5
            return;
121
        }
122
123
        // Shift elements in array.
124 3
        $firsVariable = reset($variableValues);
125 3
        array_shift($variableValues);
126
127
        // Handle possible multi values.
128 3
        if (is_array($firsVariable['value'])) {
129 2
            foreach ($firsVariable['value'] as $value) {
130 2
                $currentPreparedValues = $preparedValues;
131 2
                $currentPreparedValues[$firsVariable['variable']] = $value;
132
133 2
                $this->getColumnPosssibleValues($columnString, $variableValues, $currentPreparedValues, $valueCombinations);
134
            }
135
        } else {
136 1
            $currentPreparedValues[$firsVariable['variable']] = $firsVariable['value'];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$currentPreparedValues was never initialized. Although not strictly required by PHP, it is generally a good practice to add $currentPreparedValues = array(); before regardless.
Loading history...
137 1
            $this->getColumnPosssibleValues($columnString, $variableValues, $currentPreparedValues, $valueCombinations);
138
        }
139 3
    }
140
141
    /**
142
     * Get the name final name of the column
143
     *
144
     * @param $columnString
145
     * @param $values
146
     *
147
     * @return mixed
148
     */
149 5
    protected function getColumnName($columnString, $values)
150
    {
151 5
        $variables = [];
152 5
        $varValues = [];
153
154 5
        foreach ($values as $variableName => $value) {
155 3
            $variables[] = '{' . $variableName . '}';
156 3
            $varValues[] = $value;
157
        }
158
159 5
        return str_replace($variables, $varValues, $columnString);
160
    }
161
162
    /**
163
     * Get variables in a column.
164
     *
165
     * @param $columnsString
166
     *
167
     * @return mixed
168
     */
169 5
    protected function getColumnVariables($columnsString)
170
    {
171 5
        if (!isset($this->parsedColums[$columnsString])) {
172 5
            $matches = [];
173 5
            preg_match_all(self::VARIABLE_MATCH_REGEX, $columnsString, $matches);
174
175 5
            if (isset($matches['variables'])) {
176 5
                $this->parsedColums[$columnsString] = $matches['variables'];
177
            } else {
178
                $this->parsedColums[$columnsString] = [];
179
            }
180
        }
181
182 5
        return $this->parsedColums[$columnsString];
183
    }
184
}