Completed
Push — master ( 920166...6999ec )
by Andreas
17:15
created

midcom_core_dbaobject::get_parent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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