Subversion Repositories oidplus

Rev

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