Passed
Push — master ( 3ee6a0...ec740c )
by Dmitry
02:21
created

ModelTransformer::findSupportedModelTransformer()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 14
rs 8.8571
cc 6
eloc 7
nc 4
nop 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
        /** @var ContextInterface $context */
93
        $context = (func_num_args() == 3) ? func_get_arg(2) : null;
94
95
        $modelTransformer = $this->findSupportedModelTransformer($object, $targetClass, $context);
96
        if ($modelTransformer instanceof ContextualModelTransformerInterface) {
97
            return $modelTransformer->transform($object, $targetClass, $context);
98
        }
99
100
        if (($modelTransformer instanceof ModelTransformerInterface) && $modelTransformer->supports($object, $targetClass)) {
101
            return $modelTransformer->transform($object, $targetClass);
102
        }
103
104
        $objectType = is_object($object) ? get_class($object) : gettype($object);
105
        throw new UnsupportedTransformationException(sprintf(
106
            'Can not transform object of type "%s" to object of type "%s"',
107
            $objectType,
108
            $targetClass
109
        ));
110
    }
111
112
    /**
113
     * Finds and returns model transformer which supports specified object and target class.
114
     *
115
     * @param object|array $object
116
     * @param string $targetClass
117
     * @param ContextInterface|null $context
118
     *
119
     * @return null|ModelTransformerInterface
120
     */
121
    public function findSupportedModelTransformer($object, $targetClass, ContextInterface $context = null)
122
    {
123
        foreach ($this->getModelTransformers() as $modelTransformer) {
124
            if (($modelTransformer instanceof ContextualModelTransformerInterface) && $modelTransformer->supports($object, $targetClass, $context)) {
125
                return $modelTransformer;
126
            }
127
128
            if (($modelTransformer instanceof ModelTransformerInterface) && $modelTransformer->supports($object, $targetClass)) {
129
                return $modelTransformer;
130
            }
131
        }
132
133
        return null;
134
    }
135
}
136