Subversion Repositories oidplus

Rev

Rev 1127 | Rev 1137 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1127 Rev 1130
1
<?php
1
<?php
2
 
2
 
3
/*
3
/*
4
 * OIDplus 2.0
4
 * OIDplus 2.0
5
 * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft
5
 * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft
6
 *
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with 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
9
 * You may obtain a copy of the License at
10
 *
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
17
 * limitations under the License.
18
 */
18
 */
19
 
19
 
20
namespace ViaThinkSoft\OIDplus;
20
namespace ViaThinkSoft\OIDplus;
21
 
21
 
22
// phpcs:disable PSR1.Files.SideEffects
22
// phpcs:disable PSR1.Files.SideEffects
23
\defined('INSIDE_OIDPLUS') or die;
23
\defined('INSIDE_OIDPLUS') or die;
24
// phpcs:enable PSR1.Files.SideEffects
24
// phpcs:enable PSR1.Files.SideEffects
25
 
25
 
26
abstract class OIDplusObject extends OIDplusBaseClass {
26
abstract class OIDplusObject extends OIDplusBaseClass {
-
 
27
 
-
 
28
        /**
-
 
29
         *
-
 
30
         */
27
        const UUID_NAMEBASED_NS_OidPlusMisc = 'ad1654e6-7e15-11e4-9ef6-78e3b5fc7f22';
31
        const UUID_NAMEBASED_NS_OidPlusMisc = 'ad1654e6-7e15-11e4-9ef6-78e3b5fc7f22';
28
 
32
 
29
        /**
33
        /**
30
         * Please overwrite this function!
34
         * Please overwrite this function!
31
         * @param string $node_id
35
         * @param string $node_id
32
         * @return OIDplusObject|null
36
         * @return OIDplusObject|null
33
         */
37
         */
34
        public static function parse(string $node_id)/*: ?OIDplusObject*/ {
38
        public static function parse(string $node_id)/*: ?OIDplusObject*/ {
35
                foreach (OIDplus::getEnabledObjectTypes() as $ot) {
39
                foreach (OIDplus::getEnabledObjectTypes() as $ot) {
36
                        try {
40
                        try {
37
                                $good = false;
41
                                $good = false;
38
                                if (get_parent_class($ot) == OIDplusObject::class) {
42
                                if (get_parent_class($ot) == OIDplusObject::class) {
39
                                        $reflector = new \ReflectionMethod($ot, 'parse');
43
                                        $reflector = new \ReflectionMethod($ot, 'parse');
40
                                        $isImplemented = ($reflector->getDeclaringClass()->getName() === $ot);
44
                                        $isImplemented = ($reflector->getDeclaringClass()->getName() === $ot);
41
                                        if ($isImplemented) { // avoid endless loop if parse is not overriden
45
                                        if ($isImplemented) { // avoid endless loop if parse is not overriden
42
                                                $good = true;
46
                                                $good = true;
43
                                        }
47
                                        }
44
                                }
48
                                }
45
                                // We need to do the workaround with "$good", otherwise PHPstan shows
49
                                // We need to do the workaround with "$good", otherwise PHPstan shows
46
                                // "Call to an undefined static method object::parse()"
50
                                // "Call to an undefined static method object::parse()"
47
                                if ($good && $obj = $ot::parse($node_id)) return $obj;
51
                                if ($good && $obj = $ot::parse($node_id)) return $obj;
48
                        } catch (\Exception $e) {}
52
                        } catch (\Exception $e) {}
49
                }
53
                }
50
                return null;
54
                return null;
51
        }
55
        }
52
 
56
 
53
        /**
57
        /**
54
         * @return OIDplusAltId[]
58
         * @return OIDplusAltId[]
55
         * @throws OIDplusException
59
         * @throws OIDplusException
56
         */
60
         */
57
        public function getAltIds(): array {
61
        public function getAltIds(): array {
58
                if ($this->isRoot()) return array();
62
                if ($this->isRoot()) return array();
59
 
63
 
60
                $ids = array();
64
                $ids = array();
61
 
65
 
62
                // Creates an OIDplus-Hash-OID
66
                // Creates an OIDplus-Hash-OID
63
                if ($this->ns() != 'oid') {
67
                if ($this->ns() != 'oid') {
64
                        $sid = OIDplus::getSystemId(true);
68
                        $sid = OIDplus::getSystemId(true);
65
                        if (!empty($sid)) {
69
                        if (!empty($sid)) {
66
                                $ns_oid = $this->getPlugin()->getManifest()->getOid();
70
                                $ns_oid = $this->getPlugin()->getManifest()->getOid();
67
                                if (str_starts_with($ns_oid, '1.3.6.1.4.1.37476.2.5.2.')) {
71
                                if (str_starts_with($ns_oid, '1.3.6.1.4.1.37476.2.5.2.')) {
68
                                        // Official ViaThinkSoft object type plugins
72
                                        // Official ViaThinkSoft object type plugins
69
                                        // For backwards compatibility with existing IDs,
73
                                        // For backwards compatibility with existing IDs,
70
                                        // set the hash_payload as '<namespace>:<id>'
74
                                        // set the hash_payload as '<namespace>:<id>'
71
                                        $hash_payload = $this->nodeId(true);
75
                                        $hash_payload = $this->nodeId(true);
72
                                } else {
76
                                } else {
73
                                        // Third-party object type plugins
77
                                        // Third-party object type plugins
74
                                        // Set the hash_payload as '<plugin oid>:<id>'
78
                                        // Set the hash_payload as '<plugin oid>:<id>'
75
                                        $hash_payload = $ns_oid.':'.$this->nodeId(false);
79
                                        $hash_payload = $ns_oid.':'.$this->nodeId(false);
76
                                }
80
                                }
77
                                $oid = $sid . '.' . smallhash($hash_payload);
81
                                $oid = $sid . '.' . smallhash($hash_payload);
78
                                $ids[] = new OIDplusAltId('oid', $oid, _L('OIDplus Information Object OID'));
82
                                $ids[] = new OIDplusAltId('oid', $oid, _L('OIDplus Information Object OID'));
79
                        }
83
                        }
80
                }
84
                }
81
 
85
 
82
                // Make a namebased UUID, but...
86
                // Make a namebased UUID, but...
83
                // ... exclude GUID, because a GUID is already a GUID
87
                // ... exclude GUID, because a GUID is already a GUID
84
                // ... exclude OID, because an OID already has a record UUID_NAMEBASED_NS_OID (defined by IETF) set by class OIDplusOid
88
                // ... exclude OID, because an OID already has a record UUID_NAMEBASED_NS_OID (defined by IETF) set by class OIDplusOid
85
                if (($this->ns() != 'guid') && ($this->ns() != 'oid')) {
89
                if (($this->ns() != 'guid') && ($this->ns() != 'oid')) {
86
                        $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'));
90
                        $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'));
87
                        $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'));
91
                        $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'));
88
                }
92
                }
89
 
93
 
90
                // Make a AID based on ViaThinkSoft schema
94
                // Make a AID based on ViaThinkSoft schema
91
                // ... but not for OIDs below oid:1.3.6.1.4.1.37476.30.9, because these are the definition of these Information Object AIDs (which will be decoded in the OID object type plugin)
95
                // ... but not for OIDs below oid:1.3.6.1.4.1.37476.30.9, because these are the definition of these Information Object AIDs (which will be decoded in the OID object type plugin)
92
                if (($this->ns() != 'aid') && !str_starts_with($this->nodeId(true), 'oid:1.3.6.1.4.1.37476.30.9.')) {
96
                if (($this->ns() != 'aid') && !str_starts_with($this->nodeId(true), 'oid:1.3.6.1.4.1.37476.30.9.')) {
93
                        $sid = OIDplus::getSystemId(false);
97
                        $sid = OIDplus::getSystemId(false);
94
                        if ($sid !== false) {
98
                        if ($sid !== false) {
95
                                $ns_oid = $this->getPlugin()->getManifest()->getOid();
99
                                $ns_oid = $this->getPlugin()->getManifest()->getOid();
96
                                if (str_starts_with($ns_oid, '1.3.6.1.4.1.37476.2.5.2.')) {
100
                                if (str_starts_with($ns_oid, '1.3.6.1.4.1.37476.2.5.2.')) {
97
                                        // Official ViaThinkSoft object type plugins
101
                                        // Official ViaThinkSoft object type plugins
98
                                        // For backwards compatibility with existing IDs,
102
                                        // For backwards compatibility with existing IDs,
99
                                        // set the hash_payload as '<namespace>:<id>'
103
                                        // set the hash_payload as '<namespace>:<id>'
100
                                        $hash_payload = $this->nodeId(true);
104
                                        $hash_payload = $this->nodeId(true);
101
                                } else {
105
                                } else {
102
                                        // Third-party object type plugins
106
                                        // Third-party object type plugins
103
                                        // Set the hash_payload as '<plugin oid>:<id>'
107
                                        // Set the hash_payload as '<plugin oid>:<id>'
104
                                        $hash_payload = $ns_oid.':'.$this->nodeId(false);
108
                                        $hash_payload = $ns_oid.':'.$this->nodeId(false);
105
                                }
109
                                }
106
 
110
 
107
                                $sid_hex = strtoupper(str_pad(dechex((int)$sid),8,'0',STR_PAD_LEFT));
111
                                $sid_hex = strtoupper(str_pad(dechex((int)$sid),8,'0',STR_PAD_LEFT));
108
                                $obj_hex = strtoupper(str_pad(dechex(smallhash($hash_payload)),8,'0',STR_PAD_LEFT));
112
                                $obj_hex = strtoupper(str_pad(dechex(smallhash($hash_payload)),8,'0',STR_PAD_LEFT));
109
                                $aid = 'D276000186B20005'.$sid_hex.$obj_hex;
113
                                $aid = 'D276000186B20005'.$sid_hex.$obj_hex;
110
                                $ids[] = new OIDplusAltId('aid', $aid, _L('OIDplus Information Object Application Identifier (ISO/IEC 7816)'), ' ('._L('No PIX allowed').')');
114
                                $ids[] = new OIDplusAltId('aid', $aid, _L('OIDplus Information Object Application Identifier (ISO/IEC 7816)'), ' ('._L('No PIX allowed').')');
111
                        }
115
                        }
112
                }
116
                }
113
 
117
 
114
                return $ids;
118
                return $ids;
115
        }
119
        }
116
 
120
 
117
        /**
121
        /**
118
         * @return string
122
         * @return string
119
         */
123
         */
120
        public abstract static function objectTypeTitle(): string;
124
        public abstract static function objectTypeTitle(): string;
121
 
125
 
122
        /**
126
        /**
123
         * @return string
127
         * @return string
124
         */
128
         */
125
        public abstract static function objectTypeTitleShort(): string;
129
        public abstract static function objectTypeTitleShort(): string;
126
 
130
 
127
        /**
131
        /**
128
         * @return OIDplusObjectTypePlugin|null
132
         * @return OIDplusObjectTypePlugin|null
129
         */
133
         */
130
        public function getPlugin()/*: ?OIDplusObjectTypePlugin */ {
134
        public function getPlugin()/*: ?OIDplusObjectTypePlugin */ {
131
                $plugins = OIDplus::getObjectTypePlugins();
135
                $plugins = OIDplus::getObjectTypePlugins();
132
                foreach ($plugins as $plugin) {
136
                foreach ($plugins as $plugin) {
133
                        if (get_class($this) == $plugin::getObjectTypeClassName()) {
137
                        if (get_class($this) == $plugin::getObjectTypeClassName()) {
134
                                return $plugin;
138
                                return $plugin;
135
                        }
139
                        }
136
                }
140
                }
137
                return null;
141
                return null;
138
        }
142
        }
139
 
143
 
140
        /**
144
        /**
141
         * @return string
145
         * @return string
142
         */
146
         */
143
        public abstract static function ns(): string;
147
        public abstract static function ns(): string;
144
 
148
 
145
        /**
149
        /**
146
         * @return string
150
         * @return string
147
         */
151
         */
148
        public abstract static function root(): string;
152
        public abstract static function root(): string;
149
 
153
 
150
        /**
154
        /**
151
         * @return bool
155
         * @return bool
152
         */
156
         */
153
        public abstract function isRoot(): bool;
157
        public abstract function isRoot(): bool;
154
 
158
 
155
        /**
159
        /**
156
         * @param bool $with_ns
160
         * @param bool $with_ns
157
         * @return string
161
         * @return string
158
         */
162
         */
159
        public abstract function nodeId(bool $with_ns=true): string;
163
        public abstract function nodeId(bool $with_ns=true): string;
160
 
164
 
161
        /**
165
        /**
162
         * @param string $str
166
         * @param string $str
163
         * @return string mixed
167
         * @return string mixed
164
         * @throws OIDplusException
168
         * @throws OIDplusException
165
         */
169
         */
166
        public abstract function addString(string $str): string;
170
        public abstract function addString(string $str): string;
167
 
171
 
168
        /**
172
        /**
169
         * @param OIDplusObject $parent
173
         * @param OIDplusObject $parent
170
         * @return string
174
         * @return string
171
         */
175
         */
172
        public abstract function crudShowId(OIDplusObject $parent): string;
176
        public abstract function crudShowId(OIDplusObject $parent): string;
173
 
177
 
174
        /**
178
        /**
175
         * @return string
179
         * @return string
176
         */
180
         */
177
        public function crudInsertPrefix(): string {
181
        public function crudInsertPrefix(): string {
178
                return '';
182
                return '';
179
        }
183
        }
180
 
184
 
181
        /**
185
        /**
182
         * @return string
186
         * @return string
183
         */
187
         */
184
        public function crudInsertSuffix(): string {
188
        public function crudInsertSuffix(): string {
185
                return '';
189
                return '';
186
        }
190
        }
187
 
191
 
188
        /**
192
        /**
189
         * @param OIDplusObject|null $parent
193
         * @param OIDplusObject|null $parent
190
         * @return string
194
         * @return string
191
         */
195
         */
192
        public abstract function jsTreeNodeName(OIDplusObject $parent = null): string;
196
        public abstract function jsTreeNodeName(OIDplusObject $parent = null): string;
193
 
197
 
194
        /**
198
        /**
195
         * @return string
199
         * @return string
196
         */
200
         */
197
        public abstract function defaultTitle(): string;
201
        public abstract function defaultTitle(): string;
198
 
202
 
199
        /**
203
        /**
200
         * @return bool
204
         * @return bool
201
         */
205
         */
202
        public abstract function isLeafNode(): bool;
206
        public abstract function isLeafNode(): bool;
203
 
207
 
204
        /**
208
        /**
205
         * @param string $title
209
         * @param string $title
206
         * @param string $content
210
         * @param string $content
207
         * @param string $icon
211
         * @param string $icon
208
         * @return void
212
         * @return void
209
         */
213
         */
210
        public abstract function getContentPage(string &$title, string &$content, string &$icon);
214
        public abstract function getContentPage(string &$title, string &$content, string &$icon);
211
 
215
 
212
        /**
216
        /**
213
         * @param OIDplusRA|string|null $ra
217
         * @param OIDplusRA|string|null $ra
214
         * @return array
218
         * @return array
215
         * @throws OIDplusConfigInitializationException
219
         * @throws OIDplusConfigInitializationException
216
         * @throws OIDplusException
220
         * @throws OIDplusException
217
         */
221
         */
218
        public static function getRaRoots($ra=null) : array{
222
        public static function getRaRoots($ra=null) : array{
219
                if ($ra instanceof OIDplusRA) $ra = $ra->raEmail();
223
                if ($ra instanceof OIDplusRA) $ra = $ra->raEmail();
220
 
224
 
221
                $out = array();
225
                $out = array();
222
 
226
 
223
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
227
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
224
                        if (!$ra) {
228
                        if (!$ra) {
225
                                $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 ".
229
                                $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 ".
226
                                                            "left join ###objects as oParent on oChild.parent = oParent.id ".
230
                                                            "left join ###objects as oParent on oChild.parent = oParent.id ".
227
                                                            "order by ".OIDplus::db()->natOrder('oChild.id'));
231
                                                            "order by ".OIDplus::db()->natOrder('oChild.id'));
228
                                while ($row = $res->fetch_array()) {
232
                                while ($row = $res->fetch_array()) {
229
                                        if (!OIDplus::authUtils()->isRaLoggedIn($row['parent_mail']) && OIDplus::authUtils()->isRaLoggedIn($row['child_mail'])) {
233
                                        if (!OIDplus::authUtils()->isRaLoggedIn($row['parent_mail']) && OIDplus::authUtils()->isRaLoggedIn($row['child_mail'])) {
230
                                                $x = self::parse($row['id']); // can be NULL if namespace was disabled
234
                                                $x = self::parse($row['id']); // can be NULL if namespace was disabled
231
                                                if ($x) $out[] = $x;
235
                                                if ($x) $out[] = $x;
232
                                        }
236
                                        }
233
                                }
237
                                }
234
                        } else {
238
                        } else {
235
                                $res = OIDplus::db()->query("select oChild.id as id from ###objects as oChild ".
239
                                $res = OIDplus::db()->query("select oChild.id as id from ###objects as oChild ".
236
                                                            "left join ###objects as oParent on oChild.parent = oParent.id ".
240
                                                            "left join ###objects as oParent on oChild.parent = oParent.id ".
237
                                                            "where (".OIDplus::db()->getSlang()->isNullFunction('oParent.ra_email',"''")." <> ? and ".
241
                                                            "where (".OIDplus::db()->getSlang()->isNullFunction('oParent.ra_email',"''")." <> ? and ".
238
                                                            OIDplus::db()->getSlang()->isNullFunction('oChild.ra_email',"''")." = ?) or ".
242
                                                            OIDplus::db()->getSlang()->isNullFunction('oChild.ra_email',"''")." = ?) or ".
239
                                                            "      (oParent.ra_email is null and ".OIDplus::db()->getSlang()->isNullFunction('oChild.ra_email',"''")." = ?) ".
243
                                                            "      (oParent.ra_email is null and ".OIDplus::db()->getSlang()->isNullFunction('oChild.ra_email',"''")." = ?) ".
240
                                                            "order by ".OIDplus::db()->natOrder('oChild.id'), array($ra, $ra, $ra));
244
                                                            "order by ".OIDplus::db()->natOrder('oChild.id'), array($ra, $ra, $ra));
241
                                while ($row = $res->fetch_array()) {
245
                                while ($row = $res->fetch_array()) {
242
                                        $x = self::parse($row['id']); // can be NULL if namespace was disabled
246
                                        $x = self::parse($row['id']); // can be NULL if namespace was disabled
243
                                        if ($x) $out[] = $x;
247
                                        if ($x) $out[] = $x;
244
                                }
248
                                }
245
                        }
249
                        }
246
                } else {
250
                } else {
247
                        if (!$ra) {
251
                        if (!$ra) {
248
                                $ra_mails_to_check = OIDplus::authUtils()->loggedInRaList();
252
                                $ra_mails_to_check = OIDplus::authUtils()->loggedInRaList();
249
                                if (count($ra_mails_to_check) == 0) return $out;
253
                                if (count($ra_mails_to_check) == 0) return $out;
250
                        } else {
254
                        } else {
251
                                $ra_mails_to_check = array($ra);
255
                                $ra_mails_to_check = array($ra);
252
                        }
256
                        }
253
 
257
 
254
                        self::buildObjectInformationCache();
258
                        self::buildObjectInformationCache();
255
 
259
 
256
                        foreach ($ra_mails_to_check as $check_ra_mail) {
260
                        foreach ($ra_mails_to_check as $check_ra_mail) {
257
                                $out_part = array();
261
                                $out_part = array();
258
 
262
 
259
                                foreach (self::$object_info_cache as $id => $cacheitem) {
263
                                foreach (self::$object_info_cache as $id => $cacheitem) {
260
                                        if ($cacheitem[self::CACHE_RA_EMAIL] == $check_ra_mail) {
264
                                        if ($cacheitem[self::CACHE_RA_EMAIL] == $check_ra_mail) {
261
                                                $parent = $cacheitem[self::CACHE_PARENT];
265
                                                $parent = $cacheitem[self::CACHE_PARENT];
262
                                                if (!isset(self::$object_info_cache[$parent]) || (self::$object_info_cache[$parent][self::CACHE_RA_EMAIL] != $check_ra_mail)) {
266
                                                if (!isset(self::$object_info_cache[$parent]) || (self::$object_info_cache[$parent][self::CACHE_RA_EMAIL] != $check_ra_mail)) {
263
                                                        $out_part[] = $id;
267
                                                        $out_part[] = $id;
264
                                                }
268
                                                }
265
                                        }
269
                                        }
266
                                }
270
                                }
267
 
271
 
268
                                natsort($out_part);
272
                                natsort($out_part);
269
 
273
 
270
                                foreach ($out_part as $id) {
274
                                foreach ($out_part as $id) {
271
                                        $obj = self::parse($id);
275
                                        $obj = self::parse($id);
272
                                        if ($obj) $out[] = $obj;
276
                                        if ($obj) $out[] = $obj;
273
                                }
277
                                }
274
                        }
278
                        }
275
                }
279
                }
276
 
280
 
277
                return $out;
281
                return $out;
278
        }
282
        }
279
 
283
 
280
        /**
284
        /**
281
         * @return array
285
         * @return array
282
         * @throws OIDplusException
286
         * @throws OIDplusException
283
         */
287
         */
284
        public static function getAllNonConfidential(): array {
288
        public static function getAllNonConfidential(): array {
285
                $out = array();
289
                $out = array();
286
 
290
 
287
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
291
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
288
                        $res = OIDplus::db()->query("select id from ###objects where confidential = ? order by ".OIDplus::db()->natOrder('id'), array(false));
292
                        $res = OIDplus::db()->query("select id from ###objects where confidential = ? order by ".OIDplus::db()->natOrder('id'), array(false));
289
 
293
 
290
                        while ($row = $res->fetch_array()) {
294
                        while ($row = $res->fetch_array()) {
291
                                $obj = self::parse($row['id']); // will be NULL if the object type is not registered
295
                                $obj = self::parse($row['id']); // will be NULL if the object type is not registered
292
                                if ($obj && (!$obj->isConfidential())) {
296
                                if ($obj && (!$obj->isConfidential())) {
293
                                        $out[] = $row['id'];
297
                                        $out[] = $row['id'];
294
                                }
298
                                }
295
                        }
299
                        }
296
                } else {
300
                } else {
297
                        self::buildObjectInformationCache();
301
                        self::buildObjectInformationCache();
298
 
302
 
299
                        foreach (self::$object_info_cache as $id => $cacheitem) {
303
                        foreach (self::$object_info_cache as $id => $cacheitem) {
300
                                $confidential = $cacheitem[self::CACHE_CONFIDENTIAL];
304
                                $confidential = $cacheitem[self::CACHE_CONFIDENTIAL];
301
                                if (!$confidential) {
305
                                if (!$confidential) {
302
                                        $obj = self::parse($id); // will be NULL if the object type is not registered
306
                                        $obj = self::parse($id); // will be NULL if the object type is not registered
303
                                        if ($obj && (!$obj->isConfidential())) {
307
                                        if ($obj && (!$obj->isConfidential())) {
304
                                                $out[] = $id;
308
                                                $out[] = $id;
305
                                        }
309
                                        }
306
                                }
310
                                }
307
                        }
311
                        }
308
                }
312
                }
309
 
313
 
310
                return $out;
314
                return $out;
311
        }
315
        }
312
 
316
 
313
        /**
317
        /**
314
         * @return bool
318
         * @return bool
315
         * @throws OIDplusException
319
         * @throws OIDplusException
316
         */
320
         */
317
        public function isConfidential(): bool {
321
        public function isConfidential(): bool {
318
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
322
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
319
                        //static $confidential_cache = array();
323
                        //static $confidential_cache = array();
320
                        $curid = $this->nodeId();
324
                        $curid = $this->nodeId();
321
                        //$orig_curid = $curid;
325
                        //$orig_curid = $curid;
322
                        //if (isset($confidential_cache[$curid])) return $confidential_cache[$curid];
326
                        //if (isset($confidential_cache[$curid])) return $confidential_cache[$curid];
323
                        // Recursively search for the confidential flag in the parents
327
                        // Recursively search for the confidential flag in the parents
324
                        while (($res = OIDplus::db()->query("select parent, confidential from ###objects where id = ?", array($curid)))->any()) {
328
                        while (($res = OIDplus::db()->query("select parent, confidential from ###objects where id = ?", array($curid)))->any()) {
325
                                $row = $res->fetch_array();
329
                                $row = $res->fetch_array();
326
                                if ($row['confidential']) {
330
                                if ($row['confidential']) {
327
                                        //$confidential_cache[$curid] = true;
331
                                        //$confidential_cache[$curid] = true;
328
                                        //$confidential_cache[$orig_curid] = true;
332
                                        //$confidential_cache[$orig_curid] = true;
329
                                        return true;
333
                                        return true;
330
                                } else {
334
                                } else {
331
                                        //$confidential_cache[$curid] = false;
335
                                        //$confidential_cache[$curid] = false;
332
                                }
336
                                }
333
                                $curid = $row['parent'];
337
                                $curid = $row['parent'];
334
                                //if (isset($confidential_cache[$curid])) {
338
                                //if (isset($confidential_cache[$curid])) {
335
                                        //$confidential_cache[$orig_curid] = $confidential_cache[$curid];
339
                                        //$confidential_cache[$orig_curid] = $confidential_cache[$curid];
336
                                        //return $confidential_cache[$curid];
340
                                        //return $confidential_cache[$curid];
337
                                //}
341
                                //}
338
                        }
342
                        }
339
 
343
 
340
                        //$confidential_cache[$orig_curid] = false;
344
                        //$confidential_cache[$orig_curid] = false;
341
                        return false;
345
                        return false;
342
                } else {
346
                } else {
343
                        self::buildObjectInformationCache();
347
                        self::buildObjectInformationCache();
344
 
348
 
345
                        $curid = $this->nodeId();
349
                        $curid = $this->nodeId();
346
                        // Recursively search for the confidential flag in the parents
350
                        // Recursively search for the confidential flag in the parents
347
                        while (isset(self::$object_info_cache[$curid])) {
351
                        while (isset(self::$object_info_cache[$curid])) {
348
                                if (self::$object_info_cache[$curid][self::CACHE_CONFIDENTIAL]) return true;
352
                                if (self::$object_info_cache[$curid][self::CACHE_CONFIDENTIAL]) return true;
349
                                $curid = self::$object_info_cache[$curid][self::CACHE_PARENT];
353
                                $curid = self::$object_info_cache[$curid][self::CACHE_PARENT];
350
                        }
354
                        }
351
                        return false;
355
                        return false;
352
                }
356
                }
353
        }
357
        }
354
 
358
 
355
        /**
359
        /**
356
         * @param OIDplusObject $obj
360
         * @param OIDplusObject $obj
357
         * @return bool
361
         * @return bool
358
         * @throws OIDplusException
362
         * @throws OIDplusException
359
         */
363
         */
360
        public function isChildOf(OIDplusObject $obj): bool {
364
        public function isChildOf(OIDplusObject $obj): bool {
361
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
365
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
362
                        $curid = $this->nodeId();
366
                        $curid = $this->nodeId();
363
                        while (($res = OIDplus::db()->query("select parent from ###objects where id = ?", array($curid)))->any()) {
367
                        while (($res = OIDplus::db()->query("select parent from ###objects where id = ?", array($curid)))->any()) {
364
                                $row = $res->fetch_array();
368
                                $row = $res->fetch_array();
365
                                if ($curid == $obj->nodeId()) return true;
369
                                if ($curid == $obj->nodeId()) return true;
366
                                $curid = $row['parent'];
370
                                $curid = $row['parent'];
367
                        }
371
                        }
368
                        return false;
372
                        return false;
369
                } else {
373
                } else {
370
                        self::buildObjectInformationCache();
374
                        self::buildObjectInformationCache();
371
 
375
 
372
                        $curid = $this->nodeId();
376
                        $curid = $this->nodeId();
373
                        while (isset(self::$object_info_cache[$curid])) {
377
                        while (isset(self::$object_info_cache[$curid])) {
374
                                if ($curid == $obj->nodeId()) return true;
378
                                if ($curid == $obj->nodeId()) return true;
375
                                $curid = self::$object_info_cache[$curid][self::CACHE_PARENT];
379
                                $curid = self::$object_info_cache[$curid][self::CACHE_PARENT];
376
                        }
380
                        }
377
                        return false;
381
                        return false;
378
                }
382
                }
379
        }
383
        }
380
 
384
 
381
        /**
385
        /**
382
         * @return array
386
         * @return array
383
         * @throws OIDplusException
387
         * @throws OIDplusException
384
         */
388
         */
385
        public function getChildren(): array {
389
        public function getChildren(): array {
386
                $out = array();
390
                $out = array();
387
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
391
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
388
                        $res = OIDplus::db()->query("select id from ###objects where parent = ?", array($this->nodeId()));
392
                        $res = OIDplus::db()->query("select id from ###objects where parent = ?", array($this->nodeId()));
389
                        while ($row = $res->fetch_array()) {
393
                        while ($row = $res->fetch_array()) {
390
                                $obj = self::parse($row['id']);
394
                                $obj = self::parse($row['id']);
391
                                if (!$obj) continue;
395
                                if (!$obj) continue;
392
                                $out[] = $obj;
396
                                $out[] = $obj;
393
                        }
397
                        }
394
                } else {
398
                } else {
395
                        self::buildObjectInformationCache();
399
                        self::buildObjectInformationCache();
396
 
400
 
397
                        foreach (self::$object_info_cache as $id => $cacheitem) {
401
                        foreach (self::$object_info_cache as $id => $cacheitem) {
398
                                $parent = $cacheitem[self::CACHE_PARENT];
402
                                $parent = $cacheitem[self::CACHE_PARENT];
399
                                if ($parent == $this->nodeId()) {
403
                                if ($parent == $this->nodeId()) {
400
                                        $obj = self::parse($id);
404
                                        $obj = self::parse($id);
401
                                        if (!$obj) continue;
405
                                        if (!$obj) continue;
402
                                        $out[] = $obj;
406
                                        $out[] = $obj;
403
                                }
407
                                }
404
                        }
408
                        }
405
                }
409
                }
406
                return $out;
410
                return $out;
407
        }
411
        }
408
 
412
 
409
        /**
413
        /**
410
         * @return OIDplusRA
414
         * @return OIDplusRA
411
         * @throws OIDplusException
415
         * @throws OIDplusException
412
         */
416
         */
413
        public function getRa(): OIDplusRA {
417
        public function getRa(): OIDplusRA {
414
                return new OIDplusRA($this->getRaMail());
418
                return new OIDplusRA($this->getRaMail());
415
        }
419
        }
416
 
420
 
417
        /**
421
        /**
418
         * @param OIDplusRA|string|null $ra
422
         * @param OIDplusRA|string|null $ra
419
         * @return bool
423
         * @return bool
420
         * @throws OIDplusConfigInitializationException
424
         * @throws OIDplusConfigInitializationException
421
         * @throws OIDplusException
425
         * @throws OIDplusException
422
         */
426
         */
423
        public function userHasReadRights($ra=null): bool {
427
        public function userHasReadRights($ra=null): bool {
424
                if ($ra instanceof OIDplusRA) $ra = $ra->raEmail();
428
                if ($ra instanceof OIDplusRA) $ra = $ra->raEmail();
425
 
429
 
426
                // If it is not confidential, everybody can read/see it.
430
                // If it is not confidential, everybody can read/see it.
427
                // Note: This also checks if superior OIDs are confidential.
431
                // Note: This also checks if superior OIDs are confidential.
428
                if (!$this->isConfidential()) return true;
432
                if (!$this->isConfidential()) return true;
429
 
433
 
430
                if (!$ra) {
434
                if (!$ra) {
431
                        // Admin may do everything
435
                        // Admin may do everything
432
                        if (OIDplus::authUtils()->isAdminLoggedIn()) return true;
436
                        if (OIDplus::authUtils()->isAdminLoggedIn()) return true;
433
 
437
 
434
                        // If the RA is logged in, then they can see the OID.
438
                        // If the RA is logged in, then they can see the OID.
435
                        if (OIDplus::authUtils()->isRaLoggedIn($this->getRaMail())) return true;
439
                        if (OIDplus::authUtils()->isRaLoggedIn($this->getRaMail())) return true;
436
                } else {
440
                } else {
437
                        // If this OID belongs to the requested RA, then they may see it.
441
                        // If this OID belongs to the requested RA, then they may see it.
438
                        if ($this->getRaMail() == $ra) return true;
442
                        if ($this->getRaMail() == $ra) return true;
439
                }
443
                }
440
 
444
 
441
                // If someone has rights to an object below our confidential node,
445
                // If someone has rights to an object below our confidential node,
442
                // we let him see the confidential node,
446
                // we let him see the confidential node,
443
                // Otherwise he could not browse through to his own node.
447
                // Otherwise he could not browse through to his own node.
444
                $roots = $this->getRaRoots($ra);
448
                $roots = $this->getRaRoots($ra);
445
                foreach ($roots as $root) {
449
                foreach ($roots as $root) {
446
                        if ($root->isChildOf($this)) return true;
450
                        if ($root->isChildOf($this)) return true;
447
                }
451
                }
448
 
452
 
449
                return false;
453
                return false;
450
        }
454
        }
451
 
455
 
452
        /**
456
        /**
453
         * @param array|null $row
457
         * @param array|null $row
454
         * @return string|null
458
         * @return string|null
455
         * @throws OIDplusException
459
         * @throws OIDplusException
456
         */
460
         */
457
        public function getIcon(array $row=null) {
461
        public function getIcon(array $row=null) {
458
                $namespace = $this->ns(); // must use $this, not self::, otherwise the virtual method will not be called
462
                $namespace = $this->ns(); // must use $this, not self::, otherwise the virtual method will not be called
459
 
463
 
460
                if (is_null($row)) {
464
                if (is_null($row)) {
461
                        $ra_email = $this->getRaMail();
465
                        $ra_email = $this->getRaMail();
462
                } else {
466
                } else {
463
                        $ra_email = $row['ra_email'];
467
                        $ra_email = $row['ra_email'];
464
                }
468
                }
465
 
469
 
466
                // $dirs = glob(OIDplus::localpath().'plugins/'.'*'.'/objectTypes/'.$namespace.'/');
470
                // $dirs = glob(OIDplus::localpath().'plugins/'.'*'.'/objectTypes/'.$namespace.'/');
467
                // if (count($dirs) == 0) return null; // default icon (folder)
471
                // if (count($dirs) == 0) return null; // default icon (folder)
468
                // $dir = substr($dirs[0], strlen(OIDplus::localpath()));
472
                // $dir = substr($dirs[0], strlen(OIDplus::localpath()));
469
                $reflection = new \ReflectionClass($this);
473
                $reflection = new \ReflectionClass($this);
470
                $dir = dirname($reflection->getFilename());
474
                $dir = dirname($reflection->getFilename());
471
                $dir = substr($dir, strlen(OIDplus::localpath()));
475
                $dir = substr($dir, strlen(OIDplus::localpath()));
-
 
476
                $dir = str_replace('\\', '/', $dir);
472
 
477
 
473
                if ($this->isRoot()) {
478
                if ($this->isRoot()) {
474
                        $icon = $dir . '/' . $this::treeIconFilename('root');
479
                        $icon = $dir . '/' . $this::treeIconFilename('root');
475
                } else {
480
                } else {
476
                        // We use $this:: instead of self:: , because we want to call the overridden methods
481
                        // We use $this:: instead of self:: , because we want to call the overridden methods
477
                        if ($ra_email && OIDplus::authUtils()->isRaLoggedIn($ra_email)) {
482
                        if ($ra_email && OIDplus::authUtils()->isRaLoggedIn($ra_email)) {
478
                                if ($this->isLeafNode()) {
483
                                if ($this->isLeafNode()) {
479
                                        $icon = $dir . '/' . $this::treeIconFilename('own_leaf');
484
                                        $icon = $dir . '/' . $this::treeIconFilename('own_leaf');
480
                                        if (!file_exists($icon)) $icon = $dir . '/' . $this::treeIconFilename('own');
485
                                        if (!file_exists($icon)) $icon = $dir . '/' . $this::treeIconFilename('own');
481
                                } else {
486
                                } else {
482
                                        $icon = $dir . '/' . $this::treeIconFilename('own');
487
                                        $icon = $dir . '/' . $this::treeIconFilename('own');
483
                                }
488
                                }
484
                        } else {
489
                        } else {
485
                                if ($this->isLeafNode()) {
490
                                if ($this->isLeafNode()) {
486
                                        $icon = $dir . '/' . $this::treeIconFilename('general_leaf');
491
                                        $icon = $dir . '/' . $this::treeIconFilename('general_leaf');
487
                                        if (!file_exists($icon)) $icon = $dir . '/' . $this::treeIconFilename('general');
492
                                        if (!file_exists($icon)) $icon = $dir . '/' . $this::treeIconFilename('general');
488
                                } else {
493
                                } else {
489
                                        $icon = $dir . '/' . $this::treeIconFilename('general');
494
                                        $icon = $dir . '/' . $this::treeIconFilename('general');
490
                                }
495
                                }
491
                        }
496
                        }
492
                }
497
                }
493
 
498
 
494
                if (!file_exists($icon)) return null; // default icon (folder)
499
                if (!file_exists($icon)) return null; // default icon (folder)
495
 
500
 
496
                return $icon;
501
                return $icon;
497
        }
502
        }
498
 
503
 
499
        /**
504
        /**
500
         * @param string $id
505
         * @param string $id
501
         * @return bool
506
         * @return bool
502
         * @throws OIDplusException
507
         * @throws OIDplusException
503
         */
508
         */
504
        public static function exists(string $id): bool {
509
        public static function exists(string $id): bool {
505
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
510
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
506
                        $res = OIDplus::db()->query("select id from ###objects where id = ?", array($id));
511
                        $res = OIDplus::db()->query("select id from ###objects where id = ?", array($id));
507
                        return $res->any();
512
                        return $res->any();
508
                } else {
513
                } else {
509
                        self::buildObjectInformationCache();
514
                        self::buildObjectInformationCache();
510
                        return isset(self::$object_info_cache[$id]);
515
                        return isset(self::$object_info_cache[$id]);
511
                }
516
                }
512
        }
517
        }
513
 
518
 
514
        /**
519
        /**
515
         * Get parent gives the next possible parent which is EXISTING in OIDplus
520
         * Get parent gives the next possible parent which is EXISTING in OIDplus
516
         * It does not give the immediate parent
521
         * It does not give the immediate parent
517
         * @return OIDplusObject|null
522
         * @return OIDplusObject|null
518
         * @throws OIDplusException
523
         * @throws OIDplusException
519
         */
524
         */
520
        public function getParent()/*: ?OIDplusObject*/ {
525
        public function getParent()/*: ?OIDplusObject*/ {
521
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
526
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
522
                        $res = OIDplus::db()->query("select parent from ###objects where id = ?", array($this->nodeId()));
527
                        $res = OIDplus::db()->query("select parent from ###objects where id = ?", array($this->nodeId()));
523
                        if (!$res->any()) return null;
528
                        if (!$res->any()) return null;
524
                        $row = $res->fetch_array();
529
                        $row = $res->fetch_array();
525
                        $parent = $row['parent'];
530
                        $parent = $row['parent'];
526
                        $obj = OIDplusObject::parse($parent);
531
                        $obj = OIDplusObject::parse($parent);
527
                        if ($obj) return $obj;
532
                        if ($obj) return $obj;
528
                        // TODO: Also implement one_up() like below
533
                        // TODO: Also implement one_up() like below
529
                } else {
534
                } else {
530
                        self::buildObjectInformationCache();
535
                        self::buildObjectInformationCache();
531
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
536
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
532
                                $parent = self::$object_info_cache[$this->nodeId()][self::CACHE_PARENT];
537
                                $parent = self::$object_info_cache[$this->nodeId()][self::CACHE_PARENT];
533
                                $obj = OIDplusObject::parse($parent);
538
                                $obj = OIDplusObject::parse($parent);
534
                                if ($obj) return $obj;
539
                                if ($obj) return $obj;
535
                        }
540
                        }
536
 
541
 
537
                        // 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()
542
                        // 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()
538
                        $cur = $this->one_up();
543
                        $cur = $this->one_up();
539
                        if (!$cur) return null;
544
                        if (!$cur) return null;
540
                        do {
545
                        do {
541
                                // findFitting() checks if that OID exists
546
                                // findFitting() checks if that OID exists
542
                                if ($fitting = self::findFitting($cur->nodeId())) return $fitting;
547
                                if ($fitting = self::findFitting($cur->nodeId())) return $fitting;
543
 
548
 
544
                                $prev = $cur;
549
                                $prev = $cur;
545
                                $cur = $cur->one_up();
550
                                $cur = $cur->one_up();
546
                                if (!$cur) return null;
551
                                if (!$cur) return null;
547
                        } while ($prev !== $cur);
552
                        } while ($prev !== $cur);
548
                }
553
                }
549
                return null;
554
                return null;
550
        }
555
        }
551
 
556
 
552
        /**
557
        /**
553
         * @return false|string|null
558
         * @return false|string|null
554
         * @throws OIDplusException
559
         * @throws OIDplusException
555
         */
560
         */
556
        public function getRaMail() {
561
        public function getRaMail() {
557
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
562
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
558
                        $res = OIDplus::db()->query("select ra_email from ###objects where id = ?", array($this->nodeId()));
563
                        $res = OIDplus::db()->query("select ra_email from ###objects where id = ?", array($this->nodeId()));
559
                        if (!$res->any()) return null;
564
                        if (!$res->any()) return null;
560
                        $row = $res->fetch_array();
565
                        $row = $res->fetch_array();
561
                        return $row['ra_email'];
566
                        return $row['ra_email'];
562
                } else {
567
                } else {
563
                        self::buildObjectInformationCache();
568
                        self::buildObjectInformationCache();
564
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
569
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
565
                                return self::$object_info_cache[$this->nodeId()][self::CACHE_RA_EMAIL];
570
                                return self::$object_info_cache[$this->nodeId()][self::CACHE_RA_EMAIL];
566
                        }
571
                        }
567
                        return false;
572
                        return false;
568
                }
573
                }
569
        }
574
        }
570
 
575
 
571
        /**
576
        /**
572
         * @return false|string|null
577
         * @return false|string|null
573
         * @throws OIDplusException
578
         * @throws OIDplusException
574
         */
579
         */
575
        public function getTitle() {
580
        public function getTitle() {
576
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
581
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
577
                        $res = OIDplus::db()->query("select title from ###objects where id = ?", array($this->nodeId()));
582
                        $res = OIDplus::db()->query("select title from ###objects where id = ?", array($this->nodeId()));
578
                        if (!$res->any()) return null;
583
                        if (!$res->any()) return null;
579
                        $row = $res->fetch_array();
584
                        $row = $res->fetch_array();
580
                        return $row['title'];
585
                        return $row['title'];
581
                } else {
586
                } else {
582
                        self::buildObjectInformationCache();
587
                        self::buildObjectInformationCache();
583
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
588
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
584
                                return self::$object_info_cache[$this->nodeId()][self::CACHE_TITLE];
589
                                return self::$object_info_cache[$this->nodeId()][self::CACHE_TITLE];
585
                        }
590
                        }
586
                        return false;
591
                        return false;
587
                }
592
                }
588
        }
593
        }
589
 
594
 
590
        /**
595
        /**
591
         * @return false|string|null
596
         * @return false|string|null
592
         * @throws OIDplusException
597
         * @throws OIDplusException
593
         */
598
         */
594
        public function getDescription() {
599
        public function getDescription() {
595
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
600
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
596
                        $res = OIDplus::db()->query("select description from ###objects where id = ?", array($this->nodeId()));
601
                        $res = OIDplus::db()->query("select description from ###objects where id = ?", array($this->nodeId()));
597
                        if (!$res->any()) return null;
602
                        if (!$res->any()) return null;
598
                        $row = $res->fetch_array();
603
                        $row = $res->fetch_array();
599
                        return $row['description'];
604
                        return $row['description'];
600
                } else {
605
                } else {
601
                        self::buildObjectInformationCache();
606
                        self::buildObjectInformationCache();
602
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
607
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
603
                                return self::$object_info_cache[$this->nodeId()][self::CACHE_DESCRIPTION];
608
                                return self::$object_info_cache[$this->nodeId()][self::CACHE_DESCRIPTION];
604
                        }
609
                        }
605
                        return false;
610
                        return false;
606
                }
611
                }
607
        }
612
        }
608
 
613
 
609
        /**
614
        /**
610
         * @return false|string|null
615
         * @return false|string|null
611
         * @throws OIDplusException
616
         * @throws OIDplusException
612
         */
617
         */
613
        public function getComment() {
618
        public function getComment() {
614
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
619
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
615
                        $res = OIDplus::db()->query("select comment from ###objects where id = ?", array($this->nodeId()));
620
                        $res = OIDplus::db()->query("select comment from ###objects where id = ?", array($this->nodeId()));
616
                        if (!$res->any()) return null;
621
                        if (!$res->any()) return null;
617
                        $row = $res->fetch_array();
622
                        $row = $res->fetch_array();
618
                        return $row['comment'];
623
                        return $row['comment'];
619
                } else {
624
                } else {
620
                        self::buildObjectInformationCache();
625
                        self::buildObjectInformationCache();
621
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
626
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
622
                                return self::$object_info_cache[$this->nodeId()][self::CACHE_COMMENT];
627
                                return self::$object_info_cache[$this->nodeId()][self::CACHE_COMMENT];
623
                        }
628
                        }
624
                        return false;
629
                        return false;
625
                }
630
                }
626
        }
631
        }
627
 
632
 
628
        /**
633
        /**
629
         * @return false|string|null
634
         * @return false|string|null
630
         * @throws OIDplusException
635
         * @throws OIDplusException
631
         */
636
         */
632
        public function getCreatedTime() {
637
        public function getCreatedTime() {
633
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
638
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
634
                        $res = OIDplus::db()->query("select created from ###objects where id = ?", array($this->nodeId()));
639
                        $res = OIDplus::db()->query("select created from ###objects where id = ?", array($this->nodeId()));
635
                        if (!$res->any()) return null;
640
                        if (!$res->any()) return null;
636
                        $row = $res->fetch_array();
641
                        $row = $res->fetch_array();
637
                        return $row['created'];
642
                        return $row['created'];
638
                } else {
643
                } else {
639
                        self::buildObjectInformationCache();
644
                        self::buildObjectInformationCache();
640
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
645
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
641
                                return self::$object_info_cache[$this->nodeId()][self::CACHE_CREATED];
646
                                return self::$object_info_cache[$this->nodeId()][self::CACHE_CREATED];
642
                        }
647
                        }
643
                        return false;
648
                        return false;
644
                }
649
                }
645
        }
650
        }
646
 
651
 
647
        /**
652
        /**
648
         * @return false|string|null
653
         * @return false|string|null
649
         * @throws OIDplusException
654
         * @throws OIDplusException
650
         */
655
         */
651
        public function getUpdatedTime() {
656
        public function getUpdatedTime() {
652
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
657
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
653
                        $res = OIDplus::db()->query("select updated from ###objects where id = ?", array($this->nodeId()));
658
                        $res = OIDplus::db()->query("select updated from ###objects where id = ?", array($this->nodeId()));
654
                        if (!$res->any()) return null;
659
                        if (!$res->any()) return null;
655
                        $row = $res->fetch_array();
660
                        $row = $res->fetch_array();
656
                        return $row['updated'];
661
                        return $row['updated'];
657
                } else {
662
                } else {
658
                        self::buildObjectInformationCache();
663
                        self::buildObjectInformationCache();
659
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
664
                        if (isset(self::$object_info_cache[$this->nodeId()])) {
660
                                return self::$object_info_cache[$this->nodeId()][self::CACHE_UPDATED];
665
                                return self::$object_info_cache[$this->nodeId()][self::CACHE_UPDATED];
661
                        }
666
                        }
662
                        return false;
667
                        return false;
663
                }
668
                }
664
        }
669
        }
665
 
670
 
666
        /**
671
        /**
667
         * @param OIDplusRA|string|null $ra
672
         * @param OIDplusRA|string|null $ra
668
         * @return bool
673
         * @return bool
669
         * @throws OIDplusException
674
         * @throws OIDplusException
670
         */
675
         */
671
        public function userHasParentalWriteRights($ra=null) {
676
        public function userHasParentalWriteRights($ra=null): bool {
672
                if ($ra instanceof OIDplusRA) $ra = $ra->raEmail();
677
                if ($ra instanceof OIDplusRA) $ra = $ra->raEmail();
673
 
678
 
674
                if (!$ra) {
679
                if (!$ra) {
675
                        if (OIDplus::authUtils()->isAdminLoggedIn()) return true;
680
                        if (OIDplus::authUtils()->isAdminLoggedIn()) return true;
676
                }
681
                }
677
 
682
 
678
                $objParent = $this->getParent();
683
                $objParent = $this->getParent();
679
                if (!$objParent) return false;
684
                if (!$objParent) return false;
680
                return $objParent->userHasWriteRights($ra);
685
                return $objParent->userHasWriteRights($ra);
681
        }
686
        }
682
 
687
 
683
        /**
688
        /**
684
         * @param OIDplusRA|string|null $ra
689
         * @param OIDplusRA|string|null $ra
685
         * @return bool
690
         * @return bool
686
         * @throws OIDplusException
691
         * @throws OIDplusException
687
         */
692
         */
688
        public function userHasWriteRights($ra=null): bool {
693
        public function userHasWriteRights($ra=null): bool {
689
                if ($ra instanceof OIDplusRA) $ra = $ra->raEmail();
694
                if ($ra instanceof OIDplusRA) $ra = $ra->raEmail();
690
 
695
 
691
                if (!$ra) {
696
                if (!$ra) {
692
                        if (OIDplus::authUtils()->isAdminLoggedIn()) return true;
697
                        if (OIDplus::authUtils()->isAdminLoggedIn()) return true;
693
                        return OIDplus::authUtils()->isRaLoggedIn($this->getRaMail());
698
                        return OIDplus::authUtils()->isRaLoggedIn($this->getRaMail());
694
                } else {
699
                } else {
695
                        return $this->getRaMail() == $ra;
700
                        return $this->getRaMail() == $ra;
696
                }
701
                }
697
        }
702
        }
698
 
703
 
699
        /**
704
        /**
700
         * @param string|OIDplusObject $to
705
         * @param string|OIDplusObject $to
701
         * @return int|null
706
         * @return int|null
702
         */
707
         */
703
        public function distance($to)/*: ?int*/ {
708
        public function distance($to)/*: ?int*/ {
704
                return null; // not implemented
709
                return null; // not implemented
705
        }
710
        }
706
 
711
 
707
        /**
712
        /**
708
         * @param OIDplusObject $obj
713
         * @param OIDplusObject|string $obj
709
         * @return bool
714
         * @return bool
710
         */
715
         */
711
        public function equals(OIDplusObject $obj): bool {
716
        public function equals($obj): bool {
712
                if (!$obj) return false;
717
                if (!$obj) return false;
713
                if (!is_object($obj)) $obj = OIDplusObject::parse($obj);
718
                if (!is_object($obj)) $obj = OIDplusObject::parse($obj);
714
                if (!$obj) return false;
719
                if (!$obj) return false;
715
                if (!($obj instanceof $this)) return false;
720
                if (!($obj instanceof $this)) return false;
716
 
721
 
717
                $distance = $this->distance($obj);
722
                $distance = $this->distance($obj);
718
                if (is_numeric($distance)) return $distance === 0; // if the distance function is implemented, use it
723
                if (is_numeric($distance)) return $distance === 0; // if the distance function is implemented, use it
719
 
724
 
720
                return $this->nodeId() == $obj->nodeId(); // otherwise compare the node id case-sensitive
725
                return $this->nodeId() == $obj->nodeId(); // otherwise compare the node id case-sensitive
721
        }
726
        }
722
 
727
 
723
        /**
728
        /**
724
         * @param string $id
729
         * @param string $id
725
         * @return OIDplusObject|false
730
         * @return OIDplusObject|false
726
         * @throws OIDplusException
731
         * @throws OIDplusException
727
         */
732
         */
728
        public static function findFitting(string $id) {
733
        public static function findFitting(string $id) {
729
                $obj = OIDplusObject::parse($id);
734
                $obj = OIDplusObject::parse($id);
730
                if (!$obj) return false; // e.g. if ObjectType plugin is disabled
735
                if (!$obj) return false; // e.g. if ObjectType plugin is disabled
731
 
736
 
732
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
737
                if (!OIDplus::baseConfig()->getValue('OBJECT_CACHING', true)) {
733
                        $res = OIDplus::db()->query("select id from ###objects where id like ?", array($obj->ns().':%'));
738
                        $res = OIDplus::db()->query("select id from ###objects where id like ?", array($obj->ns().':%'));
734
                        while ($row = $res->fetch_object()) {
739
                        while ($row = $res->fetch_object()) {
735
                                $test = OIDplusObject::parse($row->id);
740
                                $test = OIDplusObject::parse($row->id);
736
                                if ($obj->equals($test)) return $test;
741
                                if ($obj->equals($test)) return $test;
737
                        }
742
                        }
738
                        return false;
743
                        return false;
739
                } else {
744
                } else {
740
                        self::buildObjectInformationCache();
745
                        self::buildObjectInformationCache();
741
                        foreach (self::$object_info_cache as $id => $cacheitem) {
746
                        foreach (self::$object_info_cache as $id => $cacheitem) {
742
                                if (strpos($id, $obj->ns().':') === 0) {
747
                                if (strpos($id, $obj->ns().':') === 0) {
743
                                        $test = OIDplusObject::parse($id);
748
                                        $test = OIDplusObject::parse($id);
744
                                        if ($obj->equals($test)) return $test;
749
                                        if ($obj->equals($test)) return $test;
745
                                }
750
                                }
746
                        }
751
                        }
747
                        return false;
752
                        return false;
748
                }
753
                }
749
        }
754
        }
750
 
755
 
751
        /**
756
        /**
752
         * @return OIDplusObject|null
757
         * @return OIDplusObject|null
753
         */
758
         */
754
        public function one_up()/*: ?OIDplusObject*/ {
759
        public function one_up()/*: ?OIDplusObject*/ {
755
                return null; // not implemented
760
                return null; // not implemented
756
        }
761
        }
757
 
762
 
758
        // Caching stuff
763
        // Caching stuff
759
 
764
 
760
        protected static $object_info_cache = null;
765
        protected static $object_info_cache = null;
761
 
766
 
762
        /**
767
        /**
763
         * @return void
768
         * @return void
764
         */
769
         */
765
        public static function resetObjectInformationCache() {
770
        public static function resetObjectInformationCache() {
766
                self::$object_info_cache = null;
771
                self::$object_info_cache = null;
767
        }
772
        }
768
 
773
 
769
        const CACHE_ID = 'id';
774
        const CACHE_ID = 'id';
770
        const CACHE_PARENT = 'parent';
775
        const CACHE_PARENT = 'parent';
771
        const CACHE_TITLE = 'title';
776
        const CACHE_TITLE = 'title';
772
        const CACHE_DESCRIPTION = 'description';
777
        const CACHE_DESCRIPTION = 'description';
773
        const CACHE_RA_EMAIL = 'ra_email';
778
        const CACHE_RA_EMAIL = 'ra_email';
774
        const CACHE_CONFIDENTIAL = 'confidential';
779
        const CACHE_CONFIDENTIAL = 'confidential';
775
        const CACHE_CREATED = 'created';
780
        const CACHE_CREATED = 'created';
776
        const CACHE_UPDATED = 'updated';
781
        const CACHE_UPDATED = 'updated';
777
        const CACHE_COMMENT = 'comment';
782
        const CACHE_COMMENT = 'comment';
778
 
783
 
779
        /**
784
        /**
780
         * @return void
785
         * @return void
781
         * @throws OIDplusException
786
         * @throws OIDplusException
782
         */
787
         */
783
        private static function buildObjectInformationCache() {
788
        private static function buildObjectInformationCache() {
784
                if (is_null(self::$object_info_cache)) {
789
                if (is_null(self::$object_info_cache)) {
785
                        self::$object_info_cache = array();
790
                        self::$object_info_cache = array();
786
                        $res = OIDplus::db()->query("select * from ###objects");
791
                        $res = OIDplus::db()->query("select * from ###objects");
787
                        while ($row = $res->fetch_array()) {
792
                        while ($row = $res->fetch_array()) {
788
                                self::$object_info_cache[$row['id']] = $row;
793
                                self::$object_info_cache[$row['id']] = $row;
789
                        }
794
                        }
790
                }
795
                }
791
        }
796
        }
792
 
797
 
793
        /**
798
        /**
794
         * override this function if you want your object type to save
799
         * override this function if you want your object type to save
795
         * attachments in directories with easy names.
800
         * attachments in directories with easy names.
796
         * Take care that your custom directory name will not allow jailbreaks (../) !
801
         * Take care that your custom directory name will not allow jailbreaks (../) !
797
         * @return string
802
         * @return string
798
         * @throws OIDplusException
803
         * @throws OIDplusException
799
         */
804
         */
800
        public function getDirectoryName(): string {
805
        public function getDirectoryName(): string {
801
                if ($this->isRoot()) return $this->ns();
806
                if ($this->isRoot()) return $this->ns();
802
                return $this->getLegacyDirectoryName();
807
                return $this->getLegacyDirectoryName();
803
        }
808
        }
804
 
809
 
805
        /**
810
        /**
806
         * @return string
811
         * @return string
807
         * @throws OIDplusException
812
         * @throws OIDplusException
808
         */
813
         */
809
        public final function getLegacyDirectoryName(): string {
814
        public final function getLegacyDirectoryName(): string {
810
                if ($this::ns() == 'oid') {
815
                if ($this::ns() == 'oid') {
811
                        $oid = $this->nodeId(false);
816
                        $oid = $this->nodeId(false);
812
                } else {
817
                } else {
813
                        $oid = null;
818
                        $oid = null;
814
                        $alt_ids = $this->getAltIds();
819
                        $alt_ids = $this->getAltIds();
815
                        foreach ($alt_ids as $alt_id) {
820
                        foreach ($alt_ids as $alt_id) {
816
                                if ($alt_id->getNamespace() == 'oid') {
821
                                if ($alt_id->getNamespace() == 'oid') {
817
                                        $oid = $alt_id->getId();
822
                                        $oid = $alt_id->getId();
818
                                        break; // we prefer the first OID (for GUIDs, the first OID is the OIDplus-OID, and the second OID is the UUID OID)
823
                                        break; // we prefer the first OID (for GUIDs, the first OID is the OIDplus-OID, and the second OID is the UUID OID)
819
                                }
824
                                }
820
                        }
825
                        }
821
                }
826
                }
822
 
827
 
823
                if (!is_null($oid) && ($oid != '')) {
828
                if (!is_null($oid) && ($oid != '')) {
824
                        // For OIDs, it is the OID, for other identifiers
829
                        // For OIDs, it is the OID, for other identifiers
825
                        // it it the OID alt ID (generated using the SystemID)
830
                        // it it the OID alt ID (generated using the SystemID)
826
                        return str_replace('.', '_', $oid);
831
                        return str_replace('.', '_', $oid);
827
                } else {
832
                } else {
828
                        // Can happen if you don't have a system ID (due to missing OpenSSL plugin)
833
                        // Can happen if you don't have a system ID (due to missing OpenSSL plugin)
829
                        return md5($this->nodeId(true)); // we don't use $id, because $this->nodeId(true) is possibly more canonical than $id
834
                        return md5($this->nodeId(true)); // we don't use $id, because $this->nodeId(true) is possibly more canonical than $id
830
                }
835
                }
831
        }
836
        }
832
 
837
 
833
        /**
838
        /**
834
         * @param string $mode
839
         * @param string $mode
835
         * @return string
840
         * @return string
836
         */
841
         */
837
        public static function treeIconFilename(string $mode): string {
842
        public static function treeIconFilename(string $mode): string {
838
                // for backwards-compatibility with older plugins
843
                // for backwards-compatibility with older plugins
839
                return 'img/treeicon_'.$mode.'.png';
844
                return 'img/treeicon_'.$mode.'.png';
840
        }
845
        }
841
 
846
 
842
}
847
}
843
 
848