ILIAS  trunk Revision v12.0_alpha-1227-g7ff6d300864
class.ilDclBaseFieldModel.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22{
23 protected string $id = "";
24 protected int $table_id = 0;
25 protected string $title = "";
26 protected string $description = "";
27 protected int $datatype_id = 0;
28 protected ?int $order = null;
30 protected array $property = [];
31 protected bool $exportable = false;
32 protected ?ilDclDatatype $datatype = null;
36 protected ?int $storage_location_override = null;
40 public const PROP_LENGTH = "lenght";
41 public const PROP_REGEX = "regex";
42 public const PROP_REFERENCE = "table_id";
43 public const PROP_URL = "url";
44 public const PROP_REFERENCE_LINK = "reference_link";
45 public const PROP_UNIQUE = "unique";
46 public const PROP_LEARNING_PROGRESS = "learning_progress";
47 public const PROP_ILIAS_REFERENCE_LINK = "ILIAS_reference_link";
48 public const PROP_N_REFERENCE = "multiple_selection";
49 public const PROP_FORMULA_EXPRESSION = "expression";
50 public const PROP_DISPLAY_COPY_LINK_ACTION_MENU = "display_action_menu";
51 public const PROP_LINK_DETAIL_PAGE_TEXT = "link_detail_page_text";
52 public const PROP_LINK_DETAIL_PAGE_MOB = "link_detail_page_mob";
53 public const PROP_SUPPORTED_FILE_TYPES = "supported_file_types";
54 public const PROP_PLUGIN_HOOK_NAME = "plugin_hook_name";
55 // type of table il_dcl_view
56 public const EDIT_VIEW = 2;
57 public const EXPORTABLE_VIEW = 4;
58
59 protected ilDBInterface $db;
60 protected ilLanguage $lng;
61
62 public function __construct(int $a_id = 0)
63 {
64 global $DIC;
65 $this->db = $DIC->database();
66 $this->lng = $DIC->language();
67
68 if ($a_id != 0) {
69 $this->id = (string) $a_id;
70 $this->doRead();
71 }
72 }
73
77 public static function _getTitleInvalidChars(bool $a_as_regex = true): string
78 {
79 if ($a_as_regex) {
80 return '/^[^<>\\\\":]*$/i';
81 } else {
82 return '\ < > " :';
83 }
84 }
85
86 public static function _getFieldIdByTitle(string $title, int $table_id): int
87 {
88 global $DIC;
89 $ilDB = $DIC->database();
90
91 $result = $ilDB->query(
92 'SELECT id FROM il_dcl_field WHERE title = ' . $ilDB->quote($title, 'text') . ' AND table_id = '
93 . $ilDB->quote($table_id, 'integer')
94 );
95 $id = 0;
96 while ($rec = $ilDB->fetchAssoc($result)) {
97 $id = $rec['id'];
98 }
99
100 return $id;
101 }
102
107 public function setId($a_id): void
108 {
109 $this->id = (string) $a_id;
110 }
111
115 public function getId(): string
116 {
117 return $this->id;
118 }
119
123 public function setTableId(int $a_id): void
124 {
125 $this->table_id = $a_id;
126 }
127
131 public function getTableId(): int
132 {
133 return $this->table_id;
134 }
135
139 public function setTitle(string $a_title): void
140 {
141 //title cannot begin with _ as this is saved for other purposes. make __ instead.
142 if (substr($a_title, 0, 1) == "_" && substr($a_title, 0, 2) != "__") {
143 $a_title = "_" . $a_title;
144 }
145 $this->title = $a_title;
146 }
147
151 public function getTitle(): string
152 {
153 return $this->title;
154 }
155
159 public function setDescription(string $a_desc): void
160 {
161 $this->description = $a_desc;
162 }
163
167 public function getDescription(): string
168 {
169 return $this->description;
170 }
171
175 public function setDatatypeId(int $a_id): void
176 {
177 //unset the cached datatype.
178 $this->datatype = null;
179 $this->datatype_id = $a_id;
180 }
181
185 public function getDatatypeId(): ?int
186 {
187 if ($this->isStandardField()) {
189 }
190
191 return $this->datatype_id;
192 }
193
194 public function getDatatype(): ilDclDatatype
195 {
196 $this->loadDatatype();
197
198 return $this->datatype;
199 }
200
201 public function getDatatypeTitle(): string
202 {
203 $this->loadDatatype();
204 return $this->datatype->getTitle();
205 }
206
207 public function getPresentationTitle(): string
208 {
209 return $this->lng->txt('dcl_' . $this->getDatatypeTitle());
210 }
211
212 public function getPresentationDescription(): string
213 {
214 return $this->lng->txt('dcl_' . $this->getDatatypeTitle() . '_desc');
215 }
216
220 public function getStorageLocation(): ?int
221 {
222 if ($this->getStorageLocationOverride() !== null) {
223 return $this->getStorageLocationOverride();
224 }
225
226 $this->loadDatatype();
227
228 return $this->datatype->getStorageLocation();
229 }
230
234 protected function loadDatatype(): void
235 {
236 if ($this->datatype == null) {
237 $this->datatype = ilDclCache::getDatatype($this->datatype_id);
238 }
239 }
240
244 protected function loadTableFieldSetting(): void
245 {
246 $tablefield_setting = ilDclTableFieldSetting::getInstance($this->getTableId(), $this->getId());
247 $this->exportable = $tablefield_setting->isExportable();
248 $this->order = $tablefield_setting->getFieldOrder();
249 }
250
254 public function getExportable(): bool
255 {
256 if (!isset($this->exportable)) {
257 $this->loadExportability();
258 }
259
260 return $this->exportable;
261 }
262
266 private function loadExportability(): void
267 {
268 if ($this->exportable == null) {
269 $this->loadTableFieldSetting();
270 }
271 }
272
273 public function toArray(): array
274 {
275 return (array) $this;
276 }
277
278 public function isStandardField(): bool
279 {
280 return false;
281 }
282
283 public function doRead(): void
284 {
285 //THEN 1 ELSE 0 END AS has_options FROM il_dcl_field f WHERE id = ".$ilDB->quote($this->getId(),"integer");
286 $query = "SELECT * FROM il_dcl_field WHERE id = " . $this->db->quote($this->getId(), "integer");
287 $set = $this->db->query($query);
288 $rec = $this->db->fetchAssoc($set);
289
290 if ($rec) {
291 $this->setTableId($rec["table_id"]);
292 if (null !== $rec["title"]) {
293 $this->setTitle($rec["title"]);
294 }
295 if (null !== $rec["description"]) {
296 $this->setDescription($rec["description"]);
297 }
298 $this->setDatatypeId($rec["datatype_id"]);
299 }
300
301 $this->loadProperties();
302 $this->loadTableFieldSetting();
303 }
304
308 public function buildFromDBRecord(array $rec): void
309 {
310 $this->setId($rec["id"]);
311 $this->setTableId($rec["table_id"]);
312 $this->setTitle($rec["title"]);
313 $this->setDescription($rec["description"]);
314 $this->setDatatypeId($rec["datatype_id"]);
315 }
316
317 public function doCreate(): void
318 {
319 if (!ilDclTable::_tableExists($this->getTableId())) {
320 throw new ilException("The field does not have a related table!");
321 }
322
323 $id = $this->db->nextId("il_dcl_field");
324 $this->setId($id);
325 $query = "INSERT INTO il_dcl_field (" . "id" . ", table_id" . ", datatype_id" . ", title" . ", description"
326 . " ) VALUES (" . $this->db->quote($this->getId(), "integer") . "," . $this->db->quote(
327 $this->getTableId(),
328 "integer"
329 ) . ","
330 . $this->db->quote($this->getDatatypeId(), "integer") . "," . $this->db->quote($this->getTitle(), "text") . ","
331 . $this->db->quote($this->getDescription(), "text") . ")";
332 $this->db->manipulate($query);
333
335
336 $this->addToTableViews();
337 }
338
342 protected function addToTableViews(): void
343 {
344 foreach (ilDclTableView::getAllForTableId($this->table_id) as $tableview) {
345 $tableview->createFieldSetting($this->id);
346 }
347 }
348
349 public function doUpdate(): void
350 {
351 $this->db->update(
352 "il_dcl_field",
353 [
354 "table_id" => [
355 "integer",
356 $this->getTableId(),
357 ],
358 "datatype_id" => [
359 "text",
360 $this->getDatatypeId(),
361 ],
362 "title" => [
363 "text",
364 $this->getTitle(),
365 ],
366 "description" => [
367 "text",
368 $this->getDescription(),
369 ],
370 ],
371 [
372 "id" => [
373 "integer",
374 $this->getId(),
375 ],
376 ]
377 );
379 $this->updateProperties();
380 }
381
385 public function updateProperties(): void
386 {
387 foreach ($this->property as $prop) {
388 $prop->store();
389 }
390 }
391
395 protected function updateTableFieldSetting(): void
396 {
397 $tablefield_setting = ilDclTableFieldSetting::getInstance($this->getTableId(), $this->getId());
398 $tablefield_setting->setExportable($this->exportable);
399 $tablefield_setting->setFieldOrder($this->getOrder());
400 $tablefield_setting->store();
401 }
402
406 public function doDelete(): void
407 {
408 // delete tablefield setting.
409 ilDclTableFieldSetting::getInstance($this->getTableId(), $this->getId())->delete();
410
411 $query = "DELETE FROM il_dcl_field_prop WHERE field_id = " . $this->db->quote($this->getId(), "text");
412 $this->db->manipulate($query);
413
414 $query = "DELETE FROM il_dcl_field WHERE id = " . $this->db->quote($this->getId(), "text");
415 $this->db->manipulate($query);
416
417 foreach ($this->getViewSettings() as $field_setting) {
418 $field_setting->delete();
419 }
420 }
421
425 public function getViewSettings(): array
426 {
427 return ilDclTableViewFieldSetting::where(['field' => $this->getId()])->get();
428 }
429
430 public function getViewSetting(int $tableview_id): ilDclTableViewFieldSetting
431 {
432 return ilDclTableViewFieldSetting::getTableViewFieldSetting($this->getId(), $tableview_id);
433 }
434
435 public function getOrder(): int
436 {
437 if ($this->order == null) {
438 $this->loadTableFieldSetting();
439 }
440
441 return !$this->order ? 0 : $this->order;
442 }
443
444 public function setOrder(int $order): void
445 {
446 $this->order = $order;
447 }
448
452 protected function loadProperties(): void
453 {
454 $this->property = ilDclCache::getFieldProperties($this->getId());
455 }
456
460 public function hasProperty(string $key): bool
461 {
462 $this->loadProperties();
463
464 return (isset($this->property[$key]) && $this->property[$key]->getValue() != null);
465 }
466
467 public function getProperty(string $key): mixed
468 {
469 $instance = $this->getPropertyInstance($key);
470
471 return ($instance !== null) ? $instance->getValue() : null;
472 }
473
474 public function getPropertyInstance(string $key): ?ilDclFieldProperty
475 {
476 $this->loadProperties();
477 if ($this->hasProperty($key)) {
478 return $this->property[$key];
479 }
480
481 return null;
482 }
483
484 public function setProperty(string $key, $value): ?ilDclFieldProperty
485 {
486 $this->loadProperties();
487 if (isset($this->property[$key])) {
488 $this->property[$key]->setValue($value);
489 } else {
491 $property->setName($key);
492 $property->setFieldId((int) $this->getId());
493 $property->setValue($value);
494
495 $this->property[$key] = $property;
496 }
497
498 return $this->property[$key];
499 }
500
504 public function getValidFieldProperties(): array
505 {
506 return [];
507 }
508
509 public function checkValidityFromForm(ilPropertyFormGUI &$form, ?int $record_id): void
510 {
511 $value = $form->getInput('field_' . $this->getId());
512 $this->checkValidity($value, $record_id);
513 }
514
520 public function checkValidity($value, ?int $record_id): bool
521 {
522 return true;
523 }
524
525 protected function areEqual($value_1, $value_2): bool
526 {
527 return $this->normalizeValue($value_1) === $this->normalizeValue($value_2);
528 }
529
530 protected function normalizeValue(mixed $value)
531 {
532 if (is_string($value)) {
533 $value = trim(preg_replace("/\\s+/uism", " ", $value));
534 }
535
536 return $value;
537 }
538
542 public function cloneStructure(int $original_id): void
543 {
544 $original = ilDclCache::getFieldCache($original_id);
545 $this->setTitle($original->getTitle());
546 $this->setDatatypeId($original->getDatatypeId());
547 $this->setDescription($original->getDescription());
548 $this->setOrder($original->getOrder());
549 $this->setExportable($original->getExportable());
550 $this->doCreate();
551 $this->cloneProperties($original);
552
553 // mandatory for all cloning functions
554 ilDclCache::setCloneOf($original_id, (int) $this->getId(), ilDclCache::TYPE_FIELD);
555 }
556
557 public function afterClone(array $records)
558 {
559 foreach ($records as $rec) {
560 ilDclCache::getRecordFieldCache($rec, $this)->afterClone();
561 }
562 }
563
564 public function cloneProperties(ilDclBaseFieldModel $originalField): void
565 {
566 $orgProps = $originalField->getValidFieldProperties();
567 if (count($orgProps) == 0) {
568 return;
569 }
570 foreach ($orgProps as $prop_name) {
571 $fieldprop_obj = new ilDclFieldProperty();
572 $fieldprop_obj->setFieldId((int) $this->getId());
573 $fieldprop_obj->setName($prop_name);
574
575 $value = $originalField->getProperty($prop_name);
576
577 if (
579 (
582 )
583 ) {
584 $value = null;
585 }
586
587 if ($value) {
588 $fieldprop_obj->setValue($value);
589 $fieldprop_obj->create();
590 }
591 }
592 }
593
594 public function setExportable(bool $exportable): void
595 {
596 $this->exportable = $exportable;
597 }
598
599 public function allowFilterInListView(): bool
600 {
601 return true;
602 }
603
609 string $direction = "asc",
610 bool $sort_by_status = false
612 $sql_obj = new ilDclRecordQueryObject();
613
614 $select_str = "sort_stloc_{$this->getId()}.value AS field_{$this->getId()}";
615 $join_str
616 = "LEFT JOIN il_dcl_record_field AS sort_record_field_{$this->getId()} ON (sort_record_field_{$this->getId()}.record_id = record.id AND sort_record_field_{$this->getId()}.field_id = "
617 . $this->db->quote($this->getId(), 'integer') . ") ";
618 $join_str .= "LEFT JOIN il_dcl_stloc{$this->getStorageLocation()}_value AS sort_stloc_{$this->getId()} ON (sort_stloc_{$this->getId()}.record_field_id = sort_record_field_{$this->getId()}.id)";
619
620 $sql_obj->setSelectStatement($select_str);
621 $sql_obj->setJoinStatement($join_str);
622 $sql_obj->setOrderStatement("field_{$this->getId()} $direction, ID ASC");
623
624 return $sql_obj;
625 }
626
632 $filter_value = "",
633 ?ilDclBaseFieldModel $sort_field = null
635 return null;
636 }
637
641 public function getSortField(): string
642 {
643 return $this->getTitle();
644 }
645
649 public function hasNumericSorting(): bool
650 {
651 if ($this->getDatatypeId() == ilDclDatatype::INPUTFORMAT_NUMBER) {
652 return true;
653 }
654
655 return false;
656 }
657
663 public function checkFieldCreationInput(ilPropertyFormGUI $form): bool
664 {
665 return true;
666 }
667
668 public function checkUniqueProp(ilPropertyFormGUI $form): bool
669 {
670 if ($this->getId() !== '' && $form->getInput('prop_' . ilDclBaseFieldModel::PROP_UNIQUE) === '1') {
671 $values = [];
672 foreach (ilDclCache::getTableCache($this->getTableId())->getRecords() as $record) {
673 $new = $record->getRecordFieldValue($this->getId());
674 foreach ($values as $value) {
675 if ($this->areEqual($new, $value)) {
676 $form->getItemByPostVar('prop_' . ilDclBaseFieldModel::PROP_UNIQUE)->setAlert($this->lng->txt('duplicate_entries_exist'));
677 return false;
678 }
679 }
680 $values[] = $new;
681 }
682 }
683 return true;
684 }
685
686 public function checkUnique($value, ?int $record_id): bool
687 {
688 if ($value && $this->getProperty(ilDclBaseFieldModel::PROP_UNIQUE) === '1') {
689 foreach (ilDclCache::getTableCache($this->getTableId())->getRecords() as $record) {
690 if ($record->getId() !== $record_id) {
691 $x = $record->getRecordFieldValue($this->getId());
692 if ($this->areEqual($record->getRecordFieldValue($this->getId()), $value)) {
694 }
695 }
696 }
697 }
698
699 return true;
700 }
701
705 public function getStorageLocationOverride(): ?int
706 {
707 return $this->storage_location_override;
708 }
709
713 public function setStorageLocationOverride(?int $storage_location_override): void
714 {
715 $this->storage_location_override = $storage_location_override;
716 }
717
718 public function fillHeaderExcel(ilExcel $worksheet, int &$row, int &$col): void
719 {
720 $worksheet->setCell($row, $col, $this->getTitle());
721 $col++;
722 }
723
724 public function checkTitlesForImport(array &$titles, array &$import_fields): void
725 {
726 foreach ($titles as $k => $title) {
727 if (!mb_detect_encoding($title, "UTF-8", true) == "UTF-8") {
728 $title = mb_convert_encoding($title, 'UTF-8', 'ISO-8859-1');
729 }
730 if ($title == $this->getTitle()) {
731 $import_fields[$k] = $this;
732 }
733 }
734 }
735
739 public function storePropertiesFromForm(ilPropertyFormGUI $form): void
740 {
741 $field_props = $this->getValidFieldProperties();
743
744 foreach ($field_props as $property) {
745 $value = $form->getInput($representation->getPropertyInputFieldId($property));
746
747 // save non empty values and set them to null, when they already exist. Do not override plugin-hook when already set.
748 if (!empty($value) || ($this->getPropertyInstance($property) != null && $property != self::PROP_PLUGIN_HOOK_NAME)) {
749 $this->setProperty($property, $value)?->store();
750 }
751 }
752 }
753
757 public function fillPropertiesForm(ilPropertyFormGUI &$form): bool
758 {
759 $values = [
760 'table_id' => $this->getTableId(),
761 'field_id' => $this->getId(),
762 'title' => $this->getTitle(),
763 'datatype' => $this->getDatatypeId(),
764 'description' => $this->getDescription(),
765 ];
766
767 $properties = $this->getValidFieldProperties();
768 foreach ($properties as $prop) {
769 $values['prop_' . $prop] = $this->getProperty($prop);
770 }
771
772 $form->setValuesByArray($values);
773
774 return true;
775 }
776
781 public function isConfirmationRequired(ilPropertyFormGUI $form): bool
782 {
783 return false;
784 }
785
790 {
791 $ilConfirmationGUI = new ilConfirmationGUI();
792 $ilConfirmationGUI->setFormAction($form->getFormAction());
793 $ilConfirmationGUI->addHiddenItem('confirmed', "1");
794 $ilConfirmationGUI->addHiddenItem('field_id', $form->getInput('field_id'));
795 $ilConfirmationGUI->addHiddenItem('title', $form->getInput('title'));
796 $ilConfirmationGUI->addHiddenItem('description', $form->getInput('description'));
797 $ilConfirmationGUI->addHiddenItem('datatype', $form->getInput('datatype'));
798 $ilConfirmationGUI->setConfirm($this->lng->txt('dcl_update_field'), 'update');
799 $ilConfirmationGUI->setCancel($this->lng->txt('cancel'), 'edit');
800
801 return $ilConfirmationGUI;
802 }
803}
static where($where, $operator=null)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setDatatypeId(int $a_id)
Set datatype id.
setTitle(string $a_title)
Set title.
getViewSetting(int $tableview_id)
int $storage_location_override
With this property the datatype-storage-location can be overwritten.
hasProperty(string $key)
Checks if a certain property for a field is set.
doDelete()
Remove field and properties.
getRecordQuerySortObject(string $direction="asc", bool $sort_by_status=false)
Returns a query-object for building the record-loader-sql-query.
updateTableFieldSetting()
update exportable and fieldorder
updateProperties()
Update properties of this field in Database.
setProperty(string $key, $value)
getRecordQueryFilterObject( $filter_value="", ?ilDclBaseFieldModel $sort_field=null)
Returns a query-object for building the record-loader-sql-query.
static _getFieldIdByTitle(string $title, int $table_id)
fillPropertiesForm(ilPropertyFormGUI &$form)
called to fill the 'edit field' form
loadTableFieldSetting()
loadTableFieldSetting
loadDatatype()
Load datatype for model.
static _getTitleInvalidChars(bool $a_as_regex=true)
All valid chars for filed titles.
getConfirmationGUI(ilPropertyFormGUI $form)
called by ilDclFieldEditGUI if isConfirmationRequired returns true
addToTableViews()
create ilDclTableViewFieldSettings for this field in each tableview
storePropertiesFromForm(ilPropertyFormGUI $form)
called when saving the 'edit field' form
isConfirmationRequired(ilPropertyFormGUI $form)
called by ilDclFieldEditGUI when updating field properties if you overwrite this method,...
checkValidity($value, ?int $record_id)
Check if input is valid.
getValidFieldProperties()
Returns all valid properties for a field-type.
checkUniqueProp(ilPropertyFormGUI $form)
cloneProperties(ilDclBaseFieldModel $originalField)
loadProperties()
Get all properties of a field.
getStorageLocation()
Get storage location for the model.
checkValidityFromForm(ilPropertyFormGUI &$form, ?int $record_id)
loadExportability()
Load exportability.
setDescription(string $a_desc)
Set description.
buildFromDBRecord(array $rec)
Builds model from db record.
hasNumericSorting()
Set to true, when the sorting should be handled numerical.
setStorageLocationOverride(?int $storage_location_override)
checkTitlesForImport(array &$titles, array &$import_fields)
const PROP_LENGTH
General properties.
getSortField()
Returns the sort-field id.
setTableId(int $a_id)
Set table id.
fillHeaderExcel(ilExcel $worksheet, int &$row, int &$col)
checkFieldCreationInput(ilPropertyFormGUI $form)
Checks input of specific fields befor saving.
checkUnique($value, ?int $record_id)
static getRecordFieldCache(object $record, object $field)
static getFieldProperties(string $field_id)
Cache Field properties.
static getTableCache(?int $table_id=null)
static getFieldCache(int $field_id=0)
static setCloneOf(int $old, int $new, string $type)
static getDatatype(int $datatyp_id)
Get cached datatypes.
static getFieldRepresentationInstance(ilDclBaseFieldModel $field)
setSelectStatement(string $selectStatement)
static _getDatatypeForId(string $id)
gives you the datatype id of a specified standard field.
static getInstance(int $table_id, string $field)
static getTableViewFieldSetting(string $id, int $tableview_id)
static getAllForTableId(int $table_id)
static _tableExists(int $table_id)
setCell(int $a_row, int $col, $value, ?string $datatype=null)
Set cell value.
Base class for ILIAS Exception handling.
language handling
This class represents a property form user interface.
setValuesByArray(array $a_values, bool $a_restrict_to_value_keys=false)
getInput(string $a_post_var, bool $ensureValidation=true)
Returns the input of an item, if item provides getInput method and as fallback the value of the HTTP-...
getItemByPostVar(string $a_post_var)
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Interface ilDBInterface.
getValue()
Get the value that is displayed in the input client side.
Definition: Group.php:49
global $DIC
Definition: shib_login.php:26