Passed
Push — master ( a1252b...3ee6a0 )
by Dmitry
02:32
created

ModelTransformer   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 114
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 9
Bugs 3 Features 2
Metric Value
c 9
b 3
f 2
dl 0
loc 114
wmc 20
lcom 1
cbo 2
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A addModelTransformer() 0 17 4
A getModelTransformers() 0 14 3
B supports() 0 17 7
A transform() 0 14 3
A findSupportedModelTransformer() 0 10 3
1
<?php
2
3
namespace Tonic\Component\ApiLayer\ModelTransformer;
4
5
use Tonic\Component\ApiLayer\ModelTransformer\Exception\UnsupportedTransformationException;
6
7
/**
8
 * Manages transformers.
9
 */
10
class ModelTransformer implements ModelTransformerInterface
11
{
12
    /**
13
     * @var array
14
     */
15
    private $modelTransformers = [];
16
17
    /**
18
     * @var array
19
     */
20
    private $sorted = [];
21
22
    /**
23
     * @param ModelTransformerInterface $modelTransformer
24
     * @param int $priority
25
     *
26
     * @return $this|ModelTransformerInterface
27
     *
28
     * @throws \RuntimeException
29
     */
30
    public function addModelTransformer($modelTransformer, $priority = 0)
31
    {
32
        if (!(($modelTransformer instanceof ModelTransformerInterface) || ($modelTransformer instanceof ContextualModelTransformerInterface))) {
33
            throw new \RuntimeException(
34
                sprintf('Model transformer should be an instance of "%s" or "%s"', ModelTransformerInterface::class, ContextualModelTransformerInterface::class)
35
            );
36
        }
37
38
        if (!isset($this->modelTransformers[$priority])) {
39
            $this->modelTransformers[$priority] = [];
40
        }
41
42
        $this->modelTransformers[$priority][] = $modelTransformer;
43
        unset($this->sorted);
44
45
        return $this;
46
    }
47
48
    /**
49
     * @return ModelTransformerInterface[]
50
     */
51
    public function getModelTransformers()
52
    {
53
        if (isset($this->sorted)) {
54
            return $this->sorted;
55
        }
56
57
        krsort($this->modelTransformers);
58
        $this->sorted = [];
59
        foreach ($this->modelTransformers as $modelTransformers) {
60
            $this->sorted = array_merge($this->sorted, $modelTransformers);
61
        }
62
63
        return $this->sorted;
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69
    public function supports($object, $targetClass)
70
    {
71
        /** @var ContextInterface $context */
72
        $context = (func_num_args() == 3) ? func_get_arg(2) : null;
73
74
        foreach ($this->getModelTransformers() as $modelTransformer) {
75
            if (($modelTransformer instanceof ContextualModelTransformerInterface) && $modelTransformer->supports($object, $targetClass, $context)) {
76
                return true;
77
            }
78
79
            if (($modelTransformer instanceof ModelTransformerInterface) && $modelTransformer->supports($object, $targetClass)) {
80
                return true;
81
            }
82
        }
83
84
        return false;
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90
    public function transform($object, $targetClass)
91
    {
92
        $modelTransformer = $this->findSupportedModelTransformer($object, $targetClass);
93
        if ($modelTransformer) {
94
            return $modelTransformer->transform($object, $targetClass);
95
        }
96
97
        $objectType = is_object($object) ? get_class($object) : gettype($object);
98
        throw new UnsupportedTransformationException(sprintf(
99
            'Can not transform object of type "%s" to object of type "%s"',
100
            $objectType,
101
            $targetClass
102
        ));
103
    }
104
105
    /**
106
     * Finds and returns model transformer which supports specified object and target class.
107
     *
108
     * @param object|array $object
109
     * @param string $targetClass
110
     *
111
     * @return ModelTransformerInterface|null
112
     */
113
    public function findSupportedModelTransformer($object, $targetClass)
114
    {
115
        foreach ($this->getModelTransformers() as $modelTransformer) {
116
            if ($modelTransformer->supports($object, $targetClass)) {
117
                return $modelTransformer;
118
            }
119
        }
120
121
        return null;
122
    }
123
}
124