TreeStore::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 5
dl 0
loc 7
rs 10
c 1
b 0
f 1
cc 1
nc 1
nop 4
1
<?php
2
namespace arc\store;
3
4
final class TreeStore implements Store {
5
6
    private $tree;
7
    private $queryParser;
8
    private $resultHandler;
9
    private $path;
10
11
    /**
12
     * MemStore constructor.
13
     * @param \arc\tree\Node $tree
14
     * @param callable $queryParser
15
     * @param callable $resultHandler
16
     * @param string $path
17
     */
18
    public function __construct($tree = null, $queryParser = null, $resultHandler = null, $path = '/')
19
    {
20
        $this->tree          = $tree;
21
        $this->queryParser   = $queryParser;
22
        $this->resultHandlerFactory = $resultHandler;
0 ignored issues
show
Bug Best Practice introduced by
The property resultHandlerFactory does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
23
        $this->resultHandler = $resultHandler($this->tree);
24
        $this->path          = \arc\path::collapse($path);
25
    }
26
27
    /**
28
     * change the current path, returns a new store instance for that path
29
     * @param string $path
30
     * @return PSQLStore
31
     */
32
    public function cd($path)
33
    {
34
        return new self( $this->tree, $this->queryParser, $this->resultHandlerFactory, \arc\path::collapse($path, $this->path) );
0 ignored issues
show
Bug Best Practice introduced by
The expression return new self($this->t...se($path, $this->path)) returns the type arc\store\TreeStore which is incompatible with the documented return type arc\store\PSQLStore.
Loading history...
35
    }
36
37
    /**
38
     * creates sql query for the search query and returns the resulthandler
39
     * @param string $query
40
     * @param string $path
41
     * @return mixed
42
     */
43
    public function find($query, $path='')
44
    {
45
        $path = \arc\path::collapse($path, $this->path);
46
        $root = $this->tree->cd($path);
0 ignored issues
show
Unused Code introduced by
The assignment to $root is dead and can be removed.
Loading history...
Bug introduced by
The method cd() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

46
        /** @scrutinizer ignore-call */ 
47
        $root = $this->tree->cd($path);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
47
        $f    = $this->queryParser->parse($query, $path);
0 ignored issues
show
Bug introduced by
The method parse() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

47
        /** @scrutinizer ignore-call */ 
48
        $f    = $this->queryParser->parse($query, $path);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
48
        return call_user_func($this->resultHandler, $f );
49
    }
50
51
    /**
52
     * get a single object from the store by path
53
     * @param string $path
54
     * @return mixed
55
     */
56
    public function get($path='')
57
    {
58
        $path   = \arc\path::collapse($path, $this->path);
59
        $result = $this->tree->cd($path);
60
        return $result;
61
    }
62
63
    /**
64
     * list all parents, including self, by path, starting from the root
65
     * @param string $path
66
     * @param string $top
67
     * @return mixed
68
     */
69
    public function parents($path='', $top='/')
70
    {
71
        $path   = \arc\path::collapse($path, $this->path);
72
        return ($this->resultHandler)(
73
            'strtolower($node->path)==strtolower(substring("'
74
            .$path.'",1,'.sizeof($path)
0 ignored issues
show
Bug introduced by
$path of type string is incompatible with the type Countable|array expected by parameter $value of sizeof(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

74
            .$path.'",1,'.sizeof(/** @scrutinizer ignore-type */ $path)
Loading history...
75
            .') && like(strtolower($node->path),strtolower("'.$top.'")'
76
        );
77
    }
78
79
    /**
80
     * list all child objects by path
81
     * @param string $path
82
     * @return mixed
83
     */
84
    public function ls($path='')
85
    {
86
        $path  = \arc\path::collapse($path, $this->path);
87
        return $this->tree->cd($path)->ls(function($node) {
88
            return json_decode(json_encode($node->nodeValue),false);
89
        });
90
    }
91
92
    /**
93
     * returns true if an object with the given path exists
94
     * @param string $path
95
     * @return bool
96
     */
97
    public function exists($path='')
98
    {
99
        $path   = \arc\path::collapse($path, $this->path);
100
        if ($path!='/') {
101
            $parent = ($path=='/' ? '' : \arc\path::parent($path));
102
            $name   = basename($path);
103
            return $this->tree->cd($parent)->childNodes->offsetExists($name);
104
        }
105
        return true;
106
    }
107
108
    /**
109
     * initialize the postgresql database, if it wasn't before
110
     * @return bool|mixed
111
     */
112
    public function initialize() {
113
        return $this->save(\arc\prototype::create([
114
            'name' => 'Root'
115
        ]),'/');
116
    }
117
118
    /**
119
     * save (insert or update) a single object on the given path
120
     * @param $data
121
     * @param string $path
122
     * @return mixed
123
     */
124
    public function save($data, $path='') {
125
        $path   = \arc\path::collapse($path, $this->path);
126
        $parent = ($path=='/' ? '' : \arc\path::parent($path));
127
        if ($path!='/' && !$this->exists($parent)) {
128
            throw new \arc\IllegalRequest("Parent $parent not found.", \arc\exceptions::OBJECT_NOT_FOUND);
129
        }
130
        $parentNode = $this->tree->cd($parent);
131
        $name = ($path=='/' ? '' : basename($path));
132
        if ($name) {
133
            $parentNode->appendChild($name, $data);
134
        } else {
135
            $parentNode->nodeValue = $data;
136
        }
137
        return true;
138
    }
139
140
    /**
141
     * remove the object with the given path and all its children
142
     * won't remove the root object ever
143
     * @param string $path
144
     * @return mixed
145
     */
146
    public function delete($path = '') {
147
        $path   = \arc\path::collapse($path, $this->path);
148
        $parent = \arc\path::parent($path);
149
        $name   = basename($path);
150
        $this->tree->cd($parent)->removeChild($name);
151
        return true;
152
    }
153
154
155
    public static function getResultHandler($tree)
156
    {
157
        return function($callback) use ($tree) {
158
            $dataset = \arc\tree::filter($tree, $callback);
159
            foreach($dataset as $path => $node) {
160
                $node = json_decode(json_encode($node),false);
161
                $dataset[$path] = $node;
162
            }
163
            return $dataset;
164
        };
165
    }
166
}
167