ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
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_WIDTH = "width";
47 public const PROP_HEIGHT = "height";
48 public const PROP_LEARNING_PROGRESS = "learning_progress";
49 public const PROP_ILIAS_REFERENCE_LINK = "ILIAS_reference_link";
50 public const PROP_N_REFERENCE = "multiple_selection";
51 public const PROP_FORMULA_EXPRESSION = "expression";
52 public const PROP_DISPLAY_COPY_LINK_ACTION_MENU = "display_action_menu";
53 public const PROP_LINK_DETAIL_PAGE_TEXT = "link_detail_page_text";
54 public const PROP_LINK_DETAIL_PAGE_MOB = "link_detail_page_mob";
55 public const PROP_SUPPORTED_FILE_TYPES = "supported_file_types";
56 public const PROP_PLUGIN_HOOK_NAME = "plugin_hook_name";
57 // type of table il_dcl_view
58 public const EDIT_VIEW = 2;
59 public const EXPORTABLE_VIEW = 4;
60
61 protected ilDBInterface $db;
62 protected ilLanguage $lng;
63
64 public function __construct(int $a_id = 0)
65 {
66 global $DIC;
67 $this->db = $DIC->database();
68 $this->lng = $DIC->language();
69
70 if ($a_id != 0) {
71 $this->id = (string) $a_id;
72 $this->doRead();
73 }
74 }
75
79 public static function _getTitleInvalidChars(bool $a_as_regex = true): string
80 {
81 if ($a_as_regex) {
82 return '/^[^<>\\\\":]*$/i';
83 } else {
84 return '\ < > " :';
85 }
86 }
87
88 public static function _getFieldIdByTitle(string $title, int $table_id): int
89 {
90 global $DIC;
91 $ilDB = $DIC->database();
92
93 $result = $ilDB->query(
94 'SELECT id FROM il_dcl_field WHERE title = ' . $ilDB->quote($title, 'text') . ' AND table_id = '
95 . $ilDB->quote($table_id, 'integer')
96 );
97 $id = 0;
98 while ($rec = $ilDB->fetchAssoc($result)) {
99 $id = $rec['id'];
100 }
101
102 return $id;
103 }
104
109 public function setId($a_id): void
110 {
111 $this->id = (string) $a_id;
112 }
113
117 public function getId(): string
118 {
119 return $this->id;
120 }
121
125 public function setTableId(int $a_id): void
126 {
127 $this->table_id = $a_id;
128 }
129
133 public function getTableId(): int
134 {
135 return $this->table_id;
136 }
137
141 public function setTitle(string $a_title): void
142 {
143 //title cannot begin with _ as this is saved for other purposes. make __ instead.
144 if (substr($a_title, 0, 1) == "_" && substr($a_title, 0, 2) != "__") {
145 $a_title = "_" . $a_title;
146 }
147 $this->title = $a_title;
148 }
149
153 public function getTitle(): string
154 {
155 return $this->title;
156 }
157
161 public function setDescription(string $a_desc): void
162 {
163 $this->description = $a_desc;
164 }
165
169 public function getDescription(): string
170 {
171 return $this->description;
172 }
173
177 public function setDatatypeId(int $a_id): void
178 {
179 //unset the cached datatype.
180 $this->datatype = null;
181 $this->datatype_id = $a_id;
182 }
183
187 public function getDatatypeId(): ?int
188 {
189 if ($this->isStandardField()) {
191 }
192
193 return $this->datatype_id;
194 }
195
196 public function getDatatype(): ilDclDatatype
197 {
198 $this->loadDatatype();
199
200 return $this->datatype;
201 }
202
203 public function getDatatypeTitle(): string
204 {
205 $this->loadDatatype();
206 return $this->datatype->getTitle();
207 }
208
209 public function getPresentationTitle(): string
210 {
211 return $this->lng->txt('dcl_' . $this->getDatatypeTitle());
212 }
213
214 public function getPresentationDescription(): string
215 {
216 return $this->lng->txt('dcl_' . $this->getDatatypeTitle() . '_desc');
217 }
218
222 public function getStorageLocation(): ?int
223 {
224 if ($this->getStorageLocationOverride() !== null) {
225 return $this->getStorageLocationOverride();
226 }
227
228 $this->loadDatatype();
229
230 return $this->datatype->getStorageLocation();
231 }
232
236 protected function loadDatatype(): void
237 {
238 if ($this->datatype == null) {
239 $this->datatype = ilDclCache::getDatatype($this->datatype_id);
240 }
241 }
242
246 protected function loadTableFieldSetting(): void
247 {
248 $tablefield_setting = ilDclTableFieldSetting::getInstance($this->getTableId(), $this->getId());
249 $this->exportable = $tablefield_setting->isExportable();
250 $this->order = $tablefield_setting->getFieldOrder();
251 }
252
256 public function getExportable(): bool
257 {
258 if (!isset($this->exportable)) {
259 $this->loadExportability();
260 }
261
262 return $this->exportable;
263 }
264
268 private function loadExportability(): void
269 {
270 if ($this->exportable == null) {
271 $this->loadTableFieldSetting();
272 }
273 }
274
275 public function toArray(): array
276 {
277 return (array) $this;
278 }
279
280 public function isStandardField(): bool
281 {
282 return false;
283 }
284
285 public function doRead(): void
286 {
287 //THEN 1 ELSE 0 END AS has_options FROM il_dcl_field f WHERE id = ".$ilDB->quote($this->getId(),"integer");
288 $query = "SELECT * FROM il_dcl_field WHERE id = " . $this->db->quote($this->getId(), "integer");
289 $set = $this->db->query($query);
290 $rec = $this->db->fetchAssoc($set);
291
292 if ($rec) {
293 $this->setTableId($rec["table_id"]);
294 if (null !== $rec["title"]) {
295 $this->setTitle($rec["title"]);
296 }
297 if (null !== $rec["description"]) {
298 $this->setDescription($rec["description"]);
299 }
300 $this->setDatatypeId($rec["datatype_id"]);
301 }
302
303 $this->loadProperties();
304 $this->loadTableFieldSetting();
305 }
306
310 public function buildFromDBRecord(array $rec): void
311 {
312 $this->setId($rec["id"]);
313 $this->setTableId($rec["table_id"]);
314 $this->setTitle($rec["title"]);
315 $this->setDescription($rec["description"]);
316 $this->setDatatypeId($rec["datatype_id"]);
317 }
318
319 public function doCreate(): void
320 {
321 if (!ilDclTable::_tableExists($this->getTableId())) {
322 throw new ilException("The field does not have a related table!");
323 }
324
325 $id = $this->db->nextId("il_dcl_field");
326 $this->setId($id);
327 $query = "INSERT INTO il_dcl_field (" . "id" . ", table_id" . ", datatype_id" . ", title" . ", description"
328 . " ) VALUES (" . $this->db->quote($this->getId(), "integer") . "," . $this->db->quote(
329 $this->getTableId(),
330 "integer"
331 ) . ","
332 . $this->db->quote($this->getDatatypeId(), "integer") . "," . $this->db->quote($this->getTitle(), "text") . ","
333 . $this->db->quote($this->getDescription(), "text") . ")";
334 $this->db->manipulate($query);
335
337
338 $this->addToTableViews();
339 }
340
344 protected function addToTableViews(): void
345 {
346 foreach (ilDclTableView::getAllForTableId($this->table_id) as $tableview) {
347 $tableview->createFieldSetting($this->id);
348 }
349 }
350
351 public function doUpdate(): void
352 {
353 $this->db->update(
354 "il_dcl_field",
355 [
356 "table_id" => [
357 "integer",
358 $this->getTableId(),
359 ],
360 "datatype_id" => [
361 "text",
362 $this->getDatatypeId(),
363 ],
364 "title" => [
365 "text",
366 $this->getTitle(),
367 ],
368 "description" => [
369 "text",
370 $this->getDescription(),
371 ],
372 ],
373 [
374 "id" => [
375 "integer",
376 $this->getId(),
377 ],
378 ]
379 );
381 $this->updateProperties();
382 }
383
387 public function updateProperties(): void
388 {
389 foreach ($this->property as $prop) {
390 $prop->store();
391 }
392 }
393
397 protected function updateTableFieldSetting(): void
398 {
399 $tablefield_setting = ilDclTableFieldSetting::getInstance($this->getTableId(), $this->getId());
400 $tablefield_setting->setExportable($this->exportable);
401 $tablefield_setting->setFieldOrder($this->getOrder());
402 $tablefield_setting->store();
403 }
404
408 public function doDelete(): void
409 {
410 // delete tablefield setting.
411 ilDclTableFieldSetting::getInstance($this->getTableId(), $this->getId())->delete();
412
413 $query = "DELETE FROM il_dcl_field_prop WHERE field_id = " . $this->db->quote($this->getId(), "text");
414 $this->db->manipulate($query);
415
416 $query = "DELETE FROM il_dcl_field WHERE id = " . $this->db->quote($this->getId(), "text");
417 $this->db->manipulate($query);
418
419 foreach ($this->getViewSettings() as $field_setting) {
420 $field_setting->delete();
421 }
422 }
423
427 public function getViewSettings(): array
428 {
429 return ilDclTableViewFieldSetting::where(['field' => $this->getId()])->get();
430 }
431
432 public function getViewSetting(int $tableview_id): ilDclTableViewFieldSetting
433 {
434 return ilDclTableViewFieldSetting::getTableViewFieldSetting($this->getId(), $tableview_id);
435 }
436
437 public function getOrder(): int
438 {
439 if ($this->order == null) {
440 $this->loadTableFieldSetting();
441 }
442
443 return !$this->order ? 0 : $this->order;
444 }
445
446 public function setOrder(int $order): void
447 {
448 $this->order = $order;
449 }
450
454 protected function loadProperties(): void
455 {
456 $this->property = ilDclCache::getFieldProperties($this->getId());
457 }
458
462 public function hasProperty(string $key): bool
463 {
464 $this->loadProperties();
465
466 return (isset($this->property[$key]) && $this->property[$key]->getValue() != null);
467 }
468
469 public function getProperty(string $key): mixed
470 {
471 $instance = $this->getPropertyInstance($key);
472
473 return ($instance !== null) ? $instance->getValue() : null;
474 }
475
476 public function getPropertyInstance(string $key): ?ilDclFieldProperty
477 {
478 $this->loadProperties();
479 if ($this->hasProperty($key)) {
480 return $this->property[$key];
481 }
482
483 return null;
484 }
485
486 public function setProperty(string $key, $value): ?ilDclFieldProperty
487 {
488 $this->loadProperties();
489 if (isset($this->property[$key])) {
490 $this->property[$key]->setValue($value);
491 } else {
493 $property->setName($key);
494 $property->setFieldId((int) $this->getId());
495 $property->setValue($value);
496
497 $this->property[$key] = $property;
498 }
499
500 return $this->property[$key];
501 }
502
506 public function getValidFieldProperties(): array
507 {
508 return [];
509 }
510
511 public function checkValidityFromForm(ilPropertyFormGUI &$form, ?int $record_id): void
512 {
513 $value = $form->getInput('field_' . $this->getId());
514 $this->checkValidity($value, $record_id);
515 }
516
522 public function checkValidity($value, ?int $record_id): bool
523 {
524 return true;
525 }
526
527 protected function areEqual($value_1, $value_2): bool
528 {
529 return $this->normalizeValue($value_1) === $this->normalizeValue($value_2);
530 }
531
532 protected function normalizeValue(mixed $value)
533 {
534 if (is_string($value)) {
535 $value = trim(preg_replace("/\\s+/uism", " ", $value));
536 }
537
538 return $value;
539 }
540
544 public function cloneStructure(int $original_id): void
545 {
546 $original = ilDclCache::getFieldCache($original_id);
547 $this->setTitle($original->getTitle());
548 $this->setDatatypeId($original->getDatatypeId());
549 $this->setDescription($original->getDescription());
550 $this->setOrder($original->getOrder());
551 $this->setExportable($original->getExportable());
552 $this->doCreate();
553 $this->cloneProperties($original);
554
555 // mandatory for all cloning functions
556 ilDclCache::setCloneOf($original_id, (int) $this->getId(), ilDclCache::TYPE_FIELD);
557 }
558
559 public function afterClone(array $records)
560 {
561 foreach ($records as $rec) {
562 ilDclCache::getRecordFieldCache($rec, $this)->afterClone();
563 }
564 }
565
566 public function cloneProperties(ilDclBaseFieldModel $originalField): void
567 {
568 $orgProps = $originalField->getValidFieldProperties();
569 if (count($orgProps) == 0) {
570 return;
571 }
572 foreach ($orgProps as $prop_name) {
573 $fieldprop_obj = new ilDclFieldProperty();
574 $fieldprop_obj->setFieldId((int) $this->getId());
575 $fieldprop_obj->setName($prop_name);
576
577 $value = $originalField->getProperty($prop_name);
578
579 if (
581 (
584 )
585 ) {
586 $value = null;
587 }
588
589 if ($value) {
590 $fieldprop_obj->setValue($value);
591 $fieldprop_obj->create();
592 }
593 }
594 }
595
596 public function setExportable(bool $exportable): void
597 {
598 $this->exportable = $exportable;
599 }
600
601 public function allowFilterInListView(): bool
602 {
603 return true;
604 }
605
611 string $direction = "asc",
612 bool $sort_by_status = false
614 $sql_obj = new ilDclRecordQueryObject();
615
616 $select_str = "sort_stloc_{$this->getId()}.value AS field_{$this->getId()}";
617 $join_str
618 = "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 = "
619 . $this->db->quote($this->getId(), 'integer') . ") ";
620 $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)";
621
622 $sql_obj->setSelectStatement($select_str);
623 $sql_obj->setJoinStatement($join_str);
624 $sql_obj->setOrderStatement("field_{$this->getId()} $direction, ID ASC");
625
626 return $sql_obj;
627 }
628
634 $filter_value = "",
635 ?ilDclBaseFieldModel $sort_field = null
637 return null;
638 }
639
643 public function getSortField(): string
644 {
645 return $this->getTitle();
646 }
647
651 public function hasNumericSorting(): bool
652 {
653 if ($this->getDatatypeId() == ilDclDatatype::INPUTFORMAT_NUMBER) {
654 return true;
655 }
656
657 return false;
658 }
659
665 public function checkFieldCreationInput(ilPropertyFormGUI $form): bool
666 {
667 return true;
668 }
669
670 public function checkUniqueProp(ilPropertyFormGUI $form): bool
671 {
672 if ($this->getId() !== '' && $form->getInput('prop_' . ilDclBaseFieldModel::PROP_UNIQUE) === '1') {
673 $values = [];
674 foreach (ilDclCache::getTableCache($this->getTableId())->getRecords() as $record) {
675 $new = $record->getRecordFieldValue($this->getId());
676 foreach ($values as $value) {
677 if ($this->areEqual($new, $value)) {
678 $form->getItemByPostVar('prop_' . ilDclBaseFieldModel::PROP_UNIQUE)->setAlert($this->lng->txt('duplicate_entries_exist'));
679 return false;
680 }
681 }
682 $values[] = $new;
683 }
684 }
685 return true;
686 }
687
688 public function checkUnique($value, ?int $record_id): bool
689 {
690 if ($value && $this->getProperty(ilDclBaseFieldModel::PROP_UNIQUE) === '1') {
691 foreach (ilDclCache::getTableCache($this->getTableId())->getRecords() as $record) {
692 if ($record->getId() !== $record_id) {
693 $x = $record->getRecordFieldValue($this->getId());
694 if ($this->areEqual($record->getRecordFieldValue($this->getId()), $value)) {
696 }
697 }
698 }
699 }
700
701 return true;
702 }
703
707 public function getStorageLocationOverride(): ?int
708 {
709 return $this->storage_location_override;
710 }
711
715 public function setStorageLocationOverride(?int $storage_location_override): void
716 {
717 $this->storage_location_override = $storage_location_override;
718 }
719
720 public function fillHeaderExcel(ilExcel $worksheet, int &$row, int &$col): void
721 {
722 $worksheet->setCell($row, $col, $this->getTitle());
723 $col++;
724 }
725
726 public function checkTitlesForImport(array &$titles, array &$import_fields): void
727 {
728 foreach ($titles as $k => $title) {
729 if (!mb_detect_encoding($title, "UTF-8", true) == "UTF-8") {
730 $title = mb_convert_encoding($title, 'UTF-8', 'ISO-8859-1');
731 }
732 if ($title == $this->getTitle()) {
733 $import_fields[$k] = $this;
734 }
735 }
736 }
737
741 public function storePropertiesFromForm(ilPropertyFormGUI $form): void
742 {
743 $field_props = $this->getValidFieldProperties();
745
746 foreach ($field_props as $property) {
747 $value = $form->getInput($representation->getPropertyInputFieldId($property));
748
749 // save non empty values and set them to null, when they already exist. Do not override plugin-hook when already set.
750 if (!empty($value) || ($this->getPropertyInstance($property) != null && $property != self::PROP_PLUGIN_HOOK_NAME)) {
751 $this->setProperty($property, $value)?->store();
752 }
753 }
754 }
755
759 public function fillPropertiesForm(ilPropertyFormGUI &$form): bool
760 {
761 $values = [
762 'table_id' => $this->getTableId(),
763 'field_id' => $this->getId(),
764 'title' => $this->getTitle(),
765 'datatype' => $this->getDatatypeId(),
766 'description' => $this->getDescription(),
767 ];
768
769 $properties = $this->getValidFieldProperties();
770 foreach ($properties as $prop) {
771 $values['prop_' . $prop] = $this->getProperty($prop);
772 }
773
774 $form->setValuesByArray($values);
775
776 return true;
777 }
778
783 public function isConfirmationRequired(ilPropertyFormGUI $form): bool
784 {
785 return false;
786 }
787
792 {
793 $ilConfirmationGUI = new ilConfirmationGUI();
794 $ilConfirmationGUI->setFormAction($form->getFormAction());
795 $ilConfirmationGUI->addHiddenItem('confirmed', "1");
796 $ilConfirmationGUI->addHiddenItem('field_id', $form->getInput('field_id'));
797 $ilConfirmationGUI->addHiddenItem('title', $form->getInput('title'));
798 $ilConfirmationGUI->addHiddenItem('description', $form->getInput('description'));
799 $ilConfirmationGUI->addHiddenItem('datatype', $form->getInput('datatype'));
800 $ilConfirmationGUI->setConfirm($this->lng->txt('dcl_update_field'), 'update');
801 $ilConfirmationGUI->setCancel($this->lng->txt('cancel'), 'edit');
802
803 return $ilConfirmationGUI;
804 }
805}
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, bool $disable_strip_tags_for_strings=false)
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