Completed
Push — master ( 9c4836...819134 )
by Stefano
02:40
created

Structure::create()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Structure
5
 *
6
 * Access properties with associative array or object notation seamlessly.
7
 *
8
 * @package core
9
 * @author [email protected]
10
 * @copyright Caffeina srl - 2015 - http://caffeina.it
11
 */
12
13
class Structure extends ArrayObject {
14
15
    /**
16
     * An Structure can wrap a StdClass, an array or an object from a JSON encoded string.
17
     *
18
     * This class is useful for wrapping API responses and access their properties in
19
     * an easy way.
20
     *
21
     * @param mixed  $input The object/array/json_encoded object to wrap
22
     * @param boolean $deep  Wrap also deep branches as Objects
23
     */
24
    public function __construct($input=[], $deep=true){
25
        $data = is_string($input) ? json_decode($input,true) : (array)$input;
26
        if (is_array($data)){
27
            if ($deep) {
28
                foreach ($data as $key => &$value) {
29
                    if (is_array($value) || is_a($value,'stdClass')){
30
                        $value = new self($value);
31
                    }
32
                }
33
            }
34
           parent::__construct($data, static::ARRAY_AS_PROPS);
35
        } else {
36
            throw new InvalidArgumentException(
37
                'Argument must be a string containing valid JSON, an array or an stdClass.'
38
            );
39
        }
40
    }
41
42
    /**
43
     * ArrayObject::offsetSet
44
     */
45
    public function offsetSet($key, $value){
46
        if ( is_array($value) )
47
          parent::offsetSet($key, new static($value));
48
        else
49
          parent::offsetSet($key, $value);
50
    }
51
52
    /**
53
     * ArrayObject::offsetGet
54
     */
55
    public function offsetGet($key){
56
        $raw = parent::offsetGet($key);
57
        return is_callable($raw) ? call_user_func($raw) : $raw;
58
    }
59
60
    /**
61
     * Emulate object methods
62
     */
63
    public function __call($method, $args){
64
        $raw = parent::offsetGet($method);
65
        if (is_callable($raw)) {
66
            if ($raw instanceof \Closure) $raw->bindTo($this);
67
            return call_user_func_array($raw, $args);
68
        }
69
    }
70
71
    /**
72
     * If casted as a string, return a JSON rappresentation of the wrapped payload
73
     * @return string
74
     */
75
    public function __toString(){
76
        return json_encode($this,JSON_NUMERIC_CHECK);
77
    }
78
79
    /**
80
     * Dot-Notation Array Path Resolver
81
     * @param  string $path The dot-notation path
82
     * @param  array $root The array to navigate
83
     * @return mixed The pointed value
84
     */
85
86
    public static function fetch($path, $root) {
87
      $_ = (array)$root;
88
      if (strpos($path,'.') === false) {
89
        return isset($_[$path]) ? $_[$path] : null;
90
      } else {
91
        list($frag,$rest) = explode('.', $path, 2);
92
        if ($rest) {
93
          return isset($_[$frag]) ? self::fetch($rest, $_[$frag]) : null;
94
        } elseif ($frag) {
95
          return (array)$_[$frag];
96
        } else {
97
          return null;
98
        }
99
      }
100
    }
101
102
    public static function create($class, $args = null){
103
        return is_array($args) ? (new ReflectionClass($class))->newInstanceArgs($args) : new $class;
104
    }
105
106
    public static function canBeString($var) {
107
      return $var === null || is_scalar($var) || is_callable([$var, '__toString']);
108
    }
109
110
}
111