ILIAS  trunk Revision v13.0_alpha-52-g21c366bbdd4
class.ActiveRecord.php
Go to the documentation of this file.
1<?php
2
26#[\AllowDynamicProperties]
27abstract class ActiveRecord
28{
29 protected bool $ar_safe_read = true;
30 protected string $connector_container_name = '';
31 protected bool $is_new = true;
32
33 public function getArConnector(): \arConnector
34 {
35 return arConnectorMap::get($this);
36 }
37
38 public function getArFieldList(): \arFieldList
39 {
40 return arFieldCache::get($this);
41 }
42
48 public static function returnDbTableName(): string
49 {
50 throw new arException(
52 'Implement getConnectorContainerName in your child-class'
53 );
54 }
55
59 public function getConnectorContainerName(): string
60 {
61 // WILL BE ABSTRACT TO REPLACE returnDbTableName() IN NEXT VERSION
62 if ($this->connector_container_name !== '' && $this->connector_container_name !== '0') {
64 }
65
67
68 return $ar::returnDbTableName();
69 }
70
72 {
73 $this->connector_container_name = $connector_container_name;
74 }
75
79 public function getPrimaryFieldValue()
80 {
81 $primary_fieldname = arFieldCache::getPrimaryFieldName($this);
82
83 return $this->{$primary_fieldname};
84 }
85
89 public function setPrimaryFieldValue($value): void
90 {
91 $primary_fieldname = arFieldCache::getPrimaryFieldName($this);
92
93 $this->{$primary_fieldname} = $value;
94 }
95
96 public function __construct(mixed $primary_key = 0)
97 {
98 $arFieldList = arFieldCache::get($this);
99
100 $primaryFieldName = $arFieldList->getPrimaryFieldName();
101 $this->{$primaryFieldName} = $primary_key;
102 if ($primary_key === 0) {
103 return;
104 }
105 if ($primary_key === null) {
106 return;
107 }
108 if ($primary_key === false) {
109 return;
110 }
111 $this->read();
112 }
113
114 public function storeObjectToCache(): void
115 {
117 }
118
119 public function asStdClass(): \stdClass
120 {
121 $return = new stdClass();
122 foreach ($this->getArFieldList()->getFields() as $arField) {
123 $fieldname = $arField->getName();
124 $return->{$fieldname} = $this->{$fieldname};
125 }
126
127 return $return;
128 }
129
133 public function asArray(): array
134 {
135 $return = [];
136 foreach ($this->getArFieldList()->getFields() as $arField) {
137 $fieldname = $arField->getName();
138 $return[$fieldname] = $this->{$fieldname};
139 }
140
141 return $return;
142 }
143
144 public function buildFromArray(array $array): static
145 {
146 $class = static::class;
147 $primary = $this->getArFieldList()->getPrimaryFieldName();
148 $primary_value = $array[$primary];
149 if ($primary_value && arObjectCache::isCached($class, $primary_value)) {
150 return arObjectCache::get($class, $primary_value);
151 }
152 foreach ($array as $field_name => $value) {
153 $waked = $this->wakeUp($field_name, $value);
154 $this->{$field_name} = $waked ?? $value;
155 }
157
158 return $this;
159 }
160
167 public function fixDateField($field_name, string $value)
168 {
169 if ($this->getArFieldList()->getFieldByName($field_name)->isDateField()) {
170 return $this->getArConnector()->fixDate($value);
171 }
172
173 return $value;
174 }
175
180 public function sleep($field_name)
181 {
182 return null;
183 }
184
190 public function wakeUp($field_name, $field_value)
191 {
192 return null;
193 }
194
198 final public function getArrayForConnector(): array
199 {
200 $data = [];
201 foreach ($this->getArFieldList()->getFields() as $arField) {
202 $field_name = $arField->getName();
203 $sleeped = $this->sleep($field_name);
204 $var = $sleeped ?? ($this->{$field_name});
205 $data[$field_name] = [$arField->getFieldType(), $var];
206 }
207
208 return $data;
209 }
210
211
212
213
214 //
215 // Collector Modifications
216 //
221 protected static function getCalledClass(): \ActiveRecord
222 {
223 $class = static::class;
224
225 return arCalledClassCache::get($class);
226 }
227
233 final public static function installDB(): bool
234 {
235 return self::getCalledClass()->installDatabase();
236 }
237
241 public function installConnector(): bool
242 {
243 return $this->installDatabase();
244 }
245
250 final public static function renameDBField(string $old_name, string $new_name): bool
251 {
252 return self::getCalledClass()->getArConnector()->renameField(self::getCalledClass(), $old_name, $new_name);
253 }
254
255 final public static function tableExists(): bool
256 {
257 return self::getCalledClass()->getArConnector()->checkTableExists(self::getCalledClass());
258 }
259
263 final public static function fieldExists(string $field_name): bool
264 {
265 return self::getCalledClass()->getArConnector()->checkFieldExists(self::getCalledClass(), $field_name);
266 }
267
271 final public static function removeDBField(string $field_name): bool
272 {
273 return self::getCalledClass()->getArConnector()->removeField(self::getCalledClass(), $field_name);
274 }
275
279 final protected function installDatabase(): bool
280 {
281 if (!self::tableExists()) {
282 $fields = [];
283 foreach ($this->getArFieldList()->getFields() as $arField) {
284 $fields[$arField->getName()] = $arField->getAttributesForConnector();
285 }
286
287 return $this->getArConnector()->installDatabase($this, $fields);
288 }
289
290 return $this->getArConnector()->updateDatabase($this);
291 }
292
296 final public static function updateDB(): bool
297 {
298 if (!self::tableExists()) {
299 self::getCalledClass()->installDatabase();
300
301 return true;
302 }
303
304 return self::getCalledClass()->getArConnector()->updateDatabase(self::getCalledClass());
305 }
306
310 final public static function resetDB(): bool
311 {
312 return self::getCalledClass()->getArConnector()->resetDatabase(self::getCalledClass());
313 }
314
318 final public static function truncateDB(): void
319 {
320 self::getCalledClass()->getArConnector()->truncateDatabase(self::getCalledClass());
321 }
322
326 final public static function flushDB(): void
327 {
328 self::truncateDB();
329 }
330
331 //
332 // CRUD
333 //
334 public function store(): void
335 {
336 $primary_fieldname = arFieldCache::getPrimaryFieldName($this);
337 $primary_value = $this->getPrimaryFieldValue();
338
339 if (!self::where([$primary_fieldname => $primary_value])->hasSets()) {
340 $this->create();
341 } else {
342 $this->update();
343 }
344 }
345
346 public function save(): void
347 {
348 $this->store();
349 }
350
351 public function create(): void
352 {
353 if ($this->getArFieldList()->getPrimaryField()->getSequence()) {
354 $primary_fieldname = arFieldCache::getPrimaryFieldName($this);
355 $this->{$primary_fieldname} = $this->getArConnector()->nextID($this);
356 }
357
358 $this->getArConnector()->create($this);
360 }
361
365 public function copy(int $new_id = 0): self
366 {
367 if (self::where([$this->getArFieldList()->getPrimaryFieldName() => $new_id])->hasSets()) {
369 }
370 $new_obj = clone($this);
371 $new_obj->setPrimaryFieldValue($new_id);
372
373 return $new_obj;
374 }
375
376 public function afterObjectLoad(): void
377 {
378 }
379
383 public function read(): void
384 {
385 $records = $this->getArConnector()->read($this);
386 if ($this->ar_safe_read && is_array($records) && $records === []) {
387 throw new arException(arException::RECORD_NOT_FOUND, $this->getPrimaryFieldValue());
388 }
389 if (!$this->ar_safe_read && is_array($records) && $records === []) {
390 $this->is_new = true;
391 }
392 $records = is_array($records) ? $records : [];
393 foreach ($records as $record) {
394 foreach (array_keys($this->getArrayForConnector()) as $k) {
395 $waked = $this->wakeUp($k, $record->{$k} ?? null);
396 $this->{$k} = $waked ?? $record->{$k} ?? null;
397 }
399 }
400 }
401
402 public function update(): void
403 {
404 $this->getArConnector()->update($this);
406 }
407
408 public function delete(): void
409 {
410 $this->getArConnector()->delete($this);
412 }
413
414
415
416 //
417 // Collection
418 //
422 public static function preloadObjects(): array
423 {
424 return self::get();
425 }
426
430 public static function additionalParams(array $additional_params): \ActiveRecordList
431 {
432 $activeRecordList = new ActiveRecordList(self::getCalledClass());
433 $activeRecordList->additionalParams($additional_params);
434
435 return $activeRecordList;
436 }
437
441 public static function find($primary_key, array $add_constructor_args = []): ?\ActiveRecord
442 {
446 try {
447 $class_name = static::class;
448 if (!arObjectCache::isCached($class_name, $primary_key)) {
449 $obj = arFactory::getInstance($class_name, $primary_key, $add_constructor_args);
450 $obj->storeObjectToCache();
451
452 return $obj;
453 }
454 } catch (arException) {
455 return null;
456 }
457
458 try {
459 $obj = arObjectCache::get($class_name, $primary_key);
460 } catch (arException) {
461 return null;
462 }
463
464 return $obj;
465 }
466
472 public static function findOrFail($primary_key, array $add_constructor_args = []): \ActiveRecord
473 {
474 $obj = self::find($primary_key, $add_constructor_args);
475 if (is_null($obj)) {
477 }
478
479 return $obj;
480 }
481
487 public static function findOrGetInstance($primary_key, array $add_constructor_args = []): \ActiveRecord
488 {
489 $obj = self::find($primary_key, $add_constructor_args);
490 if ($obj !== null) {
491 return $obj;
492 }
493
494 $class_name = static::class;
495 $obj = arFactory::getInstance($class_name, 0, $add_constructor_args);
496 $obj->setPrimaryFieldValue($primary_key);
497 $obj->is_new = true;
498 $obj->storeObjectToCache();
499
500 return $obj;
501 }
502
507 public static function where($where, $operator = null): \ActiveRecordList
508 {
509 $activeRecordList = new ActiveRecordList(self::getCalledClass());
510 $activeRecordList->where($where, $operator);
511
512 return $activeRecordList;
513 }
514
520 public static function innerjoinAR(
521 ActiveRecord $activeRecord,
522 $on_this,
523 string $on_external,
524 array $fields = ['*'],
525 string $operator = '=',
526 bool $both_external = false
527 ): \ActiveRecordList {
528 return self::innerjoin(
529 $activeRecord->getConnectorContainerName(),
530 $on_this,
531 $on_external,
532 $fields,
533 $operator,
534 $both_external
535 );
536 }
537
544 public static function innerjoin(
545 string $tablename,
546 $on_this,
547 string $on_external,
548 array $fields = ['*'],
549 string $operator = '=',
550 bool $both_external = false
551 ): \ActiveRecordList {
552 $activeRecordList = new ActiveRecordList(self::getCalledClass());
553
554 return $activeRecordList->innerjoin($tablename, $on_this, $on_external, $fields, $operator, $both_external);
555 }
556
563 public static function leftjoin(
564 string $tablename,
565 $on_this,
566 string $on_external,
567 array $fields = ['*'],
568 string $operator = '=',
569 bool $both_external = false
570 ): \ActiveRecordList {
571 $activeRecordList = new ActiveRecordList(self::getCalledClass());
572
573 return $activeRecordList->leftjoin($tablename, $on_this, $on_external, $fields, $operator, $both_external);
574 }
575
579 public static function orderBy(string $orderBy, string $orderDirection = 'ASC'): \ActiveRecordList
580 {
581 $activeRecordList = new ActiveRecordList(self::getCalledClass());
582 $activeRecordList->orderBy($orderBy, $orderDirection);
583
584 return $activeRecordList;
585 }
586
587 public static function dateFormat(string $date_format = 'd.m.Y - H:i:s'): \ActiveRecordList
588 {
589 $activeRecordList = new ActiveRecordList(self::getCalledClass());
590 $activeRecordList->dateFormat($date_format);
591
592 return $activeRecordList;
593 }
594
599 public static function limit(int $start, int $end): \ActiveRecordList
600 {
601 $activeRecordList = new ActiveRecordList(self::getCalledClass());
602 $activeRecordList->limit($start, $end);
603
604 return $activeRecordList;
605 }
606
607 public static function affectedRows(): int
608 {
609 $activeRecordList = new ActiveRecordList(self::getCalledClass());
610
611 return $activeRecordList->affectedRows();
612 }
613
614 public static function count(): int
615 {
616 return self::affectedRows();
617 }
618
622 public static function get(): array
623 {
624 $activeRecordList = new ActiveRecordList(self::getCalledClass());
625
626 return $activeRecordList->get();
627 }
628
629 public static function debug(): \ActiveRecordList
630 {
631 $activeRecordList = new ActiveRecordList(self::getCalledClass());
632
633 return $activeRecordList->debug();
634 }
635
636 public static function first(): ?\ActiveRecord
637 {
638 $activeRecordList = new ActiveRecordList(self::getCalledClass());
639
640 return $activeRecordList->first();
641 }
642
643 public static function getCollection(): \ActiveRecordList
644 {
645 return new ActiveRecordList(self::getCalledClass());
646 ;
647 }
648
649 public static function last(): ?\ActiveRecord
650 {
651 $activeRecordList = new ActiveRecordList(self::getCalledClass());
652
653 return $activeRecordList->last();
654 }
655
659 public static function getFirstFromLastQuery(): ?\ActiveRecord
660 {
661 $activeRecordList = new ActiveRecordList(self::getCalledClass());
662
663 return $activeRecordList->getFirstFromLastQuery();
664 }
665
666 public static function connector(arConnector $arConnector): \ActiveRecordList
667 {
668 $activeRecordList = new ActiveRecordList(self::getCalledClass());
669
670 return $activeRecordList->connector($arConnector);
671 }
672
673 public static function raw(bool $set_raw = true): \ActiveRecordList
674 {
675 $activeRecordList = new ActiveRecordList(self::getCalledClass());
676
677 return $activeRecordList->raw($set_raw);
678 }
679
684 public static function getArray(?string $key = null, string|array|null $values = null): array
685 {
686 $activeRecordList = new ActiveRecordList(self::getCalledClass());
687
688 return $activeRecordList->getArray($key, $values);
689 }
690
691 //
692 // Magic Methods & Helpers
693 //
700 public function __call($name, $arguments)
701 {
702 // Getter
703 if (preg_match("/get([a-zA-Z]*)/u", (string) $name, $matches) && (is_countable($arguments) ? count(
705 ) : 0) === 0) {
706 return $this->{self::fromCamelCase($matches[1])};
707 }
708 // Setter
709 if (!preg_match("/set([a-zA-Z]*)/u", (string) $name, $matches)) {
710 return null;
711 }
712 if (count($arguments) !== 1) {
713 return null;
714 }
715 $this->{self::fromCamelCase($matches[1])} = $arguments[0];
716 return null;
717 }
718
719 public static function _toCamelCase(string $str, bool $capitalise_first_char = false): ?string
720 {
721 if ($capitalise_first_char) {
722 $str[0] = strtoupper($str[0]);
723 }
724
725 return preg_replace_callback('/_([a-z])/', fn($c): string => strtoupper($c[1]), $str);
726 }
727
728 protected static function fromCamelCase(string $str): ?string
729 {
730 $str[0] = strtolower($str[0]);
731
732 return preg_replace_callback('/([A-Z])/', fn($c): string => "_" . strtolower($c[1]), $str);
733 }
734}
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
innerjoin(string $tablename, $on_this, string $on_external, array $fields=[' *'], string $operator='=', bool $both_external=false)
leftjoin(string $tablename, $on_this, string $on_external, array $fields=[' *'], string $operator='=', bool $both_external=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static flushDB()
@depracated never use in ILIAS Core, Plugins only
getConnectorContainerName()
@description Return the Name of your Connector Table
static removeDBField(string $field_name)
static connector(arConnector $arConnector)
setPrimaryFieldValue($value)
string $connector_container_name
fixDateField($field_name, string $value)
static where($where, $operator=null)
static returnDbTableName()
static _toCamelCase(string $str, bool $capitalise_first_char=false)
sleep($field_name)
static dateFormat(string $date_format='d.m.Y - H:i:s')
__call($name, $arguments)
static getArray(?string $key=null, string|array|null $values=null)
static renameDBField(string $old_name, string $new_name)
buildFromArray(array $array)
static innerjoinAR(ActiveRecord $activeRecord, $on_this, string $on_external, array $fields=[' *'], string $operator='=', bool $both_external=false)
static raw(bool $set_raw=true)
static fromCamelCase(string $str)
wakeUp($field_name, $field_value)
setConnectorContainerName(string $connector_container_name)
static orderBy(string $orderBy, string $orderDirection='ASC')
static getCalledClass()
@description Returns an instance of the instatiated calling active record (needs to be done in static...
static getFirstFromLastQuery()
static innerjoin(string $tablename, $on_this, string $on_external, array $fields=[' *'], string $operator='=', bool $both_external=false)
static leftjoin(string $tablename, $on_this, string $on_external, array $fields=[' *'], string $operator='=', bool $both_external=false)
static limit(int $start, int $end)
static additionalParams(array $additional_params)
__construct(mixed $primary_key=0)
copy(int $new_id=0)
static findOrFail($primary_key, array $add_constructor_args=[])
Tries to find the object and throws an Exception if object is not found, instead of returning null.
static fieldExists(string $field_name)
static findOrGetInstance($primary_key, array $add_constructor_args=[])
static get(string $class_name)
static get(ActiveRecord $activeRecord)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const COPY_DESTINATION_ID_EXISTS
const UNKNONWN_EXCEPTION
static get(ActiveRecord $activeRecord)
static getPrimaryFieldName(ActiveRecord $activeRecord)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static purge(ActiveRecord $activeRecord)
static isCached($class, $id)
static get(string $class, string $id)
static store(ActiveRecord $activeRecord)
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', 'vtt', 'wav', 'webm', 'wmv', 'wmx', 'wmz', 'woff', 'wwd', 'xhtml', 'xif', 'xls', 'xlsx', 'xmind', 'xml', 'xsl', 'xsd', 'zip']
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
get(string $class_name)
$data
Definition: storeScorm.php:45