Transformer::transform()   B
last analyzed

Complexity

Conditions 4
Paths 28

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 15
nc 28
nop 2
1
<?php
2
3
namespace Abacaphiliac\Zend\Transformer;
4
5
use Abacaphiliac\Zend\Transformer\Exception\TransformationException;
6
use Assert\Assertion;
7
use Assert\AssertionFailedException;
8
use Zend\Hydrator\ExtractionInterface;
9
use Zend\Hydrator\HydrationInterface;
10
use Zend\Validator\ValidatorInterface;
11
12
class Transformer implements TransformerInterface
13
{
14
    /** @var ValidatorInterface */
15
    private $inputValidator;
16
    
17
    /** @var ExtractionInterface */
18
    private $extractor;
19
    
20
    /** @var callable */
21
    private $transformer;
22
    
23
    /** @var HydrationInterface */
24
    private $hydrator;
25
    
26
    /** @var ValidatorInterface */
27
    private $outputValidator;
28
    
29
    /**
30
     * Transformer constructor.
31
     * @param ValidatorInterface $inputValidator
32
     * @param ExtractionInterface $extractor
33
     * @param callable $transformer
34
     * @param HydrationInterface $hydrator
35
     * @param ValidatorInterface $outputValidator
36
     */
37
    public function __construct(
38
        ValidatorInterface $inputValidator,
39
        ExtractionInterface $extractor,
40
        callable $transformer,
41
        HydrationInterface $hydrator,
42
        ValidatorInterface $outputValidator
43
    ) {
44
        $this->inputValidator = $inputValidator;
45
        $this->extractor = $extractor;
46
        $this->transformer = $transformer;
47
        $this->hydrator = $hydrator;
48
        $this->outputValidator = $outputValidator;
49
    }
50
    
51
    /**
52
     * @param mixed $input
53
     * @param mixed|string $output
54
     * @return mixed
55
     * @throws \Abacaphiliac\Zend\Transformer\Exception\TransformationException
56
     */
57
    public function transform($input, $output)
58
    {
59
        try {
60
            if (is_string($output)) {
61
                Assertion::classExists($output);
62
                $output = new $output;
63
            }
64
            
65
            $this->validateObject($input, $this->inputValidator);
66
        
67
            $inputData = $this->extract($input);
68
        
69
            $outputData = $this->transformInputData($inputData);
70
        
71
            $output = $this->hydrate($outputData, $output);
72
        
73
            $this->validateObject($output, $this->outputValidator);
74
        } catch (AssertionFailedException $e) {
75
            throw new TransformationException('Transformation failed.', null, $e);
76
        } catch (\Exception $e) {
77
            throw new TransformationException('Transformation failed.', null, $e);
78
        }
79
        
80
        return $output;
81
    }
82
    
83
    /**
84
     * @param mixed $object
85
     * @param ValidatorInterface $validator
86
     * @return void
87
     * @throws \Zend\Validator\Exception\RuntimeException
88
     * @throws AssertionFailedException
89
     */
90
    private function validateObject($object, ValidatorInterface $validator)
91
    {
92
        Assertion::isObject($object);
93
    
94
        $isValid = $validator->isValid($object);
95
    
96
        Assertion::true($isValid, 'Validation failed: ' . json_encode($validator->getMessages()));
97
    }
98
    
99
    /**
100
     * @param mixed $object
101
     * @return mixed[]
102
     * @throws AssertionFailedException
103
     */
104
    private function extract($object)
105
    {
106
        Assertion::isObject($object);
107
        
108
        $data = $this->extractor->extract($object);
109
        
110
        Assertion::isArray($data);
111
        
112
        return $data;
113
    }
114
    
115
    /**
116
     * @param mixed[] $input
117
     * @return mixed[]
118
     * @throws AssertionFailedException
119
     */
120
    private function transformInputData(array $input)
121
    {
122
        $output = call_user_func($this->transformer, $input);
123
        
124
        Assertion::isArray($output);
125
        
126
        return $output;
127
    }
128
    
129
    /**
130
     * @param mixed[] $data
131
     * @param mixed|string $object
132
     * @return mixed
133
     * @throws AssertionFailedException
134
     */
135
    private function hydrate(array $data, $object)
136
    {
137
        Assertion::isObject($object);
138
        
139
        $output = $this->hydrator->hydrate($data, $object);
140
        
141
        Assertion::isObject($output);
142
        
143
        return $output;
144
    }
145
}
146