midcom_core_dbaobject::has_dependents()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package midcom
4
 * @author The Midgard Project, http://www.midgard-project.org
5
 * @copyright The Midgard Project, http://www.midgard-project.org
6
 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
7
 */
8
9
use midcom\events\dbaevent;
10
use midgard\portable\api\error\exception as mgd_exception;
11
use midcom\dba\parameters;
12
use midcom\dba\attachments;
13
use midcom\dba\privileges;
14
use midgard\portable\api\mgdobject;
15
use midcom\dba\softdelete;
16
17
/**
18
 * MidCOM DBA baseclass for MgdSchema object decorators.
19
 *
20
 * @property integer $id Local non-replication-safe database identifier
21
 * @property string $guid
22
 * @property midcom_helper_metadata $metadata the object's metadata
23
 * @package midcom
24
 */
25
abstract class midcom_core_dbaobject
26
{
27
    use parameters, attachments, privileges;
0 ignored issues
show
introduced by
The trait midcom\dba\privileges requires some properties which are not provided by midcom_core_dbaobject: $auth, $user
Loading history...
Bug introduced by
The trait midcom\dba\attachments requires the property $dbfactory which is not provided by midcom_core_dbaobject.
Loading history...
Bug introduced by
The trait midcom\dba\parameters requires the property $dispatcher which is not provided by midcom_core_dbaobject.
Loading history...
28
29
    public string $__midcom_class_name__;
30
31
    public string $__mgdschema_class_name__;
32
33
    /**
34
     * MgdSchema object
35
     */
36
    public mgdobject $__object;
37
38
    private ?midcom_helper_metadata $__metadata = null;
39
40
    /**
41
     * Should the revision control system be enabled for object updates
42
     */
43
    public bool $_use_rcs = true;
44
45
    /**
46
     * Change message used for RCS and the Activity Log summary
47
     */
48
    private string $_rcs_message = '';
49
50
    /**
51
     * Should it be allowed to automatically generate unique name in case of clash
52
     *
53
     * @see http://trac.midgard-project.org/ticket/809
54
     */
55
    public bool $allow_name_catenate = false;
56
57
    /**
58
     * May contain a list of dbaclass => field entries. When deleting an object,
59
     * these dependent objects are automatically deleted beforehand
60
     */
61
    public array $autodelete_dependents = [];
62
63
    /**
64
     * Creates an abstraction layer for an MgdSchema object.
65
     */
66 558
    public function __construct($id = null)
67
    {
68 558
        if (is_object($id)) {
69 299
            if (midcom::get()->dbclassloader->is_midcom_db_object($id)) {
70 13
                $id = $id->__object;
71
            }
72 299
            $this->__object = $id;
73
        } else {
74 515
            if (   is_int($id)
75 515
                && $id < 1) {
76
                throw new midcom_error($id . ' is not a valid database ID');
77
            }
78
79
            try {
80 515
                $mgdschemaclass = $this->__mgdschema_class_name__;
81 515
                $this->__object = new $mgdschemaclass($id);
82 32
            } catch (mgd_exception $e) {
83 32
                debug_add('Constructing ' . $this->__mgdschema_class_name__ . ' object ' . $id . ' failed, reason: ' . $e->getMessage(), MIDCOM_LOG_WARN);
84 32
                throw new midcom_error_midgard($e, $id);
85
            }
86
87
            //Some useful information for performance tuning
88 515
            if (   midcom::get()->config->get('log_level') >= MIDCOM_LOG_DEBUG
89 515
                && $this->__object->guid) {
90 274
                static $guids = [];
91 274
                static $total = 0;
92
93 274
                $total++;
94
95
                //If the GUID was loaded already, write the appropriate log entry
96 274
                if (array_key_exists($this->__object->guid, $guids)) {
97 150
                    $guids[$this->__object->guid]++;
98 150
                    $message = $this->__mgdschema_class_name__ . ' ' . $this->__object->guid;
99 150
                    $message .= ' loaded from db ' . $guids[$this->__object->guid] . ' times.';
100 150
                    $stats = 'Objects loaded (Total/Unique): ' . $total . '/' . count($guids);
101
102 150
                    debug_add($message);
103 150
                    debug_add($stats);
104
                } else {
105 220
                    $guids[$this->__object->guid] = 1;
106
                }
107
            }
108
        }
109
110 558
        if ($this->__object->guid) {
111 402
            midcom_baseclasses_core_dbobject::post_db_load_checks($this);
112
        }
113
    }
114
115
    /**
116
     * Magic getter for object property mapping
117
     *
118
     * @param string $property Name of the property
119
     */
120 570
    public function __get($property)
121
    {
122 570
        if ($property === 'metadata') {
123 428
            $this->__metadata ??= new midcom_helper_metadata($this);
124 428
            return $this->__metadata;
125
        }
126
127 562
        return $this->__object->$property;
128
    }
129
130
    /**
131
     * Magic setter for object property mapping
132
     *
133
     * @param string $property  Name of the property
134
     * @param mixed $value      Property value
135
     */
136 405
    public function __set($property, $value)
137
    {
138 405
        $this->__object->$property = $value;
139
    }
140
141
    /**
142
     * Shortcut for accessing MidCOM Query Builder
143
     */
144 485
    public static function new_query_builder() : midcom_core_querybuilder
145
    {
146 485
        return midcom::get()->dbfactory->new_query_builder(static::class);
147
    }
148
149
    /**
150
     * Shortcut for accessing MidCOM Collector
151
     *
152
     * @param string $domain The domain property of the collector instance
153
     * @param mixed $value Value match for the collector instance
154
     */
155 127
    public static function new_collector(?string $domain = null, $value = null) : midcom_core_collector
156
    {
157 127
        return midcom::get()->dbfactory->new_collector(static::class, $domain, $value);
158
    }
159
160
    /**
161
     * Shortcut for accessing MidCOM object cache.
162
     *
163
     * @param mixed $src GUID of object (ids work but are discouraged)
164
     * @return static Reference to the object
165
     */
166 233
    public static function get_cached($src) : self
167
    {
168 233
        return midcom::get()->dbfactory->get_cached(static::class, $src);
169
    }
170
171
    public function set_guid(string $guid)
172
    {
173
        $this->__object->set_guid($guid);
174
    }
175
176
    /**
177
     * Magic isset test for object property mapping
178
     *
179
     * @param string $property  Name of the property
180
     */
181 493
    public function __isset($property)
182
    {
183 493
        return isset($this->__object->$property);
184
    }
185
186
    /**
187
     * API for creating a new object
188
     */
189 313
    public function create() : bool
190
    {
191 313
        return midcom_baseclasses_core_dbobject::create($this);
192
    }
193
194
    /**
195
     * Delete the current object
196
     */
197 209
    public function delete() : bool
198
    {
199 209
        return midcom_baseclasses_core_dbobject::delete($this);
200
    }
201
202
    /**
203
     * Undelete object defined by a GUID
204
     *
205
     * @return int Size of undeleted objects
206
     */
207
    public static function undelete(string $guid) : int
208
    {
209
        return softdelete::undelete([$guid]);
210
    }
211
212
    /**
213
     * Purge the current object from database
214
     */
215 179
    public function purge() : bool
216
    {
217 179
        return $this->__object->purge();
218
    }
219
220
    /**
221
     * Delete the current object tree, starting from this object
222
     */
223 1
    public function delete_tree() : bool
224
    {
225 1
        return midcom_baseclasses_core_dbobject::delete_tree($this);
226
    }
227
228
    public function get_by_guid(string $guid) : bool
229
    {
230
        return midcom_baseclasses_core_dbobject::get_by_guid($this, $guid);
231
    }
232
233 212
    public function get_by_id(int $id) : bool
234
    {
235 212
        return midcom_baseclasses_core_dbobject::get_by_id($this, $id);
236
    }
237
238 1
    public function get_by_path(string $path) : bool
239
    {
240 1
        return midcom_baseclasses_core_dbobject::get_by_path($this, $path);
241
    }
242
243 337
    public function get_parent() : ?self
244
    {
245 337
        return midcom::get()->dbfactory->get_parent($this);
246
    }
247
    public function has_dependents() : bool
248
    {
249
        return $this->__object->has_dependents();
250
    }
251
    public function has_attachments() : bool
252
    {
253
        return $this->__object->has_attachments();
254
    }
255
    public function find_attachments(array $constraints)
256
    {
257
        return $this->__object->find_attachments($constraints);
258
    }
259
    public function delete_attachments(array $constraints)
260
    {
261
        return $this->__object->delete_attachments($constraints);
262
    }
263
    public function purge_attachments(array $constraints)
264
    {
265
        return $this->__object->purge_attachments($constraints);
266
    }
267
    public function has_parameters() : bool
268
    {
269
        return $this->__object->has_parameters();
270
    }
271
    public function find_parameters(array $constraints)
272
    {
273
        return $this->__object->find_parameters($constraints);
274
    }
275
    public function delete_parameters(array $constraints)
276
    {
277
        return $this->__object->delete_parameters($constraints);
278
    }
279
    public function purge_parameters(array $constraints)
280
    {
281
        return $this->__object->purge_parameters($constraints);
282
    }
283 212
    public function refresh() : bool
284
    {
285 212
        return midcom_baseclasses_core_dbobject::refresh($this);
286
    }
287 130
    public function update() : bool
288
    {
289 130
        return midcom_baseclasses_core_dbobject::update($this);
290
    }
291 1
    public function is_locked() : bool
292
    {
293 1
        return $this->__object->is_locked();
294
    }
295 45
    public function lock() : bool
296
    {
297 45
        return $this->__object->is_locked() || $this->__object->lock();
298
    }
299 13
    public function unlock() : bool
300
    {
301 13
        return !$this->__object->is_locked() || $this->__object->unlock();
302
    }
303 239
    public function is_approved() : bool
304
    {
305 239
        return $this->__object->is_approved();
306
    }
307 1
    public function approve() : bool
308
    {
309 1
        if ($this->__object->is_approved()) {
310
            return true;
311
        }
312 1
        if ($this->__object->approve()) {
313
            midcom::get()->dispatcher->dispatch(new dbaevent($this), dbaevent::APPROVE);
314
            return true;
315
        }
316 1
        return false;
317
    }
318
319 1
    public function unapprove() : bool
320
    {
321 1
        if (!$this->__object->is_approved()) {
322 1
            return true;
323
        }
324
        if ($this->__object->unapprove()) {
325
            midcom::get()->dispatcher->dispatch(new dbaevent($this), dbaevent::UNAPPROVE);
326
            return true;
327
        }
328
        return false;
329
    }
330
331 28
    public function get_properties() : array
332
    {
333 28
        return midcom_helper_reflector::get_object_fieldnames($this);
334
    }
335
336
    // ACL Shortcuts
337 470
    public function can_do(string $privilege, $user = null) : bool
338
    {
339 470
        return midcom::get()->auth->can_do($privilege, $this, $user);
340
    }
341 11
    public function can_user_do(string $privilege, $user = null) : bool
342
    {
343 11
        return midcom::get()->auth->can_user_do($privilege, $user, $this->__midcom_class_name__);
344
    }
345 122
    public function require_do(string $privilege, ?string $message = null)
346
    {
347 122
        midcom::get()->auth->require_do($privilege, $this, $message);
348
    }
349
    public function require_user_do(string $privilege, ?string $message = null)
350
    {
351
        midcom::get()->auth->require_user_do($privilege, $message, $this->__midcom_class_name__);
352
    }
353
354
    // DBA API
355 14
    public function get_class_magic_default_privileges() : array
356
    {
357 14
        return [
358 14
            'EVERYONE' => [],
359 14
            'ANONYMOUS' => [],
360 14
            'USERS' => []
361 14
        ];
362
    }
363
364 210
    private function _delete_dependents() : bool
365
    {
366 210
        foreach ($this->autodelete_dependents as $classname => $link_property) {
367 82
            if (!class_exists($classname)) {
368
                continue;
369
            }
370 82
            $qb = midcom::get()->dbfactory->new_query_builder($classname);
371 82
            $qb->add_constraint($link_property, '=', $this->id);
372 82
            foreach ($qb->execute() as $result) {
373 24
                if (!$result->delete()) {
374
                    debug_add('Could not delete dependent ' . $classname . ' #' . $result->id . ', aborting', MIDCOM_LOG_WARN);
375
                    return false;
376
                }
377
            }
378
        }
379 210
        return true;
380
    }
381
382
    // Event handlers
383 225
    public function _on_created()
384
    {
385 225
    }
386 247
    public function _on_creating() : bool
387
    {
388 247
        return true;
389
    }
390 166
    public function _on_deleted()
391
    {
392 166
    }
393 210
    public function _on_deleting() : bool
394
    {
395 210
        return $this->_delete_dependents();
396
    }
397 173
    public function _on_loaded()
398
    {
399 173
    }
400 491
    public static function _on_execute(midcom_core_query $query) : bool
401
    {
402 491
        return true;
403
    }
404 486
    public static function _on_process_query_result(array &$result)
405
    {
406 486
    }
407 139
    public static function _on_process_collector_result(array &$result)
408
    {
409 139
    }
410 83
    public function _on_updated()
411
    {
412 83
    }
413 85
    public function _on_updating() : bool
414
    {
415 85
        return true;
416
    }
417
    public function _on_imported()
418
    {
419
    }
420
    public function _on_importing() : bool
421
    {
422
        return true;
423
    }
424
425
    // functions related to the RCS service.
426
    public function disable_rcs()
427
    {
428
        $this->_use_rcs = false;
429
    }
430
    public function enable_rcs()
431
    {
432
        $this->_use_rcs = true;
433
    }
434 1
    public function set_rcs_message(string $msg)
435
    {
436 1
        $this->_rcs_message = $msg;
437
    }
438 245
    public function get_rcs_message() : string
439
    {
440 245
        return $this->_rcs_message;
441
    }
442
}
443