Completed
Push — master ( 02a1e8...a4a997 )
by Hong
02:57
created

Tree::getDelimiter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

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 1
eloc 2
nc 1
nop 0
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
 * @see     ObjectAbstract
25
 * @see     TreeInterface
26
 * @version 2.0.3
27
 * @since   2.0.3 added
28
 * @since   2.0.5 added deleteNode(), using TreeInterface
29
 */
30
class Tree extends ObjectAbstract implements TreeInterface
31
{
32
    /**
33
     * node splitter
34
     *
35
     * @var    string
36
     * @access protected
37
     */
38
    protected $splitter = '.';
39
40
    /**
41
     * the result tree
42
     *
43
     * @var    array
44
     * @access protected
45
     */
46
    protected $tree;
47
48
    /**
49
     * construct a tree
50
     *
51
     * @param  array $data
52
     * @param  string $splitter
53
     * @access public
54
     * @api
55
     */
56
    public function __construct(array $data = [], /*# string */ $splitter = '.')
57
    {
58
        $this->splitter = $splitter;
59
        $this->tree = $this->fixTree($data);
60
    }
61
62
    /**
63
     * {@inheritDoc}
64
     */
65
    public function getTree()/*# : array */
66
    {
67
        return $this->tree;
68
    }
69
70
    /**
71
     * {@inheritDoc}
72
     */
73
    public function &getNode(/*# string */ $nodeName)
74
    {
75
        if ('' === $nodeName) {
76
            $result = &$this->tree;
77
        } else {
78
            $result = &$this->searchNode($nodeName, $this->tree, false);
79
        }
80
        return $result;
81
    }
82
83
    /**
84
     * {@inheritDoc}
85
     */
86
    public function hasNode(/*# string */ $nodeName)/*# : bool */
87
    {
88
        if (null === $this->getNode($nodeName)) {
89
            return false;
90
        } else {
91
            return true;
92
        }
93
    }
94
95
    /**
96
     * {@inheritDoc}
97
     */
98
    public function addNode(/*# string */ $nodeName, $data)
99
    {
100
        $node = &$this->searchNode($nodeName, $this->tree, true);
101
        $node = $this->fixTree($data);
102
        return $this;
103
    }
104
105
    /**
106
     * {@inheritDoc}
107
     */
108
    public function deleteNode(/*# string */ $nodeName)
109
    {
110
        if ('' === $nodeName) {
111
            $this->tree = [];
112
        } else {
113
            $current = &$this->getNode($nodeName);
114
            if (null !== $current) {
115
                $split = explode($this->splitter, $nodeName);
116
                $name  = array_pop($split);
117
                $upper = &$this->getNode(join($this->splitter, $split));
118
                unset($upper[$name]);
119
            }
120
        }
121
        return $this;
122
    }
123
124
    /**
125
     * {@inheritDoc}
126
     */
127
    public function getDelimiter()/*# : string */
128
    {
129
        return $this->splitter;
130
    }
131
132
    /**
133
     * Fix array, convert flat name to tree node name
134
     *
135
     * @param  array $data
136
     * @return array
137
     * @access protected
138
     */
139
    protected function fixTree(array $data)/*# : array */
140
    {
141
        $result = [];
142
        foreach ($data as $k => $v) {
143
            $res = &$this->searchNode($k, $result);
144
            $res = is_array($v) ? $this->fixTree($v) : $v;
145
        }
146
        return $result;
147
    }
148
149
    /**
150
     * Search a node in the $data
151
     *
152
     * @param  string $key
153
     * @param  array &$data
154
     * @param  bool $create
155
     * @access protected
156
     */
157
    protected function &searchNode(
158
        /*# string */ $key,
159
        array &$data,
160
        /*# bool */ $create = true
161
    ) {
162
        $found = &$data;
163
        foreach (explode($this->splitter, $key) as $k) {
164
            if (isset($found[$k])) {
165
                $found = &$found[$k];
166
            } elseif ($create) {
167
                $found[$k] = [];
168
                $found = &$found[$k];
169
            } else {
170
                $found = null;
171
                break;
172
            }
173
        }
174
        return $found;
175
    }
176
}
177