Completed
Push — master ( 54ecd3...0fcd81 )
by Hong
02:25
created

Tree::deleteNode()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 15
rs 9.4285
cc 3
eloc 11
nc 3
nop 1
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Shared
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Shared\Tree;
16
17
use Phossa2\Shared\Base\ObjectAbstract;
18
19
/**
20
 * Dealing with tree structure
21
 *
22
 * @package Phossa2\Shared
23
 * @author  Hong Zhang <[email protected]>
24
 * @version 2.0.3
25
 * @since   2.0.3 added
26
 * @since   2.0.5 added deleteNode()
27
 */
28
class Tree extends ObjectAbstract
29
{
30
    /**
31
     * node splitter
32
     *
33
     * @var    string
34
     * @access protected
35
     */
36
    protected $splitter = '.';
37
38
    /**
39
     * the result tree
40
     *
41
     * @var    array
42
     * @access protected
43
     */
44
    protected $tree;
45
46
    /**
47
     * construct a tree
48
     *
49
     * @param  array $data
50
     * @param  string $splitter
51
     * @access public
52
     * @api
53
     */
54
    public function __construct(array $data, /*# string */ $splitter = '.')
55
    {
56
        $this->splitter = $splitter;
57
        $this->tree = $this->fixTree($data);
58
    }
59
60
    /**
61
     * return the whole tree
62
     *
63
     * @return array
64
     * @access public
65
     * @api
66
     */
67
    public function getTree()/*# : array */
68
    {
69
        return $this->tree;
70
    }
71
72
    /**
73
     * Get one node, NULL if not found
74
     *
75
     * @param  string $nodeName
76
     * @return mixed
77
     * @access public
78
     * @api
79
     */
80
    public function &getNode(/*# string */ $nodeName)
81
    {
82
        if ('' === $nodeName) {
83
            $result = &$this->tree;
84
        } else {
85
            $result = &$this->searchNode($nodeName, $this->tree, false);
86
        }
87
        return $result;
88
    }
89
90
    /**
91
     * Delete one node if exists
92
     *
93
     * @param  string $nodeName
94
     * @return $this
95
     * @access public
96
     * @since  2.0.5
97
     * @api
98
     */
99
    public function deleteNode(/*# string */ $nodeName)
100
    {
101
        if ('' === $nodeName) {
102
            $this->tree = [];
103
        } else {
104
            $current = &$this->getNode($nodeName);
105
            if (null !== $current) {
106
                $split = explode($this->splitter, $nodeName);
107
                $name  = array_pop($split);
108
                $upper = &$this->getNode(join($this->splitter, $split));
109
                unset($upper[$name]);
110
            }
111
        }
112
        return $this;
113
    }
114
115
    /**
116
     * Fix array, convert flat name to tree node name
117
     *
118
     * @param  array $data
119
     * @return array
120
     * @access protected
121
     */
122
    protected function fixTree(array $data)/*# : array */
123
    {
124
        $result = [];
125
        foreach ($data as $k => $v) {
126
            $res = &$this->searchNode($k, $result);
127
            $res = is_array($v) ? $this->fixTree($v) : $v;
128
        }
129
        return $result;
130
    }
131
132
    /**
133
     * Search a node in the $data
134
     *
135
     * @param  string $key
136
     * @param  array &$data
137
     * @param  bool $create
138
     * @access protected
139
     */
140
    protected function &searchNode(
141
        /*# string */ $key,
142
        array &$data,
143
        /*# bool */ $create = true
144
    ) {
145
        $found = &$data;
146
        foreach (explode($this->splitter, $key) as $k) {
147
            if (isset($found[$k])) {
148
                $found = &$found[$k];
149
            } elseif ($create) {
150
                $found[$k] = [];
151
                $found = &$found[$k];
152
            } else {
153
                $found = null;
154
                break;
155
            }
156
        }
157
        return $found;
158
    }
159
}
160