Completed
Push — master ( 22a264...8e04bf )
by Stefano
03:00
created

Map::delete()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
rs 10
cc 2
eloc 3
nc 2
nop 2
1
<?php
2
3
/**
4
 * Map class
5
 *
6
 * The map class allow to handle a repository of key-values data.
7
 * Values are accessibles via a dot notation key path.
8
 * 
9
 * @package core
10
 * @author [email protected]
11
 * @copyright Caffeina srl - 2016 - http://caffeina.com
12
 */
13
14
class Map implements JsonSerializable {
15
16
    protected $fields = [];
17
18
    /**
19
     * Returns the map as an associative array
20
     * @return array reference
21
     */
22
    public function & all(){
23
        return $this->fields;
24
    }
25
26
    /**
27
     * Get a value assigned to a key path from the map
28
     * @param  string $key The key path of the value in dot notation 
29
     * @param  mixed $default (optional) The default value. If is a callable it will executed and the return value will be used.
30
     * @return mixed The value of the key or the default (resolved) value if the key not existed.
31
     */
32
    public function get($key, $default=null){
33
        if ($ptr =& static::find($key,false)){
34
            return $ptr;
35
        } else {
36
            if ($default !== null){
37
                return static::set($key, is_callable($default) ? call_user_func($default) : $default);
38
            } else {
39
                return null;
40
            }
41
        }
42
    }
43
44
    /**
45
     * Set a value for a key path from map
46
     * @param  string $key The key path of the value in dot notation 
47
     * @param  mixed $value (optional) The value. If is a callable it will executed and the return value will be used.
48
     * @return mixed The value of the key or the default (resolved) value if the key not existed.
49
     */
50
    public function set($key, $value=null){
51
        if (is_array($key)) {
52
            return static::merge($key);
53
        } else {
54
            $ptr = & static::find($key,true);
55
            return $ptr = $value;
56
        }
57
    }
58
59
    /**
60
     * Delete a value and the key path from map.
61
     * @param  string $key The key path in dot notation 
62
     * @param  boolean $compact (optional) Compact map removing empty paths.
63
     */
64
    public function delete($key, $compact=true){
65
        static::set($key,null);
66
        if ($compact) static::compact();
67
    }
68
69
    /**
70
     * Check if a key path exists in map.
71
     * @param  string $key The key path in dot notation 
72
     * @return boolean
73
     */
74
    public function exists($key){
75
        return null !== static::find($key,false);
76
    }
77
78
    /**
79
     * Clear all key path in map.
80
     */
81
    public function clear(){
82
        $this->fields = [];
83
    }
84
85
    public function __construct($fields=null){
86
        $this->load($fields);
87
    }
88
    
89
    /**
90
     * Load an associative array/object as the map source.
91
     * @param  string $fields The array to merge
92
     */
93
    public function load($fields){
94
        if ($fields) $this->fields = (array)$fields;
95
    }
96
97
    /**
98
     * Merge an associative array to the map. 
99
     * @param  array   $array The array to merge
100
     * @param  boolean $merge_back If `true` merge the map over the $array, if `false` (default) the reverse.
101
     */
102
    public function merge(array $array, $merge_back=false){
103
        $this->fields = $merge_back
104
            ? array_replace_recursive($array, $this->fields)
105
            : array_replace_recursive($this->fields, $array);
106
    }
107
108
    /**
109
     * Compact map removing empty paths
110
     */
111
    protected function compact(){
112
        function array_filter_rec($input, $callback = null) { 
113
            foreach ($input as &$value) { 
114
                if (is_array($value)) { 
115
                    $value = array_filter_rec($value, $callback); 
116
                } 
117
            } 
118
            return array_filter($input, $callback); 
119
        } 
120
121
        $this->fields = array_filter_rec($this->fields,function($a){ return $a !== null; });
122
    }
123
124
    /**
125
     * Navigate map and find the element from the path in dot notation.
126
     * @param  string  $path Key path in dot notation.
127
     * @param  boolean $create If true will create empty paths.
128
     * @param  callable  If passed this callback will be applied to the founded value.
129
     * @return mixed The founded value.
130
     */
131
    protected static function & find($path, $create=false, callable $operation=null) {
132
        $tok = strtok($path,'.');        
133
        if($create){
134
            $value =& $this->fields;
0 ignored issues
show
Bug introduced by
The variable $this does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
135
        } else {
136
            $value = $this->fields;
137
        }
138
        while($tok !== false){
139
            $value =& $value[$tok];
140
            $tok = strtok('.');
141
        }
142
        if (is_callable($operation)) $operation($value);
143
        return $value;
144
    }
145
146
    /**
147
     * JsonSerializable Interface handler
148
     *
149
     * @method jsonSerialize
150
     *
151
     * @return string        The json object
152
     */
153
    public function jsonSerialize(){
154
      return $this->fields;
155
    }
156
157
158
}
159