Completed
Push — master ( 55925d...e386b5 )
by Andre
01:56
created

Factory::getClassName()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 14
rs 9.4285
cc 3
eloc 7
nc 3
nop 1
1
<?php
2
3
namespace TheIconic\Synopsis;
4
5
use Exception;
6
use TheIconic\Synopsis\Object\IteratorSynopsis;
7
use TheIconic\Synopsis\Resource\FileSynopsis;
8
use TheIconic\Synopsis\Resource\StreamSynopsis;
9
10
/**
11
 * the synopsis factory spawns synopsis instances
12
 *
13
 * @package TheIconic\Synopsis
14
 */
15
class Factory
16
{
17
    /**
18
     * @var array mappings from types to synopsis classes
19
     */
20
    protected $typeMap = [
21
        'null' => NullSynopsis::class,
22
        'boolean' => BooleanSynopsis::class,
23
        'string' => StringSynopsis::class,
24
        'double' => DoubleSynopsis::class,
25
        'integer' => IntegerSynopsis::class,
26
        'array' => ArraySynopsis::class,
27
        'object' => ObjectSynopsis::class,
28
        'resource' => ResourceSynopsis::class,
29
        'exception' => ExceptionSynopsis::class,
30
    ];
31
32
    /**
33
     * @var array mappings from value classes to synopsis classes
34
     */
35
    protected $objectMap = [
36
        'Iterator' => IteratorSynopsis::class,
37
        'IteratorAggregate' => IteratorSynopsis::class,
38
        'ArrayAccess' => IteratorSynopsis::class,
39
    ];
40
41
    /**
42
     * @var array mappings from resource types to synopsis classes
43
     */
44
    protected $resourceMap = [
45
        'bzip2' => FileSynopsis::class,
46
        'cpdf' => FileSynopsis::class,
47
        'fdf' => FileSynopsis::class,
48
        'zlib' => FileSynopsis::class,
49
        'stream' => StreamSynopsis::class,
50
    ];
51
52
    /**
53
     * creates the fitting synopsis instance for a value
54
     *
55
     * @param $value
56
     * @param $depth
57
     * @return mixed
58
     */
59
    public function synopsize($value, $depth = 3)
60
    {
61
        $depth--;
62
        if ($depth <= 0) {
63
            $depth = false;
64
        }
65
66
        $className = $this->getClassName($value);
67
68
        /** @var AbstractSynopsis $synopsis */
69
        $synopsis = new $className();
70
        $synopsis->setFactory($this);
71
        $synopsis->process($value, $depth);
72
73
        return $synopsis;
74
    }
75
76
    /**
77
     * get the synopsis classname to use for processing value
78
     *
79
     * @param $value
80
     * @return string
81
     */
82
    protected function getClassName($value)
83
    {
84
        $type = $this->detectType($value);
85
86
        if ($type === 'object') {
87
            return $this->getClassNameForObject($value);
88
        }
89
90
        if ($type === 'resource') {
91
            return $this->getClassNameForResource($value);
92
        }
93
94
        return $this->getClassNameForType($type);
95
    }
96
97
    /**
98
     * detect the primitive type of value
99
     *
100
     * @param $value
101
     * @return string
102
     */
103
    protected function detectType($value)
104
    {
105
        if ($value === null) {
106
            return 'null';
107
        }
108
109
        if ($value instanceof Exception) {
110
            return 'exception';
111
        }
112
113
        return gettype($value);
114
    }
115
116
    /**
117
     * @param string $type
118
     * @return string
119
     */
120
    protected function getClassNameForType(string $type)
121
    {
122
        if (isset($this->typeMap[$type])) {
123
            $className = $this->typeMap[$type];
124
125
            if (class_exists($className)) {
126
                return $className;
127
            }
128
        }
129
130
        return StandardSynopsis::class;
131
    }
132
133
    /**
134
     * get the fitting synopsis class name for the given object
135
     *
136
     * @param $value
137
     * @return string
138
     */
139
    protected function getClassNameForObject($value): string
140
    {
141
        foreach ($this->objectMap as $type => $className) {
142
            if (!is_a($value, $type)) {
143
                continue;
144
            }
145
146
            if (class_exists($className)) {
147
                return $className;
148
            }
149
        }
150
151
        return $this->typeMap['object'];
152
    }
153
154
    /**
155
     * get the fitting synopsis class name for the given resource
156
     *
157
     * @param $value
158
     * @return string
159
     */
160
    protected function getClassNameForResource($value): string
161
    {
162
        $type = get_resource_type($value);
163
164
        if (isset($this->resourceMap[$type])) {
165
            $className = $this->resourceMap[$type];
166
167
            if (class_exists($className)) {
168
                return $className;
169
            }
170
        }
171
172
        return $this->typeMap['resource'];
173
    }
174
175
    /**
176
     * register a Synopsis class for resource type
177
     *
178
     * @param $type
179
     * @param $className
180
     * @return $this
181
     */
182
    public function addResourceType($type, $className)
183
    {
184
        $this->resourceMap[$type] = $className;
185
186
        return $this;
187
    }
188
189
    /**
190
     * register a Synopsis class for an object type
191
     *
192
     * @param $type
193
     * @param $className
194
     * @return $this
195
     */
196
    public function addObjectType($type, $className)
197
    {
198
        $this->objectMap[$type] = $className;
199
200
        return $this;
201
    }
202
203
    /**
204
     * register a Synopsis class for a type
205
     *
206
     * @param $type
207
     * @param $className
208
     * @return $this
209
     */
210
    public function addType($type, $className)
211
    {
212
        $this->typeMap[$type] = $className;
213
214
        return $this;
215
    }
216
}
217