Failed Conditions
Branch master (e245a2)
by Arnold
03:11
created

DataEnricher::hasProcessorProperty()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 10
ccs 0
cts 5
cp 0
rs 9.4285
cc 1
eloc 6
nc 1
nop 1
crap 2
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 4
    public function __construct($source)
57
    {
58 4
        if (!is_object($source)) {
59 2
            throw new \Exception("Data enricher on works on an object, not on a " . gettype($source));
60
        }
61
        
62 4
        $this->source = $source;
63
        
64 4
        foreach (static::$defaultProcessors as $property => $processor) {
65 1
            if (is_string($processor)) {
66 1
                $class = $processor;
67 1
                $processor = new $class($this, $property);
68 1
            }
69
            
70 1
            $this->processors[] = $processor;
71 4
        }
72 4
    }
73
    
74
    /**
75
     * Get the source object
76
     * 
77
     * @return object
78
     */
79 1
    public function getSource()
80
    {
81 1
        return $this->source;
82
    }
83
    
84
    
85
    /**
86
     * Apply processing instructions
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
            $this->applyToNode($node);
104
        }
105
        
106
        $this->applyNodeResults($target);
107
    }
108
    
109
    /**
110
     * Apply processing instructions to node
111
     * 
112
     * @param Node $node
113
     */
114
    protected function applyToNode(Node $node)
115
    {
116
        foreach ($this->processors as $processor) {
117
            if ($node->hasInstruction($processor)) {
118
                $processor->applyToNode($node);
119
            }
120
        }
121
    }
122
123
    /**
124
     * Find nodes that have processing instructions
125
     * 
126
     * @param array|object $target
127
     * @return array
128
     */
129
    public function findNodes(&$target)
130
    {
131
        $nodes = [];
132
        
133
        foreach ($target as $key => &$value) {
134
            if (is_array($value) || (is_object($value) && !$value instanceof Node)) {
135
                $nodes = array_merge($nodes, $this->findNodes($value));
136
            }
137
            
138
            if ($value instanceof \stdClass && $this->hasProcessorProperty($value)) {
139
                $value = new Node($value);
140
                $nodes[] = $value;
141
            }
142
        }
143
        
144
        return $nodes;
145
    }
146
    
147
    /**
148
     * Check if object has at leas one process property
149
     * 
150
     * @param \stdClass $value
151
     * @return boolean
152
     */
153
    protected function hasProcessorProperty($value)
154
    {
155
        $processorProps = array_map(function ($processor) {
156
            return $processor->getProperty();
157
        }, $this->processors);
158
        
159
        $valueProps = array_keys(get_object_vars($value));
160
        
161
        return count(array_intersect($valueProps, $processorProps)) > 0;
162
    }
163
    
164
    /**
165
     * Replace nodes with their results
166
     * 
167
     * @param array|object $target
168
     */
169
    public function applyNodeResults(&$target)
170
    {
171
        foreach ($target as &$value) {
172
            if ($value instanceof Node) {
173
                $value = $value->getResult();
174
            } elseif (is_array($value) || is_object($value)) {
175
                $this->applyNodeResults($value);
176
            }
177
        }
178
    }
179
    
180
    /**
181
     * Enrich object
182
     * 
183
     * @param object $subject
184
     */
185
    public static function process($subject)
186
    {
187
        $enrich = new static($subject);
188
        $enrich->applyTo($subject);
189
    }
190
}
191