Completed
Push — master ( 7527cc...0ae322 )
by Changwan
02:46
created

Restifier::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 6
ccs 3
cts 4
cp 0.75
crap 2.0625
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 8
    public function __construct(array $transformers = [])
14
    {
15 8
        foreach ($transformers as $name => $transformer) {
16
            $this->addTransformer($name, $transformer);
17
        }
18 8
    }
19
20
    /**
21
     * @param string $name
22
     * @param callable $transformer
23
     */
24 6
    public function addTransformer(string $name, callable $transformer)
25
    {
26 6
        if (is_callable($transformer)) {
27 6
            $this->transformers[$name] = $transformer;
28 6
            return;
29
        }
30
        throw new InvalidArgumentException("Argument 2 passed to pushTransformer() must be callable");
31
    }
32
    
33
    /**
34
     * @param mixed $resource
35
     * @param array $includes
36
     * @param callable $transformer
37
     * @return array
38
     */
39 8
    public function restify($resource, array $includes = [], callable $transformer = null): array
40
    {
41 8
        if (!$transformer) {
42 7
            $transformer = $this->findTransformer($resource);
43
        }
44 7
        $parsedIncludes = $this->parseIncludes($includes, $resource);
45 7
        $entity = call_user_func($transformer, $resource, $this, $parsedIncludes);
46 7
        foreach ($parsedIncludes as $key => $nextIncludes) {
47 2
            if (is_object($transformer) && method_exists($transformer, $key)) {
48 2
                $entity = array_merge(
49 2
                    $entity,
50 2
                    $transformer->{$key}($resource, $this, $nextIncludes)
51
                );
52
            }
53
        }
54 7
        return $entity;
55
    }
56
57
    /**
58
     * @param array|\Traversable $resource
59
     * @param array $includes
60
     * @param callable $transformer
61
     * @return array
62
     */
63 1
    public function restifyMany($resource, array $includes = [], callable $transformer = null): array
64
    {
65 1
        $result = [];
66 1
        foreach ($resource as $key => $value) {
67 1
            $result[$key] = $this->restify($value, $includes, $transformer);
68
        }
69 1
        return $result;
70
    }
71
72 7
    protected function findTransformer($resource)
73
    {
74 7
        $className = null;
75 7
        if (is_object($resource) && $className = get_class($resource)) {
76 7
            if (array_key_exists($className, $this->transformers)) {
77 6
                return $this->transformers[$className];
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 7
    private function parseIncludes(array $includes = [], $resource)
94
    {
95 7
        $parsedIncludes = [];
96 7
        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 7
        return $parsedIncludes;
119
    }
120
}
121