Subversion Repositories oidplus

Rev

Rev 68 | Rev 84 | 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 function parse($node_id) { // please overwrite this function!
22
                // TODO: in case we are not calling this class directly, check if function is overwritten and throw exception otherwise
61 daniel-mar 23
                foreach (OIDplus::getRegisteredObjectTypes() as $ot) {
2 daniel-mar 24
                        if ($obj = $ot::parse($node_id)) return $obj;
25
                }
26
                return null;
27
        }
28
 
83 daniel-mar 29
        public function getOid() {
30
                if ($this->ns() == 'oid') {
31
                        return $this->getDotNotation();
32
                } else {
33
                        return OIDplus::system_id(true) . '.' . smallhash($this->nodeId());
34
                }
35
        }
36
 
2 daniel-mar 37
        public abstract static function objectTypeTitle();
38
 
39
        public abstract static function objectTypeTitleShort();
40
 
41
        public abstract static function ns();
42
 
43
        public abstract static function root();
44
 
45
        public abstract function isRoot();
46
 
47
        public abstract function nodeId();
48
 
49
        public abstract function addString($str);
50
 
51
        public abstract function crudShowId(OIDplusObject $parent);
52
 
53
        public abstract function crudInsertPrefix();
54
 
55
        public abstract function jsTreeNodeName(OIDplusObject $parent = null);
56
 
57
        public abstract function defaultTitle();
58
 
16 daniel-mar 59
        public abstract function isLeafNode();
60
 
34 daniel-mar 61
        public abstract function getContentPage(&$title, &$content, &$icon);
2 daniel-mar 62
 
27 daniel-mar 63
        public static function getRaRoots($ra_email=null) {
64
                $out = array();
65
                if (is_null($ra_email)) {
66
                        $res = OIDplus::db()->query("select oChild.id as id, oChild.ra_email as child_mail, oParent.ra_email as parent_mail from ".OIDPLUS_TABLENAME_PREFIX."objects as oChild ".
67
                                                    "left join ".OIDPLUS_TABLENAME_PREFIX."objects as oParent on oChild.parent = oParent.id ".
68
                                                    "order by ".OIDplus::db()->natOrder('oChild.id'));
69
                        while ($row = OIDplus::db()->fetch_array($res)) {
70
                                if (!OIDplus::authUtils()::isRaLoggedIn($row['parent_mail']) && OIDplus::authUtils()::isRaLoggedIn($row['child_mail'])) {
68 daniel-mar 71
                                        $x = self::parse($row['id']); // can be FALSE if namespace was disabled
72
                                        if ($x) $out[] = $x;
27 daniel-mar 73
                                }
2 daniel-mar 74
                        }
75
                } else {
27 daniel-mar 76
                        $res = OIDplus::db()->query("select oChild.id as id from ".OIDPLUS_TABLENAME_PREFIX."objects as oChild ".
77
                                                    "left join ".OIDPLUS_TABLENAME_PREFIX."objects as oParent on oChild.parent = oParent.id ".
83 daniel-mar 78
                                                    "where (ifnull(oParent.ra_email,'') <> '".OIDplus::db()->real_escape_string($ra_email)."' and ifnull(oChild.ra_email,'') = '".OIDplus::db()->real_escape_string($ra_email)."') or ".
79
                                                    "      (oParent.ra_email is null and ifnull(oChild.ra_email,'') = '".OIDplus::db()->real_escape_string($ra_email)."') ".
27 daniel-mar 80
                                                    "order by ".OIDplus::db()->natOrder('oChild.id'));
81
                        while ($row = OIDplus::db()->fetch_array($res)) {
68 daniel-mar 82
                                $x = self::parse($row['id']); // can be FALSE if namespace was disabled
83
                                if ($x) $out[] = self::parse($row['id']);
2 daniel-mar 84
                        }
85
                }
86
                return $out;
87
        }
88
 
89
        private static function getAllNonConfidential_rec($parent=null, &$out) {
90
                if (is_null($parent)) {
91
                        $roots = array();
61 daniel-mar 92
                        foreach (OIDplus::getRegisteredObjectTypes() as $ot) {
2 daniel-mar 93
                                $roots[] = "parent = '" . OIDplus::db()->real_escape_string($ot::root()) . "'";
94
                        }
95
                        $roots = implode(' or ', $roots);
96
                } else {
97
                        $roots = "parent = '" . OIDplus::db()->real_escape_string($parent) . "'";
98
                }
99
 
100
                $res = OIDplus::db()->query("select id, confidential from ".OIDPLUS_TABLENAME_PREFIX."objects where $roots order by ".OIDplus::db()->natOrder('id'));
101
 
102
                while ($row = OIDplus::db()->fetch_array($res)) {
103
                        if ($row['confidential'] == '1') {
104
                                // do nothing
105
                        } else {
106
                                $out[] = $row['id'];
107
                                self::getAllNonConfidential_rec($row['id'], $out);
108
                        }
109
                }
110
        }
111
 
112
        public static function getAllNonConfidential() {
113
                $out = array();
114
                self::getAllNonConfidential_rec(null, $out);
115
                return $out;
116
        }
117
 
118
        public function isConfidential() {
119
                $curid = $this->nodeId();
120
                // Recursively search for the confidential flag in the parents
121
                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) {
122
                        $row = OIDplus::db()->fetch_array($res);
123
                        if ($row['confidential']) return true;
124
                        $curid = $row['parent'];
125
                }
126
 
127
                return false;
128
        }
129
 
130
        public function isChildOf(OIDplusObject $obj) {
131
                $curid = $this->nodeId();
132
                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) {
133
                        $row = OIDplus::db()->fetch_array($res);
134
                        if ($curid == $obj->nodeId()) return true;
135
                        $curid = $row['parent'];
136
                }
137
 
138
                return false;
139
        }
140
 
141
        public function userHasReadRights($ra_email=null) {
142
                // Admin may do everything
143
                if (OIDplus::authUtils()::isAdminLoggedIn()) return true;
144
 
145
                // If it is not confidential, everybody can read/see it.
146
                if (!$this->isConfidential()) return true;
147
 
148
                // If we own the object, we may see it
149
                if (is_null($ra_email)) {
150
                        if ($this->userHasWriteRights()) return true;
151
                } else {
152
                        $res = OIDplus::db()->query("select ra_email from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
153
                        $row = OIDplus::db()->fetch_array($res);
154
                        if ($row['ra_email'] == $ra_email) return true;
155
                }
156
 
157
                // If someone has rights to an object below our confidential node,
158
                // we let him see the confidential node,
159
                // Otherwise he could not browse through to his own node.
160
                $roots = $this->getRaRoots($ra_email);
161
                foreach ($roots as $root) {
162
                        if ($root->isChildOf($this)) return true;
163
                }
164
 
165
                return false;
166
        }
167
 
168
        public function getIcon($row=null) {
20 daniel-mar 169
                $namespace = $this->ns(); // must use $this, not self::, otherwise the virtual method will not be called
2 daniel-mar 170
 
171
                if (is_null($row)) {
172
                        $res = OIDplus::db()->query("select ra_email from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
173
                        $row = OIDplus::db()->fetch_array($res);
174
                }
175
                // TODO: have different icons for Leaf-Nodes
176
                if (OIDplus::authUtils()::isRaLoggedIn($row['ra_email'])) {
177
                        $icon = 'plugins/objectTypes/'.$namespace.'/img/treeicon_own.png';
178
                } else {
179
                        $icon = 'plugins/objectTypes/'.$namespace.'/img/treeicon_general.png';
180
                }
181
                if (!file_exists($icon)) $icon = null; // default icon (folder)
182
                return $icon;
183
        }
184
 
12 daniel-mar 185
        public static function exists($id) {
186
                $res = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($id)."'");
187
                return OIDplus::db()->num_rows($res) > 0;
188
        }
189
 
2 daniel-mar 190
        public function getParent() {
191
                $res = OIDplus::db()->query("select parent from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
192
                $row = OIDplus::db()->fetch_array($res);
193
                $parent = $row['parent'];
20 daniel-mar 194
                $obj = OIDplusObject::parse($parent);
195
                if ($obj) return $obj;
196
 
27 daniel-mar 197
                // 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 one_up()
20 daniel-mar 198
                $cur = $this->one_up();
199
                if (!$cur) return false;
200
                do {
201
                        if ($fitting = self::findFitting($cur->nodeId())) return $fitting;
202
 
203
                        $prev = $cur;
204
                        $cur = $cur->one_up();
205
                        if (!$cur) return false;
206
                } while ($prev != $cur);
207
 
208
                return false;
2 daniel-mar 209
        }
210
 
211
        public function getRaMail() {
212
                $res = OIDplus::db()->query("select ra_email from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
213
                $row = OIDplus::db()->fetch_array($res);
214
                return $row['ra_email'];
215
        }
216
 
217
        public function userHasParentalWriteRights($ra_email=null) {
218
                if (is_null($ra_email)) {
219
                        if (OIDplus::authUtils()::isAdminLoggedIn()) return true;
220
                }
221
 
222
                $objParent = $this->getParent();
223
                if (is_null($objParent)) return false;
224
                return $objParent->userHasWriteRights($ra_email);
225
        }
226
 
227
        public function userHasWriteRights($ra_email=null) {
228
                if (is_null($ra_email)) {
229
                        if (OIDplus::authUtils()::isAdminLoggedIn()) return true;
230
                        return OIDplus::authUtils()::isRaLoggedIn($this->getRaMail());
231
                } else {
232
                        return $this->getRaMail() == $ra_email;
233
                }
234
        }
12 daniel-mar 235
 
236
        public function distance($to) {
237
                return null; // not implemented
238
        }
20 daniel-mar 239
 
240
        public function equals($obj) {
241
                if (!is_object($obj)) $obj = OIDplusObject::parse($obj);
28 daniel-mar 242
                if (!($obj instanceof $this)) return false;
243
 
20 daniel-mar 244
                $distance = $this->distance($obj);
245
                if (is_numeric($distance)) return $distance === 0; // if the distance function is implemented, use it
246
 
247
                return $this->nodeId() == $obj->nodeId(); // otherwise compare the node id case-sensitive
248
        }
249
 
250
        public static function findFitting($id) {
251
                $obj = OIDplusObject::parse($id);
252
                if (!$obj) throw new Exception("findFitting: Parse failed\n");
253
 
254
                $res = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."objects where id like '".OIDplus::db()->real_escape_string($obj->ns()).":%'");
255
                while ($row = OIDplus::db()->fetch_object($res)) {
256
                        $test = OIDplusObject::parse($row->id);
257
                        if ($obj->equals($test)) return $test;
258
                }
259
                return false;
260
        }
261
 
262
        public function one_up() {
263
                return null; // not implemented
264
        }
2 daniel-mar 265
}