Subversion Repositories oidplus

Rev

Rev 956 | Rev 975 | 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
929 daniel-mar 5
 * Copyright 2019 - 2022 Daniel Marschall, ViaThinkSoft
2 daniel-mar 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
 
511 daniel-mar 20
if (!defined('INSIDE_OIDPLUS')) die();
21
 
730 daniel-mar 22
abstract class OIDplusObject extends OIDplusBaseClass {
261 daniel-mar 23
        const UUID_NAMEBASED_NS_OidPlusMisc = 'ad1654e6-7e15-11e4-9ef6-78e3b5fc7f22';
150 daniel-mar 24
 
2 daniel-mar 25
        public static function parse($node_id) { // please overwrite this function!
227 daniel-mar 26
                foreach (OIDplus::getEnabledObjectTypes() as $ot) {
954 daniel-mar 27
                        try {
956 daniel-mar 28
                                $good = false;
29
                                if (get_parent_class($ot) == 'OIDplusObject') {
30
                                        $reflector = new \ReflectionMethod($ot, 'parse');
31
                                        $isImplemented = ($reflector->getDeclaringClass()->getName() === $ot);
32
                                        if ($isImplemented) { // avoid endless loop if parse is not overriden
33
                                                $good = true;
34
                                        }
35
                                }
36
                                // We need to do the workaround with "$good", otherwise PHPstan shows
37
                                // "Call to an undefined static method object::parse()"
38
                                if ($good && $obj = $ot::parse($node_id)) return $obj;
954 daniel-mar 39
                        } catch (Exception $e) {}
2 daniel-mar 40
                }
41
                return null;
42
        }
43
 
228 daniel-mar 44
        public function /*OIDplusAltId[]*/ getAltIds() {
193 daniel-mar 45
                if ($this->isRoot()) return array();
46
 
47
                $ids = array();
48
                if ($this->ns() != 'oid') {
49
                        // Creates an OIDplus-Hash-OID
227 daniel-mar 50
                        $sid = OIDplus::getSystemId(true);
193 daniel-mar 51
                        if (!empty($sid)) {
817 daniel-mar 52
                                $ns_oid = $this->getPlugin()->getManifest()->getOid();
835 daniel-mar 53
                                if (str_starts_with($ns_oid, '1.3.6.1.4.1.37476.2.5.2.')) {
817 daniel-mar 54
                                        // Official ViaThinkSoft object type plugins
55
                                        // For backwards compatibility with existing IDs,
56
                                        // set the hash_payload as '<namespace>:<id>'
57
                                        $hash_payload = $this->nodeId(true);
58
                                } else {
59
                                        // Third-party object type plugins
60
                                        // Set the hash_payload as '<plugin oid>:<id>'
61
                                        $hash_payload = $ns_oid.':'.$this->nodeId(false);
62
                                }
63
                                $oid = $sid . '.' . smallhash($hash_payload);
360 daniel-mar 64
                                $ids[] = new OIDplusAltId('oid', $oid, _L('OIDplus Information Object ID'));
193 daniel-mar 65
                        }
929 daniel-mar 66
 
67
                        // Make a namebased UUID, but...
68
                        // ... exclude GUID, because a GUID is already a GUID
69
                        // ... exclude OID, because an OID already has a record UUID_NAMEBASED_NS_OID set  by class OIDplusOid
70
                        if ($this->ns() != 'guid') {
71
                                $ids[] = new OIDplusAltId('guid', gen_uuid_md5_namebased(self::UUID_NAMEBASED_NS_OidPlusMisc, $this->nodeId()), _L('Name based version 3 / MD5 UUID with namespace %1','UUID_NAMEBASED_NS_OidPlusMisc'));
72
                                $ids[] = new OIDplusAltId('guid', gen_uuid_sha1_namebased(self::UUID_NAMEBASED_NS_OidPlusMisc, $this->nodeId()), _L('Name based version 5 / SHA1 UUID with namespace %1','UUID_NAMEBASED_NS_OidPlusMisc'));
73
                        }
193 daniel-mar 74
                }
75
                return $ids;
83 daniel-mar 76
        }
77
 
2 daniel-mar 78
        public abstract static function objectTypeTitle();
79
 
80
        public abstract static function objectTypeTitleShort();
81
 
817 daniel-mar 82
        public function getPlugin()/*: ?OIDplusObjectTypePlugin */ {
83
                $res = null;
84
                $plugins = OIDplus::getObjectTypePlugins();
85
                foreach ($plugins as $plugin) {
86
                        if (get_class($this) == $plugin::getObjectTypeClassName($this)) {
87
                                return $plugin;
88
                        }
89
                }
90
                return $res;
91
        }
92
 
2 daniel-mar 93
        public abstract static function ns();
94
 
95
        public abstract static function root();
96
 
97
        public abstract function isRoot();
98
 
247 daniel-mar 99
        public abstract function nodeId($with_ns=true);
2 daniel-mar 100
 
101
        public abstract function addString($str);
102
 
103
        public abstract function crudShowId(OIDplusObject $parent);
104
 
707 daniel-mar 105
        public function crudInsertPrefix() {
106
                return '';
107
        }
2 daniel-mar 108
 
707 daniel-mar 109
        public function crudInsertSuffix() {
110
                return '';
111
        }
112
 
2 daniel-mar 113
        public abstract function jsTreeNodeName(OIDplusObject $parent = null);
114
 
115
        public abstract function defaultTitle();
116
 
16 daniel-mar 117
        public abstract function isLeafNode();
118
 
34 daniel-mar 119
        public abstract function getContentPage(&$title, &$content, &$icon);
2 daniel-mar 120
 
27 daniel-mar 121
        public static function getRaRoots($ra_email=null) {
115 daniel-mar 122
                if ($ra_email instanceof OIDplusRA) $ra_email = $ra_email->raEmail();
123
 
27 daniel-mar 124
                $out = array();
150 daniel-mar 125
 
261 daniel-mar 126
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
150 daniel-mar 127
                        if (is_null($ra_email)) {
261 daniel-mar 128
                                $res = OIDplus::db()->query("select oChild.id as id, oChild.ra_email as child_mail, oParent.ra_email as parent_mail from ###objects as oChild ".
129
                                                            "left join ###objects as oParent on oChild.parent = oParent.id ".
150 daniel-mar 130
                                                            "order by ".OIDplus::db()->natOrder('oChild.id'));
236 daniel-mar 131
                                while ($row = $res->fetch_array()) {
549 daniel-mar 132
                                        if (!OIDplus::authUtils()->isRaLoggedIn($row['parent_mail']) && OIDplus::authUtils()->isRaLoggedIn($row['child_mail'])) {
150 daniel-mar 133
                                                $x = self::parse($row['id']); // can be FALSE if namespace was disabled
134
                                                if ($x) $out[] = $x;
135
                                        }
136
                                }
137
                        } else {
261 daniel-mar 138
                                $res = OIDplus::db()->query("select oChild.id as id from ###objects as oChild ".
139
                                                            "left join ###objects as oParent on oChild.parent = oParent.id ".
433 daniel-mar 140
                                                            "where (".OIDplus::db()->getSlang()->isNullFunction('oParent.ra_email',"''")." <> ? and ".
141
                                                            OIDplus::db()->getSlang()->isNullFunction('oChild.ra_email',"''")." = ?) or ".
142
                                                            "      (oParent.ra_email is null and ".OIDplus::db()->getSlang()->isNullFunction('oChild.ra_email',"''")." = ?) ".
150 daniel-mar 143
                                                            "order by ".OIDplus::db()->natOrder('oChild.id'), array($ra_email, $ra_email, $ra_email));
236 daniel-mar 144
                                while ($row = $res->fetch_array()) {
68 daniel-mar 145
                                        $x = self::parse($row['id']); // can be FALSE if namespace was disabled
150 daniel-mar 146
                                        if ($x) $out[] = self::parse($row['id']);
27 daniel-mar 147
                                }
2 daniel-mar 148
                        }
149
                } else {
150 daniel-mar 150
                        if (is_null($ra_email)) {
415 daniel-mar 151
                                $ra_mails_to_check = OIDplus::authUtils()->loggedInRaList();
150 daniel-mar 152
                                if (count($ra_mails_to_check) == 0) return $out;
153
                        } else {
154
                                $ra_mails_to_check = array($ra_email);
2 daniel-mar 155
                        }
150 daniel-mar 156
 
157
                        self::buildObjectInformationCache();
158
 
159
                        foreach ($ra_mails_to_check as $check_ra_mail) {
193 daniel-mar 160
                                $out_part = array();
150 daniel-mar 161
 
193 daniel-mar 162
                                foreach (self::$object_info_cache as $id => list($confidential, $parent, $ra_email, $title)) {
163
                                        // If the OID RA is the RA we are searching, then add the object to the choice list
164
                                        if ($ra_email == $check_ra_mail) $out_part[] = $id;
150 daniel-mar 165
                                }
166
 
193 daniel-mar 167
                                foreach (self::$object_info_cache as $id => list($confidential, $parent, $ra_email, $title)) {
168
                                        if (isset(self::$object_info_cache[$parent])) {
169
                                                if (self::$object_info_cache[$parent][self::CACHE_RA_EMAIL] == $ra_email) {
170
                                                        // if the parent has the same RA, then this OID cannot be a root => remove the element from the choice list
171
                                                        foreach (array_keys($out_part, $id) as $key) unset($out_part[$key]);
150 daniel-mar 172
                                                }
173
                                        }
174
                                }
175
 
176
                                natsort($out_part);
177
 
178
                                foreach ($out_part as $id) {
179
                                        $obj = self::parse($id);
180
                                        if ($obj) $out[] = $obj;
181
                                }
182
                        }
2 daniel-mar 183
                }
150 daniel-mar 184
 
2 daniel-mar 185
                return $out;
186
        }
187
 
150 daniel-mar 188
        public static function getAllNonConfidential() {
189
                $out = array();
190
 
261 daniel-mar 191
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
443 daniel-mar 192
                        $res = OIDplus::db()->query("select id from ###objects where confidential = ? order by ".OIDplus::db()->natOrder('id'), array(false));
150 daniel-mar 193
 
236 daniel-mar 194
                        while ($row = $res->fetch_array()) {
150 daniel-mar 195
                                $obj = self::parse($row['id']); // will be NULL if the object type is not registered
169 daniel-mar 196
                                if ($obj && (!$obj->isConfidential())) {
150 daniel-mar 197
                                        $out[] = $row['id'];
198
                                }
2 daniel-mar 199
                        }
200
                } else {
150 daniel-mar 201
                        self::buildObjectInformationCache();
2 daniel-mar 202
 
193 daniel-mar 203
                        foreach (self::$object_info_cache as $id => list($confidential, $parent, $ra_email, $title)) {
150 daniel-mar 204
                                if (!$confidential) {
205
                                        $obj = self::parse($id); // will be NULL if the object type is not registered
169 daniel-mar 206
                                        if ($obj && (!$obj->isConfidential())) {
150 daniel-mar 207
                                                $out[] = $id;
208
                                        }
209
                                }
2 daniel-mar 210
                        }
211
                }
212
 
213
                return $out;
214
        }
215
 
216
        public function isConfidential() {
261 daniel-mar 217
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
426 daniel-mar 218
                        //static $confidential_cache = array();
150 daniel-mar 219
                        $curid = $this->nodeId();
426 daniel-mar 220
                        //$orig_curid = $curid;
221
                        //if (isset($confidential_cache[$curid])) return $confidential_cache[$curid];
150 daniel-mar 222
                        // Recursively search for the confidential flag in the parents
790 daniel-mar 223
                        while (($res = OIDplus::db()->query("select parent, confidential from ###objects where id = ?", array($curid)))->any()) {
236 daniel-mar 224
                                $row = $res->fetch_array();
150 daniel-mar 225
                                if ($row['confidential']) {
426 daniel-mar 226
                                        //$confidential_cache[$curid] = true;
227
                                        //$confidential_cache[$orig_curid] = true;
150 daniel-mar 228
                                        return true;
229
                                } else {
426 daniel-mar 230
                                        //$confidential_cache[$curid] = false;
150 daniel-mar 231
                                }
232
                                $curid = $row['parent'];
426 daniel-mar 233
                                //if (isset($confidential_cache[$curid])) {
234
                                        //$confidential_cache[$orig_curid] = $confidential_cache[$curid];
235
                                        //return $confidential_cache[$curid];
236
                                //}
150 daniel-mar 237
                        }
238
 
426 daniel-mar 239
                        //$confidential_cache[$orig_curid] = false;
150 daniel-mar 240
                        return false;
241
                } else {
242
                        self::buildObjectInformationCache();
243
 
244
                        $curid = $this->nodeId();
245
                        // Recursively search for the confidential flag in the parents
169 daniel-mar 246
                        while (isset(self::$object_info_cache[$curid])) {
150 daniel-mar 247
                                if (self::$object_info_cache[$curid][self::CACHE_CONFIDENTIAL]) return true;
248
                                $curid = self::$object_info_cache[$curid][self::CACHE_PARENT];
249
                        }
250
                        return false;
2 daniel-mar 251
                }
252
        }
253
 
254
        public function isChildOf(OIDplusObject $obj) {
261 daniel-mar 255
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
150 daniel-mar 256
                        $curid = $this->nodeId();
790 daniel-mar 257
                        while (($res = OIDplus::db()->query("select parent from ###objects where id = ?", array($curid)))->any()) {
236 daniel-mar 258
                                $row = $res->fetch_array();
150 daniel-mar 259
                                if ($curid == $obj->nodeId()) return true;
260
                                $curid = $row['parent'];
261
                        }
262
                        return false;
263
                } else {
264
                        self::buildObjectInformationCache();
265
 
266
                        $curid = $this->nodeId();
169 daniel-mar 267
                        while (isset(self::$object_info_cache[$curid])) {
150 daniel-mar 268
                                if ($curid == $obj->nodeId()) return true;
269
                                $curid = self::$object_info_cache[$curid][self::CACHE_PARENT];
270
                        }
271
                        return false;
2 daniel-mar 272
                }
150 daniel-mar 273
        }
2 daniel-mar 274
 
150 daniel-mar 275
        public function getChildren() {
276
                $out = array();
261 daniel-mar 277
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
278
                        $res = OIDplus::db()->query("select id from ###objects where parent = ?", array($this->nodeId()));
236 daniel-mar 279
                        while ($row = $res->fetch_array()) {
150 daniel-mar 280
                                $obj = self::parse($row['id']);
281
                                if (!$obj) continue;
282
                                $out[] = $obj;
283
                        }
284
                } else {
285
                        self::buildObjectInformationCache();
286
 
193 daniel-mar 287
                        foreach (self::$object_info_cache as $id => list($confidential, $parent, $ra_email, $title)) {
150 daniel-mar 288
                                if ($parent == $this->nodeId()) {
289
                                        $obj = self::parse($id);
290
                                        if (!$obj) continue;
291
                                        $out[] = $obj;
292
                                }
293
                        }
294
                }
295
                return $out;
2 daniel-mar 296
        }
297
 
115 daniel-mar 298
        public function getRa() {
150 daniel-mar 299
                return new OIDplusRA($this->getRaMail());
115 daniel-mar 300
        }
301
 
2 daniel-mar 302
        public function userHasReadRights($ra_email=null) {
115 daniel-mar 303
                if ($ra_email instanceof OIDplusRA) $ra_email = $ra_email->raEmail();
304
 
2 daniel-mar 305
                // If it is not confidential, everybody can read/see it.
416 daniel-mar 306
                // Note: This also checks if superior OIDs are confidential.
2 daniel-mar 307
                if (!$this->isConfidential()) return true;
308
 
309
                if (is_null($ra_email)) {
416 daniel-mar 310
                        // Admin may do everything
549 daniel-mar 311
                        if (OIDplus::authUtils()->isAdminLoggedIn()) return true;
416 daniel-mar 312
 
313
                        // If the RA is logged in, then they can see the OID.
549 daniel-mar 314
                        if (OIDplus::authUtils()->isRaLoggedIn($this->getRaMail())) return true;
2 daniel-mar 315
                } else {
416 daniel-mar 316
                        // If this OID belongs to the requested RA, then they may see it.
150 daniel-mar 317
                        if ($this->getRaMail() == $ra_email) return true;
2 daniel-mar 318
                }
319
 
320
                // If someone has rights to an object below our confidential node,
321
                // we let him see the confidential node,
322
                // Otherwise he could not browse through to his own node.
323
                $roots = $this->getRaRoots($ra_email);
324
                foreach ($roots as $root) {
325
                        if ($root->isChildOf($this)) return true;
326
                }
327
 
328
                return false;
329
        }
330
 
331
        public function getIcon($row=null) {
20 daniel-mar 332
                $namespace = $this->ns(); // must use $this, not self::, otherwise the virtual method will not be called
2 daniel-mar 333
 
334
                if (is_null($row)) {
150 daniel-mar 335
                        $ra_email = $this->getRaMail();
336
                } else {
337
                        $ra_email = $row['ra_email'];
2 daniel-mar 338
                }
339
                // TODO: have different icons for Leaf-Nodes
632 daniel-mar 340
 
635 daniel-mar 341
                $dirs = glob(OIDplus::localpath().'plugins/'.'*'.'/objectTypes/'.$namespace.'/');
632 daniel-mar 342
 
343
                if (count($dirs) == 0) return null; // default icon (folder)
344
 
345
                $dir = substr($dirs[0], strlen(OIDplus::localpath()));
346
 
805 daniel-mar 347
                // We use $this:: instead of self:: , because we want to call the overridden methods
549 daniel-mar 348
                if (OIDplus::authUtils()->isRaLoggedIn($ra_email)) {
805 daniel-mar 349
                        $icon = $dir.'/'.$this::treeIconFilename('own');
2 daniel-mar 350
                } else {
805 daniel-mar 351
                        $icon = $dir.'/'.$this::treeIconFilename('general');
2 daniel-mar 352
                }
632 daniel-mar 353
 
354
                if (!file_exists($icon)) return null; // default icon (folder)
355
 
2 daniel-mar 356
                return $icon;
357
        }
358
 
12 daniel-mar 359
        public static function exists($id) {
261 daniel-mar 360
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
361
                        $res = OIDplus::db()->query("select id from ###objects where id = ?", array($id));
790 daniel-mar 362
                        return $res->any();
150 daniel-mar 363
                } else {
364
                        self::buildObjectInformationCache();
365
                        return isset(self::$object_info_cache[$id]);
366
                }
12 daniel-mar 367
        }
368
 
415 daniel-mar 369
        // Get parent gives the next possible parent which is EXISTING in OIDplus
370
        // It does not give the immediate parent
2 daniel-mar 371
        public function getParent() {
261 daniel-mar 372
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
373
                        $res = OIDplus::db()->query("select parent from ###objects where id = ?", array($this->nodeId()));
790 daniel-mar 374
                        if (!$res->any()) return null;
236 daniel-mar 375
                        $row = $res->fetch_array();
150 daniel-mar 376
                        $parent = $row['parent'];
377
                        $obj = OIDplusObject::parse($parent);
378
                        if ($obj) return $obj;
415 daniel-mar 379
                        // TODO: Also implement one_up() like below
150 daniel-mar 380
                } else {
381
                        self::buildObjectInformationCache();
382
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
383
                                $parent = self::$object_info_cache[$this->nodeId()][self::CACHE_PARENT];
384
                                $obj = OIDplusObject::parse($parent);
385
                                if ($obj) return $obj;
386
                        }
20 daniel-mar 387
 
150 daniel-mar 388
                        // 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()
389
                        $cur = $this->one_up();
418 daniel-mar 390
                        if (!$cur) return null;
150 daniel-mar 391
                        do {
415 daniel-mar 392
                                // findFitting() checks if that OID exists
150 daniel-mar 393
                                if ($fitting = self::findFitting($cur->nodeId())) return $fitting;
20 daniel-mar 394
 
150 daniel-mar 395
                                $prev = $cur;
396
                                $cur = $cur->one_up();
418 daniel-mar 397
                                if (!$cur) return null;
150 daniel-mar 398
                        } while ($prev != $cur);
399
 
418 daniel-mar 400
                        return null;
150 daniel-mar 401
                }
2 daniel-mar 402
        }
403
 
404
        public function getRaMail() {
261 daniel-mar 405
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
406
                        $res = OIDplus::db()->query("select ra_email from ###objects where id = ?", array($this->nodeId()));
790 daniel-mar 407
                        if (!$res->any()) return null;
236 daniel-mar 408
                        $row = $res->fetch_array();
150 daniel-mar 409
                        return $row['ra_email'];
410
                } else {
411
                        self::buildObjectInformationCache();
412
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
413
                                return self::$object_info_cache[$this->nodeId()][self::CACHE_RA_EMAIL];
414
                        }
415
                        return false;
416
                }
2 daniel-mar 417
        }
418
 
192 daniel-mar 419
        public function getTitle() {
261 daniel-mar 420
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
421
                        $res = OIDplus::db()->query("select title from ###objects where id = ?", array($this->nodeId()));
790 daniel-mar 422
                        if (!$res->any()) return null;
236 daniel-mar 423
                        $row = $res->fetch_array();
192 daniel-mar 424
                        return $row['title'];
425
                } else {
426
                        self::buildObjectInformationCache();
427
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
428
                                return self::$object_info_cache[$this->nodeId()][self::CACHE_TITLE];
429
                        }
430
                        return false;
431
                }
432
        }
433
 
2 daniel-mar 434
        public function userHasParentalWriteRights($ra_email=null) {
115 daniel-mar 435
                if ($ra_email instanceof OIDplusRA) $ra_email = $ra_email->raEmail();
436
 
2 daniel-mar 437
                if (is_null($ra_email)) {
549 daniel-mar 438
                        if (OIDplus::authUtils()->isAdminLoggedIn()) return true;
2 daniel-mar 439
                }
440
 
441
                $objParent = $this->getParent();
419 daniel-mar 442
                if (!$objParent) return false;
2 daniel-mar 443
                return $objParent->userHasWriteRights($ra_email);
444
        }
445
 
446
        public function userHasWriteRights($ra_email=null) {
115 daniel-mar 447
                if ($ra_email instanceof OIDplusRA) $ra_email = $ra_email->raEmail();
448
 
2 daniel-mar 449
                if (is_null($ra_email)) {
549 daniel-mar 450
                        if (OIDplus::authUtils()->isAdminLoggedIn()) return true;
451
                        return OIDplus::authUtils()->isRaLoggedIn($this->getRaMail());
2 daniel-mar 452
                } else {
453
                        return $this->getRaMail() == $ra_email;
454
                }
455
        }
12 daniel-mar 456
 
457
        public function distance($to) {
458
                return null; // not implemented
459
        }
20 daniel-mar 460
 
461
        public function equals($obj) {
462
                if (!is_object($obj)) $obj = OIDplusObject::parse($obj);
28 daniel-mar 463
                if (!($obj instanceof $this)) return false;
464
 
20 daniel-mar 465
                $distance = $this->distance($obj);
466
                if (is_numeric($distance)) return $distance === 0; // if the distance function is implemented, use it
467
 
468
                return $this->nodeId() == $obj->nodeId(); // otherwise compare the node id case-sensitive
469
        }
470
 
471
        public static function findFitting($id) {
472
                $obj = OIDplusObject::parse($id);
969 daniel-mar 473
                if (!$obj) return false; // e.g. if ObjectType plugin is disabled
20 daniel-mar 474
 
261 daniel-mar 475
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
476
                        $res = OIDplus::db()->query("select id from ###objects where id like ?", array($obj->ns().':%'));
236 daniel-mar 477
                        while ($row = $res->fetch_object()) {
150 daniel-mar 478
                                $test = OIDplusObject::parse($row->id);
479
                                if ($obj->equals($test)) return $test;
480
                        }
481
                        return false;
482
                } else {
483
                        self::buildObjectInformationCache();
193 daniel-mar 484
                        foreach (self::$object_info_cache as $id => list($confidential, $parent, $ra_email, $title)) {
150 daniel-mar 485
                                if (strpos($id, $obj->ns().':') === 0) {
486
                                        $test = OIDplusObject::parse($id);
487
                                        if ($obj->equals($test)) return $test;
488
                                }
489
                        }
490
                        return false;
20 daniel-mar 491
                }
492
        }
493
 
494
        public function one_up() {
495
                return null; // not implemented
496
        }
150 daniel-mar 497
 
498
        // Caching stuff
499
 
500
        protected static $object_info_cache = null;
501
 
502
        public static function resetObjectInformationCache() {
503
                self::$object_info_cache = null;
504
        }
505
 
193 daniel-mar 506
        const CACHE_CONFIDENTIAL = 0; // TODO: An object would be better so you can use $cacheitem->isConfidential() etc.
150 daniel-mar 507
        const CACHE_PARENT = 1;
508
        const CACHE_RA_EMAIL = 2;
192 daniel-mar 509
        const CACHE_TITLE = 3;
150 daniel-mar 510
 
511
        private static function buildObjectInformationCache() {
512
                if (is_null(self::$object_info_cache)) {
513
                        self::$object_info_cache = array();
261 daniel-mar 514
                        $res = OIDplus::db()->query("select id, parent, confidential, ra_email, title from ###objects");
236 daniel-mar 515
                        while ($row = $res->fetch_array()) {
192 daniel-mar 516
                                self::$object_info_cache[$row['id']] = array($row['confidential'], $row['parent'], $row['ra_email'], $row['title']);
150 daniel-mar 517
                        }
518
                }
519
        }
513 daniel-mar 520
 
521
        // override this function if you want your object type to save
522
        // attachments in directories with easy names.
523
        // Take care that your custom directory name will not allow jailbreaks (../) !
524
        public function getDirectoryName() {
514 daniel-mar 525
                if ($this->isRoot()) return $this->ns();
526
                return $this->getLegacyDirectoryName();
513 daniel-mar 527
        }
528
 
514 daniel-mar 529
        public final function getLegacyDirectoryName() {
804 daniel-mar 530
                if ($this::ns() == 'oid') {
513 daniel-mar 531
                        $oid = $this->nodeId(false);
532
                } else {
533
                        $oid = null;
534
                        $alt_ids = $this->getAltIds();
535
                        foreach ($alt_ids as $alt_id) {
536
                                if ($alt_id->getNamespace() == 'oid') {
537
                                        $oid = $alt_id->getId();
538
                                        break; // we prefer the first OID (for GUIDs, the first OID is the OIDplus-OID, and the second OID is the UUID OID)
539
                                }
540
                        }
541
                }
542
 
543
                if (!is_null($oid) && ($oid != '')) {
544
                        // For OIDs, it is the OID, for other identifiers
545
                        // it it the OID alt ID (generated using the SystemID)
546
                        return str_replace('.', '_', $oid);
547
                } else {
548
                        // Can happen if you don't have a system ID (due to missing OpenSSL plugin)
549
                        return md5($this->nodeId(true)); // we don't use $id, because $this->nodeId(true) is possibly more canonical than $id
550
                }
551
        }
800 daniel-mar 552
 
805 daniel-mar 553
        public static function treeIconFilename($mode) {
800 daniel-mar 554
                // for backwards-compatibility with older plugins
555
                return 'img/treeicon_'.$mode.'.png';
556
        }
557
 
415 daniel-mar 558
}