Completed
Pull Request — master (#6)
by Arnold
07:00
created

DataEnricher::applyTo()   B

Complexity

Conditions 6
Paths 16

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 2
Metric Value
c 4
b 0
f 2
dl 0
loc 22
rs 8.6737
cc 6
eloc 11
nc 16
nop 1
1
<?php
2
3
namespace LegalThings;
4
5
use LegalThings\DataEnricher\Node;
6
use LegalThings\DataEnricher\Processor;
7
8
/**
9
 * Enrich objects by processing special properties.
10
 */
11
class DataEnricher
12
{
13
    /**
14
     * Default processors
15
     * @var array
16
     */
17
    public static $defaultProcessors = [
18
        '<ifset>' => Processor\IfSet::class,
19
        '<ref>' => Processor\Reference::class,
20
        '<switch>' => Processor\SwitchChoose::class,
21
        '<src>' => Processor\Http::class,
22
        '<merge>' => Processor\Merge::class,
23
        '<jmespath>' => Processor\JmesPath::class,
24
        '<tpl>' => Processor\Mustache::class,
25
        '<transformation>' => Processor\Transform::class,
26
        
27
        // Deprecated
28
        '_ref' => Processor\Reference::class,
29
        '_switch' => Processor\SwitchChoose::class,
30
        '_src' => Processor\Http::class,
31
        '_merge' => Processor\Merge::class,
32
        '_jmespath' => Processor\JmesPath::class,
33
        '_tpl' => Processor\Mustache::class,
34
        '_transformation' => Processor\Transform::class
35
    ];
36
    
37
    
38
    /**
39
     * @var object
40
     */
41
    protected $source;
42
    
43
    /**
44
     * Processors, applied in specified order.
45
     * 
46
     * @var DataEnricher\Processor[]
47
     */
48
    public $processors;
49
    
50
    
51
    /**
52
     * Class constructor
53
     * 
54
     * @param object $source  Data source
55
     */
56
    public function __construct($source)
57
    {
58
        if (!is_object($source)) {
59
            throw new \Exception("Data enricher on works on an object, not on a " . gettype($source));
60
        }
61
        
62
        $this->source = $source;
63
        
64
        foreach (static::$defaultProcessors as $property => $processor) {
65
            if (is_string($processor)) {
66
                $class = $processor;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 5 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
67
                $processor = new $class($this, $property);
68
            }
69
            
70
            $this->processors[] = $processor;
71
        }
72
    }
73
    
74
    /**
75
     * Get the source object
76
     * 
77
     * @return object
78
     */
79
    public function getSource()
80
    {
81
        return $this->source;
82
    }
83
    
84
    
85
    /**
86
     * Invoke enricher 
87
     * 
88
     * @param array|object|string $target  Target or dot key path
89
     */
90
    public function applyTo($target)
91
    {
92
        if (is_string($target)) {
93
            $target = \DotKey::on($this->source)->get($target);
94
        }
95
        
96
        $nodes = $this->findNodes($target);
97
98
        foreach ($this->processors as $processor) {
99
            $processor->prepare($nodes);
100
        }
101
        
102
        foreach ($nodes as $node) {
103
            foreach ($this->processors as $processor) {
104
                if ($node->hasInstruction($processor)) {
105
                    $processor->applyToNode($node);
106
                }
107
            }
108
        }
109
        
110
        $this->applyNodeResults($target);
111
    }
112
113
    /**
114
     * Find nodes that have processing instructions
115
     * 
116
     * @param array|object $target
117
     * @return array
118
     */
119
    public function findNodes(&$target)
120
    {
121
        $nodes = [];
122
        
123
        foreach ($target as $key => &$value) {
124
            if (is_array($value) || (is_object($value) && !$value instanceof Node)) {
125
                $nodes = array_merge($nodes, $this->findNodes($value));
126
            }
127
            
128
            if ($value instanceof \stdClass && $this->hasProcessorProperty($value)) {
129
                $value = new Node($value);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
130
                $nodes[] = $value;
131
            }
132
        }
133
        
134
        return $nodes;
135
    }
136
    
137
    /**
138
     * Check if object has at leas one process property
139
     * 
140
     * @param \stdClass $value
141
     * @return boolean
142
     */
143
    protected function hasProcessorProperty($value)
144
    {
145
        $processorProps = array_map(function ($processor) {
146
            return $processor->getProperty();
147
        }, $this->processors);
148
        
149
        $valueProps = array_keys(get_object_vars($value));
150
        
151
        return count(array_intersect($valueProps, $processorProps)) > 0;
152
    }
153
    
154
    /**
155
     * Replace nodes with their results
156
     * 
157
     * @param array|object $target
158
     */
159
    public function applyNodeResults(&$target)
160
    {
161
        foreach ($target as &$value) {
162
            if ($value instanceof Node) {
163
                $value = $value->getResult();
164
            } elseif (is_array($value) || is_object($value)) {
165
                $this->applyNodeResults($value);
166
            }
167
        }
168
    }
169
    
170
    /**
171
     * Enrich object
172
     * 
173
     * @param object $subject
174
     */
175
    public static function process($subject)
176
    {
177
        $enrich = new static($subject);
178
        $enrich->applyTo($subject);
179
    }
180
}
181