Subversion Repositories oidplus

Rev

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