Completed
Push — master ( d0a3bd...df04fd )
by Changwan
04:12
created

Restifier::addTransformer()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2.032

Importance

Changes 0
Metric Value
cc 2
eloc 5
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 8
ccs 4
cts 5
cp 0.8
crap 2.032
rs 9.4285
1
<?php
2
namespace Wandu\Restifier;
3
4
use InvalidArgumentException;
5
use Wandu\Restifier\Contracts\Restifiable;
6
use Wandu\Restifier\Exception\NotFoundTransformerException;
7
8
class Restifier implements Restifiable
9
{
10
    /** @var callable[] */
11
    protected $transformers = [];
12
    
13 10
    public function __construct(array $transformers = [])
14
    {
15 10
        foreach ($transformers as $name => $transformer) {
16
            $this->addTransformer($name, $transformer);
17
        }
18 10
    }
19
20
    /**
21
     * @param string $name
22
     * @param callable $transformer
23
     */
24 7
    public function addTransformer(string $name, callable $transformer)
25
    {
26 7
        if (is_callable($transformer)) {
27 7
            $this->transformers[$name] = $transformer;
28 7
            return;
29
        }
30
        throw new InvalidArgumentException("Argument 2 passed to pushTransformer() must be callable");
31
    }
32
    
33
    /**
34
     * {@inheritdoc}
35
     */
36 10
    public function restify($resource, array $includes = [], callable $transformer = null)
37
    {
38 10
        if ($resource === null) return null;
39 9
        if (!$transformer) {
40 8
            $transformer = $this->findTransformer($resource);
41
        }
42 8
        $parsedIncludes = $this->parseIncludes($includes, $resource);
43 8
        $entity = call_user_func($transformer, $resource, $this, $parsedIncludes);
44 8
        foreach ($parsedIncludes as $key => $nextIncludes) {
45 2
            if (is_object($transformer) && method_exists($transformer, $key)) {
46 2
                $entity = array_merge(
47 2
                    $entity,
48 2
                    $transformer->{$key}($resource, $this, $nextIncludes)
49
                );
50
            }
51
        }
52 8
        return $entity;
53
    }
54
55
    /**
56
     * {@inheritdoc}
57
     */
58 1
    public function restifyMany($resource, array $includes = [], callable $transformer = null): array
59
    {
60 1
        $result = [];
61 1
        foreach ($resource as $key => $value) {
62 1
            $result[$key] = $this->restify($value, $includes, $transformer);
63
        }
64 1
        return $result;
65
    }
66
67 8
    protected function findTransformer($resource)
68
    {
69 8
        $className = null;
70 8
        if (is_object($resource) && $className = get_class($resource)) {
71 8
            if (array_key_exists($className, $this->transformers)) {
72 7
                return $this->transformers[$className];
73
            }
74 2
            foreach ($this->transformers as $name => $transformer) {
75 1
                if ($resource instanceof $name) {
76 1
                    return $transformer;
77
                }
78
            }
79
        }
80 1
        if ($className) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $className of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
81 1
            throw new NotFoundTransformerException(
82 1
                sprintf("cannot find the transformer named %s.", $className)
83
            );
84
        }
85 1
        throw new NotFoundTransformerException("resource is not an object.");
86
    }
87
    
88
    /**
89
     * @param array $includes
90
     * @param mixed $resource
91
     * @return array
92
     */
93 8
    private function parseIncludes(array $includes = [], $resource)
94
    {
95 8
        $parsedIncludes = [];
96 8
        foreach ($includes as $include => $condition) {
97 2
            if (is_integer($include)) {
98 2
                $include = $condition;
99 2
                $condition = true;
100
            }
101 2
            while (is_callable($condition)) {
102 1
                $condition = call_user_func($condition, $resource);
103
            }
104 2
            if (!$condition) continue;
105 2
            if (strpos($include, '.') === false) {
106 2
                $key = $include;
107 2
                $param = null;
108
            } else {
109 1
                list($key, $param) = explode('.', $include, 2);
110
            }
111 2
            if (!isset($parsedIncludes[$key])) {
112 2
                $parsedIncludes[$key] = [];
113
            }
114 2
            if ($param) {
115 2
                $parsedIncludes[$key][] = $param;
116
            }
117
        }
118 8
        return $parsedIncludes;
119
    }
120
}
121