Passed
Pull Request — master (#3)
by De Cramer
07:09
created

RuleTransformOperation::getColumnPossibleValues()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 27
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 14
nc 4
nop 4
dl 0
loc 27
rs 9.7998
c 0
b 0
f 0
ccs 7
cts 7
cp 1
crap 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Oliverde8\Component\PhpEtl\ChainOperation\Transformer;
6
7
use oliverde8\AssociativeArraySimplified\AssociativeArray;
8
use Oliverde8\Component\PhpEtl\ChainOperation\AbstractChainOperation;
9
use Oliverde8\Component\PhpEtl\ChainOperation\DataChainOperationInterface;
10
use Oliverde8\Component\PhpEtl\Item\DataItem;
11
use Oliverde8\Component\PhpEtl\Item\DataItemInterface;
12
use Oliverde8\Component\PhpEtl\Item\ItemInterface;
13
use Oliverde8\Component\PhpEtl\Model\ExecutionContext;
14
use Oliverde8\Component\RuleEngine\RuleApplier;
15
16
/**
17
 * Class RuleTransformOperation
18
 *
19
 * @author    de Cramer Oliver<[email protected]>
20
 * @copyright 2018 Oliverde8
21
 * @package Oliverde8\Component\PhpEtl\ChainOperation\Transformer
22
 */
23
class RuleTransformOperation extends AbstractChainOperation implements DataChainOperationInterface
24
{
25
    const VARIABLE_MATCH_REGEX = '/{(?<variables>[^{}]+)}/';
26
27
    /** @var string[] */
28
    protected array $parsedColumns = [];
29
30
    /** @var RuleApplier */
31
    protected RuleApplier $ruleApplier;
32
33
    /** @var array */
34
    protected array $rules;
35
36
    /** @var boolean */
37
    protected bool $add;
38
39
    public function __construct(RuleApplier $ruleApplier, array $rules, bool $add)
40
    {
41
        $this->ruleApplier = $ruleApplier;
42
        $this->rules = $rules;
43 5
        $this->add = $add;
44
    }
45 5
46 5
    public function processData(DataItemInterface $item, ExecutionContext $context): DataItemInterface
47 5
    {
48 5
        $data = $item->getData();
49
        $newData = [];
50
51
        // We add data and don't send new data.
52
        if ($this->add) {
53
            $newData = $data;
54
        }
55
56
        foreach ($this->rules as $column => $rule) {
57
            // Add context to the data.
58 5
            $data['@context'] = array_merge($context->getParameters(), $rule['context'] ?? []);
59
//            var_dump($data);
60 5
61 5
            $columnsValues = $this->resolveColumnVariables((string) $column, $data, $newData);
62
            $possibleColumns = [];
63
            $this->getColumnPossibleValues($column, $columnsValues, [], $possibleColumns);
64 5
65 1
            foreach ($possibleColumns as $column => $values) {
0 ignored issues
show
Comprehensibility Bug introduced by
$column is overwriting a variable from outer foreach loop.
Loading history...
66
                $data['@column'] = $values;
67
                AssociativeArray::setFromKey($newData, $column, $this->ruleApplier->apply($data, $newData, $rule['rules'], []));
68 5
            }
69
        }
70 5
71
        return new DataItem($newData);
72 5
    }
73 5
74 5
    protected function resolveColumnVariables(string $columnString, array $data, array $newData): array
75
    {
76 5
        $variables = $this->getColumnVariables($columnString);
77 5
        $variableValues = [];
78 5
79
        foreach ($variables as $variable) {
80
            $data['@new'] = $newData;
81
            $variableValues[] = ['variable' => $variable,  'value' => AssociativeArray::getFromKey($data, $variable, "")];
82 5
        }
83
84
        return $variableValues;
85
    }
86
87
    protected function getColumnPossibleValues(
88
        string $columnString,
89
        array $variableValues,
90
        array $preparedValues,
91
        array &$valueCombinations
92
    ): void {
93
        if (empty($variableValues)) {
94 5
            $key = $this->getColumnName($columnString, $preparedValues);
95
            $valueCombinations[$key] = $preparedValues;
96 5
            return;
97 5
        }
98
99 5
        // Shift elements in array.
100 3
        $firsVariable = reset($variableValues);
101 3
        array_shift($variableValues);
102
103
        // Handle possible multi values.
104 5
        if (is_array($firsVariable['value'])) {
105
            foreach ($firsVariable['value'] as $value) {
106
                $currentPreparedValues = $preparedValues;
107
                $currentPreparedValues[$firsVariable['variable']] = $value;
108
109
                $this->getColumnPossibleValues($columnString, $variableValues, $currentPreparedValues, $valueCombinations);
110
            }
111
        } else {
112
            $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...
113
            $this->getColumnPossibleValues($columnString, $variableValues, $currentPreparedValues, $valueCombinations);
114
        }
115 5
    }
116
117 5
    protected function getColumnName(string $columnString, array $values): string
118 5
    {
119 5
        $variables = [];
120 5
        $varValues = [];
121
122
        foreach ($values as $variableName => $value) {
123
            $variables[] = '{' . $variableName . '}';
124 3
            $varValues[] = $value;
125 3
        }
126
127
        return str_replace($variables, $varValues, $columnString);
128 3
    }
129 2
130 2
    /**
131 2
     * Get variables in a column.
132
     */
133 2
    protected function getColumnVariables(string $columnsString): array
134
    {
135
        if (!isset($this->parsedColumns[$columnsString])) {
136 1
            $matches = [];
137 1
            preg_match_all(self::VARIABLE_MATCH_REGEX, $columnsString, $matches);
138
139 3
            if (isset($matches['variables'])) {
140
                $this->parsedColumns[$columnsString] = $matches['variables'];
141
            } else {
142
                $this->parsedColumns[$columnsString] = [];
143
            }
144
        }
145
146
        return $this->parsedColumns[$columnsString];
147
    }
148
}