ILIAS  release_8 Revision v8.24
class.ActiveRecord.php
Go to the documentation of this file.
1<?php
2
3/******************************************************************************
4 *
5 * This file is part of ILIAS, a powerful learning management system.
6 *
7 * ILIAS is licensed with the GPL-3.0, you should have received a copy
8 * of said license along with the source code.
9 *
10 * If this is not the case or you just want to try ILIAS, you'll find
11 * us at:
12 * https://www.ilias.de
13 * https://github.com/ILIAS-eLearning
14 *
15 *****************************************************************************/
24abstract class ActiveRecord
25{
26 protected bool $ar_safe_read = true;
27 protected string $connector_container_name = '';
28 protected bool $is_new = true;
29
30 public function getArConnector(): \arConnector
31 {
32 return arConnectorMap::get($this);
33 }
34
35 public function getArFieldList(): \arFieldList
36 {
37 return arFieldCache::get($this);
38 }
39
44 public static function returnDbTableName(): string
45 {
46 throw new arException(
48 'Implement getConnectorContainerName in your child-class'
49 );
50 }
51
55 public function getConnectorContainerName(): string
56 {
57 // WILL BE ABSTRACT TO REPLACE returnDbTableName() IN NEXT VERSION
58 if ($this->connector_container_name) {
60 }
61
63
64 return $ar::returnDbTableName();
65 }
66
68 {
69 $this->connector_container_name = $connector_container_name;
70 }
71
75 public function getPrimaryFieldValue()
76 {
77 $primary_fieldname = arFieldCache::getPrimaryFieldName($this);
78
79 return $this->{$primary_fieldname};
80 }
81
85 public function setPrimaryFieldValue($value): void
86 {
87 $primary_fieldname = arFieldCache::getPrimaryFieldName($this);
88
89 $this->{$primary_fieldname} = $value;
90 }
91
95 public function __construct($primary_key = 0)
96 {
97 $arFieldList = arFieldCache::get($this);
98
99 $key = $arFieldList->getPrimaryFieldName();
100 $this->{$key} = $primary_key;
101 if ($primary_key !== 0 && $primary_key !== null && $primary_key !== false) {
102 $this->read();
103 }
104 }
105
106 public function storeObjectToCache(): void
107 {
109 }
110
111 public function asStdClass(): \stdClass
112 {
113 $return = new stdClass();
114 foreach ($this->getArFieldList()->getFields() as $field) {
115 $fieldname = $field->getName();
116 $return->{$fieldname} = $this->{$fieldname};
117 }
118
119 return $return;
120 }
121
122 public function buildFromArray(array $array): \ActiveRecord
123 {
124 $class = get_class($this);
125 $primary = $this->getArFieldList()->getPrimaryFieldName();
126 $primary_value = $array[$primary];
127 if ($primary_value && arObjectCache::isCached($class, $primary_value)) {
128 return arObjectCache::get($class, $primary_value);
129 }
130 foreach ($array as $field_name => $value) {
131 $waked = $this->wakeUp($field_name, $value);
132 $this->{$field_name} = $waked ?? $value;
133 }
135
136 return $this;
137 }
138
145 public function fixDateField($field_name, $value)
146 {
147 if ($this->getArFieldList()->getFieldByName($field_name)->isDateField()) {
148 return $this->getArConnector()->fixDate($value);
149 }
150
151 return $value;
152 }
153
158 public function sleep($field_name)
159 {
160 return null;
161 }
162
168 public function wakeUp($field_name, $field_value)
169 {
170 return null;
171 }
172
173 final public function getArrayForConnector(): array
174 {
175 $data = array();
176 foreach ($this->getArFieldList()->getFields() as $field) {
177 $field_name = $field->getName();
178 $sleeped = $this->sleep($field_name);
179 $var = $sleeped ?? ($this->{$field_name});
180 $data[$field_name] = array($field->getFieldType(), $var);
181 }
182
183 return $data;
184 }
185
186
187
188
189 //
190 // Collector Modifications
191 //
196 protected static function getCalledClass(): \ActiveRecord
197 {
198 $class = static::class;
199
200 return arCalledClassCache::get($class);
201 }
202
208 final public static function installDB(): bool
209 {
210 return self::getCalledClass()->installDatabase();
211 }
212
216 public function installConnector(): bool
217 {
218 return $this->installDatabase();
219 }
220
225 final public static function renameDBField(string $old_name, string $new_name): bool
226 {
227 return self::getCalledClass()->getArConnector()->renameField(self::getCalledClass(), $old_name, $new_name);
228 }
229
230 final public static function tableExists(): bool
231 {
232 return self::getCalledClass()->getArConnector()->checkTableExists(self::getCalledClass());
233 }
234
238 final public static function fieldExists(string $field_name): bool
239 {
240 return self::getCalledClass()->getArConnector()->checkFieldExists(self::getCalledClass(), $field_name);
241 }
242
246 final public static function removeDBField(string $field_name): bool
247 {
248 return self::getCalledClass()->getArConnector()->removeField(self::getCalledClass(), $field_name);
249 }
253 final protected function installDatabase(): bool
254 {
255 if (!self::tableExists()) {
256 $fields = array();
257 if (isset($this)) {
258 foreach ($this->getArFieldList()->getFields() as $field) {
259 $fields[$field->getName()] = $field->getAttributesForConnector();
260 }
261 }
262
263 return $this->getArConnector()->installDatabase($this, $fields);
264 }
265
266 return $this->getArConnector()->updateDatabase($this);
267 }
268
272 final public static function updateDB(): bool
273 {
274 if (!self::tableExists()) {
275 self::getCalledClass()->installDatabase();
276
277 return true;
278 }
279
280 return self::getCalledClass()->getArConnector()->updateDatabase(self::getCalledClass());
281 }
285 final public static function resetDB(): bool
286 {
287 return self::getCalledClass()->getArConnector()->resetDatabase(self::getCalledClass());
288 }
289
293 final public static function truncateDB(): void
294 {
295 self::getCalledClass()->getArConnector()->truncateDatabase(self::getCalledClass());
296 }
300 final public static function flushDB(): void
301 {
302 self::truncateDB();
303 }
304
305 //
306 // CRUD
307 //
308 public function store(): void
309 {
310 $primary_fieldname = arFieldCache::getPrimaryFieldName($this);
311 $primary_value = $this->getPrimaryFieldValue();
312
313 if (!self::where(array($primary_fieldname => $primary_value))->hasSets()) {
314 $this->create();
315 } else {
316 $this->update();
317 }
318 }
319
320 public function save(): void
321 {
322 $this->store();
323 }
324
325 public function create(): void
326 {
327 if ($this->getArFieldList()->getPrimaryField()->getSequence()) {
328 $primary_fieldname = arFieldCache::getPrimaryFieldName($this);
329 $this->{$primary_fieldname} = $this->getArConnector()->nextID($this);
330 }
331
332 $this->getArConnector()->create($this);
334 }
335
339 public function copy(int $new_id = 0): self
340 {
341 if (self::where(array($this->getArFieldList()->getPrimaryFieldName() => $new_id))->hasSets()) {
343 }
344 $new_obj = clone($this);
345 $new_obj->setPrimaryFieldValue($new_id);
346
347 return $new_obj;
348 }
349
350 public function afterObjectLoad(): void
351 {
352 }
353
357 public function read(): void
358 {
359 $records = $this->getArConnector()->read($this);
360 if ($this->ar_safe_read === true && is_array($records) && count($records) === 0) {
361 throw new arException(arException::RECORD_NOT_FOUND, $this->getPrimaryFieldValue());
362 } elseif ($this->ar_safe_read === false && is_array($records) && count($records) === 0) {
363 $this->is_new = true;
364 }
365 $records = is_array($records) ? $records : array();
366 foreach ($records as $rec) {
367 foreach ($this->getArrayForConnector() as $k => $v) {
368 $waked = $this->wakeUp($k, $rec->{$k} ?? null);
369 $this->{$k} = $waked ?? $rec->{$k} ?? null;
370 }
372 }
373 }
374
375 public function update()
376 {
377 $this->getArConnector()->update($this);
379 }
380
381 public function delete()
382 {
383 $this->getArConnector()->delete($this);
385 }
386
387
388
389 //
390 // Collection
391 //
395 public static function preloadObjects(): array
396 {
397 return self::get();
398 }
399
403 public static function additionalParams(array $additional_params): \ActiveRecordList
404 {
405 $srModelObjectList = new ActiveRecordList(self::getCalledClass());
406 $srModelObjectList->additionalParams($additional_params);
407
408 return $srModelObjectList;
409 }
410
414 public static function find($primary_key, array $add_constructor_args = array()): ?\ActiveRecord
415 {
419 try {
420 $class_name = static::class;
421 if (!arObjectCache::isCached($class_name, $primary_key)) {
422 $obj = arFactory::getInstance($class_name, $primary_key, $add_constructor_args);
423 $obj->storeObjectToCache();
424
425 return $obj;
426 }
427 } catch (arException $e) {
428 return null;
429 }
430
431 try {
432 $obj = arObjectCache::get($class_name, $primary_key);
433 } catch (arException $e) {
434 return null;
435 }
436
437 return $obj;
438 }
439
445 public static function findOrFail($primary_key, array $add_constructor_args = array()): \ActiveRecord
446 {
447 $obj = self::find($primary_key, $add_constructor_args);
448 if (is_null($obj)) {
450 }
451
452 return $obj;
453 }
454
460 public static function findOrGetInstance($primary_key, array $add_constructor_args = array())
461 {
462 $obj = self::find($primary_key, $add_constructor_args);
463 if ($obj !== null) {
464 return $obj;
465 }
466
467 $class_name = static::class;
468 $obj = arFactory::getInstance($class_name, 0, $add_constructor_args);
469 $obj->setPrimaryFieldValue($primary_key);
470 $obj->is_new = true;
471 $obj->storeObjectToCache();
472
473 return $obj;
474 }
475
480 public static function where($where, $operator = null): \ActiveRecordList
481 {
482 $srModelObjectList = new ActiveRecordList(self::getCalledClass());
483 $srModelObjectList->where($where, $operator);
484
485 return $srModelObjectList;
486 }
487
493 public static function innerjoinAR(
494 ActiveRecord $ar,
495 $on_this,
496 $on_external,
497 array $fields = array('*'),
498 string $operator = '=',
499 $both_external = false
500 ): \ActiveRecordList {
501 return self::innerjoin(
502 $ar->getConnectorContainerName(),
503 $on_this,
504 $on_external,
505 $fields,
506 $operator,
507 $both_external
508 );
509 }
510
517 public static function innerjoin(
518 $tablename,
519 $on_this,
520 $on_external,
521 array $fields = array('*'),
522 string $operator = '=',
523 bool $both_external = false
524 ): \ActiveRecordList {
525 $srModelObjectList = new ActiveRecordList(self::getCalledClass());
526
527 return $srModelObjectList->innerjoin($tablename, $on_this, $on_external, $fields, $operator, $both_external);
528 }
529
536 public static function leftjoin(
537 $tablename,
538 $on_this,
539 $on_external,
540 array $fields = array('*'),
541 string $operator = '=',
542 bool $both_external = false
543 ): \ActiveRecordList {
544 $srModelObjectList = new ActiveRecordList(self::getCalledClass());
545
546 return $srModelObjectList->leftjoin($tablename, $on_this, $on_external, $fields, $operator, $both_external);
547 }
548
552 public static function orderBy($orderBy, string $orderDirection = 'ASC'): \ActiveRecordList
553 {
554 $srModelObjectList = new ActiveRecordList(self::getCalledClass());
555 $srModelObjectList->orderBy($orderBy, $orderDirection);
556
557 return $srModelObjectList;
558 }
559
560 public static function dateFormat(string $date_format = 'd.m.Y - H:i:s'): \ActiveRecordList
561 {
562 $srModelObjectList = new ActiveRecordList(self::getCalledClass());
563 $srModelObjectList->dateFormat($date_format);
564
565 return $srModelObjectList;
566 }
567
572 public static function limit($start, $end): \ActiveRecordList
573 {
574 $srModelObjectList = new ActiveRecordList(self::getCalledClass());
575 $srModelObjectList->limit($start, $end);
576
577 return $srModelObjectList;
578 }
579
580 public static function affectedRows(): int
581 {
582 $srModelObjectList = new ActiveRecordList(self::getCalledClass());
583
584 return $srModelObjectList->affectedRows();
585 }
586
587 public static function count(): int
588 {
589 return self::affectedRows();
590 }
591
595 public static function get(): array
596 {
597 $srModelObjectList = new ActiveRecordList(self::getCalledClass());
598
599 return $srModelObjectList->get();
600 }
601
602 public static function debug(): \ActiveRecordList
603 {
604 $srModelObjectList = new ActiveRecordList(self::getCalledClass());
605
606 return $srModelObjectList->debug();
607 }
608
609 public static function first(): ?\ActiveRecord
610 {
611 $srModelObjectList = new ActiveRecordList(self::getCalledClass());
612
613 return $srModelObjectList->first();
614 }
615
616 public static function getCollection(): \ActiveRecordList
617 {
618 return new ActiveRecordList(self::getCalledClass());
619 ;
620 }
621
622 public static function last(): ?\ActiveRecord
623 {
624 $srModelObjectList = new ActiveRecordList(self::getCalledClass());
625
626 return $srModelObjectList->last();
627 }
628
632 public static function getFirstFromLastQuery(): ?\ActiveRecord
633 {
634 $srModelObjectList = new ActiveRecordList(self::getCalledClass());
635
636 return $srModelObjectList->getFirstFromLastQuery();
637 }
638
639 public static function connector(arConnector $connector): \ActiveRecordList
640 {
641 $srModelObjectList = new ActiveRecordList(self::getCalledClass());
642
643 return $srModelObjectList->connector($connector);
644 }
645
646 public static function raw(bool $set_raw = true): \ActiveRecordList
647 {
648 $srModelObjectList = new ActiveRecordList(self::getCalledClass());
649
650 return $srModelObjectList->raw($set_raw);
651 }
652
656 public static function getArray(?string $key = null, $values = null): array
657 {
658 $record_list = new ActiveRecordList(self::getCalledClass());
659
660 return $record_list->getArray($key, $values);
661 }
662
663 //
664 // Magic Methods & Helpers
665 //
672 public function __call($name, $arguments)
673 {
674 // Getter
675 if (preg_match("/get([a-zA-Z]*)/u", $name, $matches) && count($arguments) === 0) {
676 return $this->{self::fromCamelCase($matches[1])};
677 }
678 // Setter
679 if (preg_match("/set([a-zA-Z]*)/u", $name, $matches) && count($arguments) === 1) {
680 $this->{self::fromCamelCase($matches[1])} = $arguments[0];
681 }
682 }
683
684 public static function _toCamelCase(string $str, bool $capitalise_first_char = false): ?string
685 {
686 if ($capitalise_first_char) {
687 $str[0] = strtoupper($str[0]);
688 }
689
690 return preg_replace_callback('/_([a-z])/', fn ($c) => strtoupper($c[1]), $str);
691 }
692
693 protected static function fromCamelCase(string $str): ?string
694 {
695 $str[0] = strtolower($str[0]);
696
697 return preg_replace_callback('/([A-Z])/', fn ($c) => "_" . strtolower($c[1]), $str);
698 }
699}
@noinspection NullPointerExceptionInspection
innerjoin( $tablename, $on_this, $on_external, array $fields=array(' *'), string $operator='=', bool $both_external=false)
leftjoin( $tablename, $on_this, $on_external, array $fields=array(' *'), string $operator='=', bool $both_external=false)
Class ActiveRecord.
static flushDB()
@depracated never use in ILIAS Core, Plugins only
getConnectorContainerName()
@description Return the Name of your Connector Table
static orderBy($orderBy, string $orderDirection='ASC')
static removeDBField(string $field_name)
setPrimaryFieldValue($value)
string $connector_container_name
__construct($primary_key=0)
static where($where, $operator=null)
static returnDbTableName()
fixDateField($field_name, $value)
static _toCamelCase(string $str, bool $capitalise_first_char=false)
static findOrFail($primary_key, array $add_constructor_args=array())
Tries to find the object and throws an Exception if object is not found, instead of returning null.
static connector(arConnector $connector)
sleep($field_name)
static dateFormat(string $date_format='d.m.Y - H:i:s')
__call($name, $arguments)
static findOrGetInstance($primary_key, array $add_constructor_args=array())
static renameDBField(string $old_name, string $new_name)
buildFromArray(array $array)
static limit($start, $end)
static raw(bool $set_raw=true)
static fromCamelCase(string $str)
wakeUp($field_name, $field_value)
setConnectorContainerName(string $connector_container_name)
static getCalledClass()
@description Returns an instance of the instatiated calling active record (needs to be done in static...
static getFirstFromLastQuery()
static leftjoin( $tablename, $on_this, $on_external, array $fields=array(' *'), string $operator='=', bool $both_external=false)
static getArray(?string $key=null, $values=null)
static additionalParams(array $additional_params)
static innerjoinAR(ActiveRecord $ar, $on_this, $on_external, array $fields=array(' *'), string $operator='=', $both_external=false)
copy(int $new_id=0)
static fieldExists(string $field_name)
static innerjoin( $tablename, $on_this, $on_external, array $fields=array(' *'), string $operator='=', bool $both_external=false)
static get(string $class_name)
static get(ActiveRecord $ar)
Class arConnector.
Class arException.
const COPY_DESTINATION_ID_EXISTS
const UNKNONWN_EXCEPTION
static getPrimaryFieldName(ActiveRecord $ar)
static get(ActiveRecord $ar)
Class arFieldList.
static isCached($class, $id)
static store(ActiveRecord $object)
static purge(ActiveRecord $object)
static get($class, $id)
$c
Definition: cli.php:38
return['3gp', '7z', 'ai', 'aif', 'aifc', 'aiff', 'au', 'arw', 'avi', 'backup', 'bak', 'bas', 'bpmn', 'bpmn2', 'bmp', 'bib', 'bibtex', 'bz', 'bz2', 'c', 'c++', 'cc', 'cct', 'cdf', 'cer', 'class', 'cls', 'conf', 'cpp', 'crt', 'crs', 'crw', 'cr2', 'css', 'cst', 'csv', 'cur', 'db', 'dcr', 'des', 'dng', 'doc', 'docx', 'dot', 'dotx', 'dtd', 'dvi', 'el', 'eps', 'epub', 'f', 'f77', 'f90', 'flv', 'for', 'g3', 'gif', 'gl', 'gan', 'ggb', 'gsd', 'gsm', 'gtar', 'gz', 'gzip', 'h', 'hpp', 'htm', 'html', 'htmls', 'ibooks', 'ico', 'ics', 'ini', 'ipynb', 'java', 'jbf', 'jpeg', 'jpg', 'js', 'jsf', 'jso', 'json', 'latex', 'lang', 'less', 'log', 'lsp', 'ltx', 'm1v', 'm2a', 'm2v', 'm3u', 'm4a', 'm4v', 'markdown', 'm', 'mat', 'md', 'mdl', 'mdown', 'mid', 'min', 'midi', 'mobi', 'mod', 'mov', 'movie', 'mp2', 'mp3', 'mp4', 'mpa', 'mpeg', 'mpg', 'mph', 'mpga', 'mpp', 'mpt', 'mpv', 'mpx', 'mv', 'mw', 'mv4', 'nb', 'nbp', 'nef', 'nif', 'niff', 'obj', 'obm', 'odt', 'ods', 'odp', 'odg', 'odf', 'oga', 'ogg', 'ogv', 'old', 'p', 'pas', 'pbm', 'pcl', 'pct', 'pcx', 'pdf', 'pgm', 'pic', 'pict', 'png', 'por', 'pov', 'project', 'properties', 'ppa', 'ppm', 'pps', 'ppsx', 'ppt', 'pptx', 'ppz', 'ps', 'psd', 'pwz', 'qt', 'qtc', 'qti', 'qtif', 'r', 'ra', 'ram', 'rar', 'rast', 'rda', 'rev', 'rexx', 'ris', 'rf', 'rgb', 'rm', 'rmd', 'rmi', 'rmm', 'rmp', 'rt', 'rtf', 'rtx', 'rv', 's', 's3m', 'sav', 'sbs', 'sec', 'sdml', 'sgm', 'sgml', 'smi', 'smil', 'srt', 'sps', 'spv', 'stl', 'svg', 'swa', 'swf', 'swz', 'tar', 'tex', 'texi', 'texinfo', 'text', 'tgz', 'tif', 'tiff', 'ttf', 'txt', 'tmp', 'uvproj', 'vdf', 'vimeo', 'viv', 'vivo', 'vrml', 'vsdx', 'wav', 'webm', 'wmv', 'wmx', 'wmz', 'woff', 'wwd', 'xhtml', 'xif', 'xls', 'xlsx', 'xmind', 'xml', 'xsl', 'xsd', 'zip']
if($format !==null) $name
Definition: metadata.php:247
string $key
Consumer key/client ID value.
Definition: System.php:193
get(string $key, Refinery\Transformation $t)
Get passed parameter, if not data passed, get key from http request.