Subversion Repositories oidplus

Rev

Rev 16 | Rev 27 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
5
 * Copyright 2019 Daniel Marschall, ViaThinkSoft
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
 
20
abstract class OIDplusObject {
21
        public static $registeredObjectTypes = array();
22
 
23
        public static function parse($node_id) { // please overwrite this function!
24
                // TODO: in case we are not calling this class directly, check if function is overwritten and throw exception otherwise
25
                foreach (self::$registeredObjectTypes as $ot) {
26
                        if ($obj = $ot::parse($node_id)) return $obj;
27
                }
28
                return null;
29
        }
30
 
31
        public abstract static function objectTypeTitle();
32
 
33
        public abstract static function objectTypeTitleShort();
34
 
35
        public abstract static function ns();
36
 
37
        public abstract static function root();
38
 
39
        public abstract function isRoot();
40
 
41
        public abstract function nodeId();
42
 
43
        public abstract function addString($str);
44
 
45
        public abstract function crudShowId(OIDplusObject $parent);
46
 
47
        public abstract function crudInsertPrefix();
48
 
49
        public abstract function jsTreeNodeName(OIDplusObject $parent = null);
50
 
51
        public abstract function defaultTitle();
52
 
16 daniel-mar 53
        public abstract function isLeafNode();
54
 
2 daniel-mar 55
        public abstract function getContentPage(&$title, &$content);
56
 
57
        private static function getRaRoots_rec($parent=null, $ra_email=null, &$out, $prev_owns) {
58
                if (is_null($parent)) {
59
                        $roots = array();
60
                        foreach (self::$registeredObjectTypes as $ot) {
61
                                $roots[] = "parent = '" . OIDplus::db()->real_escape_string($ot::root()) . "'";
62
                        }
63
                        $roots = implode(' or ', $roots);
64
                } else {
65
                        $roots = "parent = '" . OIDplus::db()->real_escape_string($parent) . "'";
66
                }
67
 
68
                $res = OIDplus::db()->query("select id, ra_email from ".OIDPLUS_TABLENAME_PREFIX."objects where $roots order by ".OIDplus::db()->natOrder('id'));
69
 
70
                $this_owns = array();
71
                $this_all = array();
72
                while ($row = OIDplus::db()->fetch_array($res)) {
73
                        if (is_null($ra_email)) {
74
                                // if $ra_email is null, we want to query only the roots of the currently logged in user
75
                                $owns = OIDplus::authUtils()::isRaLoggedIn($row['ra_email']);
76
                        } else {
77
                                $owns = $row['ra_email'] == $ra_email;
78
                        }
79
 
80
                        if ($owns) $this_owns[] = $row['id'];
81
                        $this_all[] = $row['id'];
82
                }
83
 
84
                foreach ($this_owns as $this_ra) {
85
                        $nogap = true;
86
                        if (!is_null($prev_owns)) {
87
                                // Check if we have any gaps. If there is a "gap" in the hierarchy, then we need to count that as a second root of that RA ("reintroduce ownership")
88
                                foreach ($prev_owns as $prev) {
89
                                        if (oid_up(explode(':',$this_ra)[1]) == explode(':',$prev)[1]) $nogap = false;
90
                                }
91
                        }
92
                        if ($nogap) $out[] = self::parse($this_ra);
93
                }
94
 
95
                foreach ($this_all as $this_ra) {
96
                        self::getRaRoots_rec($this_ra, $ra_email, $out, $this_owns);
97
                }
98
        }
99
 
100
        public static function getRaRoots($ra_email=null) {
101
                $out = array();
102
                self::getRaRoots_rec(null, $ra_email, $out, null);
103
                return $out;
104
        }
105
 
106
        private static function getAllNonConfidential_rec($parent=null, &$out) {
107
                if (is_null($parent)) {
108
                        $roots = array();
109
                        foreach (self::$registeredObjectTypes as $ot) {
110
                                $roots[] = "parent = '" . OIDplus::db()->real_escape_string($ot::root()) . "'";
111
                        }
112
                        $roots = implode(' or ', $roots);
113
                } else {
114
                        $roots = "parent = '" . OIDplus::db()->real_escape_string($parent) . "'";
115
                }
116
 
117
                $res = OIDplus::db()->query("select id, confidential from ".OIDPLUS_TABLENAME_PREFIX."objects where $roots order by ".OIDplus::db()->natOrder('id'));
118
 
119
                while ($row = OIDplus::db()->fetch_array($res)) {
120
                        if ($row['confidential'] == '1') {
121
                                // do nothing
122
                        } else {
123
                                $out[] = $row['id'];
124
                                self::getAllNonConfidential_rec($row['id'], $out);
125
                        }
126
                }
127
        }
128
 
129
        public static function getAllNonConfidential() {
130
                $out = array();
131
                self::getAllNonConfidential_rec(null, $out);
132
                return $out;
133
        }
134
 
135
        public function isConfidential() {
136
                $curid = $this->nodeId();
137
                // Recursively search for the confidential flag in the parents
138
                while (OIDplus::db()->num_rows($res = OIDplus::db()->query("select parent, confidential from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($curid)."'")) > 0) {
139
                        $row = OIDplus::db()->fetch_array($res);
140
                        if ($row['confidential']) return true;
141
                        $curid = $row['parent'];
142
                }
143
 
144
                return false;
145
        }
146
 
147
        public function isChildOf(OIDplusObject $obj) {
148
                $curid = $this->nodeId();
149
                while (OIDplus::db()->num_rows($res = OIDplus::db()->query("select parent from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($curid)."'")) > 0) {
150
                        $row = OIDplus::db()->fetch_array($res);
151
                        if ($curid == $obj->nodeId()) return true;
152
                        $curid = $row['parent'];
153
                }
154
 
155
                return false;
156
        }
157
 
158
        public function userHasReadRights($ra_email=null) {
159
                // Admin may do everything
160
                if (OIDplus::authUtils()::isAdminLoggedIn()) return true;
161
 
162
                // If it is not confidential, everybody can read/see it.
163
                if (!$this->isConfidential()) return true;
164
 
165
                // If we own the object, we may see it
166
                if (is_null($ra_email)) {
167
                        if ($this->userHasWriteRights()) return true;
168
                } else {
169
                        $res = OIDplus::db()->query("select ra_email from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
170
                        $row = OIDplus::db()->fetch_array($res);
171
                        if ($row['ra_email'] == $ra_email) return true;
172
                }
173
 
174
                // If someone has rights to an object below our confidential node,
175
                // we let him see the confidential node,
176
                // Otherwise he could not browse through to his own node.
177
                $roots = $this->getRaRoots($ra_email);
178
                foreach ($roots as $root) {
179
                        if ($root->isChildOf($this)) return true;
180
                }
181
 
182
                return false;
183
        }
184
 
185
        public function getIcon($row=null) {
20 daniel-mar 186
                $namespace = $this->ns(); // must use $this, not self::, otherwise the virtual method will not be called
2 daniel-mar 187
 
188
                if (is_null($row)) {
189
                        $res = OIDplus::db()->query("select ra_email from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
190
                        $row = OIDplus::db()->fetch_array($res);
191
                }
192
                // TODO: have different icons for Leaf-Nodes
193
                if (OIDplus::authUtils()::isRaLoggedIn($row['ra_email'])) {
194
                        $icon = 'plugins/objectTypes/'.$namespace.'/img/treeicon_own.png';
195
                } else {
196
                        $icon = 'plugins/objectTypes/'.$namespace.'/img/treeicon_general.png';
197
                }
198
                if (!file_exists($icon)) $icon = null; // default icon (folder)
199
                return $icon;
200
        }
201
 
12 daniel-mar 202
        public static function exists($id) {
203
                $res = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($id)."'");
204
                return OIDplus::db()->num_rows($res) > 0;
205
        }
206
 
2 daniel-mar 207
        public function getParent() {
208
                $res = OIDplus::db()->query("select parent from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
209
                $row = OIDplus::db()->fetch_array($res);
210
                $parent = $row['parent'];
20 daniel-mar 211
                $obj = OIDplusObject::parse($parent);
212
                if ($obj) return $obj;
213
 
214
                // If this OID does not exist, the SQL query "select parent from ..." does not work. So we try to find the next possible parent using oid_up()
215
                $cur = $this->one_up();
216
                if (!$cur) return false;
217
                do {
218
                        if ($fitting = self::findFitting($cur->nodeId())) return $fitting;
219
 
220
                        $prev = $cur;
221
                        $cur = $cur->one_up();
222
                        if (!$cur) return false;
223
                } while ($prev != $cur);
224
 
225
                return false;
2 daniel-mar 226
        }
227
 
228
        public function getRaMail() {
229
                $res = OIDplus::db()->query("select ra_email from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
230
                $row = OIDplus::db()->fetch_array($res);
231
                return $row['ra_email'];
232
        }
233
 
234
        public function userHasParentalWriteRights($ra_email=null) {
235
                if (is_null($ra_email)) {
236
                        if (OIDplus::authUtils()::isAdminLoggedIn()) return true;
237
                }
238
 
239
                $objParent = $this->getParent();
240
                if (is_null($objParent)) return false;
241
                return $objParent->userHasWriteRights($ra_email);
242
        }
243
 
244
        public function userHasWriteRights($ra_email=null) {
245
                if (is_null($ra_email)) {
246
                        if (OIDplus::authUtils()::isAdminLoggedIn()) return true;
247
                        return OIDplus::authUtils()::isRaLoggedIn($this->getRaMail());
248
                } else {
249
                        return $this->getRaMail() == $ra_email;
250
                }
251
        }
12 daniel-mar 252
 
253
        public function distance($to) {
254
                return null; // not implemented
255
        }
20 daniel-mar 256
 
257
        public function equals($obj) {
258
                if (!is_object($obj)) $obj = OIDplusObject::parse($obj);
259
                $distance = $this->distance($obj);
260
                if (is_numeric($distance)) return $distance === 0; // if the distance function is implemented, use it
261
 
262
                return $this->nodeId() == $obj->nodeId(); // otherwise compare the node id case-sensitive
263
        }
264
 
265
        public static function findFitting($id) {
266
                $obj = OIDplusObject::parse($id);
267
                if (!$obj) throw new Exception("findFitting: Parse failed\n");
268
 
269
                $res = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."objects where id like '".OIDplus::db()->real_escape_string($obj->ns()).":%'");
270
                while ($row = OIDplus::db()->fetch_object($res)) {
271
                        $test = OIDplusObject::parse($row->id);
272
                        if ($obj->equals($test)) return $test;
273
                }
274
                return false;
275
        }
276
 
277
        public function one_up() {
278
                return null; // not implemented
279
        }
2 daniel-mar 280
}