1<?php 2 3/* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */ 4 5/** 6 * Class ilDclBaseFieldModel 7 * 8 * @author Martin Studer <ms@studer-raimann.ch> 9 * @author Marcel Raimann <mr@studer-raimann.ch> 10 * @author Fabian Schmid <fs@studer-raimann.ch> 11 * @author Oskar Truffer <ot@studer-raimann.ch> 12 * @author Stefan Wanzenried <sw@studer-raimann.ch> 13 * @version $Id: 14 * 15 * @ingroup ModulesDataCollection 16 */ 17class ilDclTable 18{ 19 20 /** 21 * @var int 22 */ 23 protected $id = 0; 24 /** 25 * @var int 26 */ 27 protected $objId; 28 /** 29 * @var ilObjDataCollection 30 */ 31 protected $obj; 32 /** 33 * @var string 34 */ 35 protected $title; 36 /** 37 * @var array ilDclBaseFieldModel[] 38 */ 39 protected $fields; 40 /** 41 * @var array ilDclStandardField[] 42 */ 43 protected $stdFields; 44 /** 45 * @var array ilDclBaseRecordModel[] 46 */ 47 protected $records; 48 /** 49 * @var bool 50 */ 51 protected $is_visible; 52 /** 53 * @var bool 54 */ 55 protected $add_perm; 56 /** 57 * @var bool 58 */ 59 protected $edit_perm; 60 /** 61 * @var bool 62 */ 63 protected $delete_perm; 64 /** 65 * @var bool 66 */ 67 protected $edit_by_owner; 68 /** 69 * @var bool 70 */ 71 protected $delete_by_owner; 72 /** 73 * @var bool 74 */ 75 protected $save_confirmation; 76 /** 77 * @var bool 78 */ 79 protected $limited; 80 /** 81 * @var string 82 */ 83 protected $limit_start; 84 /** 85 * @var string 86 */ 87 protected $limit_end; 88 /** 89 * @var bool 90 */ 91 protected $export_enabled; 92 /** 93 * @var integer 94 */ 95 protected $table_order; 96 /** 97 * @var bool 98 */ 99 protected $import_enabled; 100 /** 101 * ID of the default sorting field. Can be a DB field (int) or a standard field (string) 102 * 103 * @var string 104 */ 105 protected $default_sort_field = 0; 106 /** 107 * Default sort-order (asc|desc) 108 * 109 * @var string 110 */ 111 protected $default_sort_field_order = 'asc'; 112 /** 113 * Description for this table displayed above records 114 * 115 * @var string 116 */ 117 protected $description = ''; 118 /** 119 * True if users can add comments on each record of this table 120 * 121 * @var bool 122 */ 123 protected $public_comments = 0; 124 /** 125 * True if user can only view his/her own entries in the table 126 * 127 * @var bool 128 */ 129 protected $view_own_records_perm = 0; 130 /** 131 * table fields and std fields combined 132 * 133 * @var null|array 134 */ 135 protected $all_fields = null; 136 137 138 /** 139 * @param int $a_id 140 */ 141 public function __construct($a_id = 0) 142 { 143 if ($a_id != 0) { 144 $this->id = $a_id; 145 $this->doRead(); 146 } 147 } 148 149 150 /** 151 * Read table 152 */ 153 public function doRead() 154 { 155 global $DIC; 156 $ilDB = $DIC['ilDB']; 157 158 $query = "SELECT * FROM il_dcl_table WHERE id = " . $ilDB->quote($this->getId(), "integer"); 159 $set = $ilDB->query($query); 160 $rec = $ilDB->fetchAssoc($set); 161 162 $this->setObjId($rec["obj_id"]); 163 $this->setTitle($rec["title"]); 164 $this->setAddPerm($rec["add_perm"]); 165 $this->setEditPerm($rec["edit_perm"]); 166 $this->setDeletePerm($rec["delete_perm"]); 167 $this->setEditByOwner($rec["edit_by_owner"]); 168 $this->setExportEnabled($rec["export_enabled"]); 169 $this->setImportEnabled($rec["import_enabled"]); 170 $this->setLimited($rec["limited"]); 171 $this->setLimitStart($rec["limit_start"]); 172 $this->setLimitEnd($rec["limit_end"]); 173 $this->setIsVisible($rec["is_visible"]); 174 $this->setDescription($rec['description']); 175 $this->setDefaultSortField($rec['default_sort_field_id']); 176 $this->setDefaultSortFieldOrder($rec['default_sort_field_order']); 177 $this->setPublicCommentsEnabled($rec['public_comments']); 178 $this->setViewOwnRecordsPerm($rec['view_own_records_perm']); 179 $this->setDeleteByOwner($rec['delete_by_owner']); 180 $this->setSaveConfirmation($rec['save_confirmation']); 181 $this->setOrder($rec['table_order']); 182 } 183 184 185 /** 186 * Delete table 187 * Attention this does not delete the maintable of it's the maintable of the collection. 188 * unlink the the maintable in the collections object to make this work. 189 * 190 * @param boolean $delete_main_table true to delete table anyway 191 */ 192 public function doDelete($delete_only_content = false, $omit_notification = false) 193 { 194 global $DIC; 195 $ilDB = $DIC['ilDB']; 196 197 /** @var $ilDB ilDB */ 198 foreach ($this->getRecords() as $record) { 199 $record->doDelete($omit_notification); 200 } 201 202 foreach ($this->getRecordFields() as $field) { 203 $field->doDelete(); 204 } 205 206 // // SW: Fix #12794 und #11405 207 // // Problem is that when the DC object gets deleted, $this::getCollectionObject() tries to load the DC but it's not in the DB anymore 208 // // If $delete_main_table is true, avoid getting the collection object 209 // $exec_delete = false; 210 // if ($delete_main_table) { 211 // $exec_delete = true; 212 // } 213 // if (!$exec_delete && $this->getCollectionObject()->getFirstVisibleTableId() != $this->getId()) { 214 // $exec_delete = true; 215 // } 216 if (!$delete_only_content) { 217 $query = "DELETE FROM il_dcl_table WHERE id = " . $ilDB->quote($this->getId(), "integer"); 218 $ilDB->manipulate($query); 219 } 220 } 221 222 223 /** 224 * @param bool $create_views 225 */ 226 public function doCreate($create_tablefield_setting = true, $create_standardview = true) 227 { 228 global $DIC; 229 $ilDB = $DIC['ilDB']; 230 231 $id = $ilDB->nextId("il_dcl_table"); 232 $this->setId($id); 233 $query = "INSERT INTO il_dcl_table (" . "id" . ", obj_id" . ", title" . ", add_perm" . ", edit_perm" . ", delete_perm" . ", edit_by_owner" 234 . ", limited" . ", limit_start" . ", limit_end" . ", is_visible" . ", export_enabled" . ", import_enabled" . ", default_sort_field_id" 235 . ", default_sort_field_order" . ", description" . ", public_comments" . ", view_own_records_perm" 236 . ", delete_by_owner, save_confirmation , table_order ) VALUES (" . $ilDB->quote($this->getId(), "integer") . "," 237 . $ilDB->quote($this->getObjId(), "integer") . "," . $ilDB->quote($this->getTitle(), "text") . "," 238 . $ilDB->quote($this->getAddPerm() ? 1 : 0, "integer") . "," . $ilDB->quote($this->getEditPerm() ? 1 : 0, "integer") . "," 239 . $ilDB->quote($this->getDeletePerm() ? 1 : 0, "integer") . "," . $ilDB->quote($this->getEditByOwner() ? 1 : 0, "integer") . "," 240 . $ilDB->quote($this->getLimited() ? 1 : 0, "integer") . "," . $ilDB->quote($this->getLimitStart(), "timestamp") . "," 241 . $ilDB->quote($this->getLimitEnd(), "timestamp") . "," . $ilDB->quote($this->getIsVisible() ? 1 : 0, "integer") . "," 242 . $ilDB->quote($this->getExportEnabled() ? 1 : 0, "integer") . "," . $ilDB->quote($this->getImportEnabled() ? 1 : 0, "integer") . "," 243 . $ilDB->quote($this->getDefaultSortField(), "text") . "," . $ilDB->quote($this->getDefaultSortFieldOrder(), "text") . "," 244 . $ilDB->quote($this->getDescription(), "text") . "," . $ilDB->quote($this->getPublicCommentsEnabled(), "integer") . "," 245 . $ilDB->quote($this->getViewOwnRecordsPerm(), "integer") . "," . $ilDB->quote($this->getDeleteByOwner() ? 1 : 0, 'integer') . "," 246 . $ilDB->quote($this->getSaveConfirmation() ? 1 : 0, 'integer') . "," . $ilDB->quote($this->getOrder(), 'integer') . ")"; 247 248 $ilDB->manipulate($query); 249 250 if ($create_standardview) { 251 //standard tableview 252 ilDclTableView::createOrGetStandardView($this->id); 253 } 254 255 if ($create_tablefield_setting) { 256 $this->buildOrderFields(); 257 } 258 } 259 260 261 /* 262 * doUpdate 263 */ 264 public function doUpdate() 265 { 266 global $DIC; 267 $ilDB = $DIC['ilDB']; 268 269 $ilDB->update( 270 "il_dcl_table", 271 array( 272 "obj_id" => array("integer", $this->getObjId()), 273 "title" => array("text", $this->getTitle()), 274 "add_perm" => array("integer", (int) $this->getAddPerm()), 275 "edit_perm" => array("integer", (int) $this->getEditPerm()), 276 "delete_perm" => array("integer", (int) $this->getDeletePerm()), 277 "edit_by_owner" => array("integer", (int) $this->getEditByOwner()), 278 "limited" => array("integer", $this->getLimited()), 279 "limit_start" => array("timestamp", $this->getLimitStart()), 280 "limit_end" => array("timestamp", $this->getLimitEnd()), 281 "is_visible" => array("integer", $this->getIsVisible() ? 1 : 0), 282 "export_enabled" => array("integer", $this->getExportEnabled() ? 1 : 0), 283 "import_enabled" => array("integer", $this->getImportEnabled() ? 1 : 0), 284 "description" => array("text", $this->getDescription()), 285 "default_sort_field_id" => array("text", $this->getDefaultSortField()), 286 "default_sort_field_order" => array("text", $this->getDefaultSortFieldOrder()), 287 "public_comments" => array("integer", $this->getPublicCommentsEnabled() ? 1 : 0), 288 "view_own_records_perm" => array("integer", $this->getViewOwnRecordsPerm()), 289 'delete_by_owner' => array('integer', $this->getDeleteByOwner() ? 1 : 0), 290 'save_confirmation' => array('integer', $this->getSaveConfirmation() ? 1 : 0), 291 'table_order' => array('integer', $this->getOrder()), 292 ), 293 array( 294 "id" => array("integer", $this->getId()), 295 ) 296 ); 297 } 298 299 300 /** 301 * Set table id 302 * 303 * @param int $a_id 304 */ 305 public function setId($a_id) 306 { 307 $this->id = $a_id; 308 } 309 310 311 /** 312 * Get table id 313 * 314 * @return int 315 */ 316 public function getId() 317 { 318 return $this->id; 319 } 320 321 322 /** 323 * @param $a_id 324 */ 325 public function setObjId($a_id) 326 { 327 $this->objId = $a_id; 328 } 329 330 331 /** 332 * @return int 333 */ 334 public function getObjId() 335 { 336 return $this->objId; 337 } 338 339 340 /** 341 * @param $a_title 342 */ 343 public function setTitle($a_title) 344 { 345 $this->title = $a_title; 346 } 347 348 349 /** 350 * @return string 351 */ 352 public function getTitle() 353 { 354 return $this->title; 355 } 356 357 358 /** 359 * @return ilObjDataCollection 360 */ 361 public function getCollectionObject() 362 { 363 $this->loadObj(); 364 365 return $this->obj; 366 } 367 368 369 protected function loadObj() 370 { 371 if ($this->obj == null) { 372 $this->obj = new ilObjDataCollection($this->objId, false); 373 } 374 } 375 376 377 /** 378 * @return ilDclBaseRecordModel[] 379 */ 380 public function getRecords() 381 { 382 if ($this->records == null) { 383 $this->loadRecords(); 384 } 385 386 return $this->records; 387 } 388 389 390 public function loadRecords() 391 { 392 global $DIC; 393 $ilDB = $DIC['ilDB']; 394 395 $records = array(); 396 $query = "SELECT id FROM il_dcl_record WHERE table_id = " . $ilDB->quote($this->id, "integer"); 397 $set = $ilDB->query($query); 398 399 while ($rec = $ilDB->fetchAssoc($set)) { 400 $records[$rec['id']] = ilDclCache::getRecordCache($rec['id']); 401 } 402 403 $this->records = $records; 404 } 405 406 407 /** 408 * @param $field_id 409 */ 410 public function deleteField($field_id) 411 { 412 $field = ilDclCache::getFieldCache($field_id); 413 $records = $this->getRecords(); 414 415 foreach ($records as $record) { 416 $record->deleteField($field_id); 417 } 418 419 $field->doDelete(); 420 } 421 422 423 /** 424 * @param $field_id 425 * 426 * @return ilDclBaseFieldModel|null 427 */ 428 public function getField($field_id) 429 { 430 $fields = $this->getFields(); 431 $field = null; 432 foreach ($fields as $field_1) { 433 if ($field_1->getId() == $field_id) { 434 $field = $field_1; 435 } 436 } 437 438 return $field; 439 } 440 441 442 /** 443 * @param bool $force_include_comments 444 * 445 * @return array 446 */ 447 public function getFieldIds() 448 { 449 $field_ids = array(); 450 foreach ($this->getFields() as $field) { 451 if ($field->getId()) { 452 $field_ids[] = $field->getId(); 453 } 454 } 455 456 return $field_ids; 457 } 458 459 460 protected function loadCustomFields() 461 { 462 if (!$this->fields) { 463 global $DIC; 464 $ilDB = $DIC['ilDB']; 465 /** 466 * @var $ilDB ilDBInterface 467 */ 468 $query 469 = "SELECT DISTINCT il_dcl_field.*, il_dcl_tfield_set.field_order 470 FROM il_dcl_field 471 INNER JOIN il_dcl_tfield_set 472 ON ( il_dcl_tfield_set.field NOT IN ('owner', 473 'last_update', 474 'last_edit_by', 475 'id', 476 'create_date') 477 AND il_dcl_tfield_set.table_id = il_dcl_field.table_id 478 AND il_dcl_tfield_set.field = " . $ilDB->cast("il_dcl_field.id", "text") . ") 479 WHERE il_dcl_field.table_id = %s 480 ORDER BY il_dcl_tfield_set.field_order ASC"; 481 482 $set = $ilDB->queryF($query, array('integer'), array((int) $this->getId())); 483 $fields = array(); 484 while ($rec = $ilDB->fetchAssoc($set)) { 485 $field = ilDclCache::buildFieldFromRecord($rec); 486 $fields[] = $field; 487 } 488 $this->fields = $fields; 489 490 ilDclCache::preloadFieldProperties($fields); 491 } 492 } 493 494 495 public function getCustomFields() 496 { 497 if (!$this->fields) { 498 $this->loadCustomFields(); 499 } 500 501 return $this->fields; 502 } 503 504 505 /** 506 * getNewOrder 507 * 508 * @return int returns the place where a new field should be placed. 509 */ 510 public function getNewFieldOrder() 511 { 512 $fields = $this->getFields(); 513 $place = 0; 514 foreach ($fields as $field) { 515 if (!$field->isStandardField()) { 516 $place = $field->getOrder() + 1; 517 } 518 } 519 520 return $place; 521 } 522 523 524 /** 525 * @return int 526 */ 527 public function getNewTableviewOrder() 528 { 529 return (ilDclTableView::getCountForTableId($this->getId()) + 1) * 10; 530 } 531 532 533 /** 534 * @param ilDclTableView[] $tableviews 535 */ 536 public function sortTableViews(array $tableviews = null) 537 { 538 if ($tableviews == null) { 539 $tableviews = $this->getTableViews(); 540 } 541 542 $order = 10; 543 foreach ($tableviews as $tableview) { 544 $tableview->setTableviewOrder($order); 545 $tableview->update(); 546 $order += 10; 547 } 548 } 549 550 551 /** 552 * Returns all fields of this table including the standard fields 553 * 554 * @param bool $force_include_comments by default false, so comments will only load when enabled in tablesettings 555 * 556 * @return ilDclBaseFieldModel[] 557 */ 558 public function getFields() 559 { 560 if ($this->all_fields == null) { 561 $this->reloadFields(); 562 } 563 564 return $this->all_fields; 565 } 566 567 568 public function reloadFields() 569 { 570 $this->loadCustomFields(); 571 $this->stdFields = $this->getStandardFields(); 572 $fields = array_merge($this->fields, $this->stdFields); 573 574 $this->sortByOrder($fields); 575 576 $this->all_fields = $fields; 577 } 578 579 580 /** 581 * @return ilDclTableView[] all tableviews ordered by tableview_order 582 */ 583 public function getTableViews() 584 { 585 return ilDclTableView::getAllForTableId($this->getId()); 586 } 587 588 589 /** 590 * For current user 591 * 592 * @param int $ref_id DataCollections reference 593 * @param int $user_id 594 * 595 * @return ilDclTableView[] 596 */ 597 public function getVisibleTableViews($ref_id, $with_active_detailedview = false, $user_id = 0) 598 { 599 if (ilObjDataCollectionAccess::hasWriteAccess($ref_id, $user_id) && !$with_active_detailedview) { 600 return $this->getTableViews(); 601 } 602 603 $visible_views = array(); 604 foreach ($this->getTableViews() as $tableView) { 605 if (ilObjDataCollectionAccess::hasAccessToTableView($tableView, $user_id)) { 606 if (!$with_active_detailedview || ilDclDetailedViewDefinition::isActive($tableView->getId())) { 607 $visible_views[] = $tableView; 608 } 609 } 610 } 611 612 return $visible_views; 613 } 614 615 616 /** 617 * get id of first (for current user) available view 618 * 619 * @param $ref_id 620 * @param int $user_id 621 * 622 * @return bool 623 */ 624 public function getFirstTableViewId($ref_id, $user_id = 0) 625 { 626 $tableview = array_shift($this->getVisibleTableViews($ref_id, false, $user_id)); 627 628 return $tableview ? $tableview->getId() : false; 629 } 630 631 632 /** 633 * Returns all fields of this table including the standard fields, wich are supported for formulas 634 * 635 * @return ilDclBaseFieldModel[] 636 */ 637 public function getFieldsForFormula() 638 { 639 $unsupported = array( 640 ilDclDatatype::INPUTFORMAT_ILIAS_REF, 641 ilDclDatatype::INPUTFORMAT_FORMULA, 642 ilDclDatatype::INPUTFORMAT_MOB, 643 ilDclDatatype::INPUTFORMAT_REFERENCELIST, 644 ilDclDatatype::INPUTFORMAT_REFERENCE, 645 ilDclDatatype::INPUTFORMAT_FILE, 646 ilDclDatatype::INPUTFORMAT_RATING, 647 ); 648 649 $this->loadCustomFields(); 650 $return = $this->getStandardFields(); 651 /** 652 * @var $field ilDclBaseFieldModel 653 */ 654 foreach ($this->fields as $field) { 655 if (!in_array($field->getDatatypeId(), $unsupported)) { 656 $return[] = $field; 657 } 658 } 659 660 return $return; 661 } 662 663 664 /** 665 * Returns the fields all datacollections have by default. 666 * Comments are only included if active in this table 667 * 668 * @return ilDclStandardField[] 669 */ 670 public function getStandardFields() 671 { 672 if ($this->stdFields == null) { 673 $this->stdFields = ilDclStandardField::_getStandardFields($this->id); 674 // Don't return comments as field if this feature is not activated in the settings 675 if (!$this->getPublicCommentsEnabled()) { 676 /** @var $field ilDclStandardField */ 677 foreach ($this->stdFields as $k => $field) { 678 if ($field->getId() == 'comments') { 679 unset($this->stdFields[$k]); 680 break; 681 } 682 } 683 } 684 } 685 686 return $this->stdFields; 687 } 688 689 690 /** 691 * Returns all fields of this table which are NOT standard fields. 692 * 693 * @return ilDclBaseFieldModel[] 694 */ 695 public function getRecordFields() 696 { 697 $this->loadCustomFields(); 698 699 return $this->fields; 700 } 701 702 703 /** 704 * @return array 705 */ 706 public function getEditableFields() 707 { 708 $fields = $this->getRecordFields(); 709 $editableFields = array(); 710 711 foreach ($fields as $field) { 712 if (!$field->getLocked()) { 713 $editableFields[] = $field; 714 } 715 } 716 717 return $editableFields; 718 } 719 720 721 /** 722 * Return all the fields that are marked as exportable 723 * 724 * @return array ilDclBaseFieldModel 725 */ 726 public function getExportableFields() 727 { 728 $fields = $this->getFields(); 729 $exportableFields = array(); 730 foreach ($fields as $field) { 731 if ($field->getExportable()) { 732 $exportableFields[] = $field; 733 } 734 } 735 736 return $exportableFields; 737 } 738 739 740 /** 741 * @param $ref_id int the reference id of the current datacollection object 742 * @param $record ilDclBaseRecordModel the record which will be edited 743 * 744 * @return bool 745 */ 746 public function hasPermissionToEditRecord($ref_id, ilDclBaseRecordModel $record) 747 { 748 if ($this->getObjId() != ilObjDataCollection::_lookupObjectId($ref_id)) { 749 return false; 750 } 751 if (ilObjDataCollectionAccess::hasWriteAccess($ref_id) || ilObjDataCollectionAccess::hasEditAccess($ref_id)) { 752 return true; 753 } 754 if (!ilObjDataCollectionAccess::hasAddRecordAccess($ref_id)) { 755 return false; 756 } 757 if (!$this->checkLimit()) { 758 return false; 759 } 760 if ($this->getEditPerm() && !$this->getEditByOwner()) { 761 return true; 762 } 763 if ($this->getEditByOwner()) { 764 return $this->doesRecordBelongToUser($record); 765 } 766 767 return false; 768 } 769 770 771 /** 772 * @param $ref_id int the reference id of the current datacollection object 773 * @param $record ilDclBaseRecordModel the record which will be deleted 774 * 775 * @return bool 776 */ 777 public function hasPermissionToDeleteRecord($ref_id, ilDclBaseRecordModel $record) 778 { 779 if ($this->getObjId() != ilObjDataCollection::_lookupObjectId($ref_id)) { 780 return false; 781 } 782 if (ilObjDataCollectionAccess::hasWriteAccess($ref_id)) { 783 return true; 784 } 785 if (!ilObjDataCollectionAccess::hasAddRecordAccess($ref_id)) { 786 return false; 787 } 788 if (!$this->checkLimit()) { 789 return false; 790 } 791 if ($this->getDeletePerm() && !$this->getDeleteByOwner()) { 792 return true; 793 } 794 if ($this->getDeleteByOwner()) { 795 return $this->doesRecordBelongToUser($record); 796 } 797 798 return false; 799 } 800 801 802 /** 803 * @param $ref_id 804 * 805 * @return bool 806 */ 807 public function hasPermissionToDeleteRecords($ref_id) 808 { 809 if ($this->getObjId() != ilObjDataCollection::_lookupObjectId($ref_id)) { 810 return false; 811 } 812 813 return ((ilObjDataCollectionAccess::hasAddRecordAccess($ref_id) && $this->getDeletePerm()) 814 || ilObjDataCollectionAccess::hasWriteAccess($ref_id)); 815 } 816 817 818 /** 819 * @param int $ref_id 820 * @param $record ilDclBaseRecordModel 821 * @param int $user_id 822 * 823 * @return bool 824 */ 825 public function hasPermissionToViewRecord($ref_id, $record, $user_id = 0) 826 { 827 global $DIC; 828 $ilUser = $DIC['ilUser']; 829 if ($this->getObjId() != ilObjDataCollection::_lookupObjectId($ref_id)) { 830 return false; 831 } 832 if (ilObjDataCollectionAccess::hasWriteAccess($ref_id, $user_id) || ilObjDataCollectionAccess::hasEditAccess($ref_id, $user_id)) { 833 return true; 834 } 835 if (ilObjDataCollectionAccess::hasReadAccess($ref_id)) { 836 // Check for view only own entries setting 837 if ($this->getViewOwnRecordsPerm() && ($user_id ? $user_id : $ilUser->getId()) != $record->getOwner()) { 838 return false; 839 } 840 841 return true; 842 } 843 844 return false; 845 } 846 847 848 /** 849 * @param ilDclBaseRecordModel $record 850 * 851 * @return bool 852 */ 853 protected function doesRecordBelongToUser(ilDclBaseRecordModel $record) 854 { 855 global $DIC; 856 $ilUser = $DIC['ilUser']; 857 858 return ($ilUser->getId() == $record->getOwner()); 859 } 860 861 862 /** 863 * @return bool 864 */ 865 public function checkLimit() 866 { 867 if ($this->getLimited()) { 868 $now = new ilDateTime(date("Y-m-d H:i:s"), IL_CAL_DATE); 869 $from = new ilDateTime($this->getLimitStart(), IL_CAL_DATE); 870 $to = new ilDateTime($this->getLimitEnd(), IL_CAL_DATE); 871 872 return ($from <= $now && $now <= $to); 873 } 874 875 return true; 876 } 877 878 879 /** 880 * Update fields 881 */ 882 public function updateFields() 883 { 884 foreach ($this->getFields() as $field) { 885 $field->doUpdate(); 886 } 887 } 888 889 890 /** 891 * sortFields 892 * 893 * @param $fields ilDclBaseFieldModel[] 894 */ 895 public function sortFields(&$fields) 896 { 897 $this->sortByOrder($fields); 898 //After sorting the array loses it's keys respectivly their keys are set form $field->id to 1,2,3... so we reset the keys. 899 $named = array(); 900 foreach ($fields as $field) { 901 $named[$field->getId()] = $field; 902 } 903 904 $fields = $named; 905 } 906 907 908 /** 909 * 910 * @param $array ilDclBaseFieldModel[] the array to sort 911 */ 912 protected function sortByOrder(&$array) 913 { 914 // php-bug: https://bugs.php.net/bug.php?id=50688 915 // fixed in php 7 but for now we need the @ a workaround 916 @usort($array, array($this, "compareOrder")); 917 } 918 919 920 /** 921 * buildOrderFields 922 * orders the fields. 923 */ 924 public function buildOrderFields() 925 { 926 $fields = $this->getFields(); 927 $this->sortByOrder($fields); 928 $count = 10; 929 $offset = 10; 930 foreach ($fields as $field) { 931 if (!is_null($field->getOrder())) { 932 $field->setOrder($count); 933 $count = $count + $offset; 934 $field->doUpdate(); 935 } 936 } 937 } 938 939 940 /** 941 * Get a field by title 942 * 943 * @param $title 944 * 945 * @return ilDclBaseFieldModel 946 */ 947 public function getFieldByTitle($title) 948 { 949 $return = null; 950 foreach ($this->getFields() as $field) { 951 if ($field->getTitle() == $title) { 952 $return = $field; 953 break; 954 } 955 } 956 957 return $return; 958 } 959 960 961 /** 962 * @param boolean $add_perm 963 */ 964 public function setAddPerm($add_perm) 965 { 966 $this->add_perm = $add_perm; 967 } 968 969 970 /** 971 * @return boolean 972 */ 973 public function getAddPerm() 974 { 975 return (bool) $this->add_perm; 976 } 977 978 979 /** 980 * @param boolean $delete_perm 981 */ 982 public function setDeletePerm($delete_perm) 983 { 984 $this->delete_perm = $delete_perm; 985 if (!$delete_perm) { 986 $this->setDeleteByOwner(false); 987 } 988 } 989 990 991 /** 992 * @return boolean 993 */ 994 public function getDeletePerm() 995 { 996 return (bool) $this->delete_perm; 997 } 998 999 1000 /** 1001 * @param boolean $edit_by_owner 1002 */ 1003 public function setEditByOwner($edit_by_owner) 1004 { 1005 $this->edit_by_owner = $edit_by_owner; 1006 if ($edit_by_owner) { 1007 $this->setEditPerm(true); 1008 } 1009 } 1010 1011 1012 /** 1013 * @return boolean 1014 */ 1015 public function getEditByOwner() 1016 { 1017 return (bool) $this->edit_by_owner; 1018 } 1019 1020 1021 /** 1022 * @return boolean 1023 */ 1024 public function getDeleteByOwner() 1025 { 1026 return (bool) $this->delete_by_owner; 1027 } 1028 1029 1030 /** 1031 * @param boolean $delete_by_owner 1032 */ 1033 public function setDeleteByOwner($delete_by_owner) 1034 { 1035 $this->delete_by_owner = $delete_by_owner; 1036 if ($delete_by_owner) { 1037 $this->setDeletePerm(true); 1038 } 1039 } 1040 1041 1042 /** 1043 * @param boolean $edit_perm 1044 */ 1045 public function setEditPerm($edit_perm) 1046 { 1047 $this->edit_perm = $edit_perm; 1048 if (!$edit_perm) { 1049 $this->setEditByOwner(false); 1050 } 1051 } 1052 1053 1054 /** 1055 * @return boolean 1056 */ 1057 public function getEditPerm() 1058 { 1059 return (bool) $this->edit_perm; 1060 } 1061 1062 1063 /** 1064 * @param boolean $limited 1065 */ 1066 public function setLimited($limited) 1067 { 1068 $this->limited = $limited; 1069 } 1070 1071 1072 /** 1073 * @return boolean 1074 */ 1075 public function getLimited() 1076 { 1077 return $this->limited; 1078 } 1079 1080 1081 /** 1082 * @param string $limit_end 1083 */ 1084 public function setLimitEnd($limit_end) 1085 { 1086 $this->limit_end = $limit_end; 1087 } 1088 1089 1090 /** 1091 * @return string 1092 */ 1093 public function getLimitEnd() 1094 { 1095 return $this->limit_end; 1096 } 1097 1098 1099 /** 1100 * @param string $limit_start 1101 */ 1102 public function setLimitStart($limit_start) 1103 { 1104 $this->limit_start = $limit_start; 1105 } 1106 1107 1108 /** 1109 * @return string 1110 */ 1111 public function getLimitStart() 1112 { 1113 return $this->limit_start; 1114 } 1115 1116 1117 /** 1118 * @param boolean $is_visible 1119 */ 1120 public function setIsVisible($is_visible) 1121 { 1122 $this->is_visible = $is_visible; 1123 } 1124 1125 1126 /** 1127 * @return boolean 1128 */ 1129 public function getIsVisible() 1130 { 1131 return $this->is_visible; 1132 } 1133 1134 1135 /** 1136 * @param string $description 1137 */ 1138 public function setDescription($description) 1139 { 1140 $this->description = $description; 1141 } 1142 1143 1144 /** 1145 * @return string 1146 */ 1147 public function getDescription() 1148 { 1149 return $this->description; 1150 } 1151 1152 1153 /** 1154 * 1155 * /** 1156 * @param string $default_sort_field 1157 */ 1158 public function setDefaultSortField($default_sort_field) 1159 { 1160 $default_sort_field = ($default_sort_field) ? $default_sort_field : 0; // Change null or empty strings to zero 1161 $this->default_sort_field = $default_sort_field; 1162 } 1163 1164 1165 /** 1166 * @return string 1167 */ 1168 public function getDefaultSortField() 1169 { 1170 return $this->default_sort_field; 1171 } 1172 1173 1174 /** 1175 * @param string $default_sort_field_order 1176 */ 1177 public function setDefaultSortFieldOrder($default_sort_field_order) 1178 { 1179 if (!in_array($default_sort_field_order, array('asc', 'desc'))) { 1180 $default_sort_field_order = 'asc'; 1181 } 1182 $this->default_sort_field_order = $default_sort_field_order; 1183 } 1184 1185 1186 /** 1187 * @return string 1188 */ 1189 public function getDefaultSortFieldOrder() 1190 { 1191 return $this->default_sort_field_order; 1192 } 1193 1194 1195 /** 1196 * @param boolean $public_comments 1197 */ 1198 public function setPublicCommentsEnabled($public_comments) 1199 { 1200 $this->public_comments = $public_comments; 1201 } 1202 1203 1204 /** 1205 * @return boolean 1206 */ 1207 public function getPublicCommentsEnabled() 1208 { 1209 return $this->public_comments; 1210 } 1211 1212 1213 /** 1214 * @param boolean $view_own_perm 1215 */ 1216 public function setViewOwnRecordsPerm($view_own_perm) 1217 { 1218 $this->view_own_records_perm = (int) $view_own_perm; 1219 } 1220 1221 1222 /** 1223 * @return boolean 1224 */ 1225 public function getViewOwnRecordsPerm() 1226 { 1227 return (bool) $this->view_own_records_perm; 1228 } 1229 1230 1231 /** 1232 * @return boolean 1233 */ 1234 public function getSaveConfirmation() 1235 { 1236 return $this->save_confirmation; 1237 } 1238 1239 1240 /** 1241 * @param boolean $save_confirmation 1242 */ 1243 public function setSaveConfirmation($save_confirmation) 1244 { 1245 $this->save_confirmation = $save_confirmation; 1246 } 1247 1248 1249 /** 1250 * hasCustomFields 1251 * 1252 * @return boolean 1253 */ 1254 public function hasCustomFields() 1255 { 1256 $this->loadCustomFields(); 1257 1258 return (count($this->fields) > 0) ? true : false; 1259 } 1260 1261 1262 /** 1263 * @param $a 1264 * @param $b 1265 * 1266 * @return int 1267 */ 1268 public function compareOrder($a, $b) 1269 { 1270 if (is_null($a->getOrder() == null) && is_null($b->getOrder() == null)) { 1271 return 0; 1272 } 1273 if (is_null($a->getOrder())) { 1274 return 1; 1275 } 1276 if (is_null($b->getOrder())) { 1277 return -1; 1278 } 1279 1280 return $a->getOrder() < $b->getOrder() ? -1 : 1; 1281 } 1282 1283 1284 /** 1285 * @param ilDclTable $original 1286 */ 1287 public function cloneStructure(ilDclTable $original) 1288 { 1289 $this->setTitle($original->getTitle()); 1290 $this->setDescription($original->getDescription()); 1291 $this->setIsVisible($original->getIsVisible()); 1292 $this->setEditByOwner($original->getEditByOwner()); 1293 $this->setAddPerm($original->getAddPerm()); 1294 $this->setEditPerm($original->getEditPerm()); 1295 $this->setDeleteByOwner($original->getDeleteByOwner()); 1296 $this->setSaveConfirmation($original->getSaveConfirmation()); 1297 $this->setDeletePerm($original->getDeletePerm()); 1298 $this->setLimited($original->getLimited()); 1299 $this->setLimitStart($original->getLimitStart()); 1300 $this->setLimitEnd($original->getLimitEnd()); 1301 $this->setViewOwnRecordsPerm($original->getViewOwnRecordsPerm()); 1302 $this->setExportEnabled($original->getExportEnabled()); 1303 $this->setImportEnabled($original->getImportEnabled()); 1304 $this->setPublicCommentsEnabled($original->getPublicCommentsEnabled()); 1305 $this->setDefaultSortFieldOrder($original->getDefaultSortFieldOrder()); 1306 $this->setOrder($original->getOrder()); 1307 1308 $this->doCreate(true, false); 1309 // reset stdFields to get new for the created object 1310 1311 $default_sort_field = 0; 1312 // Clone standard-fields 1313 $org_std_fields = $original->getStandardFields(); 1314 foreach ($this->getStandardFields() as $element_key => $std_field) { 1315 $std_field->cloneStructure($org_std_fields[$element_key]); 1316 if ($std_field->getId() === $original->getDefaultSortField()) { 1317 $default_sort_field = $std_field->getId(); 1318 } 1319 } 1320 1321 // Clone fields 1322 $new_fields = array(); 1323 foreach ($original->getFields() as $orig_field) { 1324 if (!$orig_field->isStandardField()) { 1325 $class_name = get_class($orig_field); 1326 $new_field = new $class_name(); 1327 $new_field->setTableId($this->getId()); 1328 $new_field->cloneStructure($orig_field->getId()); 1329 $new_fields[$orig_field->getId()] = $new_field; 1330 1331 if ($orig_field->getId() === $original->getDefaultSortField()) { 1332 $default_sort_field = $new_field->getId(); 1333 } 1334 } 1335 } 1336 1337 $this->setDefaultSortField($default_sort_field); 1338 $this->doUpdate(); 1339 1340 // Clone Records with recordfields 1341 foreach ($original->getRecords() as $orig_record) { 1342 $new_record = new ilDclBaseRecordModel(); 1343 $new_record->setTableId($this->getId()); 1344 $new_record->cloneStructure($orig_record->getId(), $new_fields); 1345 } 1346 1347 //clone tableviews (includes pageobjects) 1348 foreach ($original->getTableViews() as $orig_tableview) { 1349 $new_tableview = new ilDclTableView(); 1350 $new_tableview->setTableId($this->getId()); 1351 $new_tableview->cloneStructure($orig_tableview, $new_fields); 1352 } 1353 1354 // mandatory for all cloning functions 1355 ilDclCache::setCloneOf($original->getId(), $this->getId(), ilDclCache::TYPE_TABLE); 1356 } 1357 1358 1359 /** 1360 * 1361 */ 1362 public function afterClone() 1363 { 1364 foreach ($this->getFields() as $field) { 1365 $field->afterClone($this->getRecords()); 1366 } 1367 } 1368 1369 1370 /** 1371 * _hasRecords 1372 * 1373 * @return boolean 1374 */ 1375 public function _hasRecords() 1376 { 1377 return (count($this->getRecords()) > 0) ? true : false; 1378 } 1379 1380 1381 /** 1382 * @param $field ilDclBaseFieldModel add an already created field for eg. ordering. 1383 */ 1384 public function addField($field) 1385 { 1386 $this->all_fields[$field->getId()] = $field; 1387 } 1388 1389 1390 /** 1391 * @param $table_id int 1392 * 1393 * @return bool returns true iff there exists a table with id $table_id 1394 */ 1395 public static function _tableExists($table_id) 1396 { 1397 global $DIC; 1398 $ilDB = $DIC['ilDB']; 1399 $query = "SELECT * FROM il_dcl_table WHERE id = " . $table_id; 1400 $result = $ilDB->query($query); 1401 1402 return $result->numRows() != 0; 1403 } 1404 1405 1406 /** 1407 * @param $title Title of table 1408 * @param $obj_id DataCollection object ID where the table belongs to 1409 * 1410 * @return int 1411 */ 1412 public static function _getTableIdByTitle($title, $obj_id) 1413 { 1414 global $DIC; 1415 $ilDB = $DIC['ilDB']; 1416 $result = $ilDB->query( 1417 'SELECT id FROM il_dcl_table WHERE title = ' . $ilDB->quote($title, 'text') . ' AND obj_id = ' 1418 . $ilDB->quote($obj_id, 'integer') 1419 ); 1420 $id = 0; 1421 while ($rec = $ilDB->fetchAssoc($result)) { 1422 $id = $rec['id']; 1423 } 1424 1425 return $id; 1426 } 1427 1428 1429 /** 1430 * @param boolean $export_enabled 1431 */ 1432 public function setExportEnabled($export_enabled) 1433 { 1434 $this->export_enabled = $export_enabled; 1435 } 1436 1437 1438 /** 1439 * @return boolean 1440 */ 1441 public function getExportEnabled() 1442 { 1443 return $this->export_enabled; 1444 } 1445 1446 1447 /** 1448 * @return int 1449 */ 1450 public function getOrder() 1451 { 1452 if (!$this->table_order) { 1453 $this->updateOrder(); 1454 } 1455 1456 return $this->table_order; 1457 } 1458 1459 1460 /** 1461 * 1462 */ 1463 public function updateOrder() 1464 { 1465 global $DIC; 1466 $ilDB = $DIC['ilDB']; 1467 $result = $ilDB->query('SELECT MAX(table_order) AS table_order FROM il_dcl_table WHERE obj_id = ' . $ilDB->quote($this->getCollectionObject()->getId(), 'integer')); 1468 $this->table_order = $ilDB->fetchObject($result)->table_order + 10; 1469 $ilDB->query('UPDATE il_dcl_table SET table_order = ' . $ilDB->quote($this->table_order, 'integer') . ' WHERE id = ' . $ilDB->quote($this->getId(), 'integer')); 1470 } 1471 1472 1473 /** 1474 * @param int $table_order 1475 */ 1476 public function setOrder($table_order) 1477 { 1478 $this->table_order = $table_order; 1479 } 1480 1481 1482 /** 1483 * @param boolean $import_enabled 1484 */ 1485 public function setImportEnabled($import_enabled) 1486 { 1487 $this->import_enabled = $import_enabled; 1488 } 1489 1490 1491 /** 1492 * @return boolean 1493 */ 1494 public function getImportEnabled() 1495 { 1496 return $this->import_enabled; 1497 } 1498 1499 1500 /** 1501 * Checks if a table has a field with the given title 1502 * 1503 * @param $title Title of field 1504 * @param $obj_id Obj-ID of the table 1505 * 1506 * @return bool 1507 */ 1508 public static function _hasFieldByTitle($title, $obj_id) 1509 { 1510 global $DIC; 1511 $ilDB = $DIC['ilDB']; 1512 $result = $ilDB->query( 1513 'SELECT * FROM il_dcl_field WHERE table_id = ' . $ilDB->quote($obj_id, 'integer') . ' AND title = ' 1514 . $ilDB->quote($title, 'text') 1515 ); 1516 1517 return ($ilDB->numRows($result)) ? true : false; 1518 } 1519 1520 1521 /** 1522 * Return only the needed subset of record objects for the table, according to sorting, paging and filters 1523 * 1524 * @param string $sort Title of a field where the ilTable2GUI is sorted 1525 * @param string $direction 'desc' or 'asc' 1526 * @param int $limit Limit of records 1527 * @param int $offset Offset from records 1528 * @param array $filter Containing the filter values 1529 * 1530 * @return array Array with two keys: 'record' => Contains the record objects, 'total' => Number of total records (without slicing) 1531 */ 1532 public function getPartialRecords($sort, $direction, $limit, $offset, array $filter = array()) 1533 { 1534 global $DIC; 1535 $ilDB = $DIC['ilDB']; 1536 /** 1537 * @var $ilDB ilDBInterface 1538 */ 1539 $ilUser = $DIC['ilUser']; 1540 $rbacreview = $DIC['rbacreview']; 1541 1542 $sort_field = ($sort) ? $this->getFieldByTitle($sort) : $this->getField('id'); 1543 $direction = strtolower($direction); 1544 $direction = (in_array($direction, array('desc', 'asc'))) ? $direction : 'asc'; 1545 1546 // Sorting by a status from an ILIAS Ref field. This column is added dynamically to the table, there is no field model 1547 $sort_by_status = false; 1548 if (substr($sort, 0, 8) == '_status_') { 1549 $sort_by_status = true; 1550 $sort_field = $this->getFieldByTitle(substr($sort, 8)); 1551 } 1552 1553 if (is_null($sort_field)) { 1554 $sort_field = $this->getField('id'); 1555 } 1556 1557 $sort_query_object = $sort_field->getRecordQuerySortObject($direction, $sort_by_status); 1558 1559 $select_str = ($sort_query_object != null) ? $sort_query_object->getSelectStatement() : ''; 1560 $join_str = ($sort_query_object != null) ? $sort_query_object->getJoinStatement() : ''; 1561 $where_str = ($sort_query_object != null) ? $sort_query_object->getWhereStatement() : ''; 1562 $order_str = ($sort_query_object != null) ? $sort_query_object->getOrderStatement() : ''; 1563 $group_str = ($sort_query_object != null) ? $sort_query_object->getGroupStatement() : ''; 1564 1565 if (count($filter)) { 1566 foreach ($filter as $key => $filter_value) { 1567 $filter_field_id = substr($key, 7); 1568 $filter_field = $this->getField($filter_field_id); 1569 $filter_record_query_object = $filter_field->getRecordQueryFilterObject($filter_value, $sort_field); 1570 1571 if ($filter_record_query_object) { 1572 $select_str .= $filter_record_query_object->getSelectStatement(); 1573 $join_str .= $filter_record_query_object->getJoinStatement(); 1574 $where_str .= $filter_record_query_object->getWhereStatement(); 1575 $group_str .= $filter_record_query_object->getGroupStatement(); 1576 } 1577 } 1578 } 1579 1580 // Build the query string 1581 $sql = "SELECT DISTINCT record.id, record.owner"; 1582 if ($select_str) { 1583 $sql .= ', '; 1584 } 1585 1586 $as = ' AS '; 1587 1588 $sql .= rtrim($select_str, ',') . " FROM il_dcl_record {$as} record "; 1589 $sql .= $join_str; 1590 $sql .= " WHERE record.table_id = " . $ilDB->quote($this->getId(), 'integer'); 1591 1592 if (strlen($where_str) > 0) { 1593 $sql .= $where_str; 1594 } 1595 1596 if (strlen($group_str) > 0) { 1597 $sql .= " GROUP BY " . $group_str; 1598 } 1599 1600 if (strlen($order_str) > 0) { 1601 $sql .= " ORDER BY " . $order_str; 1602 } 1603 1604 //var_dump($sql); 1605 /*global $DIC; 1606 /*$ilLog = $DIC['ilLog']; 1607 $ilLog->write($sql, ilLogLevel::CRITICAL);*/ 1608 1609 $set = $ilDB->query($sql); 1610 $total_record_ids = array(); 1611 // Save record-ids in session to enable prev/next links in detail view 1612 $_SESSION['dcl_record_ids'] = array(); 1613 $_SESSION['dcl_table_id'] = $this->getId(); 1614 $ref = filter_input(INPUT_GET, 'ref_id'); 1615 $is_allowed_to_view = (ilObjDataCollectionAccess::hasWriteAccess($ref) || ilObjDataCollectionAccess::hasEditAccess($ref)); 1616 while ($rec = $ilDB->fetchAssoc($set)) { 1617 // Quick check if the current user is allowed to view the record 1618 if (!$is_allowed_to_view && ($this->getViewOwnRecordsPerm() && $ilUser->getId() != $rec['owner'])) { 1619 continue; 1620 } 1621 $total_record_ids[] = $rec['id']; 1622 $_SESSION['dcl_record_ids'][] = $rec['id']; 1623 } 1624 1625 if ($sort_query_object != null) { 1626 $total_record_ids = $sort_query_object->applyCustomSorting($sort_field, $total_record_ids, $direction); 1627 } 1628 1629 // Now slice the array to load only the needed records in memory 1630 $record_ids = array_slice($total_record_ids, $offset, $limit); 1631 1632 $records = array(); 1633 foreach ($record_ids as $id) { 1634 $records[] = ilDclCache::getRecordCache($id); 1635 } 1636 1637 return array('records' => $records, 'total' => count($total_record_ids)); 1638 } 1639} 1640