diff --git a/components/ILIAS/Export/xml/SchemaValidation/ilias_lpsettings_12_0.xsd b/components/ILIAS/Export/xml/SchemaValidation/ilias_lpsettings_12_0.xsd new file mode 100644 index 000000000000..ed024984177d --- /dev/null +++ b/components/ILIAS/Export/xml/SchemaValidation/ilias_lpsettings_12_0.xsd @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/ILIAS/Group/classes/class.ilGroupExporter.php b/components/ILIAS/Group/classes/class.ilGroupExporter.php index 8f5eb90e6ce4..b7d3d793d6db 100755 --- a/components/ILIAS/Group/classes/class.ilGroupExporter.php +++ b/components/ILIAS/Group/classes/class.ilGroupExporter.php @@ -85,6 +85,11 @@ public function getXmlExportTailDependencies(string $a_entity, string $a_target_ "ids" => $md_ids ); } + $deps[] = [ + "component" => "components/ILIAS/Tracking", + "entity" => "lpsettings", + "ids" => $a_ids + ]; return $deps; } diff --git a/components/ILIAS/Tracking/classes/DB/Factory.php b/components/ILIAS/Tracking/classes/DB/Factory.php new file mode 100644 index 000000000000..6fe4166c5a4a --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/Factory.php @@ -0,0 +1,67 @@ +db + ); + } + + public function lpCollection(): LPCollectionFactoryInterface + { + return new LPCollectionFactory( + $this->db + ); + } + + public function lpMarks(): LPMarksFactoryInterface + { + return new LPMarksFactory( + $this->db + ); + } + + public function lpCollectionManual(): LPCollectionManualFactoryInterface + { + return new LPCollectionManualFactory( + $this->db + ); + } +} diff --git a/components/ILIAS/Tracking/classes/DB/FactoryInterface.php b/components/ILIAS/Tracking/classes/DB/FactoryInterface.php new file mode 100644 index 000000000000..a052204a76bc --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/FactoryInterface.php @@ -0,0 +1,38 @@ +elements = $elements; + $this->index = 0; + } + + public function next(): void + { + $this->index++; + } + + public function valid(): bool + { + return isset($this->elements[$this->index]); + } + + public function rewind(): void + { + $this->index = 0; + } + + public function count(): int + { + return count($this->elements); + } + + public function withFixedNumObligatory(): LPCollectionInterface + { + $mapping = []; + foreach ($this->elements as $element) { + if (!isset($mapping[$element->getGroupingId()])) { + $mapping[$element->getGroupingId()] = []; + } + $mapping[$element->getGroupingId()][] = $element; + } + $new_elements = []; + foreach ($mapping as $grouping_id => $elements) { + $elements_in_group = count($elements); + foreach ($elements as $element) { + if ($grouping_id === 0) { + $new_elements[] = $element + ->withNumObligatory(0); + continue; + } + if ($elements_in_group === 1) { + $new_elements[] = $element + ->withNumObligatory(0) + ->withGroupingId(0); + continue; + } + if ($elements_in_group > $element->getNumObligatory()) { + $new_elements[] = $element + ->withNumObligatory(max(1, $element->getNumObligatory())); + ; + continue; + } + if ($elements_in_group <= $element->getNumObligatory()) { + $new_elements[] = $element + ->withNumObligatory(max(0, $elements_in_group - 1)); + continue; + } + } + } + $clone = clone $this; + $clone->elements = $new_elements; + return $clone; + } + + public function withObjectId( + int $object_id + ): LPCollectionInterface { + $clone = clone $this; + $clone->object_id = $object_id; + return $clone; + } + + public function withChangedNumObligatoryIdOfAllElements( + int $num_obligatory + ): LPCollectionInterface { + $new_elements = []; + foreach ($this->elements as $element) { + $new_elements[] = $element + ->withNumObligatory($num_obligatory); + } + $clone = clone $this; + $clone->elements = $new_elements; + return $clone; + } + + public function withChangedGroupingIdOfAllElements( + int $grouping_id + ): LPCollectionInterface { + $new_elements = []; + foreach ($this->elements as $element) { + $new_elements[] = $element + ->withGroupingId($grouping_id); + } + $clone = clone $this; + $clone->elements = $new_elements; + return $clone; + } + + public function withChangedActiveStatusOfAllElements( + bool $active + ): LPCollectionInterface { + $new_elements = []; + foreach ($this->elements as $element) { + $new_elements[] = $element + ->withIsActive($active); + } + $clone = clone $this; + $clone->elements = $new_elements; + return $clone; + } + + public function getSubCollectionOfActiveItems(): LPCollectionInterface + { + $elements = []; + foreach ($this->elements as $element) { + if ($element->isActive()) { + $elements[] = $element; + } + } + $clone = clone $this; + $clone->elements = $elements; + return $clone; + } + + public function getSubCollectionOfItemsByGroupingId( + int $grouping_id + ): LPCollectionInterface { + return $this->getSubCollectionOfItemsByGroupingIds($grouping_id); + } + + public function getSubCollectionOfItemsByGroupingIds( + int ...$grouping_ids + ): LPCollectionInterface { + $elements = []; + foreach ($this->elements as $element) { + if (in_array($element->getGroupingId(), $grouping_ids)) { + $elements[] = $element; + } + } + $clone = clone $this; + $clone->elements = $elements; + return $clone; + } + + public function getSubCollectionOfItemsByItemIds( + int ...$item_ids + ): LPCollectionInterface { + $elements = []; + foreach ($this->elements as $element) { + if (in_array($element->getItemId(), $item_ids)) { + $elements[] = $element; + } + } + $clone = clone $this; + $clone->elements = $elements; + return $clone; + } + + public function getSubCollectionOfItemsByActiveStatus( + bool $active + ): LPCollectionInterface { + $elements = []; + foreach ($this->elements as $element) { + if ( + ($element->isActive() && $active) || + (!$element->isActive() && !$active) + ) { + $elements[] = $element; + } + } + $clone = clone $this; + $clone->elements = $elements; + return $clone; + } + + public function getElementByItemId( + int $item_id + ): LPCollectionElementInterface|null { + foreach ($this->elements as $element) { + if ($element->getItemId() === $item_id) { + return $element; + } + } + return null; + } + + public function getObjectId(): int + { + return $this->object_id; + } + + /** + * @return int[] + */ + public function getItemIds(): array + { + $ids = []; + foreach ($this->elements as $element) { + $ids[] = $element->getItemId(); + } + return $ids; + } + + /** + * @return int[] + */ + public function getGroupingIds(): array + { + $ids = []; + foreach ($this->elements as $element) { + $ids[] = $element->getGroupingId(); + } + return $ids; + } + + /** + * @return int[] + */ + public function getGroupingIdsGreaterZero(): array + { + return array_filter($this->getGroupingIds(), fn($id) => $id > 0); + } + + public function getMaxGroupingNumber(): int + { + $ids = []; + foreach ($this->elements as $element) { + $ids[] = $element->getGroupingId(); + } + return count($ids) === 0 ? 0 : max($ids); + } + + public function current(): LPCollectionElementInterface + { + return $this->elements[$this->index]; + } + + public function key(): int + { + return $this->index; + } +} diff --git a/components/ILIAS/Tracking/classes/DB/LPCollection/Element/LPCollectionElement.php b/components/ILIAS/Tracking/classes/DB/LPCollection/Element/LPCollectionElement.php new file mode 100644 index 000000000000..060cbdf22250 --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/LPCollection/Element/LPCollectionElement.php @@ -0,0 +1,99 @@ +item_id; + } + + public function getGroupingId(): int + { + return $this->grouping_id; + } + + public function getNumObligatory(): int + { + return $this->num_obligatory; + } + + public function getLpMode(): int + { + return $this->lp_mode; + } + + public function isActive(): bool + { + return $this->active; + } + + public function withItemId( + int $item_id + ): LPCollectionElementInterface { + $clone = clone $this; + $clone->item_id = $item_id; + return $clone; + } + + public function withGroupingId( + int $grouping_id + ): LPCollectionElementInterface { + $clone = clone $this; + $clone->grouping_id = $grouping_id; + return $clone; + } + + public function withNumObligatory( + int $num_obligatory + ): LPCollectionElementInterface { + $clone = clone $this; + $clone->num_obligatory = $num_obligatory; + return $clone; + } + + public function withLPMode( + int $lp_mode + ): LPCollectionElementInterface { + $clone = clone $this; + $clone->lp_mode = $lp_mode; + return $clone; + } + + public function withIsActive( + bool $active + ): LPCollectionElementInterface { + $clone = clone $this; + $clone->active = $active; + return $clone; + } +} diff --git a/components/ILIAS/Tracking/classes/DB/LPCollection/Element/LPCollectionElementInterface.php b/components/ILIAS/Tracking/classes/DB/LPCollection/Element/LPCollectionElementInterface.php new file mode 100644 index 000000000000..8ce956030003 --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/LPCollection/Element/LPCollectionElementInterface.php @@ -0,0 +1,54 @@ +db, + $this->element() + ); + } +} diff --git a/components/ILIAS/Tracking/classes/DB/LPCollection/FactoryInterface.php b/components/ILIAS/Tracking/classes/DB/LPCollection/FactoryInterface.php new file mode 100644 index 000000000000..71fca86c91ea --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/LPCollection/FactoryInterface.php @@ -0,0 +1,30 @@ +db->quote($object_id, ilDBConstants::T_INTEGER); + $res = $this->db->query($query); + return $this->buildCollectionWithQueryResult($object_id, $res); + } + + public function readLPCollectionWithReferenceInObjectReference( + int $object_id + ): LPCollectionInterface|null { + $query = "SELECT ut_lp_collections.obj_id, ut_lp_collections.item_id, ut_lp_collections.grouping_id, ut_lp_collections.lpmode, ut_lp_collections.num_obligatory, ut_lp_collections.active FROM object_reference " + . "JOIN ut_lp_collections " + . "ON (object_reference.obj_id = " . $this->db->quote($object_id, ilDBConstants::T_INTEGER) . " " + . "AND object_reference.ref_id = ut_lp_collections.item_id)"; + $res = $this->db->query($query); + return $this->buildCollectionWithQueryResult($object_id, $res); + } + + public function writeLPCollection( + LPCollectionInterface $lp_collection + ): void { + if (count($lp_collection) === 0) { + return; + } + $tuples = []; + foreach ($lp_collection as $lp_collection_element) { + $tuple = "("; + $tuple .= $this->db->quote($lp_collection->getObjectId(), ilDBConstants::T_INTEGER) . ", "; + $tuple .= $this->db->quote($lp_collection_element->getItemId(), ilDBConstants::T_INTEGER) . ", "; + $tuple .= $this->db->quote($lp_collection_element->getGroupingId(), ilDBConstants::T_INTEGER) . ", "; + $tuple .= $this->db->quote($lp_collection_element->getNumObligatory(), ilDBConstants::T_INTEGER) . ", "; + $tuple .= $this->db->quote((int) $lp_collection_element->isActive(), ilDBConstants::T_INTEGER) . ", "; + $tuple .= $this->db->quote($lp_collection_element->getLpMode(), ilDBConstants::T_INTEGER) . ")"; + $tuples[] = $tuple; + } + $query = "INSERT INTO ut_lp_collections (obj_id, item_id, grouping_id, num_obligatory, active, lpmode)" + . " VALUES " . implode(", ", $tuples) + . " ON DUPLICATE KEY UPDATE item_id = VALUES(item_id), grouping_id = VALUES(grouping_id), num_obligatory = VALUES(num_obligatory), active = VALUES(active), lpmode = VALUES(lpmode)"; + $this->db->manipulate($query); + } + + + public function deleteLPCollection( + int $object_id + ): void { + $query = "DELETE FROM ut_lp_collections WHERE obj_id = " . $this->db->quote($object_id, ilDBConstants::T_INTEGER); + $this->db->manipulate($query); + } + + public function deleteLPCollectionEntry( + int $object_id, + int $item_id + ): void { + $query = "DELETE FROM ut_lp_collections" . + " WHERE obj_id = " . $this->db->quote($object_id, "integer") . + " AND item_id = " . $this->db->quote($item_id, "integer"); + $this->db->manipulate($query); + } + + public function deleteLPCollectionEntryByGroupingId( + int $object_id, + int $item_id, + int $grouping_id + ): void { + $query = "DELETE FROM ut_lp_collections " . + " WHERE obj_id = " . $this->db->quote($object_id, "integer") . + " AND item_id = " . $this->db->quote($item_id, "integer") . + " AND grouping_id = " . $this->db->quote($grouping_id, "integer"); + $this->db->manipulate($query); + } + + public function deleteLPCollectionManual( + int $object_id + ): void { + $query = "DELETE FROM ut_lp_coll_manual" . + " WHERE obj_id = " . $this->db->quote($object_id, "integer"); + $this->db->manipulate($query); + } + + protected function buildCollectionWithQueryResult( + int $object_id, + ilDBStatement $res + ): LPCollectionInterface|null { + $elements = []; + while ($row = $res->fetchAssoc()) { + $lp_collection_element = $this->element_factory->lpCollectionElement() + ->withItemId((int) $row['item_id']) + ->withGroupingId((int) $row['grouping_id']) + ->withLPMode((int) $row['lpmode']) + ->withNumObligatory((int) $row['num_obligatory']) + ->withIsActive((bool) $row['active']); + $elements[] = $lp_collection_element; + } + return count($elements) === 0 + ? null + : $this->element_factory->lpCollection(...$elements)->withObjectId($object_id); + } +} diff --git a/components/ILIAS/Tracking/classes/DB/LPCollection/RepositoryInterface.php b/components/ILIAS/Tracking/classes/DB/LPCollection/RepositoryInterface.php new file mode 100644 index 000000000000..a01b57e6b364 --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/LPCollection/RepositoryInterface.php @@ -0,0 +1,57 @@ +elements = $elements; + $this->index = 0; + } + + public function next(): void + { + $this->index++; + } + + public function valid(): bool + { + return isset($this->elements[$this->index]); + } + + public function rewind(): void + { + $this->index = 0; + } + + public function count(): int + { + return count($this->elements); + } + + public function current(): LPCollectionManualEntryInterface + { + return $this->elements[$this->index]; + } + + public function key(): int + { + return $this->index; + } +} diff --git a/components/ILIAS/Tracking/classes/DB/LPCollectionManual/Element/LPCollectionManualEntry.php b/components/ILIAS/Tracking/classes/DB/LPCollectionManual/Element/LPCollectionManualEntry.php new file mode 100644 index 000000000000..8c9755727a0c --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/LPCollectionManual/Element/LPCollectionManualEntry.php @@ -0,0 +1,95 @@ +object_id; + } + + public function getUserId(): int + { + return $this->user_id; + } + + public function getSubitemId(): int + { + return $this->subitem_id; + } + + public function getLastChanged(): int + { + return $this->last_change; + } + + public function isCompleted(): bool + { + return $this->completed; + } + + public function withObjectId( + int $object_id + ): LPCollectionManualEntryInterface { + $clone = clone $this; + $clone->object_id = $object_id; + return $clone; + } + + public function withUserId( + int $user_id + ): LPCollectionManualEntryInterface { + $clone = clone $this; + $clone->user_id = $user_id; + return $clone; + } + + public function withSubitemId( + int $subitem_id + ): LPCollectionManualEntryInterface { + $clone = clone $this; + $clone->subitem_id = $subitem_id; + return $clone; + } + + public function withLastChanged( + int $last_changed + ): LPCollectionManualEntryInterface { + $clone = clone $this; + $clone->last_change = $last_changed; + return $clone; + } + + public function withCompletedStatus( + bool $completed + ): LPCollectionManualEntryInterface { + $clone = clone $this; + $clone->completed = $completed; + return $clone; + } +} diff --git a/components/ILIAS/Tracking/classes/DB/LPCollectionManual/Element/LPCollectionManualEntryInterface.php b/components/ILIAS/Tracking/classes/DB/LPCollectionManual/Element/LPCollectionManualEntryInterface.php new file mode 100644 index 000000000000..84011cb6ac1e --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/LPCollectionManual/Element/LPCollectionManualEntryInterface.php @@ -0,0 +1,54 @@ +db, + $this->element() + ); + } +} diff --git a/components/ILIAS/Tracking/classes/DB/LPCollectionManual/FactoryInterface.php b/components/ILIAS/Tracking/classes/DB/LPCollectionManual/FactoryInterface.php new file mode 100644 index 000000000000..edb4b4f9124f --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/LPCollectionManual/FactoryInterface.php @@ -0,0 +1,30 @@ +db->quote($object_id, ilDBConstants::T_INTEGER); + $res = $this->db->query($query); + $elements = []; + while ($row = $res->fetchAssoc()) { + $elements[] = $this->entryFromRowData($row); + }; + return $this->element_factory->lpCollectionManual(...$elements); + } + + public function readEntryForUserOfSubitemOfObject( + int $object_id, + int $user_id, + int $subitem_id + ): LPCollectionManualEntryInterface|null { + $query = "SELECT * FROM ut_lp_coll_manual " + . "WHERE obj_id = " . $this->db->quote($object_id, ilDBConstants::T_INTEGER) . " " + . "AND usr_id = " . $this->db->quote($user_id, ilDBConstants::T_INTEGER) . " " + . "AND subitem_id = " . $this->db->quote($subitem_id, ilDBConstants::T_INTEGER); + $res = $this->db->query($query); + $row = $res->fetchAssoc(); + return is_null($row) ? null : $this->entryFromRowData($row); + } + + public function write( + LPCollectionManualEntryInterface $entry + ): void { + $this->writeCollection($this->element_factory->lpCollectionManual($entry)); + } + + public function writeCollection( + LPCollectionManualInterface $collection_manual + ): void { + if (count($collection_manual) === 0) { + return; + } + $tuples = []; + foreach ($collection_manual as $collection_manual_entry) { + $tuple = "(" + . $this->db->quote($collection_manual_entry->getObjectId(), ilDBConstants::T_INTEGER) . ", " + . $this->db->quote($collection_manual_entry->getUserId(), ilDBConstants::T_INTEGER) . ", " + . $this->db->quote($collection_manual_entry->getSubitemId(), ilDBConstants::T_INTEGER) . ", " + . $this->db->quote((int) $collection_manual_entry->isCompleted(), ilDBConstants::T_INTEGER) . ", " + . $this->db->quote($collection_manual_entry->getLastChanged(), ilDBConstants::T_INTEGER) . ")"; + $tuples[] = $tuple; + } + $query = "INSERT INTO ut_lp_coll_manual (obj_id, usr_id, subitem_id, completed, last_change)" + . " VALUES " . implode(", ", $tuples) + . " ON DUPLICATE KEY UPDATE completed=VALUES(completed), last_change=VALUES(last_change)"; + $this->db->manipulate($query); + } + + public function deleteEntriesOfObject( + int $object_id + ): void { + $query = "DELETE FROM ut_lp_coll_manual" . + " WHERE obj_id = " . $this->db->quote($object_id, ilDBConstants::T_INTEGER); + ; + $this->db->manipulate($query); + } + + protected function entryFromRowData( + array $row + ): LPCollectionManualEntryInterface { + return $this->element_factory->lpCollectionManualEntry() + ->withObjectId((int) $row['obj_id']) + ->withUserId((int) $row['usr_id']) + ->withSubitemId((int) $row['subitem_id']) + ->withLastChanged((int) $row['last_changed']) + ->withCompletedStatus((bool) ((int) $row['completed'])); + } +} diff --git a/components/ILIAS/Tracking/classes/DB/LPCollectionManual/RepositoryInterface.php b/components/ILIAS/Tracking/classes/DB/LPCollectionManual/RepositoryInterface.php new file mode 100644 index 000000000000..c84201f8bb50 --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/LPCollectionManual/RepositoryInterface.php @@ -0,0 +1,49 @@ +comment = null; + $this->mark = null; + $this->status_dirty = 0; + $this->percentage = 0; + $this->completed = false; + } + + public function withStatusChanged( + string $status_changed + ): LPMarkInterface { + $clone = clone $this; + $clone->status_changed = $status_changed; + return $clone; + } + + public function withComment( + string|null $comment + ): LPMarkInterface { + $clone = clone $this; + $clone->comment = $comment; + return $clone; + } + + public function withMark( + string|null $mark + ): LPMarkInterface { + $clone = clone $this; + $clone->mark = $mark; + return $clone; + } + + public function withObjectId( + int $object_id + ): LPMarkInterface { + $clone = clone $this; + $clone->object_id = $object_id; + return $clone; + } + + public function withUserId( + int $user_id + ): LpMarkInterface { + $clone = clone $this; + $clone->user_id = $user_id; + return $clone; + } + + public function withStatus( + int $status + ): LPMarkInterface { + $clone = clone $this; + $clone->status = $status; + return $clone; + } + + public function withStatusDirty( + int $status_dirty + ): LPMarkInterface { + $clone = clone $this; + $clone->status_dirty = $status_dirty; + return $clone; + } + + public function withPercentage( + int $percentage + ): LPMarkInterface { + $clone = clone $this; + $clone->percentage = $percentage; + return $clone; + } + + public function withCompletedStatus( + bool $completed + ): LPMarkInterface { + $clone = clone $this; + $clone->completed = $completed; + return $clone; + } + + public function getStatusChanged(): string + { + return $this->status_changed; + } + + public function getComment(): string|null + { + return $this->comment; + } + + public function getMark(): string|null + { + return $this->mark; + } + + public function getObjectId(): int + { + return $this->object_id; + } + + public function getUserId(): int + { + return $this->user_id; + } + + public function getStatus(): int + { + return $this->status; + } + + public function getStatusDirty(): int + { + return $this->status_dirty; + } + + public function getPercentage(): int + { + return $this->percentage; + } + + public function isCompleted(): bool + { + return $this->completed; + } +} diff --git a/components/ILIAS/Tracking/classes/DB/LPMarks/Element/LPMarkCollection.php b/components/ILIAS/Tracking/classes/DB/LPMarks/Element/LPMarkCollection.php new file mode 100644 index 000000000000..cdb21d02644d --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/LPMarks/Element/LPMarkCollection.php @@ -0,0 +1,158 @@ +elements = $elements; + $this->index = 0; + } + + public function asDataArray(): array + { + $data = []; + foreach ($this->elements as $element) { + $entry = [ + 'obj_id' => $element->getObjectId(), + 'usr_id' => $element->getUserId(), + 'completed' => $element->isCompleted(), + 'mark' => (string) $element->getMark(), + 'comment' => (string) $element->getComment(), + 'status' => $element->getStatus(), + 'status_changed' => $element->getStatusChanged(), + 'status_dirty' => $element->getStatusDirty(), + 'percentage' => $element->getPercentage() + ]; + $data[] = $entry; + } + return $data; + } + + /** + * @return int[] + */ + public function asUserIdArray(): array + { + $data = []; + foreach ($this->elements as $element) { + $data[] = $element->getUserId(); + } + return $data; + } + + public function getSubCollectionOfElementsByUserIds( + int ...$user_ids + ): LPMarkCollectionInterface { + $clone = clone $this; + $clone->elements = array_filter($clone->elements, fn(LPMarkInterface $element) => in_array($element->getUserId(), $user_ids)); + return $clone; + } + + public function getSubCollectionOfElementsByCompletedStatus( + bool $completed + ): LPMarkCollectionInterface { + $clone = clone $this; + $clone->elements = array_filter($clone->elements, fn(LPMarkInterface $element) => $element->isCompleted() === $completed); + return $clone; + } + + public function getSubCollectionOfElementsByStatus( + int $status + ): LPMarkCollectionInterface { + $clone = clone $this; + $clone->elements = array_filter($clone->elements, fn(LPMarkInterface $element) => $element->getStatus() === $status); + return $clone; + } + + public function getSubCollectionOfElementsByStatusDirty( + int $status_dirty + ): LPMarkCollectionInterface { + $clone = clone $this; + $clone->elements = array_filter($clone->elements, fn(LPMarkInterface $element) => $element->getStatusDirty() === $status_dirty); + return $clone; + } + + public function getSubCollectionOfElementsWithDistinctUsers(): LPMarkCollectionInterface + { + $ids = []; + $elements = []; + foreach ($this->elements as $element) { + if (in_array($element->getUserId(), $ids)) { + continue; + } + $ids[] = $element->getUserId(); + $elements[] = $element; + } + $clone = clone $this; + $clone->elements = $elements; + return $clone; + } + + public function withChangedStatusDirtyOfAllElements( + int $status_dirty + ): LPMarkCollectionInterface { + $elements = []; + foreach ($this->elements as $element) { + $elements[] = $element + ->withStatusDirty($status_dirty); + } + $clone = clone $this; + $clone->elements = $elements; + return $clone; + } + + public function next(): void + { + $this->index++; + } + + public function valid(): bool + { + return isset($this->elements[$this->index]); + } + + public function rewind(): void + { + $this->index = 0; + } + + public function count(): int + { + return count($this->elements); + } + + public function current(): LPMarkInterface + { + return $this->elements[$this->index]; + } + + public function key(): int + { + return $this->index; + } +} diff --git a/components/ILIAS/Tracking/classes/DB/LPMarks/Element/LPMarkCollectionInterface.php b/components/ILIAS/Tracking/classes/DB/LPMarks/Element/LPMarkCollectionInterface.php new file mode 100644 index 000000000000..d60e6f07af2b --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/LPMarks/Element/LPMarkCollectionInterface.php @@ -0,0 +1,57 @@ +db, + $this->element() + ); + } +} diff --git a/components/ILIAS/Tracking/classes/DB/LPMarks/FactoryInterface.php b/components/ILIAS/Tracking/classes/DB/LPMarks/FactoryInterface.php new file mode 100644 index 000000000000..a50287e414dd --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/LPMarks/FactoryInterface.php @@ -0,0 +1,30 @@ +db->quote($lp_mark->getObjectId(), ilDBConstants::T_INTEGER) . ", " + . $this->db->quote($lp_mark->getUserId(), ilDBConstants::T_INTEGER) . ", " + . $this->db->quote((int) $lp_mark->isCompleted(), ilDBConstants::T_INTEGER) . ", " + . $this->db->quote($lp_mark->getMark(), ilDBConstants::T_TEXT) . ", " + . $this->db->quote($lp_mark->getComment(), ilDBConstants::T_TEXT) . ", " + . $this->db->quote($lp_mark->getStatus(), ilDBConstants::T_INTEGER) . ", " + . $this->db->quote($lp_mark->getStatusChanged(), ilDBConstants::T_DATETIME) . ", " + . $this->db->quote($lp_mark->getStatusDirty(), ilDBConstants::T_INTEGER) . ", " + . $this->db->quote($lp_mark->getPercentage(), ilDBConstants::T_INTEGER) . ")" + . " ON DUPLICATE KEY UPDATE completed=VALUES(completed), mark=VALUES(mark), u_comment=VALUES(u_comment), status=VALUES(status), status_changed=VALUES(status_changed), status_dirty=VALUES(status_dirty), percentage=VALUES(percentage)"; + return $this->db->manipulate($query); + } + + public function writeCollection( + LPMarkCollectionInterface $lp_mark_collection + ): void { + if (count($lp_mark_collection) === 0) { + return; + } + $tuples = []; + foreach ($lp_mark_collection as $lp_mark) { + $tuple = "(" + . $this->db->quote($lp_mark->getObjectId(), ilDBConstants::T_INTEGER) . ", " + . $this->db->quote($lp_mark->getUserId(), ilDBConstants::T_INTEGER) . ", " + . $this->db->quote((int) $lp_mark->isCompleted(), ilDBConstants::T_INTEGER) . ", " + . $this->db->quote($lp_mark->getMark(), ilDBConstants::T_TEXT) . ", " + . $this->db->quote($lp_mark->getComment(), ilDBConstants::T_TEXT) . ", " + . $this->db->quote($lp_mark->getStatus(), ilDBConstants::T_INTEGER) . ", " + . $this->db->quote($lp_mark->getStatusChanged(), ilDBConstants::T_DATETIME) . ", " + . $this->db->quote($lp_mark->getStatusDirty(), ilDBConstants::T_INTEGER) . ", " + . $this->db->quote($lp_mark->getPercentage(), ilDBConstants::T_INTEGER) . ")"; + $tuples[] = $tuple; + } + $query = "INSERT INTO ut_lp_collections (obj_id, usr_id, completed, mark, u_comment, status, status_changed, status_dirty, percentage)" + . " VALUES " . implode(", ", $tuples) + . " ON DUPLICATE KEY UPDATE completed=VALUES(completed), mark=VALUES(mark), u_comment=VALUES(u_comment), status=VALUES(status), status_changed=VALUES(status_changed), status_dirty=VALUES(status_dirty), percentage=VALUES(percentage)"; + $this->db->manipulate($query); + } + + public function readAllEntriesOfObject( + int $object_id + ): LPMarkCollectionInterface { + $query = "SELECT * FROM ut_lp_marks WHERE obj_id = " . $this->db->quote($object_id, ilDBConstants::T_INTEGER); + $res = $this->db->query($query); + $elements = []; + while ($row = $this->db->fetchAssoc($res)) { + $elements[] = $this->lpMarkFromRow($row); + } + return $this->element_factory->lpMarkCollection(...$elements); + } + + public function readAllEntriesWithStatusChangedAfter( + string $timestamp + ): LPMarkCollectionInterface { + $query = "SELECT * FROM ut_lp_marks " . + " WHERE status_changed >= " . $this->db->quote($timestamp, ilDBConstants::T_TIMESTAMP); + $res = $this->db->query($query); + $elements = []; + while ($row = $this->db->fetchAssoc($res)) { + $elements[] = $this->lpMarkFromRow($row); + } + return $this->element_factory->lpMarkCollection(...$elements); + } + + public function readAllEntriesWithStatusOfObject( + int $object_id, + int $status + ): LPMarkCollectionInterface { + $query = "SELECT * FROM ut_lp_marks " + . "WHERE obj_id = " . $this->db->quote($object_id, ilDBConstants::T_INTEGER) . " " + . "AND status = " . $this->db->quote($status, ilDBConstants::T_INTEGER); + $res = $this->db->query($query); + $elements = []; + while ($row = $this->db->fetchAssoc($res)) { + $elements[] = $this->lpMarkFromRow($row); + } + return $this->element_factory->lpMarkCollection(...$elements); + } + + public function readEntriesForUserOfObjects( + int $user_id, + int ...$object_ids + ): LPMarkCollectionInterface { + if (count($object_ids) === 0) { + return $this->element_factory->lpMarkCollection(); + } + $query = "SELECT * FROM ut_lp_marks" . + " WHERE " . $this->db->in("obj_id", $object_ids, false, ilDBConstants::T_INTEGER) . + " AND usr_id = " . $this->db->quote($user_id, ilDBConstants::T_INTEGER); + $res = $this->db->query($query); + $elements = []; + while ($row = $this->db->fetchAssoc($res)) { + $elements[] = $this->lpMarkFromRow($row); + } + return $this->element_factory->lpMarkCollection(...$elements); + } + + public function readEntryForUserOfObject( + int $object_id, + int $user_id + ): LPMarkInterface|null { + $query = "SELECT * FROM ut_lp_marks " . + "WHERE usr_id = " . $this->db->quote($user_id, ilDBConstants::T_INTEGER) . " " . + "AND obj_id = " . $this->db->quote($object_id, ilDBConstants::T_INTEGER); + $res = $this->db->query($query); + $row = $res->fetchAssoc(); + if (is_null($row)) { + return null; + } + return $this->lpMarkFromRow($row); + } + + public function readByUserIdAndStatusAndTimeInterval( + int $user_id, + int $status, + string $from, + string $to + ): LPMarkCollectionInterface { + $query = "SELECT * FROM ut_lp_marks " . + "WHERE usr_id = " . $this->db->quote($user_id, ilDBConstants::T_INTEGER) . + " AND status = " . $this->db->quote($status, ilDBConstants::T_INTEGER) . + " AND status_changed >= " . $this->db->quote($from, ilDBConstants::T_TIMESTAMP) . + " AND status_changed <= " . $this->db->quote($to, ilDBConstants::T_TIMESTAMP); + $res = $this->db->query($query); + $elements = []; + while ($row = $this->db->fetchAssoc($res)) { + $elements[] = $this->lpMarkFromRow($row); + } + return $this->element_factory->lpMarkCollection(...$elements); + } + + public function delete( + int $object_id + ): void { + $query = "DELETE FROM ut_lp_marks WHERE obj_id = " . $this->db->quote($object_id, ilDBConstants::T_INTEGER); + $this->db->manipulate($query); + } + + public function deleteByUserId( + int $object_id, + int $user_id + ): void { + $this->deleteByUserIds( + $object_id, + $user_id + ); + } + + public function deleteByUserIds( + int $object_id, + int ...$user_ids + ): void { + if (count($user_ids) === 0) { + return; + } + $query = "DELETE FROM ut_lp_marks" . + " WHERE obj_id = " . $this->db->quote($object_id, ilDBConstants::T_INTEGER) . + " AND " . $this->db->in("usr_id", $user_ids, false, ilDBConstants::T_INTEGER); + $this->db->manipulate($query); + } + + public function markAllRowsAsDirty(): void + { + $query = "UPDATE ut_lp_marks SET status_dirty = " . $this->db->quote(1, ilDBConstants::T_INTEGER); + ; + $this->db->manipulate($query); + } + + protected function lpMarkFromRow(array $row): LPMarkInterface + { + return $this->element_factory->lpMark() + ->withObjectId((int) $row['obj_id']) + ->withUserId((int) $row['usr_id']) + ->withCompletedStatus((bool) ((int) $row['completed'])) + ->withMark($row['mark']) + ->withComment($row['u_comment']) + ->withStatus((int) $row['status']) + ->withStatusChanged($row['status_changed']) + ->withStatusDirty((int) $row['status_dirty']) + ->withPercentage((int) $row['percentage']); + } +} diff --git a/components/ILIAS/Tracking/classes/DB/LPMarks/RepositoryInterface.php b/components/ILIAS/Tracking/classes/DB/LPMarks/RepositoryInterface.php new file mode 100644 index 000000000000..0c93ee77e149 --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/LPMarks/RepositoryInterface.php @@ -0,0 +1,84 @@ +obj_id; + } + + public function getUMode(): int + { + return $this->u_mode; + } + + public function getVisits(): int + { + return $this->visits; + } + + public function getObjType(): string + { + return $this->obj_type; + } + + public function withObjectId( + int $obj_id + ): LPSettingsInterface { + $clone = clone $this; + $clone->obj_id = $obj_id; + return $clone; + } + + public function withUMode( + int $u_mode + ): LPSettingsInterface { + $clone = clone $this; + $clone->u_mode = $u_mode; + return $clone; + } + + public function withVisits( + int $visits + ): LPSettingsInterface { + $clone = clone $this; + $clone->visits = $visits; + return $clone; + } + + public function withObjType( + string $obj_type + ): LPSettingsInterface { + $clone = clone $this; + $clone->obj_type = $obj_type; + return $clone; + } +} diff --git a/components/ILIAS/Tracking/classes/DB/LPSettings/Element/LPSettingsCollection.php b/components/ILIAS/Tracking/classes/DB/LPSettings/Element/LPSettingsCollection.php new file mode 100644 index 000000000000..464b8ec9f004 --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/LPSettings/Element/LPSettingsCollection.php @@ -0,0 +1,65 @@ +elements = $elements; + $this->index = 0; + } + + public function next(): void + { + $this->index++; + } + + public function valid(): bool + { + return isset($this->elements[$this->index]); + } + + public function rewind(): void + { + $this->index = 0; + } + + public function count(): int + { + return count($this->elements); + } + + public function current(): LPSettingsInterface + { + return $this->elements[$this->index]; + } + + public function key(): int + { + return $this->index; + } +} diff --git a/components/ILIAS/Tracking/classes/DB/LPSettings/Element/LPSettingsCollectionInterface.php b/components/ILIAS/Tracking/classes/DB/LPSettings/Element/LPSettingsCollectionInterface.php new file mode 100644 index 000000000000..0748f8becad1 --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/LPSettings/Element/LPSettingsCollectionInterface.php @@ -0,0 +1,31 @@ +db, + $this->element() + ); + } +} diff --git a/components/ILIAS/Tracking/classes/DB/LPSettings/FactoryInterface.php b/components/ILIAS/Tracking/classes/DB/LPSettings/FactoryInterface.php new file mode 100644 index 000000000000..af5055deecb4 --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/LPSettings/FactoryInterface.php @@ -0,0 +1,32 @@ +db->quote($object_id, ilDBConstants::T_INTEGER); + $res = $this->db->query($query); + if ($row = $res->fetchAssoc()) { + return $this->element_factory->lpSettings() + ->withObjectId($object_id) + ->withUMode((int) $row['u_mode']) + ->withVisits((int) $row['visits']) + ->withObjType($row['obj_type']); + } + return null; + } + + public function readLPSettingsCollection( + int ...$object_ids + ): LPSettingsCollectionInterface|null { + $query = "SELECT * FROM ut_lp_settings WHERE " . $this->db->in('obj_id', $object_ids, false, ilDBConstants::T_INTEGER); + $res = $this->db->query($query); + $elements = []; + while ($row = $res->fetchAssoc()) { + $elements[] = $this->element_factory->lpSettings() + ->withObjectId((int) $row['obj_id']) + ->withUMode((int) $row['u_mode']) + ->withVisits((int) $row['visits']) + ->withObjType($row['obj_type']); + } + return count($elements) === 0 + ? null + : $this->element_factory->lpSettingsCollection(...$elements); + } + + public function writeLPSettings( + LPSettingsInterface $lp_settings + ): void { + $query = "INSERT INTO ut_lp_settings (obj_id, obj_type, u_mode, visits) VALUES (" + . $this->db->quote($lp_settings->getObjectId(), ilDBConstants::T_INTEGER) . ", " + . $this->db->quote($lp_settings->getObjType(), ilDBConstants::T_TEXT) . ", " + . $this->db->quote($lp_settings->getUMode(), ilDBConstants::T_INTEGER) . ", " + . $this->db->quote($lp_settings->getVisits(), ilDBConstants::T_INTEGER) . ")" + . " ON DUPLICATE KEY UPDATE obj_type=VALUES(obj_type), u_mode=VALUES(u_mode), visits=VALUES(visits)"; + $this->db->manipulate($query); + } + + public function deleteLPSettings( + int $object_id + ): void { + $query = "DELETE FROM ut_lp_settings WHERE obj_id = " . $this->db->quote($object_id, ilDBConstants::T_INTEGER); + $this->db->manipulate($query); + } + + public function isLPSettingsEntryInDB( + int $obj_id + ): bool { + return !is_null($this->readLPSettings($obj_id)); + } +} diff --git a/components/ILIAS/Tracking/classes/DB/LPSettings/RepositoryInterface.php b/components/ILIAS/Tracking/classes/DB/LPSettings/RepositoryInterface.php new file mode 100644 index 000000000000..70a804acb0df --- /dev/null +++ b/components/ILIAS/Tracking/classes/DB/LPSettings/RepositoryInterface.php @@ -0,0 +1,47 @@ +lp_status_factory, + $this->lp_settings_element_factory, + $this->lp_collection_element_factory + ); + } +} diff --git a/components/ILIAS/Tracking/classes/Export/FactoryInterface.php b/components/ILIAS/Tracking/classes/Export/FactoryInterface.php new file mode 100644 index 000000000000..570daf4f08dd --- /dev/null +++ b/components/ILIAS/Tracking/classes/Export/FactoryInterface.php @@ -0,0 +1,30 @@ +lp_status_collection; + } + + public function getLPSettings(): LPSettingsInterface|null + { + return $this->lp_settings; + } + + public function getLPCollection(): LPCollectionInterface|null + { + return $this->lp_collection; + } + + public function withLPStatusCollection( + LPStatusCollectionInterface|null $lp_status_collection + ): InfoInterface { + $clone = clone $this; + $clone->lp_status_collection = $lp_status_collection; + return $clone; + } + + public function withLPSettings( + LPSettingsInterface|null $lp_settings + ): InfoInterface { + $clone = clone $this; + $clone->lp_settings = $lp_settings; + return $clone; + } + + public function withLPCollection( + LPCollectionInterface|null $lp_collection + ): InfoInterface { + $clone = clone $this; + $clone->lp_collection = $lp_collection; + return $clone; + } +} diff --git a/components/ILIAS/Tracking/classes/Export/InfoInterface.php b/components/ILIAS/Tracking/classes/Export/InfoInterface.php new file mode 100644 index 000000000000..89955ea13525 --- /dev/null +++ b/components/ILIAS/Tracking/classes/Export/InfoInterface.php @@ -0,0 +1,46 @@ +lp_status_factory, + $this->lp_settings_element_factory, + $this->lp_collection_element_factory + ); + } + + public function writer(): WriterInterface + { + return new Writer(); + } +} diff --git a/components/ILIAS/Tracking/classes/Export/XML/FactoryInterface.php b/components/ILIAS/Tracking/classes/Export/XML/FactoryInterface.php new file mode 100644 index 000000000000..e86411ac97d7 --- /dev/null +++ b/components/ILIAS/Tracking/classes/Export/XML/FactoryInterface.php @@ -0,0 +1,28 @@ +lp_settings_element_factory->lpSettings() + ->withObjectId((int) $xml_root->attributes()->object_id) + ->withObjType((string) $xml_root->attributes()->object_type) + ->withUMode((int) $xml_root->attributes()->u_mode) + ->withVisits((int) $xml_root->attributes()->visits); + return $target_info + ->withLPSettings($lp_settings); + } + + /** + * @throws Exception + */ + public function readLPCollection( + string $xml, + InfoInterface $target_info + ): InfoInterface { + $xml_root = new SimpleXMLElement($xml); + $xml_lp_collection = $xml_root->LPCollection; + $elements = []; + foreach ($xml_lp_collection->children() as $xml_lp_collection_element) { + $lp_collection_element = $this->lp_collection_element_factory->lpCollectionElement() + ->withNumObligatory((int) $xml_lp_collection_element->attributes()->num_obligatory) + ->withLPMode((int) $xml_lp_collection_element->attributes()->lp_mode) + ->withItemId((int) $xml_lp_collection_element->attributes()->item_id) + ->withIsActive((bool) ((int) $xml_lp_collection_element->attributes()->active)) + ->withGroupingId((int) $xml_lp_collection_element->attributes()->grouping_id); + $elements[] = $lp_collection_element; + } + $lp_collection = $this->lp_collection_element_factory->lpCollection(...$elements) + ->withObjectId((int) $xml_root->attributes()->object_id); + return $target_info + ->withLPCollection($lp_collection); + } + + /** + * @throws Exception + */ + public function readLPStatusCollection( + string $xml, + InfoInterface $target_info + ): InfoInterface { + $xml_root = new SimpleXMLElement($xml); + $xml_lp_status_collection = $xml_root->LPStatusCollection; + $lp_status_ids = []; + foreach ($xml_lp_status_collection->children() as $xml_lp_status_element) { + $lp_status_ids[] = (string) $xml_lp_status_element->attributes()->lp_status_id; + } + return $target_info + ->withLPStatusCollection($this->lp_status_factory->allLPStatusImplementations()->getElementsByStatusIds(...$lp_status_ids)); + } + + /** + * @return array + * @throws Exception + */ + public function readAdditionalContentRootsIdentifierMap( + string $xml + ): array { + $xml_root = new SimpleXMLElement($xml); + $xml_lp_status_collection = $xml_root->LPStatusCollection; + $map = []; + foreach ($xml_lp_status_collection->children() as $xml_lp_status_element) { + $lp_status_id = (string) $xml_lp_status_element->attributes()->lp_status_id; + $content = count($xml_lp_status_element->children()) > 0 ? $xml_lp_status_element->children()[0] : null; + if (is_null($content)) { + continue; + } + $map[$lp_status_id] = $content; + } + return $map; + } +} diff --git a/components/ILIAS/Tracking/classes/Export/XML/ReaderInterface.php b/components/ILIAS/Tracking/classes/Export/XML/ReaderInterface.php new file mode 100644 index 000000000000..5ae6155076ed --- /dev/null +++ b/components/ILIAS/Tracking/classes/Export/XML/ReaderInterface.php @@ -0,0 +1,45 @@ +xml_root = new SimpleXMLElement(''); + } + + public function writeXMLByExportInfo( + Info $info + ): void { + $xml_root = new SimpleXMLElement(''); + $this->addLPSettings( + $info->getLPSettings(), + $xml_root + ); + $this->addLPCollection( + $info->getLPCollection(), + $xml_root + ); + $this->addLPStatus( + $info->getLPStatusCollection(), + $info->getLPSettings(), + $xml_root + ); + $this->xml_root = $xml_root; + } + + protected function addLPSettings( + LPSettingsInterface|null $lp_settings, + SimpleXMLElement $xml_root + ): void { + if (is_null($lp_settings)) { + return; + } + $xml_root->addAttribute('object_id', (string) $lp_settings->getObjectId()); + $xml_root->addAttribute('object_type', $lp_settings->getObjType()); + $xml_root->addAttribute('u_mode', (string) $lp_settings->getUMode()); + $xml_root->addAttribute('visits', (string) $lp_settings->getVisits()); + } + + protected function addLPCollection( + LPCollectionInterface|null $lp_collection, + SimpleXMLElement $xml_root + ): void { + $lp_collections = $xml_root->addChild('LPCollection'); + if (is_null($lp_collection)) { + return; + } + foreach ($lp_collection as $info_lp_collection_element) { + $lp_collection = $lp_collections->addChild('LPCollectionElement'); + $lp_collection->addAttribute('item_id', (string) $info_lp_collection_element->getItemId()); + $lp_collection->addAttribute('grouping_id', (string) $info_lp_collection_element->getGroupingId()); + $lp_collection->addAttribute('num_obligatory', (string) $info_lp_collection_element->getNumObligatory()); + $lp_collection->addAttribute('active', (string) ((int) $info_lp_collection_element->isActive())); + $lp_collection->addAttribute('lp_mode', (string) $info_lp_collection_element->getLpMode()); + } + } + + protected function addLPStatus( + LPStatusCollectionInterface|null $lp_status_collection, + LPSettingsInterface|null $lp_settings, + SimpleXMLElement $xml_root + ): void { + $xml_root_lp_status = $xml_root->addChild('LPStatusCollection'); + if ( + is_null($lp_status_collection) || + is_null($lp_settings) + ) { + return; + } + foreach ($lp_status_collection as $lp_status) { + $this->addLPStatusData($lp_settings->getObjectId(), $xml_root_lp_status, $lp_status); + } + } + + protected function addLPStatusData( + int $object_id, + SimpleXMLElement $xml_root, + LPStatusInterface $lp_status + ): void { + $status_root = $xml_root->addChild('LPStatus'); + $status_root->addAttribute('lp_status_id', $lp_status->getLPStatusId()); + $nodes_to_add = [$lp_status->getCustomLPSettingsExportXML($object_id)]; + $ref_stack = [$status_root]; + + while (count($nodes_to_add) > 0) { + $current_node_to_add = array_pop($nodes_to_add); + $pointer_node = array_pop($ref_stack); + $xml_child_node = $pointer_node->addChild(sprintf('%s', $current_node_to_add->getName())); + foreach ($current_node_to_add->attributes() as $key => $value) { + $xml_child_node->addAttribute($key, (string) $value); + } + $child_count = count($current_node_to_add->children()); + if ($child_count === 0) { + continue; + } + $nodes_to_add = array_merge($nodes_to_add, $current_node_to_add->children()); + $ref_stack = array_merge($ref_stack, array_fill(0, $child_count, $xml_child_node)); + } + } + + public function __toString(): string + { + return trim(str_replace('', '', $this->xml_root->asXML())); + } +} diff --git a/components/ILIAS/Tracking/classes/Export/XML/WriterInterface.php b/components/ILIAS/Tracking/classes/Export/XML/WriterInterface.php new file mode 100644 index 000000000000..c8fa75d046cc --- /dev/null +++ b/components/ILIAS/Tracking/classes/Export/XML/WriterInterface.php @@ -0,0 +1,32 @@ +tracking_factory = new TrackingFactory(); + } + + public function getXmlRepresentation( + string $a_entity, + string $a_schema_version, + string $a_id + ): string { + $db_factory = $this->tracking_factory->db(); + $export_factory = $this->tracking_factory->export(); + $lp_status_factory = $this->tracking_factory->status(); + $lp_settings = $db_factory->lpSettings()->repository()->readLPSettings((int) $a_id); + $lp_collection = $db_factory->lpCollection()->repository()->readLPCollection((int) $a_id); + $lp_status_collection = is_null($lp_settings) ? null : $lp_status_factory->allLPStatusImplementations()->getElementsByStatusIds(((string) $lp_settings->getUMode())); + $info = $export_factory->info() + ->withLPSettings($lp_settings) + ->withLPCollection($lp_collection) + ->withLPStatusCollection($lp_status_collection); + $writer = $export_factory->xml()->writer(); + $writer->writeXMLByExportInfo($info); + return $writer->__toString(); + } + + public function getValidSchemaVersions( + string $a_entity + ): array { + return [ + "12.0" => [ + "namespace" => 'http://www.ilias.de/Components/Tracking/trac/12', + "xsd_file" => 'ilias_trac_12_0.xsd', + "uses_dataset" => false, + "min" => "12.0", + "max" => "" + ] + ]; + } +} diff --git a/components/ILIAS/Tracking/classes/Export/class.ilTrackingImporter.php b/components/ILIAS/Tracking/classes/Export/class.ilTrackingImporter.php new file mode 100644 index 000000000000..a3b2e0d1cb2f --- /dev/null +++ b/components/ILIAS/Tracking/classes/Export/class.ilTrackingImporter.php @@ -0,0 +1,120 @@ +tracking_factory = new TrackingFactory(); + } + + /** + * @throws TrackingExportException + */ + public function importXmlRepresentation( + string $a_entity, + string $a_id, + string $a_xml, + ilImportMapping $a_mapping + ): void { + if (strcmp($a_entity, "lpsettings") === 0) { + $this->importLPSettings($a_id, $a_xml, $a_mapping); + } + } + + /** + * @throws TrackingExportException + */ + protected function importLPSettings( + string $a_id, + string $a_xml, + ilImportMapping $a_mapping + ): void { + try { + $new_id = $this->getNewId($a_id, $a_mapping); + } catch (TrackingExportException $e) { + return; + } + $export_factory = $this->tracking_factory->export(); + $db_factory = $this->tracking_factory->db(); + $reader = $export_factory->xml()->reader(); + $info = $export_factory->info(); + $info = $reader->readLPSettings($a_xml, $info); + $info = $reader->readLPCollection($a_xml, $info); + $info = $reader->readLPStatusCollection($a_xml, $info); + $info = $this->applyMappings($new_id, $a_mapping, $info); + $db_factory->lpSettings()->repository()->writeLPSettings($info->getLPSettings()); + $db_factory->lpCollection()->repository()->writeLPCollection($info->getLPCollection()); + foreach ($reader->readAdditionalContentRootsIdentifierMap($a_xml) as $lp_status_id => $xml_root) { + $info->getLPStatusCollection()->getElementByStatusId((string) $lp_status_id) + ->importCustomLPSettingsExportXML( + $new_id, + $a_mapping, + $xml_root + ); + } + } + + /** + * @throws TrackingExportException + */ + protected function getNewId( + string $id, + ilImportMapping $a_mapping + ): int { + $new_id = $a_mapping->getMapping("components/ILIAS/Tracking", "obj", $id); + if (is_null($new_id)) { + throw new TrackingExportException(sprintf("Object id (%s) during tracking import not found in mapping", $id)); + } + return (int) $new_id; + } + + protected function applyMappings( + int $new_id, + ilImportMapping $mapping, + InfoInterface $info + ): InfoInterface { + $lp_collection = $info->getLPCollection(); + $elements = []; + foreach ($lp_collection as $collection) { + $new_item_id = $mapping->getMapping("components/ILIAS/Container", "refs", (string) $collection->getItemId()); + if (is_null($new_item_id)) { + # Element is not exported, the element is ignored. + continue; + } + $new_item_id = (int) $new_item_id; + $elements[] = $collection + ->withItemId($new_item_id); + } + $new_lp_collection = $this->tracking_factory->db()->lpCollection()->element()->lpCollection(...$elements) + ->withObjectId($new_id) + ->withFixedNumObligatory(); + return $info + ->withLPSettings($info->getLPSettings()->withObjectId($new_id)) + ->withLPCollection($new_lp_collection); + } +} diff --git a/components/ILIAS/Tracking/classes/Factory.php b/components/ILIAS/Tracking/classes/Factory.php new file mode 100644 index 000000000000..1826f501dc8a --- /dev/null +++ b/components/ILIAS/Tracking/classes/Factory.php @@ -0,0 +1,73 @@ +DIC = $DIC; + $this->db = $DIC->database(); + } + + public function db(): DBFactoryInterface + { + return new DBFactory( + $this->db + ); + } + + public function export(): ExportFactoryInterface + { + return new ExportFactory( + $this->status(), + $this->db()->lpSettings()->element(), + $this->db()->lpCollection()->element() + ); + } + + public function view(): ViewFactoryInterface + { + return new ViewFactory(); + } + + public function status(): StatusFactoryInterface + { + return new StatusFactory( + $this->DIC + ); + } +} diff --git a/components/ILIAS/Tracking/classes/FactoryInterface.php b/components/ILIAS/Tracking/classes/FactoryInterface.php new file mode 100644 index 000000000000..b95a877ec25e --- /dev/null +++ b/components/ILIAS/Tracking/classes/FactoryInterface.php @@ -0,0 +1,37 @@ +getMatchingClassNames(LPStatusInterface::class)); + return new ilSetupArrayArtifact($infos); + } +} diff --git a/components/ILIAS/Tracking/classes/Setup/class.ilTrackingSetupAgent.php b/components/ILIAS/Tracking/classes/Setup/class.ilTrackingSetupAgent.php index 7e47bb21c210..cb822406cdeb 100644 --- a/components/ILIAS/Tracking/classes/Setup/class.ilTrackingSetupAgent.php +++ b/components/ILIAS/Tracking/classes/Setup/class.ilTrackingSetupAgent.php @@ -19,7 +19,6 @@ declare(strict_types=1); use ILIAS\Setup; -use ILIAS\Setup\Config; class ilTrackingSetupAgent extends Setup\Agent\NullAgent { diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/DataRetrieval.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/DataRetrieval.php index fe910095362a..2054cc63ca5a 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/DataRetrieval.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/DataRetrieval.php @@ -21,13 +21,9 @@ namespace ILIAS\Tracking\View\DataRetrieval; use ilDateTime; -use ilDBConstants; use ilDBInterface; -use ILIAS\Tracking\View\DataRetrieval\DataRetrievalInterface; -use ILIAS\Tracking\View\DataRetrieval\Info\ViewInterface; -use ILIAS\Tracking\View\DataRetrieval\FilterInterface; use ILIAS\Tracking\View\DataRetrieval\Info\FactoryInterface as InfoFactoryInterface; -use ilLPMarks; +use ILIAS\Tracking\View\DataRetrieval\Info\ViewInterface; use ilLPObjSettings; use ilObject; use ilObjectLP; diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/DataRetrievalInterface.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/DataRetrievalInterface.php index 416d58550664..6b965abd4185 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/DataRetrievalInterface.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/DataRetrievalInterface.php @@ -20,7 +20,6 @@ namespace ILIAS\Tracking\View\DataRetrieval; -use ILIAS\Tracking\View\DataRetrieval\FilterInterface; use ILIAS\Tracking\View\DataRetrieval\Info\ViewInterface; interface DataRetrievalInterface diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Factory.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Factory.php index 61438a1f9a99..63539bcf025e 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Factory.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Factory.php @@ -22,12 +22,10 @@ use ilDBInterface; use ILIAS\Tracking\View\DataRetrieval\DataRetrievalInterface as DRInterface; -use ILIAS\Tracking\View\DataRetrieval\DataRetrieval; use ILIAS\Tracking\View\DataRetrieval\FactoryInterface as DRFactoryInterface; use ILIAS\Tracking\View\DataRetrieval\FilterInterface as DRFilterInterface; -use ILIAS\Tracking\View\DataRetrieval\Filter; -use ILIAS\Tracking\View\DataRetrieval\Info\FactoryInterface as InfoFactoryInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Factory as InfoFactory; +use ILIAS\Tracking\View\DataRetrieval\Info\FactoryInterface as InfoFactoryInterface; class Factory implements DRFactoryInterface { diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Filter.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Filter.php index d3fa02e6010a..d153e186d2d9 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Filter.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Filter.php @@ -20,8 +20,6 @@ namespace ILIAS\Tracking\View\DataRetrieval; -use ILIAS\Tracking\View\DataRetrieval\FilterInterface; - class Filter implements FilterInterface { /** diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Combined.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Combined.php index 53aa2369d13f..d995c4d027f4 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Combined.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Combined.php @@ -20,8 +20,6 @@ namespace ILIAS\Tracking\View\DataRetrieval\Info; -use ILIAS\Tracking\View\DataRetrieval\Info\CombinedInterface; - class Combined implements CombinedInterface { public function __construct( diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/CombinedInterface.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/CombinedInterface.php index 9c24bb9b8269..fa1746bb4ab9 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/CombinedInterface.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/CombinedInterface.php @@ -20,9 +20,6 @@ namespace ILIAS\Tracking\View\DataRetrieval\Info; -use ILIAS\Tracking\View\DataRetrieval\Info\LPInterface; -use ILIAS\Tracking\View\DataRetrieval\Info\ObjectDataInterface; - interface CombinedInterface { public function getLPInfo(): LPInterface; diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Factory.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Factory.php index 5961617727ff..309feaa21e44 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Factory.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Factory.php @@ -21,20 +21,20 @@ namespace ILIAS\Tracking\View\DataRetrieval\Info; use ilDateTime; -use ILIAS\Tracking\View\DataRetrieval\Info\CombinedInterface as CombinedInfoInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Combined as CombinedInfo; +use ILIAS\Tracking\View\DataRetrieval\Info\CombinedInterface as CombinedInfoInterface; use ILIAS\Tracking\View\DataRetrieval\Info\FactoryInterface as InfoFactoryInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\CombinedInterface as CombinedIteratorInterface; -use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\FactoryInterface as IteratorFactoryInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\Factory as IteratorFactory; +use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\FactoryInterface as IteratorFactoryInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\LPInterface as LPIteratorInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\ObjectDataInterface as ObjectDataIteratorInterface; -use ILIAS\Tracking\View\DataRetrieval\Info\LPInterface as LPinfoInterface; use ILIAS\Tracking\View\DataRetrieval\Info\LP as LPinfo; -use ILIAS\Tracking\View\DataRetrieval\Info\ObjectDataInterface as ObjectDataInfoInterface; +use ILIAS\Tracking\View\DataRetrieval\Info\LPInterface as LPinfoInterface; use ILIAS\Tracking\View\DataRetrieval\Info\ObjectData as ObjectDataInfo; -use ILIAS\Tracking\View\DataRetrieval\Info\ViewInterface as ViewInfoInterface; +use ILIAS\Tracking\View\DataRetrieval\Info\ObjectDataInterface as ObjectDataInfoInterface; use ILIAS\Tracking\View\DataRetrieval\Info\View as ViewInfo; +use ILIAS\Tracking\View\DataRetrieval\Info\ViewInterface as ViewInfoInterface; class Factory implements InfoFactoryInterface { diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/FactoryInterface.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/FactoryInterface.php index e88265d19027..5c395aacb14a 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/FactoryInterface.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/FactoryInterface.php @@ -21,13 +21,13 @@ namespace ILIAS\Tracking\View\DataRetrieval\Info; use ilDateTime; +use ILIAS\Tracking\View\DataRetrieval\Info\CombinedInterface as CombinedInfoInterface; +use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\CombinedInterface as CombinedIteratorInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\FactoryInterface as IteratorFactoryInterface; -use ILIAS\Tracking\View\DataRetrieval\Info\LPInterface as LPInfoInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\LPInterface as LPIteratorInterface; -use ILIAS\Tracking\View\DataRetrieval\Info\ObjectDataInterface as ObjectDataInfoInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\ObjectDataInterface as ObjectDataIteratorInterface; -use ILIAS\Tracking\View\DataRetrieval\Info\CombinedInterface as CombinedInfoInterface; -use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\CombinedInterface as CombinedIteratorInterface; +use ILIAS\Tracking\View\DataRetrieval\Info\LPInterface as LPInfoInterface; +use ILIAS\Tracking\View\DataRetrieval\Info\ObjectDataInterface as ObjectDataInfoInterface; use ILIAS\Tracking\View\DataRetrieval\Info\ViewInterface as ViewInfoInterface; interface FactoryInterface diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/Combined.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/Combined.php index 7980d719424f..d5c77bc482c9 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/Combined.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/Combined.php @@ -21,7 +21,6 @@ namespace ILIAS\Tracking\View\DataRetrieval\Info\Iterator; use ILIAS\Tracking\View\DataRetrieval\Info\CombinedInterface as CombinedInfoInterface; -use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\CombinedInterface; class Combined implements CombinedInterface { diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/CombinedInterface.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/CombinedInterface.php index db49f75e4989..01cd9d1f5c3f 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/CombinedInterface.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/CombinedInterface.php @@ -20,8 +20,8 @@ namespace ILIAS\Tracking\View\DataRetrieval\Info\Iterator; -use Iterator; use ILIAS\Tracking\View\DataRetrieval\Info\CombinedInterface as CombinedInfoInterface; +use Iterator; interface CombinedInterface extends Iterator { diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/Factory.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/Factory.php index 3666c7b249db..626db47bc8c8 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/Factory.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/Factory.php @@ -21,13 +21,13 @@ namespace ILIAS\Tracking\View\DataRetrieval\Info\Iterator; use ILIAS\Tracking\View\DataRetrieval\Info\CombinedInterface as CombinedInfoInterface; -use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\CombinedInterface as CombinedIteratorInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\Combined as CombinedIterator; +use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\CombinedInterface as CombinedIteratorInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\FactoryInterface as IteratorFactoryInterface; -use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\LPInterface as LPIteratorInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\LP as LPIterator; -use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\ObjectDataInterface as ObjectDataIteratorInterface; +use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\LPInterface as LPIteratorInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\ObjectData as ObjectDataIterator; +use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\ObjectDataInterface as ObjectDataIteratorInterface; use ILIAS\Tracking\View\DataRetrieval\Info\LPInterface as LPInfoInterface; use ILIAS\Tracking\View\DataRetrieval\Info\ObjectDataInterface as ObjectDataInfoInterface; diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/FactoryInterface.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/FactoryInterface.php index f4a328910489..3f970c6c4456 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/FactoryInterface.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/FactoryInterface.php @@ -20,12 +20,12 @@ namespace ILIAS\Tracking\View\DataRetrieval\Info\Iterator; +use ILIAS\Tracking\View\DataRetrieval\Info\CombinedInterface as CombinedInfoInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\CombinedInterface as CombinedIteratorInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\LPInterface as LPIteratorInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\ObjectDataInterface as ObjectDataIteratorInterface; -use ILIAS\Tracking\View\DataRetrieval\Info\ObjectDataInterface as ObjectDataInfoInterface; use ILIAS\Tracking\View\DataRetrieval\Info\LPInterface as LPInfoInterface; -use ILIAS\Tracking\View\DataRetrieval\Info\CombinedInterface as CombinedInfoInterface; +use ILIAS\Tracking\View\DataRetrieval\Info\ObjectDataInterface as ObjectDataInfoInterface; interface FactoryInterface { diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/LP.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/LP.php index 77f7ef207909..38f23f07d7c7 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/LP.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/LP.php @@ -20,7 +20,6 @@ namespace ILIAS\Tracking\View\DataRetrieval\Info\Iterator; -use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\LPInterface; use ILIAS\Tracking\View\DataRetrieval\Info\LPInterface as LPInfoInterface; class LP implements LPInterface diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/LPInterface.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/LPInterface.php index 2448fb1deaa0..e4ad23162387 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/LPInterface.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/LPInterface.php @@ -20,8 +20,8 @@ namespace ILIAS\Tracking\View\DataRetrieval\Info\Iterator; -use Iterator; use ILIAS\Tracking\View\DataRetrieval\Info\LPInterface as LPInfoInterface; +use Iterator; interface LPInterface extends Iterator { diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/ObjectData.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/ObjectData.php index 2d63d873a1ff..6710c0eda441 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/ObjectData.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/Iterator/ObjectData.php @@ -20,7 +20,6 @@ namespace ILIAS\Tracking\View\DataRetrieval\Info\Iterator; -use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\ObjectDataInterface; use ILIAS\Tracking\View\DataRetrieval\Info\ObjectDataInterface as ObjectDataInfoInterface; class ObjectData implements ObjectDataInterface diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/LP.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/LP.php index 4b0fd5492cdf..b339726cd45c 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/LP.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/LP.php @@ -21,7 +21,6 @@ namespace ILIAS\Tracking\View\DataRetrieval\Info; use ilDateTime; -use ILIAS\Tracking\View\DataRetrieval\Info\LPInterface; class LP implements LPInterface { diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/ObjectData.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/ObjectData.php index 1d7415a6be80..594af4a6dd77 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/ObjectData.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/ObjectData.php @@ -20,8 +20,6 @@ namespace ILIAS\Tracking\View\DataRetrieval\Info; -use ILIAS\Tracking\View\DataRetrieval\Info\ObjectDataInterface; - class ObjectData implements ObjectDataInterface { public function __construct( diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/View.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/View.php index aa155e7e04f5..478b6f221dce 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/View.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/View.php @@ -23,7 +23,6 @@ use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\CombinedInterface as CombinedIteratorInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\LPInterface as LPIteratorInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\ObjectDataInterface as ObjectDataIteratorInterface; -use ILIAS\Tracking\View\DataRetrieval\Info\ViewInterface; class View implements ViewInterface { diff --git a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/ViewInterface.php b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/ViewInterface.php index d248e5a86ff8..00fca85f29be 100644 --- a/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/ViewInterface.php +++ b/components/ILIAS/Tracking/classes/View/DataRetrieval/Info/ViewInterface.php @@ -20,9 +20,9 @@ namespace ILIAS\Tracking\View\DataRetrieval\Info; -use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\ObjectDataInterface as ObjectDataIteratorInterface; -use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\LPInterface as LPIteratorInterface; use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\CombinedInterface as CombinedIteratorInterface; +use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\LPInterface as LPIteratorInterface; +use ILIAS\Tracking\View\DataRetrieval\Info\Iterator\ObjectDataInterface as ObjectDataIteratorInterface; interface ViewInterface { diff --git a/components/ILIAS/Tracking/classes/View/Factory.php b/components/ILIAS/Tracking/classes/View/Factory.php index 14ab70864744..9a3cb5004dbc 100644 --- a/components/ILIAS/Tracking/classes/View/Factory.php +++ b/components/ILIAS/Tracking/classes/View/Factory.php @@ -25,12 +25,11 @@ use ILIAS\Tracking\View\DataRetrieval\Factory as DataRetrievalFactory; use ILIAS\Tracking\View\DataRetrieval\FactoryInterface as DataRetrievalFactoryInterface; use ILIAS\Tracking\View\FactoryInterface as ViewFactoryInterface; -use ILIAS\Tracking\View\PropertyList\FactoryInterface as PropertyListFactoryInterface; +use ILIAS\Tracking\View\ProgressBlock\Factory as ProgressBlockFactory; use ILIAS\Tracking\View\PropertyList\Factory as PropertyListFactory; -use ILIAS\Tracking\View\Renderer\FactoryInterface as RendererFactoryInterface; +use ILIAS\Tracking\View\PropertyList\FactoryInterface as PropertyListFactoryInterface; use ILIAS\Tracking\View\Renderer\Factory as RendererFactory; -use ILIAS\Tracking\View\ProgressBlock\FactoryInterface as ProgressBlockFactoryInterface; -use ILIAS\Tracking\View\ProgressBlock\Factory as ProgressBlockFactory; +use ILIAS\Tracking\View\Renderer\FactoryInterface as RendererFactoryInterface; class Factory implements ViewFactoryInterface { diff --git a/components/ILIAS/Tracking/classes/View/FactoryInterface.php b/components/ILIAS/Tracking/classes/View/FactoryInterface.php index 2ba3382f1010..95666c37c316 100644 --- a/components/ILIAS/Tracking/classes/View/FactoryInterface.php +++ b/components/ILIAS/Tracking/classes/View/FactoryInterface.php @@ -20,10 +20,10 @@ namespace ILIAS\Tracking\View; -use ILIAS\Tracking\View\Renderer\FactoryInterface as RendererFactoryInterface; use ILIAS\Tracking\View\DataRetrieval\FactoryInterface as DataRetrievalFactoryInterface; -use ILIAS\Tracking\View\PropertyList\FactoryInterface as PropertyListFactoryInterface; use ILIAS\Tracking\View\ProgressBlock\FactoryInterface as ProgressBlockFactoryInterface; +use ILIAS\Tracking\View\PropertyList\FactoryInterface as PropertyListFactoryInterface; +use ILIAS\Tracking\View\Renderer\FactoryInterface as RendererFactoryInterface; interface FactoryInterface { diff --git a/components/ILIAS/Tracking/classes/View/PersonalLearningProgress/class.ilLPPersonalGUI.php b/components/ILIAS/Tracking/classes/View/PersonalLearningProgress/class.ilLPPersonalGUI.php index ccc2de8cbcab..13efe9f0b06c 100644 --- a/components/ILIAS/Tracking/classes/View/PersonalLearningProgress/class.ilLPPersonalGUI.php +++ b/components/ILIAS/Tracking/classes/View/PersonalLearningProgress/class.ilLPPersonalGUI.php @@ -18,18 +18,16 @@ declare(strict_types=0); +use ILIAS\Data\Factory as DataFactory; +use ILIAS\Data\URI as URI; use ILIAS\DI\UIServices; -use ILIAS\Refinery\Factory as RefineryFactory; -use ILIAS\Tracking\View\FactoryInterface as ViewFactoryInterface; -use ILIAS\UI\Component\Symbol\Icon\Icon as UIIconIcon; -use ILIAS\UI\Component\Symbol\Icon\Standard as UIStandardIcon; use ILIAS\HTTP\Services as HTTPServices; +use ILIAS\Refinery\Factory as RefineryFactory; +use ILIAS\StaticURL\Services as StaticURL; use ILIAS\Tracking\View\Factory as ViewFactory; -use ILIAS\UI\URLBuilder; -use ILIAS\Data\Factory as DataFactory; +use ILIAS\Tracking\View\FactoryInterface as ViewFactoryInterface; use ILIAS\UI\Component\Item\Standard as UIStandardItem; -use ILIAS\StaticURL\Services as StaticURL; -use ILIAS\Data\URI as URI; +use ILIAS\UI\URLBuilder; /** * @ilCtrl_IsCalledBy ilLPPersonalGUI: ilDashboardGUI diff --git a/components/ILIAS/Tracking/classes/View/ProgressBlock/Factory.php b/components/ILIAS/Tracking/classes/View/ProgressBlock/Factory.php index 7efa76db5126..c83b396bce3a 100644 --- a/components/ILIAS/Tracking/classes/View/ProgressBlock/Factory.php +++ b/components/ILIAS/Tracking/classes/View/ProgressBlock/Factory.php @@ -21,8 +21,8 @@ namespace ILIAS\Tracking\View\ProgressBlock; use ilDBInterface; -use ILIAS\Tracking\View\ProgressBlock\Settings\FactoryInterface as SettingsFactoryInterface; use ILIAS\Tracking\View\ProgressBlock\Settings\Factory as SettingsFactory; +use ILIAS\Tracking\View\ProgressBlock\Settings\FactoryInterface as SettingsFactoryInterface; class Factory implements FactoryInterface { diff --git a/components/ILIAS/Tracking/classes/View/ProgressBlock/Settings/Repository.php b/components/ILIAS/Tracking/classes/View/ProgressBlock/Settings/Repository.php index bd13514275b2..0baabba8d294 100644 --- a/components/ILIAS/Tracking/classes/View/ProgressBlock/Settings/Repository.php +++ b/components/ILIAS/Tracking/classes/View/ProgressBlock/Settings/Repository.php @@ -20,8 +20,8 @@ namespace ILIAS\Tracking\View\ProgressBlock\Settings; -use ilDBInterface; use ilDBConstants; +use ilDBInterface; class Repository implements RepositoryInterface { diff --git a/components/ILIAS/Tracking/classes/View/PropertyList/Builder.php b/components/ILIAS/Tracking/classes/View/PropertyList/Builder.php index 2355a4a9b367..956ef1052c84 100644 --- a/components/ILIAS/Tracking/classes/View/PropertyList/Builder.php +++ b/components/ILIAS/Tracking/classes/View/PropertyList/Builder.php @@ -20,10 +20,6 @@ namespace ILIAS\Tracking\View\PropertyList; -use ILIAS\Tracking\View\PropertyList\BuilderInterface; -use ILIAS\Tracking\View\PropertyList\PropertyListInterface; -use ILIAS\Tracking\View\PropertyList\PropertyList; - class Builder implements BuilderInterface { protected array $properties; diff --git a/components/ILIAS/Tracking/classes/View/PropertyList/BuilderInterface.php b/components/ILIAS/Tracking/classes/View/PropertyList/BuilderInterface.php index 19cdf0cb9315..79c79b6e5399 100644 --- a/components/ILIAS/Tracking/classes/View/PropertyList/BuilderInterface.php +++ b/components/ILIAS/Tracking/classes/View/PropertyList/BuilderInterface.php @@ -20,8 +20,6 @@ namespace ILIAS\Tracking\View\PropertyList; -use ILIAS\Tracking\View\PropertyList\PropertyListInterface; - interface BuilderInterface { public function withProperty(string $key, string $value): self; diff --git a/components/ILIAS/Tracking/classes/View/PropertyList/Factory.php b/components/ILIAS/Tracking/classes/View/PropertyList/Factory.php index 99ac0d80f58d..6cdd34d330a0 100644 --- a/components/ILIAS/Tracking/classes/View/PropertyList/Factory.php +++ b/components/ILIAS/Tracking/classes/View/PropertyList/Factory.php @@ -20,10 +20,6 @@ namespace ILIAS\Tracking\View\PropertyList; -use ILIAS\Tracking\View\PropertyList\FactoryInterface; -use ILIAS\Tracking\View\PropertyList\BuilderInterface; -use ILIAS\Tracking\View\PropertyList\Builder; - class Factory implements FactoryInterface { public function builder(): BuilderInterface diff --git a/components/ILIAS/Tracking/classes/View/PropertyList/FactoryInterface.php b/components/ILIAS/Tracking/classes/View/PropertyList/FactoryInterface.php index cafdda3d95b2..7bd6ddd55169 100644 --- a/components/ILIAS/Tracking/classes/View/PropertyList/FactoryInterface.php +++ b/components/ILIAS/Tracking/classes/View/PropertyList/FactoryInterface.php @@ -20,8 +20,6 @@ namespace ILIAS\Tracking\View\PropertyList; -use ILIAS\Tracking\View\PropertyList\BuilderInterface; - interface FactoryInterface { public function builder(): BuilderInterface; diff --git a/components/ILIAS/Tracking/classes/View/PropertyList/PropertyList.php b/components/ILIAS/Tracking/classes/View/PropertyList/PropertyList.php index df3bfe607e53..bd3ebb411d93 100644 --- a/components/ILIAS/Tracking/classes/View/PropertyList/PropertyList.php +++ b/components/ILIAS/Tracking/classes/View/PropertyList/PropertyList.php @@ -20,8 +20,6 @@ namespace ILIAS\Tracking\View\PropertyList; -use ILIAS\Tracking\View\PropertyList\PropertyListInterface; - class PropertyList implements PropertyListInterface { protected int $index; diff --git a/components/ILIAS/Tracking/classes/View/Renderer/Factory.php b/components/ILIAS/Tracking/classes/View/Renderer/Factory.php index fb9b07ffcfca..28dfe239acb8 100644 --- a/components/ILIAS/Tracking/classes/View/Renderer/Factory.php +++ b/components/ILIAS/Tracking/classes/View/Renderer/Factory.php @@ -20,10 +20,8 @@ namespace ILIAS\Tracking\View\Renderer; -use ILIAS\Tracking\View\Renderer\FactoryInterface as RendererFactoryInterface; -use ILIAS\Tracking\View\Renderer\RendererInterface; -use ILIAS\Tracking\View\Renderer\Renderer; use ILIAS\DI\UIServices; +use ILIAS\Tracking\View\Renderer\FactoryInterface as RendererFactoryInterface; class Factory implements RendererFactoryInterface { diff --git a/components/ILIAS/Tracking/classes/View/Renderer/FactoryInterface.php b/components/ILIAS/Tracking/classes/View/Renderer/FactoryInterface.php index 7b49ad75f05d..ee59d49ee375 100644 --- a/components/ILIAS/Tracking/classes/View/Renderer/FactoryInterface.php +++ b/components/ILIAS/Tracking/classes/View/Renderer/FactoryInterface.php @@ -20,8 +20,6 @@ namespace ILIAS\Tracking\View\Renderer; -use ILIAS\Tracking\View\Renderer\RendererInterface; - interface FactoryInterface { public function service(): RendererInterface; diff --git a/components/ILIAS/Tracking/classes/View/Renderer/Renderer.php b/components/ILIAS/Tracking/classes/View/Renderer/Renderer.php index 23654b4e0e42..e40876ef33f2 100644 --- a/components/ILIAS/Tracking/classes/View/Renderer/Renderer.php +++ b/components/ILIAS/Tracking/classes/View/Renderer/Renderer.php @@ -20,18 +20,15 @@ namespace ILIAS\Tracking\View\Renderer; +use ILIAS\Data\URI; +use ILIAS\DI\UIServices; use ILIAS\Tracking\View\DataRetrieval\Info\LPInterface; use ILIAS\Tracking\View\DataRetrieval\Info\ObjectDataInterface; use ILIAS\Tracking\View\PropertyList\PropertyListInterface; -use ILIAS\Tracking\View\Renderer\RendererInterface; use ILIAS\UI\Component\Chart\ProgressMeter\Standard as UIStandardProgressMeter; use ILIAS\UI\Component\Item\Standard as UIStandardItem; -use ILIAS\DI\UIServices; use ILIAS\UI\Component\Symbol\Icon\Icon as UIIconIcon; -use ILIAS\UI\Component\Symbol\Icon\Standard as UIStandardIcon; -use ilLPObjSettings; use ilLPStatus; -use ILIAS\Data\URI; class Renderer implements RendererInterface { diff --git a/components/ILIAS/Tracking/classes/View/Renderer/RendererInterface.php b/components/ILIAS/Tracking/classes/View/Renderer/RendererInterface.php index a41488754dbd..cf8c1eb7597e 100644 --- a/components/ILIAS/Tracking/classes/View/Renderer/RendererInterface.php +++ b/components/ILIAS/Tracking/classes/View/Renderer/RendererInterface.php @@ -20,12 +20,12 @@ namespace ILIAS\Tracking\View\Renderer; +use ILIAS\Data\URI; use ILIAS\Tracking\View\DataRetrieval\Info\LPInterface; use ILIAS\Tracking\View\DataRetrieval\Info\ObjectDataInterface; use ILIAS\Tracking\View\PropertyList\PropertyListInterface; -use ILIAS\UI\Component\Item\Standard as UIStandardItem; use ILIAS\UI\Component\Chart\ProgressMeter\Standard as UIStandardProgressMeter; -use ILIAS\Data\URI; +use ILIAS\UI\Component\Item\Standard as UIStandardItem; interface RendererInterface { diff --git a/components/ILIAS/Tracking/classes/class.ilLPCronObjectStatistics.php b/components/ILIAS/Tracking/classes/class.ilLPCronObjectStatistics.php index 1d0bd29135a4..f17d48eb48ac 100755 --- a/components/ILIAS/Tracking/classes/class.ilLPCronObjectStatistics.php +++ b/components/ILIAS/Tracking/classes/class.ilLPCronObjectStatistics.php @@ -18,10 +18,10 @@ * *********************************************************************/ -use ILIAS\Cron\Job\Schedule\JobScheduleType; +use ILIAS\Cron\CronJob; use ILIAS\Cron\Job\JobManager; use ILIAS\Cron\Job\JobResult; -use ILIAS\Cron\CronJob; +use ILIAS\Cron\Job\Schedule\JobScheduleType; /** * Cron for lp object statistics diff --git a/components/ILIAS/Tracking/classes/class.ilLPMarks.php b/components/ILIAS/Tracking/classes/class.ilLPMarks.php index 39a6afbdf5e1..508b9eb4ad53 100755 --- a/components/ILIAS/Tracking/classes/class.ilLPMarks.php +++ b/components/ILIAS/Tracking/classes/class.ilLPMarks.php @@ -16,6 +16,12 @@ * *********************************************************************/ +declare(strict_types=1); + +use ILIAS\Tracking\DB\LPMarks\Element\LPMarkInterface; +use ILIAS\Tracking\Factory as TrackingFactory; +use ILIAS\Tracking\FactoryInterface as TrackingFactoryInterface; + /** * Class ilLPMarks * @author Stefan Meyer @@ -24,8 +30,8 @@ */ class ilLPMarks { - protected ?ilDBInterface $db; - protected ilObjectDataCache $ilObjectDataCache; + protected TrackingFactoryInterface $tracking_factory; + protected LPMarkInterface $lp_mark; protected int $obj_id; protected int $usr_id; @@ -36,41 +42,38 @@ class ilLPMarks protected string $mark = ''; protected string $status_changed = ''; - protected $has_entry = false; - - public function __construct(int $a_obj_id, int $a_usr_id) - { + public function __construct( + int $a_obj_id, + int $a_usr_id + ) { global $DIC; + $this->tracking_factory = new TrackingFactory(); + $this->lp_mark = $this->tracking_factory->db()->lpMarks()->element()->lpMark() + ->withObjectId($a_obj_id) + ->withUserId($a_usr_id); - $this->ilObjectDataCache = $DIC['ilObjDataCache']; - $this->db = $DIC->database(); - - $this->obj_id = $a_obj_id; - $this->usr_id = $a_usr_id; - $this->obj_type = $this->ilObjectDataCache->lookupType($this->obj_id); + $ilObjectDataCache = $DIC['ilObjDataCache']; + $this->obj_type = $ilObjectDataCache->lookupType($this->lp_mark->getObjectId()); $this->__read(); } - public static function deleteObject(int $a_obj_id): void - { - global $DIC; - - $ilDB = $DIC['ilDB']; - - $query = "DELETE FROM ut_lp_marks " . - "WHERE obj_id = " . $ilDB->quote($a_obj_id, 'integer'); - $res = $ilDB->manipulate($query); + public static function deleteObject( + int $a_obj_id + ): void { + (new TrackingFactory())->db()->lpMarks()->repository()->delete($a_obj_id); } public function getUserId(): int { - return $this->usr_id; + return $this->lp_mark->getUserId(); } - public function setMark(string $a_mark): void - { - $this->mark = $a_mark; + public function setMark( + string $a_mark + ): void { + $this->lp_mark = $this->lp_mark + ->withMark($a_mark); } public function getMark(): string @@ -78,9 +81,11 @@ public function getMark(): string return $this->mark; } - public function setComment(string $a_comment): void - { - $this->comment = $a_comment; + public function setComment( + string $a_comment + ): void { + $this->lp_mark = $this->lp_mark + ->withComment($a_comment); } public function getComment(): string @@ -88,14 +93,16 @@ public function getComment(): string return $this->comment; } - public function setCompleted(bool $a_status): void - { - $this->completed = $a_status; + public function setCompleted( + bool $a_status + ): void { + $this->lp_mark = $this->lp_mark + ->withCompletedStatus($a_status); } public function getCompleted(): bool { - return $this->completed; + return $this->lp_mark->isCompleted(); } public function getStatusChanged(): string @@ -110,43 +117,17 @@ public function getObjId(): int public function update(): void { - if (!$this->has_entry) { - $this->__add(); - } - $query = "UPDATE ut_lp_marks " . - "SET mark = " . $this->db->quote($this->getMark(), 'text') . ", " . - "u_comment = " . $this->db->quote( - $this->getComment(), - 'text' - ) . ", " . - "completed = " . $this->db->quote( - $this->getCompleted(), - 'integer' - ) . " " . - "WHERE obj_id = " . $this->db->quote( - $this->getObjId(), - 'integer' - ) . " " . - "AND usr_id = " . $this->db->quote($this->getUserId(), 'integer'); - $res = $this->db->manipulate($query); + $this->tracking_factory->db()->lpMarks()->repository()->write($this->lp_mark); } - // Static - public static function _hasCompleted(int $a_usr_id, int $a_obj_id): bool - { - global $DIC; - - $ilDB = $DIC['ilDB']; - - $query = "SELECT * FROM ut_lp_marks " . - "WHERE usr_id = " . $ilDB->quote($a_usr_id, 'integer') . " " . - "AND obj_id = " . $ilDB->quote($a_obj_id, 'integer'); - - $res = $ilDB->query($query); - while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - return (bool) $row->completed; - } - return false; + public static function _hasCompleted( + int $a_usr_id, + int $a_obj_id + ): bool { + return (new TrackingFactory())->db()->lpMarks()->repository()->readEntryForUserOfObject( + $a_obj_id, + $a_usr_id + )->isCompleted(); } public static function getCompletionsOfUser( @@ -154,136 +135,63 @@ public static function getCompletionsOfUser( string $from, string $to ): array { - global $DIC; - - $ilDB = $DIC['ilDB']; - - $query = "SELECT * FROM ut_lp_marks " . - "WHERE usr_id = " . $ilDB->quote($user_id, 'integer') . - " AND status = " . $ilDB->quote( - ilLPStatus::LP_STATUS_COMPLETED_NUM, - 'integer' - ) . - " AND status_changed >= " . $ilDB->quote($from, "timestamp") . - " AND status_changed <= " . $ilDB->quote($to, "timestamp"); - - $set = $ilDB->query($query); - $completions = array(); - while ($rec = $ilDB->fetchAssoc($set)) { - $completion = [ - 'obj_id' => (int) $rec['obj_id'], - 'usr_id' => (int) $rec['usr_id'], - 'completed' => (bool) $rec['completed'], - 'mark' => (string) $rec['mark'], - 'comment' => (string) $rec['u_comment'], - 'status' => (int) $rec['status'], - 'status_changed' => (string) $rec['status_changed'], - 'status_dirty' => (int) $rec['status_changed'], - 'percentage' => (int) $rec['percentage'] - ]; - $completions[] = $completion; - } - return $completions; + $collection = (new TrackingFactory())->db()->lpMarks()->repository()->readByUserIdAndStatusAndTimeInterval( + $user_id, + ilLPStatus::LP_STATUS_COMPLETED_NUM, + $from, + $to + ); + return $collection->asDataArray(); } - public static function _lookupMark(int $a_usr_id, int $a_obj_id): string - { - global $DIC; - - $ilDB = $DIC['ilDB']; - - $query = "SELECT * FROM ut_lp_marks " . - "WHERE usr_id = " . $ilDB->quote($a_usr_id, 'integer') . " " . - "AND obj_id = " . $ilDB->quote($a_obj_id, 'integer'); - - $res = $ilDB->query($query); - while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - return (string) $row->mark; - } - return ''; + public static function _lookupMark( + int $a_usr_id, + int $a_obj_id + ): string { + $lp_mark = (new TrackingFactory())->db()->lpMarks()->repository()->readEntryForUserOfObject( + $a_obj_id, + $a_usr_id + ); + return is_null($lp_mark) ? '' : (string) $lp_mark->getMark(); } - public static function _lookupComment(int $a_usr_id, int $a_obj_id): string - { - global $DIC; - - $ilDB = $DIC['ilDB']; - - $query = "SELECT * FROM ut_lp_marks " . - "WHERE usr_id = " . $ilDB->quote($a_usr_id, 'integer') . " " . - "AND obj_id = " . $ilDB->quote($a_obj_id, 'integer'); - - $res = $ilDB->query($query); - while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - return (string) $row->u_comment; - } - return ''; + public static function _lookupComment( + int $a_usr_id, + int $a_obj_id + ): string { + $lp_mark = (new TrackingFactory())->db()->lpMarks()->repository()->readEntryForUserOfObject( + $a_obj_id, + $a_usr_id + ); + return is_null($lp_mark) ? '' : (string) $lp_mark->getComment(); } - // Private public function __read(): bool { - $res = $this->db->query( - "SELECT * FROM ut_lp_marks " . - "WHERE obj_id = " . $this->db->quote( - $this->obj_id, - 'integer' - ) . " " . - "AND usr_id = " . $this->db->quote($this->usr_id, 'integer') + $new_lp_mark = $this->tracking_factory->db()->lpMarks()->repository()->readEntryForUserOfObject( + $this->lp_mark->getObjectId(), + $this->lp_mark->getUserId() ); - while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - $this->has_entry = true; - $this->completed = (int) $row->completed; - $this->comment = (string) $row->u_comment; - $this->mark = (string) $row->mark; - $this->status_changed = (string) $row->status_changed; - return true; + if (is_null($new_lp_mark)) { + return false; } - return false; - } - - public function __add(): void - { - $query = "INSERT INTO ut_lp_marks (mark,u_comment, completed,obj_id,usr_id) " . - "VALUES( " . - $this->db->quote($this->getMark(), 'text') . ", " . - $this->db->quote($this->getComment(), 'text') . ", " . - $this->db->quote($this->getCompleted(), 'integer') . ", " . - $this->db->quote($this->getObjId(), 'integer') . ", " . - $this->db->quote($this->getUserId(), 'integer') . " " . - ")"; - $res = $this->db->manipulate($query); - $this->has_entry = true; + $this->lp_mark = $new_lp_mark; + return true; } public static function _deleteForUsers( int $a_obj_id, array $a_user_ids ): void { - global $DIC; - - $ilDB = $DIC['ilDB']; - $ilDB->manipulate( - "DELETE FROM ut_lp_marks" . - " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer") . - " AND " . $ilDB->in("usr_id", $a_user_ids, "", "integer") + (new TrackingFactory())->db()->lpMarks()->repository()->deleteByUserIds( + $a_obj_id, + ...$a_user_ids ); } public static function _getAllUserIds(int $a_obj_id): array { - global $DIC; - - $ilDB = $DIC['ilDB']; - - $res = array(); - $set = $ilDB->query( - "SELECT usr_id FROM ut_lp_marks" . - " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer") - ); - while ($row = $ilDB->fetchAssoc($set)) { - $res[] = (int) $row["usr_id"]; - } - return $res; + $collection = (new TrackingFactory())->db()->lpMarks()->repository()->readAllEntriesOfObject($a_obj_id); + return $collection->asUserIdArray(); } } diff --git a/components/ILIAS/Tracking/classes/class.ilLPObjSettings.php b/components/ILIAS/Tracking/classes/class.ilLPObjSettings.php index e351ba17f841..3f4054cd94bb 100755 --- a/components/ILIAS/Tracking/classes/class.ilLPObjSettings.php +++ b/components/ILIAS/Tracking/classes/class.ilLPObjSettings.php @@ -16,499 +16,239 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\Tracking\Factory as TrackingFactory; +use ILIAS\Tracking\FactoryInterface as TrackingFactoryInterface; +use ILIAS\Tracking\DB\FactoryInterface as TrackingDBFactoryInterface; +use ILIAS\Tracking\DB\LPSettings\Element\LPSettingsInterface as TrackingDBLPSettingsInterface; +use ILIAS\Tracking\Status\CollectionInterface as LPStatusCollectionInterface; -/** - * Class ilLPObjSettings - * @author Stefan Meyer - * @package ilias-tracking - */ class ilLPObjSettings { - protected int $obj_id; - protected string $obj_type; - protected int $obj_mode; - protected int $visits = self::LP_DEFAULT_VISITS; - - protected bool $is_stored = false; - - public const LP_MODE_DEACTIVATED = 0; - public const LP_MODE_TLT = 1; - public const LP_MODE_VISITS = 2; - public const LP_MODE_MANUAL = 3; - public const LP_MODE_OBJECTIVES = 4; - public const LP_MODE_COLLECTION = 5; - public const LP_MODE_SCORM = 6; - public const LP_MODE_TEST_FINISHED = 7; - public const LP_MODE_TEST_PASSED = 8; - public const LP_MODE_EXERCISE_RETURNED = 9; - public const LP_MODE_EVENT = 10; - public const LP_MODE_MANUAL_BY_TUTOR = 11; - public const LP_MODE_SCORM_PACKAGE = 12; - public const LP_MODE_UNDEFINED = 13; - public const LP_MODE_PLUGIN = 14; - public const LP_MODE_COLLECTION_TLT = 15; - public const LP_MODE_COLLECTION_MANUAL = 16; - public const LP_MODE_QUESTIONS = 17; - public const LP_MODE_SURVEY_FINISHED = 18; - public const LP_MODE_VISITED_PAGES = 19; - public const LP_MODE_CONTENT_VISITED = 20; - public const LP_MODE_COLLECTION_MOBS = 21; - public const LP_MODE_STUDY_PROGRAMME = 22; - public const LP_MODE_INDIVIDUAL_ASSESSMENT = 23; - public const LP_MODE_CMIX_COMPLETED = 24; - public const LP_MODE_CMIX_COMPL_WITH_FAILED = 25; - public const LP_MODE_CMIX_PASSED = 26; - public const LP_MODE_CMIX_PASSED_WITH_FAILED = 27; - public const LP_MODE_CMIX_COMPLETED_OR_PASSED = 28; - public const LP_MODE_CMIX_COMPL_OR_PASSED_WITH_FAILED = 29; - public const LP_MODE_LTI_OUTCOME = 31; - public const LP_MODE_COURSE_REFERENCE = 32; - public const LP_MODE_CONTRIBUTION_TO_DISCUSSION = 33; - - public const LP_DEFAULT_VISITS = 30; - - protected static array $map = array( - - self::LP_MODE_DEACTIVATED => array('ilLPStatus', - 'trac_mode_deactivated', - 'trac_mode_deactivated_info_new' - ) - - , - self::LP_MODE_TLT => array('ilLPStatusTypicalLearningTime', - 'trac_mode_tlt', - 'trac_mode_tlt_info' - ) // info has dynamic part! - - , - self::LP_MODE_VISITS => array('ilLPStatusVisits', - 'trac_mode_visits', - 'trac_mode_visits_info' - ) - - , - self::LP_MODE_MANUAL => array('ilLPStatusManual', - 'trac_mode_manual', - 'trac_mode_manual_info' - ) - - , - self::LP_MODE_OBJECTIVES => array('ilLPStatusObjectives', - 'trac_mode_objectives', - 'trac_mode_objectives_info' - ) - - , - self::LP_MODE_COLLECTION => array('ilLPStatusCollection', - 'trac_mode_collection', - 'trac_mode_collection_info' - ) - - , - self::LP_MODE_SCORM => array('ilLPStatusSCORM', - 'trac_mode_scorm', - 'trac_mode_scorm_info' - ) - - , - self::LP_MODE_TEST_FINISHED => array('ilLPStatusTestFinished', - 'trac_mode_test_finished', - 'trac_mode_test_finished_info' - ) - - , - self::LP_MODE_TEST_PASSED => array('ilLPStatusTestPassed', - 'trac_mode_test_passed', - 'trac_mode_test_passed_info' - ) - - , - self::LP_MODE_EXERCISE_RETURNED => array('ilLPStatusExerciseReturned', - 'trac_mode_exercise_returned', - 'trac_mode_exercise_returned_info' - ) - - , - self::LP_MODE_EVENT => array('ilLPStatusEvent', - 'trac_mode_event', - 'trac_mode_event_info' - ) - - , - self::LP_MODE_MANUAL_BY_TUTOR => array('ilLPStatusManualByTutor', - 'trac_mode_manual_by_tutor', - 'trac_mode_manual_by_tutor_info' - ) - - , - self::LP_MODE_SCORM_PACKAGE => array('ilLPStatusSCORMPackage', - 'trac_mode_scorm_package', - 'trac_mode_scorm_package_info' - ) - - , - self::LP_MODE_UNDEFINED => null - - , - self::LP_MODE_PLUGIN => array('ilLPStatusPlugin', - 'trac_mode_plugin', - '' - ) // no settings screen, so no info needed - - , - self::LP_MODE_COLLECTION_TLT => array('ilLPStatusCollectionTLT', - 'trac_mode_collection_tlt', - 'trac_mode_collection_tlt_info' - ) - - , - self::LP_MODE_COLLECTION_MANUAL => array('ilLPStatusCollectionManual', - 'trac_mode_collection_manual', - 'trac_mode_collection_manual_info' - ) - - , - self::LP_MODE_QUESTIONS => array('ilLPStatusQuestions', - 'trac_mode_questions', - 'trac_mode_questions_info' - ) - - , - self::LP_MODE_SURVEY_FINISHED => array('ilLPStatusSurveyFinished', - 'trac_mode_survey_finished', - 'trac_mode_survey_finished_info' - ) - - , - self::LP_MODE_VISITED_PAGES => array('ilLPStatusVisitedPages', - 'trac_mode_visited_pages', - 'trac_mode_visited_pages_info' - ) + public const int LP_MODE_DEACTIVATED = 0; + public const int LP_MODE_TLT = 1; + public const int LP_MODE_VISITS = 2; + public const int LP_MODE_MANUAL = 3; + public const int LP_MODE_OBJECTIVES = 4; + public const int LP_MODE_COLLECTION = 5; + public const int LP_MODE_SCORM = 6; + public const int LP_MODE_TEST_FINISHED = 7; + public const int LP_MODE_TEST_PASSED = 8; + public const int LP_MODE_EXERCISE_RETURNED = 9; + public const int LP_MODE_EVENT = 10; + public const int LP_MODE_MANUAL_BY_TUTOR = 11; + public const int LP_MODE_SCORM_PACKAGE = 12; + public const int LP_MODE_UNDEFINED = 13; + public const int LP_MODE_PLUGIN = 14; + public const int LP_MODE_COLLECTION_TLT = 15; + public const int LP_MODE_COLLECTION_MANUAL = 16; + public const int LP_MODE_QUESTIONS = 17; + public const int LP_MODE_SURVEY_FINISHED = 18; + public const int LP_MODE_VISITED_PAGES = 19; + public const int LP_MODE_CONTENT_VISITED = 20; + public const int LP_MODE_COLLECTION_MOBS = 21; + public const int LP_MODE_STUDY_PROGRAMME = 22; + public const int LP_MODE_INDIVIDUAL_ASSESSMENT = 23; + public const int LP_MODE_CMIX_COMPLETED = 24; + public const int LP_MODE_CMIX_COMPL_WITH_FAILED = 25; + public const int LP_MODE_CMIX_PASSED = 26; + public const int LP_MODE_CMIX_PASSED_WITH_FAILED = 27; + public const int LP_MODE_CMIX_COMPLETED_OR_PASSED = 28; + public const int LP_MODE_CMIX_COMPL_OR_PASSED_WITH_FAILED = 29; + public const int LP_DEFAULT_VISITS = 30; + public const int LP_MODE_LTI_OUTCOME = 31; + public const int LP_MODE_COURSE_REFERENCE = 32; + public const int LP_MODE_CONTRIBUTION_TO_DISCUSSION = 33; - , - self::LP_MODE_CONTENT_VISITED => array('ilLPStatusContentVisited', - 'trac_mode_content_visited', - 'trac_mode_content_visited_info' - ) - - , - self::LP_MODE_COLLECTION_MOBS => array('ilLPStatusCollectionMobs', - 'trac_mode_collection_mobs', - 'trac_mode_collection_mobs_info' - ) - - , - self::LP_MODE_STUDY_PROGRAMME => array('ilLPStatusStudyProgramme', - 'trac_mode_study_programme', - '' - ) - - , - self::LP_MODE_INDIVIDUAL_ASSESSMENT => array('ilLPStatusIndividualAssessment', - 'trac_mode_individual_assessment', - 'trac_mode_individual_assessment_info' - ) - - , - self::LP_MODE_CMIX_COMPLETED => array(ilLPStatusCmiXapiCompleted::class, - 'trac_mode_cmix_completed', - 'trac_mode_cmix_completed_info' - ) - - , - self::LP_MODE_CMIX_COMPL_WITH_FAILED => array(ilLPStatusCmiXapiCompletedWithFailed::class, - 'trac_mode_cmix_compl_with_failed', - 'trac_mode_cmix_compl_with_failed_info' - ) - - , - self::LP_MODE_CMIX_PASSED => array(ilLPStatusCmiXapiPassed::class, - 'trac_mode_cmix_passed', - 'trac_mode_cmix_passed_info' - ) - - , - self::LP_MODE_CMIX_PASSED_WITH_FAILED => array(ilLPStatusCmiXapiPassedWithFailed::class, - 'trac_mode_cmix_passed_with_failed', - 'trac_mode_cmix_passed_with_failed_info' - ) - - , - self::LP_MODE_CMIX_COMPLETED_OR_PASSED => array(ilLPStatusCmiXapiCompletedOrPassed::class, - 'trac_mode_cmix_completed_or_passed', - 'trac_mode_cmix_completed_or_passed_info' - ) - - , - self::LP_MODE_CMIX_COMPL_OR_PASSED_WITH_FAILED => array(ilLPStatusCmiXapiCompletedOrPassedWithFailed::class, - 'trac_mode_cmix_compl_or_passed_with_failed', - 'trac_mode_cmix_compl_or_passed_with_failed_info' - ) - - , - self::LP_MODE_LTI_OUTCOME => array(ilLPStatusLtiOutcome::class, - 'trac_mode_lti_outcome', - 'trac_mode_lti_outcome_info' - ) - - , - self::LP_MODE_COURSE_REFERENCE => [ - 'ilLPStatusCourseReference', - 'trac_mode_course_reference', - 'trac_mode_course_reference_info' - ], - - self::LP_MODE_CONTRIBUTION_TO_DISCUSSION => [ - ilLPStatusContributionToDiscussion::class, - 'trac_mode_contribution_to_discussion', - 'trac_mode_contribution_to_discussion_info' - ], - ); - - protected ilDBInterface $db; protected ilObjectDataCache $objectDataCache; + protected static TrackingFactoryInterface $tracking_factory; + protected static LPStatusCollectionInterface $status_collection; + protected TrackingDBFactoryInterface $tracking_db_factory; + protected TrackingDBLPSettingsInterface $lp_settings; public function __construct(int $a_obj_id) { global $DIC; - - $this->db = $DIC->database(); + self::initTrackingFactory(); + $this->tracking_db_factory = self::$tracking_factory->db(); $this->objectDataCache = $DIC['ilObjDataCache']; - - $this->obj_id = $a_obj_id; - - if (!$this->read()) { - $this->obj_type = $this->objectDataCache->lookupType($this->obj_id); - - $olp = ilObjectLP::getInstance($this->obj_id); - $this->obj_mode = $olp->getDefaultMode(); + $entry_exists = $this->tracking_db_factory->lpSettings()->repository()->isLPSettingsEntryInDB($a_obj_id); + if (!$entry_exists) { + $olp = ilObjectLP::getInstance($a_obj_id); + $this->lp_settings = $this->tracking_db_factory->lpSettings()->element()->lpSettings() + ->withObjectId($a_obj_id) + ->withObjType($this->objectDataCache->lookupType($a_obj_id)) + ->withUMode($olp->getDefaultMode()) + ->withVisits(self::LP_DEFAULT_VISITS); + } + if ($entry_exists) { + $this->lp_settings = $this->tracking_db_factory->lpSettings()->repository()->readLPSettings($a_obj_id); } } - /** - * Clone settings - * @access public - * @param int new obj id - */ - public function cloneSettings(int $a_new_obj_id): bool + protected static function initTrackingFactory(): void { - global $DIC; - - $ilDB = $DIC['ilDB']; - - $query = "INSERT INTO ut_lp_settings (obj_id,obj_type,u_mode,visits) " . - "VALUES( " . - $this->db->quote($a_new_obj_id, 'integer') . ", " . - $this->db->quote($this->getObjType(), 'text') . ", " . - $this->db->quote($this->getMode(), 'integer') . ", " . - $this->db->quote($this->getVisits(), 'integer') . - ")"; - $res = $this->db->manipulate($query); - return true; + if (!isset(self::$tracking_factory)) { + self::$tracking_factory = new TrackingFactory(); + } } - public function getVisits(): int + protected static function initStatusCollection(): void { - return $this->visits; + self::initTrackingFactory(); + if (!isset(self::$status_collection)) { + self::$status_collection = self::$tracking_factory->status()->allLPStatusImplementations(); + } } - public function setVisits(int $a_visits): void + public function cloneSettings(int $a_new_obj_id): bool { - $this->visits = $a_visits; + $this->tracking_db_factory->lpSettings()->repository()->writeLPSettings( + $this->lp_settings + ->withObjectId($a_new_obj_id) + ); + return true; } - public function setMode(int $a_mode): void + public function getVisits(): int { - $this->obj_mode = $a_mode; + return $this->lp_settings->getVisits(); } public function getMode(): int { - return $this->obj_mode; + return $this->lp_settings->getUMode(); } public function getObjId(): int { - return $this->obj_id; + return $this->lp_settings->getObjectId(); } public function getObjType(): string { - return $this->obj_type; + return $this->lp_settings->getObjType(); } - public function read(): bool - { - $res = $this->db->query( - "SELECT * FROM ut_lp_settings WHERE obj_id = " . - $this->db->quote($this->obj_id, 'integer') - ); - while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - $this->is_stored = true; - $this->obj_type = (string) $row->obj_type; - $this->obj_mode = (int) $row->u_mode; - $this->visits = (int) $row->visits; - return true; - } - return false; + public function setVisits( + int $a_visits + ): void { + $this->lp_settings = $this->lp_settings + ->withVisits($a_visits); } - public function update(bool $a_refresh_lp = true): bool - { - if (!$this->is_stored) { - return $this->insert(); - } - $query = "UPDATE ut_lp_settings SET u_mode = " . $this->db->quote( - $this->getMode(), - 'integer' - ) . ", " . - "visits = " . $this->db->quote( - $this->getVisits(), - 'integer' - ) . " " . - "WHERE obj_id = " . $this->db->quote($this->getObjId(), 'integer'); - $res = $this->db->manipulate($query); - $this->read(); - - if ($a_refresh_lp) { - $this->doLPRefresh(); - } - return true; + public function setMode( + int $a_mode + ): void { + $this->lp_settings = $this->lp_settings + ->withUMode($a_mode); } - public function insert(): bool + public function read(): bool { - $query = "INSERT INTO ut_lp_settings (obj_id,obj_type,u_mode,visits) " . - "VALUES(" . - $this->db->quote($this->getObjId(), 'integer') . ", " . - $this->db->quote($this->getObjType(), 'text') . ", " . - $this->db->quote($this->getMode(), 'integer') . ", " . - $this->db->quote($this->getVisits(), 'integer') . // #12482 - ")"; - $res = $this->db->manipulate($query); - $this->read(); - $this->doLPRefresh(); + $new_lp_settings = $this->tracking_db_factory->lpSettings()->repository()->readLPSettings($this->lp_settings->getObjectId()); + if (is_null($new_lp_settings)) { + return false; + } + $this->lp_settings = $new_lp_settings; return true; } - protected function doLPRefresh(): void - { - // refresh learning progress - ilLPStatusWrapper::_refreshStatus($this->getObjId()); + public function update( + bool $a_refresh_lp = true + ): bool { + return $this->insert($a_refresh_lp); } - public static function _delete(int $a_obj_id): bool - { - global $DIC; - - $ilDB = $DIC['ilDB']; - $query = "DELETE FROM ut_lp_settings WHERE obj_id = " . $ilDB->quote( - $a_obj_id, - 'integer' - ); - $res = $ilDB->manipulate($query); + public function insert( + bool $a_refresh_lp = true + ): bool { + $new_entry = $this->tracking_db_factory->lpSettings()->repository()->isLPSettingsEntryInDB($this->lp_settings->getObjectId()); + $this->tracking_db_factory->lpSettings()->repository()->writeLPSettings($this->lp_settings); + $this->read(); + if ($a_refresh_lp || $new_entry) { + ilLPStatusWrapper::_refreshStatus($this->getObjId()); + } return true; } - public static function _lookupVisits(int $a_obj_id): int - { - global $DIC; - - $ilDB = $DIC['ilDB']; - $query = "SELECT visits FROM ut_lp_settings " . - "WHERE obj_id = " . $ilDB->quote($a_obj_id, 'integer'); - - $res = $ilDB->query($query); - while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - return $row->visits; + public static function _lookupVisits( + int $a_obj_id + ): int { + self::initTrackingFactory(); + $tracking_db_factory = self::$tracking_factory->db(); + $lp_settings = $tracking_db_factory->lpSettings()->repository()->readLPSettings($a_obj_id); + return is_null($lp_settings) + ? self::LP_DEFAULT_VISITS + : $lp_settings->getVisits(); + } + + public static function _lookupDBModeForObjects( + array $a_obj_ids + ): array { + self::initTrackingFactory(); + $tracking_db_factory = self::$tracking_factory->db(); + $lp_settings = $tracking_db_factory->lpSettings()->repository()->readLPSettingsCollection(...$a_obj_ids); + $db_modes = []; + if (is_null($lp_settings)) { + return $db_modes; } - return self::LP_DEFAULT_VISITS; - } - - public static function _lookupDBModeForObjects(array $a_obj_ids): array - { - global $DIC; - - $ilDB = $DIC['ilDB']; - // this does NOT handle default mode! - $res = array(); - $query = "SELECT obj_id, u_mode FROM ut_lp_settings" . - " WHERE " . $ilDB->in("obj_id", $a_obj_ids, "", "integer"); - $set = $ilDB->query($query); - while ($row = $set->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - $res[(int) $row->obj_id] = (int) $row->u_mode; + foreach ($lp_settings as $lp_setting) { + $db_modes[$lp_setting->getObjectId()] = $lp_setting->getUMode(); } - return $res; + return $db_modes; } - public static function _lookupDBMode(int $a_obj_id): ?int - { - global $DIC; - - $ilDB = $DIC['ilDB']; - // this does NOT handle default mode! - $query = "SELECT u_mode FROM ut_lp_settings" . - " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer"); - $res = $ilDB->query($query); - while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - return (int) $row->u_mode; - } - return null; + public static function _lookupDBMode( + int $a_obj_id + ): ?int { + self::initTrackingFactory(); + $tracking_db_factory = self::$tracking_factory->db(); + $lp_settings = $tracking_db_factory->lpSettings()->repository()->readLPSettings($a_obj_id); + return is_null($lp_settings) + ? null + : $lp_settings->getUMode(); } - public static function _mode2Text(int $a_mode): string - { - global $DIC; - - $lng = $DIC->language(); - if (array_key_exists($a_mode, self::$map) && - is_array(self::$map[$a_mode])) { - return $lng->txt(self::$map[$a_mode][1]); - } - return ''; + public static function _mode2Text( + int $a_mode + ): string { + self::initStatusCollection(); + $status = self::$status_collection->getElementByStatusId((string) $a_mode); + return is_null($status) ? '' : $status->getLabel(); } - public static function _mode2InfoText(int $a_mode): string - { - global $DIC; - - $lng = $DIC->language(); - if (array_key_exists($a_mode, self::$map) && - is_array(self::$map[$a_mode])) { - $info = $lng->txt(self::$map[$a_mode][2]); - if ($a_mode == self::LP_MODE_TLT) { - // dynamic content - $info = sprintf($info, ilObjUserTracking::_getValidTimeSpan()); - } - return $info; - } - return ''; + public static function _mode2InfoText( + int $a_mode + ): string { + self::initStatusCollection(); + $status = self::$status_collection->getElementByStatusId((string) $a_mode); + return is_null($status) ? '' : $status->getInfo(); } public static function getClassMap(): array { - $res = array(); - foreach (self::$map as $mode => $item) { - if ($item) { - $res[$mode] = $item[0]; - } + self::initStatusCollection(); + $res = []; + foreach (self::$status_collection as $status) { + $res[$status->getLPStatusId()] = $status::class; } return $res; } - public static function _deleteByObjId(int $a_obj_id): void - { - global $DIC; - - $ilDB = $DIC['ilDB']; - // we are only removing settings for now - // invalid ut_lp_collections-entries are filtered - // ut_lp_marks is deemed private user data + public static function _deleteByObjId( + int $a_obj_id + ): void { + self::initTrackingFactory(); + $tracking_db_factory = self::$tracking_factory->db(); + $tracking_db_factory->lpSettings()->repository()->deleteLPSettings($a_obj_id); + } - $ilDB->manipulate( - "DELETE FROM ut_lp_settings" . - " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer") - ); + public static function _delete( + int $a_obj_id + ): bool { + ilLPObjSettings::_deleteByObjId($a_obj_id); + return true; } } diff --git a/components/ILIAS/Tracking/classes/class.ilLPProgressBlockGUI.php b/components/ILIAS/Tracking/classes/class.ilLPProgressBlockGUI.php index 80894e93a3c9..3f8061bcb9d3 100644 --- a/components/ILIAS/Tracking/classes/class.ilLPProgressBlockGUI.php +++ b/components/ILIAS/Tracking/classes/class.ilLPProgressBlockGUI.php @@ -18,8 +18,8 @@ declare(strict_types=1); -use ILIAS\Tracking\View\Factory as ViewFactory; use ILIAS\Tracking\View\DataRetrieval\FactoryInterface as DataRetrievalFactoryInterface; +use ILIAS\Tracking\View\Factory as ViewFactory; use ILIAS\Tracking\View\Renderer\RendererInterface as RendererInterface; /** diff --git a/components/ILIAS/Tracking/classes/class.ilLPStatus.php b/components/ILIAS/Tracking/classes/class.ilLPStatus.php index d5fa81498467..3fcf23718b2d 100755 --- a/components/ILIAS/Tracking/classes/class.ilLPStatus.php +++ b/components/ILIAS/Tracking/classes/class.ilLPStatus.php @@ -16,7 +16,10 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\Tracking\Factory as TrackingFactory; +use ILIAS\Tracking\Status\LPStatusInterface; /** * Abstract class ilLPStatus for all learning progress modes @@ -25,108 +28,110 @@ * @version $Id$ * @ingroup ServicesTracking */ -class ilLPStatus +class ilLPStatus implements LPStatusInterface { - protected int $obj_id; + public const string LP_STATUS_NOT_ATTEMPTED = 'trac_no_attempted'; + public const string LP_STATUS_IN_PROGRESS = 'trac_in_progress'; + public const string LP_STATUS_COMPLETED = 'trac_completed'; + public const string LP_STATUS_FAILED = 'trac_failed'; + public const int LP_STATUS_NOT_ATTEMPTED_NUM = 0; + public const int LP_STATUS_IN_PROGRESS_NUM = 1; + public const int LP_STATUS_COMPLETED_NUM = 2; + public const int LP_STATUS_FAILED_NUM = 3; + public const string LP_STATUS_REGISTERED = 'trac_registered'; + public const string LP_STATUS_NOT_REGISTERED = 'trac_not_registered'; + public const string LP_ut_lp_markSTATUS_PARTICIPATED = 'trac_participated'; + public const string LP_STATUS_NOT_PARTICIPATED = 'trac_not_participated'; + + public static array $list_gui_cache; + protected int $obj_id; protected ilDBInterface $db; protected ilObjectDataCache $ilObjDataCache; - public static $list_gui_cache; - - public const LP_STATUS_NOT_ATTEMPTED = 'trac_no_attempted'; - public const LP_STATUS_IN_PROGRESS = 'trac_in_progress'; - public const LP_STATUS_COMPLETED = 'trac_completed'; - public const LP_STATUS_FAILED = 'trac_failed'; - - public const LP_STATUS_NOT_ATTEMPTED_NUM = 0; - public const LP_STATUS_IN_PROGRESS_NUM = 1; - public const LP_STATUS_COMPLETED_NUM = 2; - public const LP_STATUS_FAILED_NUM = 3; - - public const LP_STATUS_REGISTERED = 'trac_registered'; - public const LP_STATUS_NOT_REGISTERED = 'trac_not_registered'; - public const LP_STATUS_PARTICIPATED = 'trac_participated'; - public const LP_STATUS_NOT_PARTICIPATED = 'trac_not_participated'; - public function __construct(int $a_obj_id) { global $DIC; - $this->obj_id = $a_obj_id; $this->db = $DIC->database(); $this->ilObjDataCache = $DIC['ilObjDataCache']; } - public static function _getCountNotAttempted(int $a_obj_id): int - { + public static function _getCountNotAttempted( + int $a_obj_id + ): int { return 0; } /** - * @param int $a_obj_id * @return int[] */ - public static function _getNotAttempted(int $a_obj_id): array - { - return array(); + public static function _getNotAttempted( + int $a_obj_id + ): array { + return []; } - public static function _getCountInProgress(int $a_obj_id): int - { + public static function _getCountInProgress( + int $a_obj_id + ): int { return 0; } - public static function _getInProgress(int $a_obj_id): array - { - return array(); + public static function _getInProgress( + int $a_obj_id + ): array { + return []; } - public static function _getCountCompleted(int $a_obj_id): int - { + public static function _getCountCompleted( + int $a_obj_id + ): int { return 0; } /** - * @param int $a_obj_id * @return int[] */ - public static function _getCompleted(int $a_obj_id): array - { - return array(); + public static function _getCompleted( + int $a_obj_id + ): array { + return []; } /** - * @param int $a_obj_id * @return int[] */ - public static function _getFailed(int $a_obj_id): array - { - return array(); + public static function _getFailed( + int $a_obj_id + ): array { + return []; } - public static function _getCountFailed(int $a_obj_id): int - { + public static function _getCountFailed( + int $a_obj_id + ): int { return 0; } - public static function _getStatusInfo(int $a_obj_id): array - { - return array(); + public static function _getStatusInfo( + int $a_obj_id + ): array { + return []; } - public static function _getTypicalLearningTime(string $type, int $obj_id, int $sub_id = 0): int - { + public static function _getTypicalLearningTime( + string $type, + int $obj_id, + int $sub_id = 0 + ): int { global $DIC; - $lom_services = $DIC->learningObjectMetadata(); $paths = $lom_services->paths(); $data_helper = $lom_services->dataHelper(); - $value = $lom_services->read($obj_id, $sub_id, $type, $paths->firstTypicalLearningTime()) ->firstData($paths->firstTypicalLearningTime()) ->value(); - return $data_helper->durationToSeconds($value); } @@ -235,7 +240,6 @@ public function _updateStatus( (is_object($a_obj) ? get_class($a_obj) : 'null') ) ); - $status = $this->determineStatus($a_obj_id, $a_usr_id, $a_obj); $percentage = $this->determinePercentage($a_obj_id, $a_usr_id, $a_obj); $old_status = ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM; @@ -247,7 +251,6 @@ public function _updateStatus( false, $old_status ); - // ak: I don't think that this is a good way to fix 15529, we should not // raise the event, if the status does not change imo. // for now the changes in the next line just prevent the event being raised twice @@ -288,41 +291,25 @@ public static function checkStatusForObject( int $a_obj_id, ?array $a_users = null ): void { - global $DIC; - - $ilDB = $DIC['ilDB']; - //@todo: there maybe the need to add extra handling for sessions here, since the // "in progress" status is time dependent here. On the other hand, if they registered // to the session, they already accessed the course and should have a "in progress" // anyway. But the status on the session itself may not be correct. - - $sql = "SELECT usr_id FROM ut_lp_marks WHERE " . - " obj_id = " . $ilDB->quote($a_obj_id, "integer") . " AND " . - " status_dirty = " . $ilDB->quote(1, "integer"); - if (is_array($a_users) && count($a_users) > 0) { - $sql .= " AND " . $ilDB->in("usr_id", $a_users, false, "integer"); - } - $set = $ilDB->query($sql); - $dirty = false; - if ($rec = $ilDB->fetchAssoc($set)) { - $dirty = true; + $valid_user_array = is_array($a_users) && count($a_users) > 0; + $db_repository = (new TrackingFactory())->db()->lpMarks()->repository(); + $collection = $db_repository->readAllEntriesOfObject( + $a_obj_id, + )->getSubCollectionOfElementsByStatusDirty(1); + if ($valid_user_array) { + $collection = $collection->getSubCollectionOfElementsByUserIds(...$a_users); } - + $dirty = count($collection) > 0; // check if any records are missing $missing = false; - if (!$dirty && is_array($a_users) && count($a_users) > 0) { - $set = $ilDB->query( - "SELECT count(usr_id) cnt FROM ut_lp_marks WHERE " . - " obj_id = " . $ilDB->quote($a_obj_id, "integer") . " AND " . - $ilDB->in("usr_id", $a_users, false, "integer") - ); - $r = $ilDB->fetchAssoc($set); - if ($r["cnt"] < count($a_users)) { - $missing = true; - } + if (!$dirty && $valid_user_array) { + $collection = $db_repository->readAllEntriesOfObject($a_obj_id)->getSubCollectionOfElementsByUserIds(...$a_users); + $missing = count($collection) < count($a_users); } - // refresh status, if records are dirty or missing if ($dirty || $missing) { $trac_obj = ilLPStatusFactory::_getInstance($a_obj_id); @@ -442,81 +429,51 @@ public static function writeStatus( ?int &$a_old_status = self::LP_STATUS_NOT_ATTEMPTED_NUM ): bool { global $DIC; - $ilDB = $DIC->database(); $log = $DIC->logger()->trac(); - $log->debug( 'Write status for: ' . "obj_id: " . $a_obj_id . ", user id: " . $a_user_id . ", status: " . $a_status . ", percentage: " . $a_percentage . ", force: " . $a_force_per ); $update_dependencies = false; - - $a_old_status = self::LP_STATUS_NOT_ATTEMPTED_NUM; - - // get status in DB - $set = $ilDB->query( - "SELECT usr_id,status,status_dirty FROM ut_lp_marks WHERE " . - " obj_id = " . $ilDB->quote($a_obj_id, "integer") . " AND " . - " usr_id = " . $ilDB->quote($a_user_id, "integer") - ); - $rec = $ilDB->fetchAssoc($set); - - // update - if ($rec) { - $a_old_status = $rec["status"]; - - // status has changed: update - if ($rec["status"] != $a_status) { - $ret = $ilDB->manipulate( - "UPDATE ut_lp_marks SET " . - " status = " . $ilDB->quote($a_status, "integer") . "," . - " status_changed = " . $ilDB->now() . "," . - " status_dirty = " . $ilDB->quote(0, "integer") . - " WHERE usr_id = " . $ilDB->quote($a_user_id, "integer") . - " AND obj_id = " . $ilDB->quote($a_obj_id, "integer") - ); - if ($ret != 0) { - $update_dependencies = true; - } - } // status has not changed: reset dirty flag - elseif ($rec["status_dirty"]) { - $ilDB->manipulate( - "UPDATE ut_lp_marks SET " . - " status_dirty = " . $ilDB->quote(0, "integer") . - " WHERE usr_id = " . $ilDB->quote($a_user_id, "integer") . - " AND obj_id = " . $ilDB->quote($a_obj_id, "integer") - ); - } - } // insert - else { - // #13783 - $ilDB->replace( - "ut_lp_marks", - array( - "obj_id" => array("integer", $a_obj_id), - "usr_id" => array("integer", $a_user_id) - ), - array( - "status" => array("integer", $a_status), - "status_changed" => array("timestamp", date("Y-m-d H:i:s")), - // was $ilDB->now() - "status_dirty" => array("integer", 0) - ) - ); - - $update_dependencies = true; + $db_repository = (new TrackingFactory())->db()->lpMarks()->repository(); + $db_element_factory = (new TrackingFactory())->db()->lpMarks()->element(); + $lp_mark_old = $db_repository->readEntryForUserOfObject($a_obj_id, $a_user_id); + $lp_mark_new = $db_element_factory->lpMark() + ->withStatus($a_status) + ->withUserId($a_user_id) + ->withObjectId($a_obj_id) + ->withStatusDirty(0); + $a_old_status = is_null($lp_mark_old) ? self::LP_STATUS_NOT_ATTEMPTED_NUM : $lp_mark_old->getStatus(); + if ( + is_null($lp_mark_old) || + $lp_mark_old->getStatus() != $a_status + ) { + $lp_mark_new = $lp_mark_new + ->withStatusChanged(date("Y-m-d H:i:s")); } - - // update percentage - if ($a_percentage || $a_force_per) { + if ( + !is_null($lp_mark_old) && + $lp_mark_old->getStatus() === $a_status + ) { + $lp_mark_new = $lp_mark_new + ->withStatusChanged($lp_mark_old->getStatusChanged()); + } + if ( + $a_percentage || + $a_force_per + ) { $a_percentage = max(0, $a_percentage); $a_percentage = min(100, $a_percentage); - $ret = $ilDB->manipulate( - "UPDATE ut_lp_marks SET " . - " percentage = " . $ilDB->quote($a_percentage, "integer") . - " WHERE usr_id = " . $ilDB->quote($a_user_id, "integer") . - " AND obj_id = " . $ilDB->quote($a_obj_id, "integer") - ); + $lp_mark_new = $lp_mark_new + ->withPercentage($a_percentage); + } + // update dependencies if new entry or the status has changed and rows are affected + $affected_rows_count = $db_repository->write($lp_mark_new); + if ( + is_null($lp_mark_old) || + ($affected_rows_count > 0 && $lp_mark_old->getStatus() != $a_status) + ) { + $update_dependencies = true; } $log->debug( @@ -542,7 +499,7 @@ public static function writeStatus( while ($rec = $ilDB->fetchAssoc($set)) { if (in_array( ilObject::_lookupType($rec["obj_id"]), - array("crs", "grp", "fold") + ["crs", "grp", "fold"] )) { $log->debug( 'Calling update status for collection obj_id: ' . $rec['obj_id'] @@ -605,29 +562,8 @@ public static function setInProgressIfNotAttempted( int $a_obj_id, int $a_user_id ): void { - global $DIC; - - $ilDB = $DIC['ilDB']; - - // #11513 - - $needs_update = false; - - $set = $ilDB->query( - "SELECT usr_id, status FROM ut_lp_marks WHERE " . - " obj_id = " . $ilDB->quote($a_obj_id, "integer") . " AND " . - " usr_id = " . $ilDB->quote($a_user_id, "integer") - ); - if ($rec = $ilDB->fetchAssoc($set)) { - // current status is not attempted, so we need to update - if ($rec["status"] == self::LP_STATUS_NOT_ATTEMPTED_NUM) { - $needs_update = true; - } - } else { - // no ut_lp_marks yet, we should update - $needs_update = true; - } - + $lp_mark = (new TrackingFactory())->db()->lpMarks()->repository()->readEntryForUserOfObject($a_obj_id, $a_user_id); + $needs_update = is_null($lp_mark) || $lp_mark->getStatus() === self::LP_STATUS_NOT_ATTEMPTED_NUM; if ($needs_update) { ilLPStatusWrapper::_updateStatus($a_obj_id, $a_user_id); } @@ -638,14 +574,7 @@ public static function setInProgressIfNotAttempted( */ public static function setAllDirty(): void { - global $DIC; - - $ilDB = $DIC['ilDB']; - - $ilDB->manipulate( - "UPDATE ut_lp_marks SET " . - " status_dirty = " . $ilDB->quote(1, "integer") - ); + (new TrackingFactory())->db()->lpMarks()->repository()->markAllRowsAsDirty(); } /** @@ -653,15 +582,10 @@ public static function setAllDirty(): void */ public static function setDirty(int $a_obj_id): void { - global $DIC; - - $ilDB = $DIC['ilDB']; - - $ilDB->manipulate( - "UPDATE ut_lp_marks SET " . - " status_dirty = " . $ilDB->quote(1, "integer") . - " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer") - ); + $db_repository = (new TrackingFactory())->db()->lpMarks()->repository(); + $collection = $db_repository->readAllEntriesOfObject($a_obj_id); + $collection = $collection->withChangedStatusDirtyOfAllElements(1); + $db_repository->writeCollection($collection); } /** @@ -672,28 +596,22 @@ public static function _lookupStatus( int $a_user_id, bool $a_create = true ): ?int { - global $DIC; - - $ilDB = $DIC['ilDB']; - - $set = $ilDB->query( - "SELECT status FROM ut_lp_marks WHERE " . - " status_dirty = " . $ilDB->quote(0, "integer") . - " AND usr_id = " . $ilDB->quote($a_user_id, "integer") . - " AND obj_id = " . $ilDB->quote($a_obj_id, "integer") - ); - if ($rec = $ilDB->fetchAssoc($set)) { - return (int) $rec["status"]; - } elseif ($a_create) { + $db_repository = (new TrackingFactory())->db()->lpMarks()->repository(); + $lp_mark = $db_repository->readEntryForUserOfObject($a_obj_id, $a_user_id); + if ( + !is_null($lp_mark) && + $lp_mark->getStatusDirty() === 0 + ) { + return $lp_mark->getStatus(); + } + if ($a_create) { ilLPStatusWrapper::_updateStatus($a_obj_id, $a_user_id); - $set = $ilDB->query( - "SELECT status FROM ut_lp_marks WHERE " . - " status_dirty = " . $ilDB->quote(0, "integer") . - " AND usr_id = " . $ilDB->quote($a_user_id, "integer") . - " AND obj_id = " . $ilDB->quote($a_obj_id, "integer") - ); - if ($rec = $ilDB->fetchAssoc($set)) { - return (int) $rec["status"]; + $lp_mark = $db_repository->readEntryForUserOfObject($a_obj_id, $a_user_id); + if ( + !is_null($lp_mark) && + $lp_mark->getStatusDirty() === 0 + ) { + return $lp_mark->getStatus(); } } return null; @@ -706,18 +624,10 @@ public static function _lookupPercentage( int $a_obj_id, int $a_user_id ): ?int { - global $DIC; - - $ilDB = $DIC['ilDB']; - - $set = $ilDB->query( - "SELECT percentage FROM ut_lp_marks WHERE " . - " status_dirty = " . $ilDB->quote(0, "integer") . - " AND usr_id = " . $ilDB->quote($a_user_id, "integer") . - " AND obj_id = " . $ilDB->quote($a_obj_id, "integer") - ); - if ($rec = $ilDB->fetchAssoc($set)) { - return $rec["percentage"]; + $db_repository = (new TrackingFactory())->db()->lpMarks()->repository(); + $lp_mark = $db_repository->readEntryForUserOfObject($a_obj_id, $a_user_id); + if (!is_null($lp_mark) && $lp_mark->getStatusDirty() === 0) { + return $lp_mark->getPercentage(); } return null; } @@ -742,29 +652,15 @@ public static function _lookupStatusChanged( int $a_obj_id, int $a_user_id ): ?string { - global $DIC; - - $ilDB = $DIC['ilDB']; - - $set = $ilDB->query( - "SELECT status_changed FROM ut_lp_marks WHERE " . - " status_dirty = " . $ilDB->quote(0, "integer") . - " AND usr_id = " . $ilDB->quote($a_user_id, "integer") . - " AND obj_id = " . $ilDB->quote($a_obj_id, "integer") - ); - if ($rec = $ilDB->fetchAssoc($set)) { - return (string) $rec["status_changed"]; - } else { - ilLPStatusWrapper::_updateStatus($a_obj_id, $a_user_id); - $set = $ilDB->query( - "SELECT status_changed FROM ut_lp_marks WHERE " . - " status_dirty = " . $ilDB->quote(0, "integer") . - " AND usr_id = " . $ilDB->quote($a_user_id, "integer") . - " AND obj_id = " . $ilDB->quote($a_obj_id, "integer") - ); - if ($rec = $ilDB->fetchAssoc($set)) { - return (string) $rec["status_changed"]; - } + $db_repository = (new TrackingFactory())->db()->lpMarks()->repository(); + $lp_mark = $db_repository->readEntryForUserOfObject($a_obj_id, $a_user_id); + if (!is_null($lp_mark) && $lp_mark->getStatusDirty() === 0) { + return $lp_mark->getStatusChanged(); + } + ilLPStatusWrapper::_updateStatus($a_obj_id, $a_user_id); + $lp_mark = $db_repository->readEntryForUserOfObject($a_obj_id, $a_user_id); + if (!is_null($lp_mark) && $lp_mark->getStatusDirty() === 0) { + return $lp_mark->getStatusChanged(); } return null; } @@ -777,36 +673,23 @@ protected static function _lookupStatusForObject( int $a_status, ?array $a_user_ids = null ): array { - global $DIC; - - $ilDB = $DIC['ilDB']; - - $sql = "SELECT usr_id, status, status_dirty FROM ut_lp_marks" . - " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer") . - " AND status = " . $ilDB->quote($a_status, "integer"); - if ($a_user_ids) { - $sql .= " AND " . $ilDB->in("usr_id", $a_user_ids, "", "integer"); + $db_repository = (new TrackingFactory())->db()->lpMarks()->repository(); + $collection = $db_repository->readAllEntriesWithStatusOfObject($a_obj_id, $a_status); + if (!is_null($a_user_ids) && count($a_user_ids) > 0) { + $collection = $collection->getSubCollectionOfElementsByUserIds(...$a_user_ids); } - - $set = $ilDB->query($sql); - $res = array(); - while ($rec = $ilDB->fetchAssoc($set)) { + foreach ($collection as $lp_mark) { // @fixme this was broken due to wrong $res['status_dirty'] access // check how to update status without recursion // check consequences of the old implementation - if ($rec["status_dirty"]) { + if ($lp_mark->getStatusDirty()) { // update status and check again - if (self::_lookupStatus( - $a_obj_id, - $rec["usr_id"] - ) != $a_status) { + if (self::_lookupStatus($a_obj_id, $lp_mark->getUserId()) != $a_status) { // update status: see comment } } - $res[] = (int) $rec["usr_id"]; } - - return $res; + return $collection->asUserIdArray(); } /** @@ -859,8 +742,7 @@ protected static function validateLPForObjects( array $a_obj_ids, int $a_parent_ref_id ): array { - $lp_invalid = array(); - + $lp_invalid = []; $memberships = ilObjectLP::getLPMemberships( $a_user_id, $a_obj_ids, @@ -875,18 +757,16 @@ protected static function validateLPForObjects( return array_diff($a_obj_ids, $lp_invalid); } - /** + /**implements * Process lp modes for given objects */ protected static function checkLPModesForObjects( array $a_obj_ids, array &$a_coll_obj_ids ): array { - $valid = array(); - + $valid = []; // all lp modes with collections (gathered separately) $coll_modes = ilLPCollection::getCollectionModes(); - // check if objects have LP activated at all (DB entries) $existing = ilLPObjSettings::_lookupDBModeForObjects($a_obj_ids); foreach ($existing as $obj_id => $obj_mode) { @@ -928,26 +808,18 @@ protected static function getLPStatusForObjects( int $a_user_id, array $a_obj_ids ): array { - global $DIC; + $collection = (new TrackingFactory())->db()->lpMarks()->repository()->readEntriesForUserOfObjects( + $a_user_id, + ...$a_obj_ids + ); - $ilDB = $DIC['ilDB']; - - $res = array(); - - // get user lp data - $sql = "SELECT status, status_dirty, obj_id FROM ut_lp_marks" . - " WHERE " . $ilDB->in("obj_id", $a_obj_ids, "", "integer") . - " AND usr_id = " . $ilDB->quote($a_user_id, "integer"); - $set = $ilDB->query($sql); - while ($row = $ilDB->fetchAssoc($set)) { - if (!$row["status_dirty"]) { - $res[$row["obj_id"]] = $row["status"]; - } else { - $res[$row["obj_id"]] = self::_lookupStatus( - $row["obj_id"], - $a_user_id - ); + $res = []; + foreach ($collection as $lp_mark) { + if (!$lp_mark->getStatusDirty()) { + $res[$lp_mark->getObjectId()] = $lp_mark->getStatus(); + continue; } + $res[$lp_mark->getObjectId()] = self::_lookupStatus($lp_mark->getObjectId(), $lp_mark->getUserId()); } // process missing user entries (same as dirty entries, see above) @@ -959,14 +831,12 @@ protected static function getLPStatusForObjects( } } } - return $res; } public static function preloadListGUIData(array $a_obj_ids): void { global $DIC; - $requested_ref_id = 0; if ($DIC->http()->wrapper()->query()->has('ref_id')) { $requested_ref_id = $DIC->http()->wrapper()->query()->retrieve( @@ -974,35 +844,27 @@ public static function preloadListGUIData(array $a_obj_ids): void $DIC->refinery()->kindlyTo()->int() ); } - $ilUser = $DIC['ilUser']; $lng = $DIC['lng']; - $user_id = $ilUser->getId(); - $res = array(); + $res = []; if ($ilUser->getId() != ANONYMOUS_USER_ID && ilObjUserTracking::_enabledLearningProgress() && ilObjUserTracking::_hasLearningProgressLearner() && // #12042 ilObjUserTracking::_hasLearningProgressListGUI()) { // -- validate - // :TODO: we need the parent ref id, but this is awful // this step removes all "not attempted" from the list, which we usually do not want - //$a_obj_ids = self::validateLPForObjects($user_id, $a_obj_ids, $requested_ref_id); - + // $a_obj_ids = self::validateLPForObjects($user_id, $a_obj_ids, $requested_ref_id); // we are not handling the collections differently yet - $coll_obj_ids = array(); + $coll_obj_ids = []; $a_obj_ids = self::checkLPModesForObjects( $a_obj_ids, $coll_obj_ids ); - // -- gather - $res = self::getLPStatusForObjects($user_id, $a_obj_ids); - // -- render - // value to icon $lng->loadLanguageModule("trac"); $icons = ilLPStatusIcons::getInstance(ilLPStatusIcons::ICON_VARIANT_LONG); @@ -1013,33 +875,63 @@ public static function preloadListGUIData(array $a_obj_ids): void ]; } } - self::$list_gui_cache = $res; } - /** - * @return string|array - */ public static function getListGUIStatus( int $a_obj_id, bool $a_image_only = true - ) { + ): string|array { if ($a_image_only) { $image = ''; if (isset(self::$list_gui_cache[$a_obj_id]["image"])) { $image = self::$list_gui_cache[$a_obj_id]["image"]; } - return $image; } return self::$list_gui_cache[$a_obj_id] ?? ""; } - public static function hasListGUIStatus(int $a_obj_id): bool - { + public static function hasListGUIStatus( + int $a_obj_id + ): bool { if (isset(self::$list_gui_cache[$a_obj_id])) { return true; } return false; } + + public function init(\ILIAS\DI\Container $DIC): void + { + // TODO: Implement init() method. + } + + public function getCustomLPSettingsExportXML( + int $object_id + ): SimpleXMLElement { + return new SimpleXMLElement(''); + } + + public function importCustomLPSettingsExportXML( + int $new_object_id, + ilImportMapping $a_mapping, + SimpleXMLElement $additional_xml_root + ): void { + # Default implementation does nothing + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_UNDEFINED; + } + + public function getLabel(): string + { + return ''; + } + + public function getInfo(): string + { + return ''; + } } diff --git a/components/ILIAS/Tracking/classes/class.ilLPStatusWrapper.php b/components/ILIAS/Tracking/classes/class.ilLPStatusWrapper.php index 8c55fcc301c4..ddf3c6a142d8 100755 --- a/components/ILIAS/Tracking/classes/class.ilLPStatusWrapper.php +++ b/components/ILIAS/Tracking/classes/class.ilLPStatusWrapper.php @@ -28,12 +28,12 @@ */ class ilLPStatusWrapper { - private static array $status_cache = array(); - private static array $info_cache = array(); - private static array $failed_cache = array(); - private static array $completed_cache = array(); - private static array $in_progress_cache = array(); - private static array $not_attempted_cache = array(); + private static array $status_cache = []; + private static array $info_cache = []; + private static array $failed_cache = []; + private static array $completed_cache = []; + private static array $in_progress_cache = []; + private static array $not_attempted_cache = []; /** * Static function to read the number of user who have the status 'not_attempted' @@ -76,12 +76,8 @@ public static function _getInProgress(int $a_obj_id): array if (isset(self::$in_progress_cache[$a_obj_id])) { return self::$in_progress_cache[$a_obj_id]; } - - global $DIC; - $class = ilLPStatusFactory::_getClassById($a_obj_id); self::$in_progress_cache[$a_obj_id] = $class::_getInProgress($a_obj_id); - return self::$in_progress_cache[$a_obj_id]; } @@ -103,7 +99,6 @@ public static function _getCompleted(int $a_obj_id): array } $class = ilLPStatusFactory::_getClassById($a_obj_id); self::$completed_cache[$a_obj_id] = $class::_getCompleted($a_obj_id); - return self::$completed_cache[$a_obj_id]; } @@ -123,11 +118,8 @@ public static function _getFailed(int $a_obj_id): array if (isset(self::$failed_cache[$a_obj_id])) { return self::$failed_cache[$a_obj_id]; } - $class = ilLPStatusFactory::_getClassById($a_obj_id); - self::$failed_cache[$a_obj_id] = $class::_getFailed($a_obj_id); - return self::$failed_cache[$a_obj_id]; } @@ -159,7 +151,7 @@ public static function _resetInfoCaches($a_obj_id) */ public static function _getTypicalLearningTime(string $type, int $a_obj_id): int { - static $cache = array(); + static $cache = []; if (isset($cache[$a_obj_id])) { return $cache[$a_obj_id]; @@ -192,7 +184,7 @@ public static function _getNotAttemptedByType( int $a_obj_id, string $a_type ): array { - static $cache = array(); + static $cache = []; if (isset($cache[$a_obj_id . '_' . $a_type])) { return $cache[$a_obj_id . '_' . $a_type]; @@ -217,7 +209,7 @@ public static function _getInProgressByType( int $a_obj_id, string $a_type ): array { - static $cache = array(); + static $cache = []; if (isset($cache[$a_obj_id . '_' . $a_type])) { return $cache[$a_obj_id . '_' . $a_type]; @@ -242,7 +234,7 @@ public static function _getCompletedByType( int $a_obj_id, string $a_type ): array { - static $cache = array(); + static $cache = []; if (isset($cache[$a_obj_id . '_' . $a_type])) { return $cache[$a_obj_id . '_' . $a_type]; @@ -265,7 +257,7 @@ public static function _getFailedByType( int $a_obj_id, string $a_type ): array { - static $cache = array(); + static $cache = []; if (isset($cache[$a_obj_id . '_' . $a_type])) { return $cache[$a_obj_id . '_' . $a_type]; @@ -281,7 +273,7 @@ public static function _getStatusInfoByType( int $a_obj_id, string $a_type ): array { - static $cache = array(); + static $cache = []; if (isset($cache[$a_obj_id . '_' . $a_type])) { return $cache[$a_obj_id . '_' . $a_type]; diff --git a/components/ILIAS/Tracking/classes/class.ilLPTableBaseGUI.php b/components/ILIAS/Tracking/classes/class.ilLPTableBaseGUI.php index 58c4ad481517..7fc4050227ff 100755 --- a/components/ILIAS/Tracking/classes/class.ilLPTableBaseGUI.php +++ b/components/ILIAS/Tracking/classes/class.ilLPTableBaseGUI.php @@ -18,11 +18,11 @@ declare(strict_types=0); -use ILIAS\User\Profile\Profile; +use ILIAS\HTTP\Services as HttpService; +use ILIAS\Refinery\Factory as RefineryFactory; use ILIAS\User\Context; use ILIAS\User\Profile\Fields\AvailableSections; -use ILIAS\Refinery\Factory as RefineryFactory; -use ILIAS\HTTP\Services as HttpService; +use ILIAS\User\Profile\Profile; /** * TableGUI class for learning progress diff --git a/components/ILIAS/Tracking/classes/class.ilLPXmlWriter.php b/components/ILIAS/Tracking/classes/class.ilLPXmlWriter.php index 3d59b3207816..5ecd1ecd485a 100755 --- a/components/ILIAS/Tracking/classes/class.ilLPXmlWriter.php +++ b/components/ILIAS/Tracking/classes/class.ilLPXmlWriter.php @@ -17,6 +17,10 @@ *********************************************************************/ declare(strict_types=0); + +use ILIAS\Tracking\DB\Factory as TrackingDBFactory; +use ILIAS\Tracking\DB\FactoryInterface as TrackingDBFactoryInterface; + /** * XML writer learning progress * @author Alex Killing @@ -27,9 +31,10 @@ class ilLPXmlWriter extends ilXmlWriter private bool $add_header = true; private string $timestamp = ""; private bool $include_ref_ids = false; - private array $type_filter = array(); + private array $type_filter = []; protected ilDBInterface $db; + protected TrackingDBFactoryInterface $tracking_db_factory; /** * Constructor @@ -37,7 +42,7 @@ class ilLPXmlWriter extends ilXmlWriter public function __construct(bool $a_add_header) { global $DIC; - + $this->tracking_db_factory = new TrackingDBFactory($DIC->database()); $this->db = $DIC->database(); $this->add_header = $a_add_header; parent::__construct(); @@ -115,36 +120,31 @@ protected function init(): void public function addLPInformation(): void { - $this->xmlStartTag('LPData', array()); - $set = $this->db->query( - $q = "SELECT * FROM ut_lp_marks " . - " WHERE status_changed >= " . $this->db->quote( - $this->getTimestamp(), - "timestamp" - ) - ); - - while ($rec = $this->db->fetchAssoc($set)) { - $ref_ids = array(); + $this->xmlStartTag('LPData', []); + + $collection = $this->tracking_db_factory->lpMarks()->repository()->readAllEntriesWithStatusChangedAfter($this->getTimestamp()); + + foreach ($collection as $lp_mark) { + $ref_ids = []; if ($this->getIncludeRefIds()) { - $ref_ids = ilObject::_getAllReferences((int) $rec["obj_id"]); + $ref_ids = ilObject::_getAllReferences($lp_mark->getObjectId()); } if (!is_array($this->getTypeFilter()) || (count($this->getTypeFilter()) == 0) || in_array( - ilObject::_lookupType((int) $rec["obj_id"]), + ilObject::_lookupType($lp_mark->getObjectId()), $this->getTypeFilter() )) { $this->xmlElement( 'LPChange', - array( - 'UserId' => (int) $rec["usr_id"], - 'ObjId' => (int) $rec["obj_id"], + [ + 'UserId' => $lp_mark->getUserId(), + 'ObjId' => $lp_mark->getObjectId(), 'RefIds' => implode(",", $ref_ids), - 'Timestamp' => $rec["status_changed"], - 'LPStatus' => (int) $rec["status"] - ) + 'Timestamp' => $lp_mark->getStatusChanged(), + 'LPStatus' => $lp_mark->getStatus() + ] ); } } diff --git a/components/ILIAS/Tracking/classes/class.ilLearningProgressBaseGUI.php b/components/ILIAS/Tracking/classes/class.ilLearningProgressBaseGUI.php index 1debd834d1de..90be7b6df734 100755 --- a/components/ILIAS/Tracking/classes/class.ilLearningProgressBaseGUI.php +++ b/components/ILIAS/Tracking/classes/class.ilLearningProgressBaseGUI.php @@ -18,11 +18,11 @@ declare(strict_types=0); -use ILIAS\Refinery\Factory as RefineryFactory; use ILIAS\HTTP\Services as HttpServices; +use ILIAS\MetaData\Services\ServicesInterface as LOMServices; +use ILIAS\Refinery\Factory as RefineryFactory; use ILIAS\UI\Factory as UIFactory; use ILIAS\UI\Renderer as UIRenderer; -use ILIAS\MetaData\Services\ServicesInterface as LOMServices; /** * Class ilObjUserTrackingGUI diff --git a/components/ILIAS/Tracking/classes/collection/class.ilLPCollection.php b/components/ILIAS/Tracking/classes/collection/class.ilLPCollection.php index e120d7e90ca9..0d5a46345b1d 100755 --- a/components/ILIAS/Tracking/classes/collection/class.ilLPCollection.php +++ b/components/ILIAS/Tracking/classes/collection/class.ilLPCollection.php @@ -16,34 +16,31 @@ * *********************************************************************/ -declare(strict_types=0); -/** - * LP collection base class - * @author Jörg Lützenkirchen - * @ingroup ServicesTracking - */ +declare(strict_types=1); + +use ILIAS\Tracking\DB\Factory as TrackingDBFactory; +use ILIAS\Tracking\DB\FactoryInterface as TrackingDBFactoryInterface; + abstract class ilLPCollection { + protected array $items; protected int $obj_id; protected int $mode; - protected array $items = []; protected ilDBInterface $db; protected ilLogger $logger; + protected TrackingDBFactoryInterface $tracking_db_factory; public function __construct(int $a_obj_id, int $a_mode) { global $DIC; - + $this->items = []; $this->db = $DIC->database(); $this->logger = $DIC->logger()->trac(); - + $this->tracking_db_factory = new TrackingDBFactory($this->db); $this->obj_id = $a_obj_id; $this->mode = $a_mode; - - if ($a_obj_id) { - $this->read($a_obj_id); - } + $this->read($a_obj_id); } public static function getInstanceByMode( @@ -79,16 +76,11 @@ public static function getInstanceByMode( public static function getCollectionModes(): array { return array( - ilLPObjSettings::LP_MODE_COLLECTION - , - ilLPObjSettings::LP_MODE_COLLECTION_TLT - , - ilLPObjSettings::LP_MODE_COLLECTION_MANUAL - , - ilLPObjSettings::LP_MODE_SCORM - , - ilLPObjSettings::LP_MODE_OBJECTIVES - , + ilLPObjSettings::LP_MODE_COLLECTION, + ilLPObjSettings::LP_MODE_COLLECTION_TLT, + ilLPObjSettings::LP_MODE_COLLECTION_MANUAL, + ilLPObjSettings::LP_MODE_SCORM, + ilLPObjSettings::LP_MODE_OBJECTIVES, ilLPObjSettings::LP_MODE_COLLECTION_MOBS ); } @@ -123,16 +115,13 @@ public function getItems(): array protected function read(int $a_obj_id): void { - $items = array(); - $res = $this->db->query( - "SELECT * FROM ut_lp_collections" . - " WHERE obj_id = " . $this->db->quote($a_obj_id, "integer") - ); - while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - if ($this->validateEntry((int) $row->item_id)) { - $items[] = $row->item_id; + $items = []; + $lp_collection = $this->tracking_db_factory->lpCollection()->repository()->readLPCollection($a_obj_id); + foreach ($lp_collection as $lp_collection_entry) { + if ($this->validateEntry($lp_collection_entry->getItemId())) { + $items[] = $lp_collection_entry->getItemId(); } else { - $this->deleteEntry($row->item_id); + $this->deleteEntry($lp_collection_entry->getItemId()); } } $this->items = $items; @@ -140,21 +129,11 @@ protected function read(int $a_obj_id): void public function delete(): void { - $query = "DELETE FROM ut_lp_collections" . - " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer"); - $this->db->manipulate($query); - - $query = "DELETE FROM ut_lp_coll_manual" . - " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer"); - $this->db->manipulate($query); - // #15462 - reset internal data - $this->items = array(); + $this->tracking_db_factory->lpCollection()->repository()->deleteLPCollection($this->obj_id); + $this->tracking_db_factory->lpCollection()->repository()->deleteLPCollectionManual($this->obj_id); + $this->items = []; } - // - // ENTRIES - // - protected function validateEntry(int $a_item_id): bool { return true; @@ -162,33 +141,27 @@ protected function validateEntry(int $a_item_id): bool public function isAssignedEntry(int $a_item_id): bool { - if (is_array($this->items)) { - return in_array($a_item_id, $this->items); - } - return false; + return in_array($a_item_id, $this->items ?? []); } protected function addEntry(int $a_item_id): bool { - if (!$this->isAssignedEntry($a_item_id)) { - $query = "INSERT INTO ut_lp_collections" . - " (obj_id, lpmode, item_id)" . - " VALUES (" . $this->db->quote($this->obj_id, "integer") . - ", " . $this->db->quote($this->mode, "integer") . - ", " . $this->db->quote($a_item_id, "integer") . - ")"; - $this->db->manipulate($query); - $this->items[] = $a_item_id; - } + $element = $this->tracking_db_factory->lpCollection()->element()->lpCollectionElement() + ->withItemId($a_item_id) + ->withLPMode($this->mode) + ->withGroupingId(0) + ->withIsActive(true) + ->withNumObligatory(0); + $collection = $this->tracking_db_factory->lpCollection()->element()->lpCollection($element) + ->withObjectId($this->obj_id); + $this->tracking_db_factory->lpCollection()->repository()->writeLPCollection($collection); + $this->items[] = $a_item_id; return true; } protected function deleteEntry(int $a_item_id): bool { - $query = "DELETE FROM ut_lp_collections" . - " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer") . - " AND item_id = " . $this->db->quote($a_item_id, "integer"); - $this->db->manipulate($query); + $this->tracking_db_factory->lpCollection()->repository()->deleteLPCollectionEntry($this->obj_id, $a_item_id); return true; } diff --git a/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfLMChapters.php b/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfLMChapters.php index e25967a07414..009a02e6eaa8 100755 --- a/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfLMChapters.php +++ b/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfLMChapters.php @@ -18,11 +18,6 @@ declare(strict_types=0); -/** - * LP collection of learning module chapters - * @author Jörg Lützenkirchen - * @ingroup ServicesTracking - */ class ilLPCollectionOfLMChapters extends ilLPCollection { protected static array $possible_items = array(); diff --git a/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfMediaObjects.php b/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfMediaObjects.php index 781412778ec6..c070262e38f4 100755 --- a/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfMediaObjects.php +++ b/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfMediaObjects.php @@ -17,11 +17,7 @@ *********************************************************************/ declare(strict_types=0); -/** - * LP collection of media objects - * @author Jörg Lützenkirchen - * @ingroup ServicesTracking - */ + class ilLPCollectionOfMediaObjects extends ilLPCollection { protected static array $possible_items = array(); diff --git a/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfObjectives.php b/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfObjectives.php index 4a6cb9070946..9112e8112f15 100755 --- a/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfObjectives.php +++ b/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfObjectives.php @@ -18,11 +18,6 @@ declare(strict_types=0); -/** - * LP collection of objectives - * @author Jörg Lützenkirchen - * @ingroup ServicesTracking - */ class ilLPCollectionOfObjectives extends ilLPCollection { protected function read(int $a_obj_id): void diff --git a/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfRepositoryObjects.php b/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfRepositoryObjects.php index f374c2f25002..9ac732cfb060 100755 --- a/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfRepositoryObjects.php +++ b/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfRepositoryObjects.php @@ -18,14 +18,11 @@ declare(strict_types=0); -/** - * LP collection of repository objects - * @author Jörg Lützenkirchen - * @ingroup ServicesTracking - */ +use ILIAS\Tracking\DB\Factory as TrackingDBFactory; + class ilLPCollectionOfRepositoryObjects extends ilLPCollection { - protected static array $possible_items = array(); + protected static array $possible_items = []; protected ilTree $tree; protected ilObjectDefinition $objDefinition; @@ -44,11 +41,9 @@ public function getPossibleItems( int $a_ref_id, bool $a_full_data = false ): array { - global $DIC; - $cache_idx = $a_ref_id . "__" . $a_full_data; if (!isset(self::$possible_items[$cache_idx])) { - $all_possible = array(); + $all_possible = []; if (!$this->tree->isDeleted($a_ref_id)) { if (!$a_full_data) { @@ -165,14 +160,12 @@ public function cloneCollection(int $a_target_id, int $a_copy_id): void $target_collection = new static($target_obj_id, $this->mode); // clone (active) groupings - foreach ($this->getGroupedItemsForLPStatus( - ) as $grouping_id => $group) { - $target_item_ids = array(); + foreach ($this->getGroupedItemsForLPStatus() as $grouping_id => $group) { + $target_item_ids = []; foreach ($group["items"] as $item) { if (!isset($mappings[$item]) or !$mappings[$item]) { continue; } - $target_item_ids[] = $mappings[$item]; } @@ -199,30 +192,26 @@ public function cloneCollection(int $a_target_id, int $a_copy_id): void protected function read(int $a_obj_id): void { - $items = array(); - $ref_ids = ilObject::_getAllReferences($a_obj_id); $ref_id = end($ref_ids); $possible = $this->getPossibleItems($ref_id); - - $res = $this->db->query( - "SELECT utc.item_id, obd.type" . - " FROM ut_lp_collections utc" . - " JOIN object_reference obr ON item_id = ref_id" . - " JOIN object_data obd ON obr.obj_id = obd.obj_id" . - " WHERE utc.obj_id = " . $this->db->quote($a_obj_id, "integer") . - " AND active = " . $this->db->quote(1, "integer") . - " ORDER BY title" - ); - while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - if (in_array($row->item_id, $possible) && - $this->validateEntry((int) $row->item_id)) { - $items[] = $row->item_id; + $collection = $this->tracking_db_factory->lpCollection()->repository()->readLPCollection($a_obj_id); + $items = []; + if (is_null($collection)) { + $this->items = $items; + return; + } + $active_collection = $collection->getSubCollectionOfItemsByActiveStatus(true); + foreach ($active_collection as $element) { + if ( + in_array($element->getItemId(), $possible) && + $this->validateEntry($element->getItemId()) + ) { + $items[] = $element->getItemId(); } else { - $this->deleteEntry((int) $row->item_id); + $this->deleteEntry($element->getItemId()); } } - $this->items = $items; } @@ -232,17 +221,15 @@ protected function addEntry(int $a_item_id): bool if (!$this->isAssignedEntry($a_item_id)) { // #13278 - because of grouping inactive items may exist $this->deleteEntry($a_item_id); - - $query = "INSERT INTO ut_lp_collections" . - " (obj_id, lpmode, item_id, grouping_id, num_obligatory, active)" . - " VALUES (" . $this->db->quote($this->obj_id, "integer") . - ", " . $this->db->quote($this->mode, "integer") . - ", " . $this->db->quote($a_item_id, "integer") . - ", " . $this->db->quote(0, "integer") . - ", " . $this->db->quote(0, "integer") . - ", " . $this->db->quote(1, "integer") . - ")"; - $this->db->manipulate($query); + $element = $this->tracking_db_factory->lpCollection()->element()->lpCollectionElement() + ->withLPMode($this->mode) + ->withItemId($a_item_id) + ->withGroupingId(0) + ->withNumObligatory(0) + ->withIsActive(true); + $collection = $this->tracking_db_factory->lpCollection()->element()->lpCollection($element) + ->withObjectId($this->obj_id); + $this->tracking_db_factory->lpCollection()->repository()->writeLPCollection($collection); $this->items[] = $a_item_id; } return true; @@ -250,56 +237,43 @@ protected function addEntry(int $a_item_id): bool protected function deleteEntry(int $a_item_id): bool { - $query = "DELETE FROM ut_lp_collections " . - " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer") . - " AND item_id = " . $this->db->quote($a_item_id, "integer") . - " AND grouping_id = " . $this->db->quote(0, "integer"); - $this->db->manipulate($query); + $this->tracking_db_factory->lpCollection()->repository()->deleteLPCollectionEntryByGroupingId($this->obj_id, $a_item_id, 0); return true; } public static function hasGroupedItems(int $a_obj_id): bool { global $DIC; - - $ilDB = $DIC['ilDB']; - $query = "SELECT item_id FROM ut_lp_collections" . - " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer") . - " AND grouping_id > " . $ilDB->quote(0, "integer"); - $res = $ilDB->query($query); - return $res->numRows() ? true : false; + $tracking_db_factory = new TrackingDBFactory($DIC->database()); + $collection = $tracking_db_factory->lpCollection()->repository()->readLPCollection($a_obj_id); + if (is_null($collection)) { + return false; + } + return $collection->getGroupingIdsGreaterZero() > 0; } protected function getNonGroupedItems(array $a_item_ids): array { - $grouped_item_ids = []; - - $query = "SELECT item_id FROM ut_lp_collections" . - " WHERE obj_id = " . $this->db->quote($this->obj_id, ilDBConstants::T_INTEGER) . - " AND " . $this->db->in("item_id", $a_item_ids, false, ilDBConstants::T_INTEGER) . - " AND grouping_id > " . $this->db->quote(0, ilDBConstants::T_INTEGER); - $res = $this->db->query($query); - while ($row = $res->fetchObject()) { - $grouped_item_ids[] = $row->item_id; + $collection = $this->tracking_db_factory->lpCollection()->repository()->readLPCollection($this->obj_id); + if (is_null($collection)) { + return $a_item_ids; } - + $grouped_item_ids = $collection + ->getSubCollectionOfItemsByItemIds(...$a_item_ids) + ->getSubCollectionOfItemsByGroupingIds(...$collection->getGroupingIdsGreaterZero()) + ->getItemIds(); return array_diff($a_item_ids, $grouped_item_ids); } protected function getGroupingIds(array $a_item_ids): array { - $grouping_ids = []; - - $query = "SELECT grouping_id FROM ut_lp_collections" . - " WHERE obj_id = " . $this->db->quote($this->obj_id, ilDBConstants::T_INTEGER) . - " AND " . $this->db->in("item_id", $a_item_ids, false, ilDBConstants::T_INTEGER) . - " AND grouping_id > " . $this->db->quote(0, ilDBConstants::T_INTEGER); - $res = $this->db->query($query); - while ($row = $res->fetchObject()) { - $grouping_ids[] = $row->grouping_id; + $collection = $this->tracking_db_factory->lpCollection()->repository()->readLPCollection($this->obj_id); + if (is_null($collection)) { + return []; } - - return $grouping_ids; + return $collection + ->getSubCollectionOfItemsByItemIds(...$a_item_ids) + ->getGroupingIdsGreaterZero(); } public function deactivateEntries(array $a_item_ids): void @@ -307,18 +281,14 @@ public function deactivateEntries(array $a_item_ids): void parent::deactivateEntries($a_item_ids); $grouping_ids = $this->getGroupingIds($a_item_ids); - if ($grouping_ids) { - $query = "UPDATE ut_lp_collections" . - " SET active = " . $this->db->quote(0, "integer") . - " WHERE " . $this->db->in( - "grouping_id", - $grouping_ids, - false, - "integer" - ) . - " AND obj_id = " . $this->db->quote($this->obj_id, "integer"); - $this->db->manipulate($query); + if (count($grouping_ids) === 0) { + return; } + $collection = $this->tracking_db_factory->lpCollection()->repository()->readLPCollection($this->obj_id); + $adjusted_collection = $collection + ->getSubCollectionOfItemsByGroupingIds(...$grouping_ids) + ->withChangedActiveStatusOfAllElements(false); + $this->tracking_db_factory->lpCollection()->repository()->writeLPCollection($adjusted_collection); } public function activateEntries(array $a_item_ids): void @@ -328,18 +298,14 @@ public function activateEntries(array $a_item_ids): void parent::activateEntries($non_grouped_ids); $grouping_ids = $this->getGroupingIds($a_item_ids); - if ($grouping_ids) { - $query = "UPDATE ut_lp_collections" . - " SET active = " . $this->db->quote(1, "integer") . - " WHERE " . $this->db->in( - "grouping_id", - $grouping_ids, - false, - "integer" - ) . - " AND obj_id = " . $this->db->quote($this->obj_id, "integer"); - $this->db->manipulate($query); + if (count($grouping_ids) === 0) { + return; } + $collection = $this->tracking_db_factory->lpCollection()->repository()->readLPCollection($this->obj_id); + $adjusted_collection = $collection + ->getSubCollectionOfItemsByGroupingIds(...$grouping_ids) + ->withChangedActiveStatusOfAllElements(true); + $this->tracking_db_factory->lpCollection()->repository()->writeLPCollection($adjusted_collection); } public function createNewGrouping( @@ -347,114 +313,60 @@ public function createNewGrouping( int $a_num_obligatory = 1 ): void { $this->activateEntries($a_item_ids); - - $all_item_ids = array(); $grouping_ids = $this->getGroupingIds($a_item_ids); - $query = "SELECT item_id FROM ut_lp_collections" . - " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer") . - " AND " . $this->db->in( - "grouping_id", - $grouping_ids, - false, - "integer" - ); - $res = $this->db->query($query); - while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - $all_item_ids[] = $row->item_id; - } - - $all_item_ids = array_unique(array_merge($all_item_ids, $a_item_ids)); - + $collection = $this->tracking_db_factory->lpCollection()->repository()->readLPCollection($this->obj_id); + $all_item_ids = array_unique( + array_merge( + $collection->getSubCollectionOfItemsByGroupingIds(...$grouping_ids)->getItemIds(), + $a_item_ids + ) + ); $this->releaseGrouping($a_item_ids); - - // Create new grouping - $query = "SELECT MAX(grouping_id) grp FROM ut_lp_collections" . - " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer") . - " GROUP BY obj_id"; - $res = $this->db->query($query); - $row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT); - $grp_id = $row->grp; - ++$grp_id; - - $query = "UPDATE ut_lp_collections SET" . - " grouping_id = " . $this->db->quote($grp_id, "integer") . - ", num_obligatory = " . $this->db->quote( - $a_num_obligatory, - "integer" - ) . - ", active = " . $this->db->quote(1, "integer") . - " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer") . - " AND " . $this->db->in("item_id", $all_item_ids, false, "integer"); - $this->db->manipulate($query); + $adjusted_collection = $collection->getSubCollectionOfItemsByItemIds(...$all_item_ids) + ->withChangedGroupingIdOfAllElements($collection->getMaxGroupingNumber() + 1) + ->withChangedNumObligatoryIdOfAllElements($a_num_obligatory) + ->withChangedActiveStatusOfAllElements(true); + $this->tracking_db_factory->lpCollection()->repository()->writeLPCollection($adjusted_collection); } public function releaseGrouping(array $a_item_ids): void { + $collection = $this->tracking_db_factory->lpCollection()->repository()->readLPCollection($this->obj_id); $grouping_ids = $this->getGroupingIds($a_item_ids); - - $query = "UPDATE ut_lp_collections" . - " SET grouping_id = " . $this->db->quote(0, "integer") . - ", num_obligatory = " . $this->db->quote(0, "integer") . - " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer") . - " AND " . $this->db->in( - "grouping_id", - $grouping_ids, - false, - "integer" - ); - $this->db->manipulate($query); + $adjusted_collection = $collection->getSubCollectionOfItemsByGroupingIds(...$grouping_ids) + ->withChangedGroupingIdOfAllElements(0) + ->withChangedNumObligatoryIdOfAllElements(0); + $this->tracking_db_factory->lpCollection()->repository()->writeLPCollection($adjusted_collection); } public function saveObligatoryMaterials(array $a_obl): void { + $collection = $this->tracking_db_factory->lpCollection()->repository()->readLPCollection($this->obj_id); foreach ($a_obl as $grouping_id => $num) { - $query = "SELECT count(obj_id) num FROM ut_lp_collections" . - " WHERE obj_id = " . $this->db->quote( - $this->obj_id, - "integer" - ) . - " AND grouping_id = " . $this->db->quote( - $grouping_id, - 'integer' - ) . - " GROUP BY obj_id"; - $res = $this->db->query($query); - while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - if ($num <= 0 || $num >= $row->num) { - throw new UnexpectedValueException(); - } + $col_num = $collection->getSubCollectionOfItemsByGroupingId($grouping_id)->count(); + if ($num <= 0 || $num >= $col_num) { + throw new UnexpectedValueException(); } } foreach ($a_obl as $grouping_id => $num) { - $query = "UPDATE ut_lp_collections" . - " SET num_obligatory = " . $this->db->quote($num, "integer") . - " WHERE obj_id = " . $this->db->quote( - $this->obj_id, - "integer" - ) . - " AND grouping_id = " . $this->db->quote( - $grouping_id, - "integer" - ); - $this->db->manipulate($query); + $adjusted_collection = $collection->getSubCollectionOfItemsByGroupingId($grouping_id) + ->withChangedNumObligatoryIdOfAllElements($num); + $this->tracking_db_factory->lpCollection()->repository()->writeLPCollection($adjusted_collection); } } public function getTableGUIData(int $a_parent_ref_id): array { $items = $this->getPossibleItems($a_parent_ref_id, true); - - $data = array(); - $done = array(); + $data = []; + $done = []; foreach ($items as $item_id => $item) { if (in_array($item_id, $done)) { continue; } - $table_item = $this->parseTableGUIItem($item_id, $item); - // grouping - $table_item['grouped'] = array(); + $table_item['grouped'] = []; $grouped_items = $this->getTableGUItemGroup($item_id); if (count((array) ($grouped_items['items'] ?? [])) > 1) { foreach ($grouped_items['items'] as $grouped_item_id) { @@ -462,14 +374,12 @@ public function getTableGUIData(int $a_parent_ref_id): array !is_array($items[$grouped_item_id] ?? false)) { // #15498 continue; } - $table_item['grouped'][] = $this->parseTableGUIItem( $grouped_item_id, $items[$grouped_item_id] ); $table_item['num_obligatory'] = $grouped_items['num_obligatory']; $table_item['grouping_id'] = $grouped_items['grouping_id']; - $done[] = $grouped_item_id; } } @@ -483,42 +393,32 @@ protected function parseTableGUIItem(int $a_id, array $a_item): array $table_item = $a_item; $table_item['id'] = $a_id; $table_item['status'] = $this->isAssignedEntry($a_id); - $olp = ilObjectLP::getInstance($a_item['obj_id']); $table_item['mode_id'] = $olp->getCurrentMode(); $table_item['mode'] = $olp->getModeText($table_item['mode_id']); $table_item['anonymized'] = $olp->isAnonymized(); - return $table_item; } protected function getTableGUItemGroup(int $item_id): array { - $items = array(); - $query = "SELECT grouping_id FROM ut_lp_collections" . - " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer") . - " AND item_id = " . $this->db->quote($item_id, "integer"); - $res = $this->db->query($query); - $grouping_id = 0; - while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - $grouping_id = (int) $row->grouping_id; + $collection = $this->tracking_db_factory->lpCollection()->repository()->readLPCollection($this->obj_id); + $items = []; + if (is_null($collection)) { + return $items; } - if ($grouping_id > 0) { - $query = "SELECT item_id, num_obligatory FROM ut_lp_collections" . - " WHERE obj_id = " . $this->db->quote( - $this->obj_id, - "integer" - ) . - " AND grouping_id = " . $this->db->quote( - $grouping_id, - "integer" - ); - $res = $this->db->query($query); - while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - $items['items'][] = (int) $row->item_id; - $items['num_obligatory'] = (int) $row->num_obligatory; - $items['grouping_id'] = (int) $grouping_id; - } + $item = $collection->getElementByItemId($item_id); + if ( + is_null($item) || + $item->getGroupingId() <= 0 + ) { + return $items; + } + $items_with_grouping_id = $collection->getSubCollectionOfItemsByGroupingId($item->getGroupingId()); + foreach ($items_with_grouping_id as $item_with_grouping_id) { + $items['items'][] = $item_with_grouping_id->getItemId(); + $items['num_obligatory'] = $item_with_grouping_id->getNumObligatory(); + $items['grouping_id'] = $item->getGroupingId(); } return $items; } @@ -526,16 +426,16 @@ protected function getTableGUItemGroup(int $item_id): array public function getGroupedItemsForLPStatus(): array { $items = $this->getItems(); - $query = " SELECT * FROM ut_lp_collections" . - " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer") . - " AND active = " . $this->db->quote(1, "integer"); - $res = $this->db->query($query); - - $grouped = array(); - while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - if (in_array($row->item_id, $items)) { - $grouped[$row->grouping_id]['items'][] = (int) $row->item_id; - $grouped[$row->grouping_id]['num_obligatory'] = (int) $row->num_obligatory; + $collection = $this->tracking_db_factory->lpCollection()->repository()->readLPCollection($this->obj_id); + if (is_null($collection)) { + return []; + } + $active_items = $collection->getSubCollectionOfActiveItems(); + $grouped = []; + foreach ($active_items as $item) { + if (in_array($item->getItemId(), $items)) { + $grouped[$item->getGroupingId()]['items'][] = $item->getItemId(); + $grouped[$item->getGroupingId()]['num_obligatory'] = $item->getNumObligatory(); } } return $grouped; diff --git a/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfSCOs.php b/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfSCOs.php index 4b330a86e4a1..ba00ba72d513 100755 --- a/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfSCOs.php +++ b/components/ILIAS/Tracking/classes/collection/class.ilLPCollectionOfSCOs.php @@ -18,11 +18,6 @@ declare(strict_types=0); -/** - * LP collection of SCOs - * @author Jörg Lützenkirchen - * @ingroup ServicesTracking - */ class ilLPCollectionOfSCOs extends ilLPCollection { protected static array $possible_items = array(); diff --git a/components/ILIAS/Tracking/classes/repository_statistics/class.ilLPListOfSettingsGUI.php b/components/ILIAS/Tracking/classes/repository_statistics/class.ilLPListOfSettingsGUI.php index 1f050a9d8304..faf2f13b2c14 100755 --- a/components/ILIAS/Tracking/classes/repository_statistics/class.ilLPListOfSettingsGUI.php +++ b/components/ILIAS/Tracking/classes/repository_statistics/class.ilLPListOfSettingsGUI.php @@ -18,9 +18,9 @@ declare(strict_types=0); -use ILIAS\UI\Component\Input\Container\Form\Standard as StandardForm; use ILIAS\Tracking\View\Factory as ViewFactory; use ILIAS\Tracking\View\ProgressBlock\Settings\RepositoryInterface as ProgressBlockSettings; +use ILIAS\UI\Component\Input\Container\Form\Standard as StandardForm; /** * Class ilLPListOfSettingsGUI diff --git a/components/ILIAS/Tracking/classes/status/Collection.php b/components/ILIAS/Tracking/classes/status/Collection.php new file mode 100644 index 000000000000..182fec3717b1 --- /dev/null +++ b/components/ILIAS/Tracking/classes/status/Collection.php @@ -0,0 +1,91 @@ +elements = $elements; + $this->index = 0; + } + + public function getElementsByStatusIds( + string ...$lp_status_ids + ): CollectionInterface { + $elements = []; + foreach ($lp_status_ids as $lp_status_id) { + $element = $this->getElementByStatusId($lp_status_id); + if (is_null($element)) { + continue; + } + $elements[] = $element; + } + return $this->factory->collection(...$elements); + } + + public function getElementByStatusId( + string $lp_status_id + ): LPStatusInterface|null { + foreach ($this->elements as $element) { + if ($element->getLPStatusId() === $lp_status_id) { + return $element; + } + } + return null; + } + + public function current(): LPStatusInterface + { + return $this->elements[$this->index]; + } + + public function key(): int + { + return $this->index; + } + + public function next(): void + { + $this->index++; + } + + public function valid(): bool + { + return isset($this->elements[$this->index]); + } + + public function rewind(): void + { + $this->index = 0; + } + + public function count(): int + { + return count($this->elements); + } +} diff --git a/components/ILIAS/Tracking/classes/status/CollectionInterface.php b/components/ILIAS/Tracking/classes/status/CollectionInterface.php new file mode 100644 index 000000000000..495cdde5e65e --- /dev/null +++ b/components/ILIAS/Tracking/classes/status/CollectionInterface.php @@ -0,0 +1,39 @@ +init($this->DIC); + $elements[] = $lp_status; + } + return $this->collection(...$elements); + } +} diff --git a/components/ILIAS/Tracking/classes/status/FactoryInterface.php b/components/ILIAS/Tracking/classes/status/FactoryInterface.php new file mode 100644 index 000000000000..aeb570731e67 --- /dev/null +++ b/components/ILIAS/Tracking/classes/status/FactoryInterface.php @@ -0,0 +1,30 @@ + - * @author Björn Heyser - * @author Stefan Schneider - */ class ilLPStatusCmiXapiCompleted extends ilLPStatusCmiXapiAbstract { + protected const string LNG_TEXT = 'trac_mode_cmix_completed'; + protected const string LNG_TEXT_INFO = 'trac_mode_cmix_completed_info'; + protected ilLanguage $lng; + protected function resultSatisfyCompleted(ilCmiXapiResult $result): bool { if ($result->getStatus() === 'completed') { return true; } - return false; } @@ -39,4 +38,25 @@ protected function resultSatisfyFailed(ilCmiXapiResult $result): bool { return false; } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_CMIX_COMPLETED; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiCompletedOrPassed.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiCompletedOrPassed.php index ce2281cf1554..c61cd55d072e 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiCompletedOrPassed.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiCompletedOrPassed.php @@ -16,26 +16,24 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\DI\Container; -/** - * Class ilLPStatusCmiXapiCompletedOrPassed - * @author Uwe Kohnle - * @author Björn Heyser - * @author Stefan Schneider - */ class ilLPStatusCmiXapiCompletedOrPassed extends ilLPStatusCmiXapiAbstract { + protected const string LNG_TEXT = 'trac_mode_cmix_completed_or_passed'; + protected const string LNG_TEXT_INFO = 'trac_mode_cmix_completed_or_passed_info'; + protected ilLanguage $lng; + protected function resultSatisfyCompleted(ilCmiXapiResult $result): bool { if ($result->getStatus() === 'completed') { return true; } - if ($result->getStatus() === 'passed') { return true; } - return false; } @@ -43,4 +41,25 @@ protected function resultSatisfyFailed(ilCmiXapiResult $result): bool { return false; } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_CMIX_COMPLETED_OR_PASSED; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiCompletedOrPassedWithFailed.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiCompletedOrPassedWithFailed.php index 868200e44f0c..6292df771831 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiCompletedOrPassedWithFailed.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiCompletedOrPassedWithFailed.php @@ -16,22 +16,43 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\DI\Container; -/** - * Class ilLPStatusCmiXapiCompletedOrPassedWithFailed - * @author Uwe Kohnle - * @author Björn Heyser - * @author Stefan Schneider - */ class ilLPStatusCmiXapiCompletedOrPassedWithFailed extends ilLPStatusCmiXapiCompletedOrPassed { + protected const string LNG_TEXT = 'trac_mode_cmix_compl_or_passed_with_failed'; + protected const string LNG_TEXT_INFO = 'trac_mode_cmix_compl_or_passed_with_failed_info'; + protected ilLanguage $lng; + protected function resultSatisfyFailed(ilCmiXapiResult $result): bool { if ($result->getStatus() === 'failed') { return true; } - return false; } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_CMIX_COMPL_OR_PASSED_WITH_FAILED; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiCompletedWithFailed.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiCompletedWithFailed.php index 0ac7b80ef480..3e3f4c37a3e0 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiCompletedWithFailed.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiCompletedWithFailed.php @@ -16,22 +16,42 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\DI\Container; -/** - * Class ilLPStatusCmiXapiCompletedWithFailed - * @author Uwe Kohnle - * @author Björn Heyser - * @author Stefan Schneider - */ class ilLPStatusCmiXapiCompletedWithFailed extends ilLPStatusCmiXapiCompleted { + protected const string LNG_TEXT = 'trac_mode_cmix_compl_with_failed'; + protected const string LNG_TEXT_INFO = 'trac_mode_cmix_compl_with_failed_info'; + protected ilLanguage $lng; + protected function resultSatisfyFailed(ilCmiXapiResult $result): bool { if ($result->getStatus() === 'failed') { return true; } - return false; } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_CMIX_COMPL_WITH_FAILED; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiPassed.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiPassed.php index 15033a57bdd2..025515e69e43 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiPassed.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiPassed.php @@ -16,22 +16,21 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\DI\Container; -/** - * Class ilLPStatusCmiXapiPassed - * @author Uwe Kohnle - * @author Björn Heyser - * @author Stefan Schneider - */ class ilLPStatusCmiXapiPassed extends ilLPStatusCmiXapiAbstract { + protected const string LNG_TEXT = 'trac_mode_cmix_passed'; + protected const string LNG_TEXT_INFO = 'trac_mode_cmix_passed_info'; + protected ilLanguage $lng; + protected function resultSatisfyCompleted(ilCmiXapiResult $result): bool { if ($result->getStatus() === 'passed') { return true; } - return false; } @@ -39,4 +38,25 @@ protected function resultSatisfyFailed(ilCmiXapiResult $result): bool { return false; } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_CMIX_PASSED; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiPassedWithFailed.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiPassedWithFailed.php index dea46cbcfc10..8c1fc69ca660 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiPassedWithFailed.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCmiXapiPassedWithFailed.php @@ -16,22 +16,42 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\DI\Container; -/** - * Class ilLPStatusCmiXapiPassedWithFailed - * @author Uwe Kohnle - * @author Björn Heyser - * @author Stefan Schneider - */ class ilLPStatusCmiXapiPassedWithFailed extends ilLPStatusCmiXapiPassed { + protected const string LNG_TEXT = 'trac_mode_cmix_passed_with_failed'; + protected const string LNG_TEXT_INFO = 'trac_mode_cmix_passed_with_failed_info'; + protected ilLanguage $lng; + protected function resultSatisfyFailed(ilCmiXapiResult $result): bool { if ($result->getStatus() === 'failed') { return true; } - return false; } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_CMIX_PASSED_WITH_FAILED; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCollection.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCollection.php index 0ab1a4b6458a..36b6a0553c2c 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCollection.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCollection.php @@ -18,31 +18,33 @@ declare(strict_types=1); -/** - * @author Stefan Meyer - * @package ilias-tracking - */ +use ILIAS\DI\Container; +use ILIAS\Tracking\View\ProgressBlock\Settings\Repository as ProgressBlockSettingsRepository; +use ILIAS\Tracking\View\ProgressBlock\Settings\RepositoryInterface as ProgressBlockSettingsRepositoryInterface; + class ilLPStatusCollection extends ilLPStatus { - private ilTree $tree; + protected const string LNG_TEXT = 'trac_mode_collection'; + protected const string LNG_TEXT_INFO = 'trac_mode_collection_info'; + protected ilLanguage $lng; + protected ilTree $tree; + protected ProgressBlockSettingsRepositoryInterface $progress_block_settings_repository; public function __construct(int $a_obj_id) { global $DIC; - parent::__construct($a_obj_id); $this->tree = $DIC->repositoryTree(); } public static function _getNotAttempted(int $a_obj_id): array { - $users = array(); - + $users = []; $members = self::getMembers($a_obj_id); if ($members) { // diff in progress and completed (use stored result in LPStatusWrapper) $users = array_diff( - (array) $members, + $members, ilLPStatusWrapper::_getInProgress($a_obj_id) ); $users = array_diff( @@ -54,14 +56,12 @@ public static function _getNotAttempted(int $a_obj_id): array ilLPStatusWrapper::_getFailed($a_obj_id) ); } - return $users; } public static function _getInProgress(int $a_obj_id): array { $users = ilChangeEvent::lookupUsersInProgress($a_obj_id); - $olp = ilObjectLP::getInstance($a_obj_id); $collection = $olp->getCollectionInstance(); if ($collection) { @@ -83,7 +83,6 @@ public static function _getInProgress(int $a_obj_id): array ); } } - // Exclude all users with status completed. $users = array_diff( $users, @@ -91,12 +90,10 @@ public static function _getInProgress(int $a_obj_id): array ); // Exclude all users with status failed. $users = array_diff($users, ilLPStatusWrapper::_getFailed($a_obj_id)); - if ($users) { // Exclude all non members $users = array_intersect(self::getMembers($a_obj_id), $users); } - return $users; } @@ -107,9 +104,7 @@ public static function _getInProgress(int $a_obj_id): array public static function _getCompleted(int $a_obj_id): array { global $DIC; - $ilObjDataCache = $DIC['ilObjDataCache']; - $olp = ilObjectLP::getInstance($a_obj_id); $collection = $olp->getCollectionInstance(); $grouped_items = []; @@ -118,15 +113,15 @@ public static function _getCompleted(int $a_obj_id): array } if (!count($grouped_items)) { // #11513 - empty collections cannot be completed - return array(); + return []; } else { // New handling for optional assignments $counter = 0; - $users = array(); + $users = []; foreach ($grouped_items as $grouping_id => $grouping) { $isGrouping = $grouping_id ? true : false; - $grouping_completed = array(); - $grouping_completed_users_num = array(); + $grouping_completed = []; + $grouping_completed_users_num = []; foreach ((array) $grouping['items'] as $item) { $item_id = $ilObjDataCache->lookupObjId((int) $item); $tmp_users = ilLPStatusWrapper::_getCompleted($item_id); @@ -160,39 +155,29 @@ public static function _getCompleted(int $a_obj_id): array } } } - $users = array_diff($users, ilLPStatusWrapper::_getFailed($a_obj_id)); - if ($users) { // Exclude all non members $users = array_intersect(self::getMembers($a_obj_id), $users); } - - return (array) $users; + return $users; } public static function _getFailed(int $a_obj_id): array { global $DIC; - $ilObjDataCache = $DIC['ilObjDataCache']; - - $users = array(); - + $users = []; $olp = ilObjectLP::getInstance($a_obj_id); $collection = $olp->getCollectionInstance(); if ($collection) { - foreach ($collection->getGroupedItemsForLPStatus( - ) as $grouping_id => $grouping) { + foreach ($collection->getGroupedItemsForLPStatus() as $grouping_id => $grouping) { $isGrouping = $grouping_id ? true : false; - - $gr_failed = array(); - $gr_failed_users_num = array(); - $counter = 0; + $gr_failed = []; + $gr_failed_users_num = []; foreach ((array) $grouping['items'] as $item) { $item_id = $ilObjDataCache->lookupObjId((int) $item); $tmp_users = ilLPStatusWrapper::_getFailed($item_id); - if ($isGrouping) { foreach ($tmp_users as $tmp_user_id) { $gr_failed_users_num[$tmp_user_id] = @@ -202,7 +187,6 @@ public static function _getFailed(int $a_obj_id): array // One item failed is sufficient for status failed. $gr_failed = array_merge($gr_failed, $tmp_users); } - $counter++; } if ($isGrouping) { $allowed_failed = count( @@ -218,19 +202,16 @@ public static function _getFailed(int $a_obj_id): array $users = array_unique(array_merge($users, $gr_failed)); } } - if ($users) { // Exclude all non members $users = array_intersect(self::getMembers($a_obj_id), $users); } - return array_unique($users); } public static function _getStatusInfo(int $a_obj_id): array { - $status_info = array(); - + $status_info = []; $olp = ilObjectLP::getInstance($a_obj_id); $collection = $olp->getCollectionInstance(); if ($collection) { @@ -239,20 +220,16 @@ public static function _getStatusInfo(int $a_obj_id): array $status_info['collections'] ); } - return $status_info; } public static function _getTypicalLearningTime(string $type, int $obj_id, int $sub_id = 0): int { global $DIC; - $ilObjDataCache = $DIC['ilObjDataCache']; - if ($type == 'sahs') { return parent::_getTypicalLearningTime($type, $obj_id); } - $tlt = 0; $status_info = ilLPStatusWrapper::_getStatusInfo($obj_id); foreach ($status_info['collections'] as $item) { @@ -271,14 +248,9 @@ public function determineStatus( int $a_usr_id, ?object $a_obj = null ): int { - global $DIC; - - $ilObjDataCache = $DIC['ilObjDataCache']; - $status['completed'] = true; $status['failed'] = false; $status['in_progress'] = false; - switch ($this->ilObjDataCache->lookupType($a_obj_id)) { case "crs": case "fold": @@ -287,7 +259,6 @@ public function determineStatus( if (ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id)) { $status['in_progress'] = true; } - $olp = ilObjectLP::getInstance($a_obj_id); $collection = $olp->getCollectionInstance(); $grouped_items = []; @@ -299,7 +270,7 @@ public function determineStatus( $status['completed'] = false; } else { foreach ($grouped_items as $grouping_id => $grouping) { - $isGrouping = $grouping_id ? true : false; + $isGrouping = (bool) $grouping_id; $status = self::determineGroupingStatus( $status, $grouping, @@ -308,7 +279,6 @@ public function determineStatus( ); } } - if ($status['completed']) { if (!$this->isMember((int) $a_obj_id, (int) $a_usr_id)) { return self::LP_STATUS_IN_PROGRESS_NUM; @@ -316,11 +286,9 @@ public function determineStatus( return self::LP_STATUS_COMPLETED_NUM; } - if ($status['failed']) { return self::LP_STATUS_FAILED_NUM; } - if ($status['in_progress']) { return self::LP_STATUS_IN_PROGRESS_NUM; } @@ -329,9 +297,6 @@ public function determineStatus( return self::LP_STATUS_NOT_ATTEMPTED_NUM; } - /** - * Determine grouping status - */ public static function determineGroupingStatus( array $status, array $gr_info, @@ -339,9 +304,7 @@ public static function determineGroupingStatus( bool $is_grouping ): array { global $DIC; - $ilObjDataCache = $DIC['ilObjDataCache']; - $items = $gr_info['items']; if ($is_grouping) { $max_allowed_failed = count($items) - $gr_info['num_obligatory']; @@ -350,18 +313,15 @@ public static function determineGroupingStatus( $max_allowed_failed = 0; $required_completed = count($items); } - // Required for grouping with a number of obligatory items $num_failed = 0; $num_completed = 0; - foreach ($items as $item_id) { $item_id = $ilObjDataCache->lookupObjId((int) $item_id); $gr_status = ilLPStatusWrapper::_determineStatus( $item_id, $user_id ); - if ($gr_status == self::LP_STATUS_FAILED_NUM) { if (++$num_failed > $max_allowed_failed) { $status['failed'] = true; @@ -380,11 +340,6 @@ public static function determineGroupingStatus( return $status; } - /** - * @param int $objId - * @param int $usrId - * @return bool - */ protected function isMember(int $objId, int $usrId): bool { switch ($this->ilObjDataCache->lookupType($objId)) { @@ -419,30 +374,24 @@ protected function isMember(int $objId, int $usrId): bool } /** - * Get members for object - * @param int $a_obj_id * @return int[] */ protected static function getMembers(int $a_obj_id): array { global $DIC; - $ilObjDataCache = $DIC['ilObjDataCache']; $tree = $DIC['tree']; - switch ($ilObjDataCache->lookupType($a_obj_id)) { case 'crs': $member_obj = ilCourseParticipants::_getInstanceByObjId( $a_obj_id ); return $member_obj->getMembers(); - case 'grp': $member_obj = ilGroupParticipants::_getInstanceByObjId( $a_obj_id ); return $member_obj->getMembers(); - case 'fold': $folder_ref_ids = ilObject::_getAllReferences($a_obj_id); $folder_ref_id = current($folder_ref_ids); @@ -465,16 +414,13 @@ protected static function getMembers(int $a_obj_id): array return $member_obj->getMembers(); } break; - case 'lso': $member_obj = ilLearningSequenceParticipants::_getInstanceByObjId( $a_obj_id ); return $member_obj->getMembers(); - break; } - - return array(); + return []; } /** @@ -487,7 +433,7 @@ public static function _lookupCompletedForObject( if (!$a_user_ids) { $a_user_ids = self::getMembers($a_obj_id); if (!$a_user_ids) { - return array(); + return []; } } return self::_lookupStatusForObject( @@ -507,7 +453,7 @@ public static function _lookupFailedForObject( if (!$a_user_ids) { $a_user_ids = self::getMembers($a_obj_id); if (!$a_user_ids) { - return array(); + return []; } } return self::_lookupStatusForObject( @@ -527,7 +473,7 @@ public static function _lookupInProgressForObject( if (!$a_user_ids) { $a_user_ids = self::getMembers($a_obj_id); if (!$a_user_ids) { - return array(); + return []; } } return self::_lookupStatusForObject( @@ -556,4 +502,45 @@ public function determinePercentage(int $a_obj_id, int $a_usr_id, ?object $a_obj } return $percentage; } + + public function init(Container $DIC): void + { + $this->progress_block_settings_repository = new ProgressBlockSettingsRepository($DIC->database()); + $this->lng = $DIC->language(); + } + + public function getCustomLPSettingsExportXML( + int $object_id, + ): SimpleXMLElement { + $show_block = $this->progress_block_settings_repository->isBlockShownForObject($object_id); + $xml_root = new SimpleXMLElement(''); + $xml_root->addAttribute('show_progress_block', (string) ((int) $show_block)); + return $xml_root; + } + + public function importCustomLPSettingsExportXML( + int $new_object_id, + ilImportMapping $a_mapping, + SimpleXMLElement $additional_xml_root + ): void { + $this->progress_block_settings_repository->setShowBlockForObject( + $new_object_id, + (bool) ((int) $additional_xml_root->attributes()->show_progress_block) + ); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_COLLECTION; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCollectionManual.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCollectionManual.php index 831df7ad431b..8013a51c31bf 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCollectionManual.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCollectionManual.php @@ -16,19 +16,22 @@ * *********************************************************************/ -declare(strict_types=0); -/** - * @author Jörg Lützenkirchen - * @package ilias-tracking - */ +declare(strict_types=1); + +use ILIAS\DI\Container; +use ILIAS\Tracking\DB\Factory as TrackingDBFactory; + class ilLPStatusCollectionManual extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_collection_manual'; + protected const string LNG_TEXT_INFO = 'trac_mode_collection_manual_info'; + protected ilLanguage $lng; + public static function _getInProgress(int $a_obj_id): array { $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); - // find any completed item - $users = array(); + $users = []; if (isset($status_info['completed'])) { foreach ($status_info['completed'] as $in_progress) { $users = array_merge($users, $in_progress); @@ -42,9 +45,8 @@ public static function _getInProgress(int $a_obj_id): array public static function _getCompleted(int $a_obj_id): array { $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); - $counter = 0; - $users = array(); + $users = []; foreach ($status_info['items'] as $item_id) { $tmp_users = $status_info['completed'][$item_id]; @@ -59,18 +61,15 @@ public static function _getCompleted(int $a_obj_id): array public static function _getStatusInfo(int $a_obj_id): array { - $status_info = array(); - + $status_info = []; $olp = ilObjectLP::getInstance($a_obj_id); $collection = $olp->getCollectionInstance(); if ($collection) { // @todo check if obj_id can be removed $status_info["items"] = $collection->getItems($a_obj_id); - foreach ($status_info["items"] as $item_id) { - $status_info["completed"][$item_id] = array(); + $status_info["completed"][$item_id] = []; } - $ref_ids = ilObject::_getAllReferences($a_obj_id); $ref_id = end($ref_ids); $possible_items = $collection->getPossibleItems($ref_id); @@ -78,10 +77,8 @@ public static function _getStatusInfo(int $a_obj_id): array array_keys($possible_items), $status_info["items"] ); - // fix order (adapt from possible items) $status_info["items"] = $chapter_ids; - if ($chapter_ids) { $status = self::_getObjectStatus($a_obj_id); @@ -107,7 +104,6 @@ public function determineStatus( ?object $a_obj = null ): int { $info = self::_getStatusInfo($a_obj_id); - if (isset($info["completed"])) { $completed = true; $in_progress = false; @@ -136,25 +132,13 @@ public static function _getObjectStatus( $a_user_id = null ): array { global $DIC; - - $ilDB = $DIC['ilDB']; - - $res = array(); - - $sql = "SELECT subitem_id, completed, usr_id, last_change" . - " FROM ut_lp_coll_manual" . - " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer"); - if ($a_user_id) { - $sql .= " AND usr_id = " . $ilDB->quote($a_user_id, "integer"); - } - $set = $ilDB->query($sql); - while ($row = $ilDB->fetchAssoc($set)) { + $res = []; + $collection = (new TrackingDBFactory($DIC->database()))->lpCollectionManual()->repository()->readEntriesOfObject($a_obj_id); + foreach ($collection as $entry) { if (!$a_user_id) { - $res[(int) $row["subitem_id"]][(int) $row["usr_id"]] = (int) $row["completed"]; + $res[$entry->getSubitemId()][$entry->getUserId()] = (int) $entry->isCompleted(); } else { - $res[(int) $row["subitem_id"]] = array((int) $row["completed"], - $row["last_change"] - ); + $res[$entry->getSubitemId()] = [(int) $entry->isCompleted(), $entry->getLastChanged()]; } } return $res; @@ -166,69 +150,60 @@ public static function _setObjectStatus( ?array $a_completed = null ): void { global $DIC; - - $ilDB = $DIC['ilDB']; - - $now = time(); - - if (!$a_completed) { - $a_completed = array(); - } - + $a_completed = is_null($a_completed) ? [] : $a_completed; $olp = ilObjectLP::getInstance($a_obj_id); $collection = $olp->getCollectionInstance(); + $db_factory = (new TrackingDBFactory($DIC->database()))->lpCollectionManual(); if ($collection) { $existing = self::_getObjectStatus($a_obj_id, $a_user_id); - foreach ($collection->getItems() as $item_id) { - if (isset($existing[$item_id])) { - // value changed - if ((!$existing[$item_id][0] && in_array( - $item_id, - $a_completed - )) || - ($existing[$item_id][0] && !in_array( - $item_id, - $a_completed - ))) { - $ilDB->manipulate( - "UPDATE ut_lp_coll_manual SET " . - " completed = " . $ilDB->quote( - in_array($item_id, $a_completed), - "integer" - ) . - " , last_change = " . $ilDB->quote( - $now, - "integer" - ) . - " WHERE obj_id = " . $ilDB->quote( - $a_obj_id, - "integer" - ) . - " AND usr_id = " . $ilDB->quote( - $a_user_id, - "integer" - ) . - " AND subitem_id = " . $ilDB->quote( - $item_id, - "integer" - ) - ); - } - } elseif (in_array($item_id, $a_completed)) { - $ilDB->manipulate( - "INSERT INTO ut_lp_coll_manual" . - "(obj_id,usr_id,subitem_id,completed,last_change)" . - " VALUES (" . $ilDB->quote($a_obj_id, "integer") . - " , " . $ilDB->quote($a_user_id, "integer") . - " , " . $ilDB->quote($item_id, "integer") . - " , " . $ilDB->quote(1, "integer") . - " , " . $ilDB->quote($now, "integer") . ")" - ); + // value changed + $completed = in_array($item_id, $a_completed); + if ( + isset($existing[$item_id]) && + (!$existing[$item_id][0] && $completed) || + ($existing[$item_id][0] && !$completed) + ) { + $entry = $db_factory->repository()->readEntryForUserOfSubitemOfObject( + $a_obj_id, + $a_user_id, + $item_id + ) + ->withCompletedStatus($completed) + ->withLastChanged(time()); + $db_factory->repository()->write($entry); + } elseif ($completed) { + $entry = $db_factory->element()->lpCollectionManualEntry() + ->withObjectId($a_obj_id) + ->withUserId($a_user_id) + ->withSubitemId($item_id) + ->withCompletedStatus($completed) + ->withLastChanged(time()); + $db_factory->repository()->write($entry); } } } - ilLPStatusWrapper::_updateStatus($a_obj_id, $a_user_id); } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_MANUAL; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCollectionMobs.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCollectionMobs.php index b2c6ace3a3d3..6025dc449933 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCollectionMobs.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCollectionMobs.php @@ -16,17 +16,19 @@ * *********************************************************************/ -declare(strict_types=0); -/** - * @author Jörg Lützenkirchen - * @package ServicesTracking - */ +declare(strict_types=1); + +use ILIAS\DI\Container; + class ilLPStatusCollectionMobs extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_collection_mobs'; + protected const string LNG_TEXT_INFO = 'trac_mode_collection_mobs_info'; + protected ilLanguage $lng; + public static function _getInProgress(int $a_obj_id): array { - $users = array(); - + $users = []; $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); if (isset($status_info["user_status"]["in_progress"])) { $users = $status_info["user_status"]["in_progress"]; @@ -36,39 +38,31 @@ public static function _getInProgress(int $a_obj_id): array public static function _getCompleted(int $a_obj_id): array { - $users = array(); - + $users = []; $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); if (isset($status_info["user_status"]["completed"])) { $users = $status_info["user_status"]["completed"]; } - return $users; } public static function _getStatusInfo(int $a_obj_id): array { global $DIC; - $ilDB = $DIC['ilDB']; - - $res = array(); - + $res = []; $coll_items = self::getCollectionItems($a_obj_id, true); - $res["items"] = array_keys($coll_items); if (sizeof($res["items"])) { // titles foreach ($coll_items as $mob_id => $item) { $res["item_titles"][$mob_id] = $item["title"]; } - // status per item foreach ($res["items"] as $mob_id) { - $res["completed"][$mob_id] = array(); - $res["in_progress"][$mob_id] = array(); + $res["completed"][$mob_id] = []; + $res["in_progress"][$mob_id] = []; } - $set = $ilDB->query( "SELECT obj_id, usr_id FROM read_event" . " WHERE " . $ilDB->in("obj_id", $res["items"], "", "integer") @@ -76,9 +70,8 @@ public static function _getStatusInfo(int $a_obj_id): array while ($row = $ilDB->fetchAssoc($set)) { $res["completed"][(int) $row["obj_id"]][] = (int) $row["usr_id"]; } - // status per user - $tmp = array(); + $tmp = []; foreach ($res["items"] as $mob_id) { foreach ($res["completed"][$mob_id] as $user_id) { $tmp[$user_id][] = (int) $mob_id; @@ -92,7 +85,6 @@ public static function _getStatusInfo(int $a_obj_id): array } } } - $users = ilChangeEvent::lookupUsersInProgress($a_obj_id); foreach ($users as $user_id) { if ((!isset($res["user_status"]["in_progress"]) || !in_array( @@ -106,27 +98,23 @@ public static function _getStatusInfo(int $a_obj_id): array $res["user_status"]["in_progress"][] = (int) $user_id; } } - return $res; } protected static function getCollectionItems( $a_obj_id, $a_include_titles = false - ) { - $res = array(); - + ): array { + $res = []; $olp = ilObjectLP::getInstance($a_obj_id); $collection = $olp->getCollectionInstance(); if ($collection) { $possible = $collection->getPossibleItems(); - // there could be invalid items in the selection $valid = array_intersect( $collection->getItems(), array_keys($possible) ); - if ($a_include_titles) { foreach ($valid as $item_id) { $res[$item_id] = $possible[$item_id]; @@ -147,14 +135,11 @@ public function determineStatus( if (ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id)) { $status = self::LP_STATUS_IN_PROGRESS_NUM; } - // an empty collection is always not attempted $items = self::getCollectionItems($a_obj_id); if (count($items) > 0) { // process mob status for user - - $found = array(); - + $found = []; $set = $this->db->query( "SELECT obj_id FROM read_event" . " WHERE usr_id = " . $this->db->quote($a_usr_id, "integer") . @@ -163,10 +148,8 @@ public function determineStatus( while ($row = $this->db->fetchAssoc($set)) { $found[] = (int) $row["obj_id"]; } - if (count($found) > 0) { $status = self::LP_STATUS_IN_PROGRESS_NUM; - if (count($found) == count($items)) { $status = self::LP_STATUS_COMPLETED_NUM; } @@ -181,13 +164,11 @@ public function determinePercentage( ?object $a_obj = null ): int { $per = 0; - // an empty collection is always not attempted $items = self::getCollectionItems($a_obj_id); if (count($items) > 0) { // process mob status for user - - $found = array(); + $found = []; $set = $this->db->query( "SELECT obj_id FROM read_event" . " WHERE usr_id = " . $this->db->quote($a_usr_id, "integer") . @@ -196,12 +177,31 @@ public function determinePercentage( while ($row = $this->db->fetchAssoc($set)) { $found[] = (int) $row["obj_id"]; } - if (count($found) > 0 && count($items) > 0) { $per = (int) round(100 / count($items) * count($found)); } } - return $per; } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_COLLECTION_MOBS; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCollectionTLT.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCollectionTLT.php index d4e25327129a..799393d56a72 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCollectionTLT.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCollectionTLT.php @@ -16,71 +16,65 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\DI\Container; /** - * Seems to only be used for collections of LM chapters. * @author Jörg Lützenkirchen * @package ilias-tracking */ class ilLPStatusCollectionTLT extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_collection_tlt'; + protected const string LNG_TEXT_INFO = 'trac_mode_collection_tlt_info'; + protected ilLanguage $lng; + public static function _getInProgress(int $a_obj_id): array { $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); - - $users = array(); + $users = []; if (isset($status_info['in_progress'])) { foreach ($status_info['in_progress'] as $in_progress) { $users = array_merge($users, $in_progress); } $users = array_unique($users); } - - $users = array_diff( + return array_diff( $users, ilLPStatusWrapper::_getCompleted($a_obj_id) ); - - return $users; } public static function _getCompleted(int $a_obj_id): array { $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); - $counter = 0; - $users = array(); + $users = []; foreach ($status_info['items'] as $item_id) { $tmp_users = $status_info['completed'][$item_id]; - if (!$counter++) { $users = $tmp_users; } else { $users = array_intersect($users, $tmp_users); } } - $users = array_unique($users); - - return $users; + return array_unique($users); } public static function _getStatusInfo(int $a_obj_id): array { global $DIC; - $ilDB = $DIC['ilDB']; - $status_info = array(); + $status_info = []; $olp = ilObjectLP::getInstance($a_obj_id); $collection = $olp->getCollectionInstance(); if ($collection) { // @todo check if obj_id can be removed $status_info["items"] = $collection->getItems($a_obj_id); - foreach ($status_info["items"] as $item_id) { - $status_info["in_progress"][$item_id] = array(); - $status_info["completed"][$item_id] = array(); - + $status_info["in_progress"][$item_id] = []; + $status_info["completed"][$item_id] = []; /* * Seems to only be used for collections of LM chapters, * so we manually set 'st' for chapters here. @@ -91,7 +85,6 @@ public static function _getStatusInfo(int $a_obj_id): array $item_id ); } - $ref_ids = ilObject::_getAllReferences($a_obj_id); $ref_id = end($ref_ids); $possible_items = $collection->getPossibleItems($ref_id); @@ -99,10 +92,8 @@ public static function _getStatusInfo(int $a_obj_id): array array_keys($possible_items), $status_info["items"] ); - // fix order (adapt from possible items) $status_info["items"] = $chapter_ids; - if ($chapter_ids) { foreach ($chapter_ids as $item_id) { $status_info["item_titles"][$item_id] = $possible_items[$item_id]["title"]; @@ -131,9 +122,7 @@ public function determineStatus( ?object $a_obj = null ): int { $info = self::_getStatusInfo($a_obj_id); - $completed_once = false; - if (isset($info["completed"])) { $completed = true; foreach ($info["completed"] as $user_ids) { @@ -149,12 +138,10 @@ public function determineStatus( return self::LP_STATUS_COMPLETED_NUM; } } - // #14997 if ($completed_once) { return self::LP_STATUS_IN_PROGRESS_NUM; } - if (isset($info["in_progress"])) { foreach ($info["in_progress"] as $user_ids) { if (in_array($a_usr_id, $user_ids)) { @@ -162,7 +149,28 @@ public function determineStatus( } } } - return self::LP_STATUS_NOT_ATTEMPTED_NUM; } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_COLLECTION_TLT; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusContentVisited.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusContentVisited.php index caa64f9542cc..8cc7f62673b8 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusContentVisited.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusContentVisited.php @@ -16,55 +16,59 @@ * *********************************************************************/ -declare(strict_types=0); -/** - * @author Michael Jansen - * @package ServicesTracking - */ +declare(strict_types=1); + +use ILIAS\DI\Container; + class ilLPStatusContentVisited extends ilLPStatus { - /** - * @inheritdoc - */ + protected const string LNG_TEXT = 'trac_mode_content_visited'; + protected const string LNG_TEXT_INFO = 'trac_mode_content_visited_info'; + protected ilLanguage $lng; + public static function _getCompleted(int $a_obj_id): array { $userIds = []; - $allReadEvents = \ilChangeEvent::_lookupReadEvents($a_obj_id); foreach ($allReadEvents as $event) { $userIds[] = $event['usr_id']; } - return $userIds; } - /** - * @inheritdoc - */ public function determineStatus( int $a_obj_id, int $a_usr_id, ?object $a_obj = null ): int { - /** - * @var $ilObjDataCache ilObjectDataCache - */ - global $DIC; + $status = self::LP_STATUS_NOT_ATTEMPTED_NUM; + if ( + in_array($this->ilObjDataCache->lookupType($a_obj_id), ['file', 'copa', 'htlm']) && + \ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id) + ) { + $status = self::LP_STATUS_COMPLETED_NUM; + } + return $status; + } - $ilObjDataCache = $DIC['ilObjDataCache']; + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } - $status = self::LP_STATUS_NOT_ATTEMPTED_NUM; + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_CONTENT_VISITED; + } - switch ($this->ilObjDataCache->lookupType($a_obj_id)) { - case 'file': - case 'copa': - case 'htlm': - if (\ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id)) { - $status = self::LP_STATUS_COMPLETED_NUM; - } - break; - } + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } - return $status; + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusContributionToDiscussion.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusContributionToDiscussion.php index 17b6237004e5..907d8d7150fa 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusContributionToDiscussion.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusContributionToDiscussion.php @@ -16,31 +16,29 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\DI\Container; -/** - * Class ilLPStatusContributionToDiscussion - * @author Michael Jansen - */ class ilLPStatusContributionToDiscussion extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_contribution_to_discussion'; + protected const string LNG_TEXT_INFO = 'trac_mode_contribution_to_discussion_info'; + protected ilLanguage $lng; + public static function _getCompleted(int $a_obj_id): array { $userIds = []; - $frm_properties = ilForumProperties::getInstance($a_obj_id); $num_required_postings = $frm_properties->getLpReqNumPostings(); - if (null === $num_required_postings) { return $userIds; } - $frm = new ilForum(); $frm->setForumId($frm_properties->getObjId()); $statistics = $frm->getUserStatistics( $frm_properties->isPostActivationEnabled() ); - return array_map( static function (array $statisic): int { return (int) $statisic['pos_author_id']; @@ -59,20 +57,16 @@ static function (array $statistic) use ( public static function _getInProgress(int $a_obj_id): array { $userIds = []; - $frm_properties = ilForumProperties::getInstance($a_obj_id); $num_required_postings = $frm_properties->getLpReqNumPostings(); - if (null === $num_required_postings) { return $userIds; } - $frm = new ilForum(); $frm->setForumId($frm_properties->getObjId()); $statistics = $frm->getUserStatistics( $frm_properties->isPostActivationEnabled() ); - return array_map( static function (array $statisic): int { return (int) $statisic['pos_author_id']; @@ -95,17 +89,13 @@ public function determineStatus( ?object $a_obj = null ): int { $status = self::LP_STATUS_NOT_ATTEMPTED_NUM; - $frm_properties = ilForumProperties::getInstance($a_obj_id); $num_required_postings = $frm_properties->getLpReqNumPostings(); - - if (null === $num_required_postings) { + if (is_null($num_required_postings)) { return $status; } - $frm = new ilForum(); $frm->setForumId($frm_properties->getObjId()); - $num_postings = $frm->getNumberOfPublishedUserPostings( $a_usr_id, $frm_properties->isPostActivationEnabled() @@ -115,7 +105,46 @@ public function determineStatus( } elseif ($num_postings > 0) { $status = self::LP_STATUS_IN_PROGRESS_NUM; } - return $status; } + + public function getCustomLPSettingsExportXML( + int $object_id + ): SimpleXMLElement { + $num_postings = ilForumProperties::getInstance($object_id)->getLpReqNumPostings(); + $xml_root = new SimpleXMLElement(''); + $xml_root->addAttribute('num_postings', (string) $num_postings); + return $xml_root; + } + + public function importCustomLPSettingsExportXML( + int $new_object_id, + ilImportMapping $a_mapping, + SimpleXMLElement $additional_xml_root + ): void { + $forum_properties = ilForumProperties::getInstance($new_object_id); + $forum_properties->setLpReqNumPostings((int) $additional_xml_root->attributes()->num_postings); + $forum_properties->update(); + } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_CONTRIBUTION_TO_DISCUSSION; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCourseReference.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCourseReference.php index 6d329caee6b8..35b55060f30d 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusCourseReference.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusCourseReference.php @@ -16,42 +16,41 @@ * *********************************************************************/ -declare(strict_types=0); -/** - * Class ilLPStatusCourseReference - * @author Stefan Meyer - */ +declare(strict_types=1); + +use ILIAS\DI\Container; +use ILIAS\Tracking\DB\Factory as TrackingDBFactory; +use ILIAS\Tracking\DB\FactoryInterface as TrackingDBFactoryInterface; + class ilLPStatusCourseReference extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_course_reference'; + protected const string LNG_TEXT_INFO = 'trac_mode_course_reference_info'; + protected ilLanguage $lng; + /** - * @var \ilLPStatusCourseReference[] + * @var ilLPStatusCourseReference[] */ - private static $instances = []; - + private static array $instances = []; private int $target_obj_id = 0; private array $status_info = []; + protected TrackingDBFactoryInterface $db_factory; public function __construct(int $a_obj_id) { global $DIC; - + $this->db_factory = new TrackingDBFactory($DIC->database()); parent::__construct($a_obj_id); $this->readTargetObjId($a_obj_id); $this->readStatusInfo($a_obj_id); } - /** - * @inheritdoc - */ public static function _getCountNotAttempted(int $a_obj_id): int { $self = self::getInstanceByObjId($a_obj_id); return count($self->getNotAttempted()); } - /** - * @inheritdoc - */ public static function _getNotAttempted(int $a_obj_id): array { $self = self::getInstanceByObjId($a_obj_id); @@ -61,23 +60,17 @@ public static function _getNotAttempted(int $a_obj_id): array /** * @return int[] */ - public function getNotAttempted() + public function getNotAttempted(): array { return $this->status_info[\ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM]; } - /** - * @inheritdoc - */ public static function _getCountInProgress(int $a_obj_id): int { $self = self::getInstanceByObjId($a_obj_id); return count($self->getInProgress()); } - /** - * @inheritdoc - */ public static function _getInProgress(int $a_obj_id): array { $self = self::getInstanceByObjId($a_obj_id); @@ -87,23 +80,17 @@ public static function _getInProgress(int $a_obj_id): array /** * @return int[] */ - public function getInProgress() + public function getInProgress(): array { return $this->status_info[\ilLPStatus::LP_STATUS_IN_PROGRESS_NUM]; } - /** - * @inheritdoc - */ public static function _getCountCompleted(int $a_obj_id): int { $self = self::getInstanceByObjId($a_obj_id); return count($self->getCompleted()); } - /** - * @inheritdoc - */ public static function _getCompleted(int $a_obj_id): array { $self = self::getInstanceByObjId($a_obj_id); @@ -113,57 +100,39 @@ public static function _getCompleted(int $a_obj_id): array /** * @return int[] */ - public function getCompleted() + public function getCompleted(): array { return $this->status_info[\ilLPStatus::LP_STATUS_COMPLETED_NUM]; } - /** - * @inheritdoc - */ public static function _getStatusInfo(int $a_obj_id): array { $self = self::getInstanceByObjId($a_obj_id); return $self->getStatusInfo(); } - public function getStatusInfo() + public function getStatusInfo(): array { return $this->status_info; } - /** - * @inheritdoc - */ public function readStatusInfo(int $a_obj_id): void { - global $DIC; - - $database = $DIC->database(); - $query = 'select status,usr_id from ut_lp_marks ' . - 'where obj_id = ' . $database->quote( - $this->target_obj_id, - \ilDBConstants::T_INTEGER - ); - $res = $database->query($query); - + $collection = $this->db_factory->lpMarks()->repository()->readAllEntriesOfObject($this->target_obj_id); $info = [ - \ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM => [], - \ilLPStatus::LP_STATUS_IN_PROGRESS_NUM => [], - \ilLPStatus::LP_STATUS_COMPLETED_NUM => [], - \ilLPStatus::LP_STATUS_FAILED_NUM => [] + ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM => [], + ilLPStatus::LP_STATUS_IN_PROGRESS_NUM => [], + ilLPStatus::LP_STATUS_COMPLETED_NUM => [], + ilLPStatus::LP_STATUS_FAILED_NUM => [] ]; - while ($row = $res->fetchRow(\ilDBConstants::FETCHMODE_OBJECT)) { - if (array_key_exists((int) $row->status, $info)) { - $info[(int) $row->status][] = (int) $row->usr_id; + foreach ($collection as $lp_mark) { + if (array_key_exists($lp_mark->getStatus(), $info)) { + $info[$lp_mark->getStatus()][] = $lp_mark->getUserId(); } } $this->status_info = $info; } - /** - * @inheritdoc - */ public function determineStatus( int $a_obj_id, int $a_usr_id, @@ -197,4 +166,25 @@ private function readTargetObjId(int $a_obj_id): void (int) ilObjCourseReference::_lookupTargetRefId($a_obj_id) ); } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_COURSE_REFERENCE; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusDeactivated.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusDeactivated.php new file mode 100644 index 000000000000..d55d4728abaa --- /dev/null +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusDeactivated.php @@ -0,0 +1,63 @@ +lng = $DIC->language(); + } + + public function getCustomLPSettingsExportXML( + int $object_id + ): SimpleXMLElement { + return new SimpleXMLElement(''); + } + + public function importCustomLPSettingsExportXML( + int $new_object_id, + ilImportMapping $a_mapping, + SimpleXMLElement $additional_xml_root + ): void { + + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_DEACTIVATED; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } +} diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusEvent.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusEvent.php index 011ba3921886..7e2add9e57a7 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusEvent.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusEvent.php @@ -16,19 +16,20 @@ * *********************************************************************/ -declare(strict_types=0); -/** - * @author Stefan Meyer - * @package ilias-tracking - */ +declare(strict_types=1); + +use ILIAS\DI\Container; + class ilLPStatusEvent extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_event'; + protected const string LNG_TEXT_INFO = 'trac_mode_event_info'; + protected ilLanguage $lng; + public static function _getNotAttempted(int $a_obj_id): array { $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); - - $users = array(); - + $users = []; $members = self::getMembers($status_info['crs_id'], true); if ($members) { // diff in progress and completed (use stored result in LPStatusWrapper) @@ -41,67 +42,61 @@ public static function _getNotAttempted(int $a_obj_id): array ilLPStatusWrapper::_getCompleted($a_obj_id) ); } - return $users; } public static function _getInProgress(int $a_obj_id): array { $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); - // If registration is disabled in_progress is not available if (!$status_info['registration']) { - return array(); + return []; } // If event has occured in_progress is impossible if ($status_info['starting_time'] < time()) { - return array(); + return []; } - // Otherwise all users who registered will get the status in progress - return $status_info['registered_users'] ?: array(); + return $status_info['registered_users'] ?: []; } public static function _getCompleted(int $a_obj_id): array { $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); - return $status_info['participated_users'] ?: array(); + return $status_info['participated_users'] ?: []; } public static function _getStatusInfo(int $a_obj_id): array { $tree = $GLOBALS['DIC']->repositoryTree(); - $references = ilObject::_getAllReferences($a_obj_id); $ref_id = end($references); - $member_ref_id = null; if ($id = $tree->checkForParentType($ref_id, 'grp')) { $member_ref_id = $id; } elseif ($id = $tree->checkForParentType($ref_id, 'crs')) { $member_ref_id = $id; } - - $status_info = array(); + if (is_null($member_ref_id)) { + throw new Exception('Could not determine member reference id of obj: ' . $a_obj_id); + } + $status_info = []; $status_info['crs_id'] = ilObject::_lookupObjId($member_ref_id); $status_info['registration'] = ilObjSession::_lookupRegistrationEnabled( $a_obj_id ); $status_info['title'] = ilObject::_lookupTitle($a_obj_id); $status_info['description'] = ilObject::_lookupDescription($a_obj_id); - $time_info = ilSessionAppointment::_lookupAppointment($a_obj_id); $status_info['starting_time'] = $time_info['start']; $status_info['ending_time'] = $time_info['end']; $status_info['fullday'] = $time_info['fullday']; - $status_info['registered_users'] = ilEventParticipants::_getRegistered( $a_obj_id ); $status_info['participated_users'] = ilEventParticipants::_getParticipated( $a_obj_id ); - return $status_info; } @@ -110,46 +105,35 @@ public function determineStatus( int $a_usr_id, ?object $a_obj = null ): int { - global $DIC; - - $ilObjDataCache = $DIC['ilObjDataCache']; - $status = self::LP_STATUS_NOT_ATTEMPTED_NUM; - switch ($this->ilObjDataCache->lookupType($a_obj_id)) { - case 'sess': - - $time_info = ilSessionAppointment::_lookupAppointment( - $a_obj_id - ); - $registration = ilObjSession::_lookupRegistrationEnabled( - $a_obj_id - ); - - // If registration is disabled in_progress is not available - // If event has occured in_progress is impossible - if ($registration && $time_info['start'] >= time()) { - // is user registered -> in progress - if (ilEventParticipants::_isRegistered( - $a_usr_id, - $a_obj_id - )) { - $status = self::LP_STATUS_IN_PROGRESS_NUM; - } - } - if (ilEventParticipants::_hasParticipated( + if (strcmp($this->ilObjDataCache->lookupType($a_obj_id), 'sess') === 0) { + $time_info = ilSessionAppointment::_lookupAppointment( + $a_obj_id + ); + $registration = ilObjSession::_lookupRegistrationEnabled( + $a_obj_id + ); + // If registration is disabled in_progress is not available + // If event has occured in_progress is impossible + if ($registration && $time_info['start'] >= time()) { + // is user registered -> in progress + if (ilEventParticipants::_isRegistered( $a_usr_id, $a_obj_id )) { - $status = self::LP_STATUS_COMPLETED_NUM; + $status = self::LP_STATUS_IN_PROGRESS_NUM; } - break; + } + if (ilEventParticipants::_hasParticipated( + $a_usr_id, + $a_obj_id + )) { + $status = self::LP_STATUS_COMPLETED_NUM; + } } return $status; } - /** - * Get members for object - */ protected static function getMembers( int $a_obj_id, bool $a_is_crs_id = false @@ -158,8 +142,6 @@ protected static function getMembers( $tree = $GLOBALS['DIC']->repositoryTree(); $references = ilObject::_getAllReferences($a_obj_id); $ref_id = end($references); - - $member_ref_id = null; if ($id = $tree->checkForParentType($ref_id, 'grp')) { $member_ref_id = $id; } elseif ($id = $tree->checkForParentType($ref_id, 'crs')) { @@ -171,7 +153,6 @@ protected static function getMembers( } else { $member_obj_id = $a_obj_id; } - $member_obj = ilParticipants::getInstanceByObjId($member_obj_id); return $member_obj->getMembers(); } @@ -186,7 +167,7 @@ public static function _lookupCompletedForObject( if (!$a_user_ids) { $a_user_ids = self::getMembers($a_obj_id); if (!$a_user_ids) { - return array(); + return []; } } return self::_lookupStatusForObject( @@ -203,7 +184,7 @@ public static function _lookupFailedForObject( int $a_obj_id, ?array $a_user_ids = null ): array { - return array(); + return []; } /** @@ -216,7 +197,7 @@ public static function _lookupInProgressForObject( if (!$a_user_ids) { $a_user_ids = self::getMembers($a_obj_id); if (!$a_user_ids) { - return array(); + return []; } } return self::_lookupStatusForObject( @@ -225,4 +206,26 @@ public static function _lookupInProgressForObject( $a_user_ids ); } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_EVENT; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusExerciseReturned.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusExerciseReturned.php index a11c3820862b..671881d78430 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusExerciseReturned.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusExerciseReturned.php @@ -16,17 +16,19 @@ * *********************************************************************/ -declare(strict_types=0); -/** - * @author Stefan Meyer - * @package ilias-tracking - */ +declare(strict_types=1); + +use ILIAS\DI\Container; + class ilLPStatusExerciseReturned extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_exercise_returned'; + protected const string LNG_TEXT_INFO = 'trac_mode_exercise_returned_info'; + protected ilLanguage $lng; + public static function _getNotAttempted(int $a_obj_id): array { - $users = array(); - + $users = []; $members = self::getMembers($a_obj_id); if ($members) { $users = array_diff( @@ -50,18 +52,15 @@ public static function _getInProgress(int $a_obj_id): array $users = ilExerciseMembers::_getReturned($a_obj_id); $all = ilChangeEvent::lookupUsersInProgress($a_obj_id); $users = $users + $all; - $users = array_diff( $users, ilLPStatusWrapper::_getCompleted($a_obj_id) ); $users = array_diff($users, ilLPStatusWrapper::_getFailed($a_obj_id)); - if ($users) { // Exclude all non members $users = array_intersect(self::getMembers($a_obj_id), $users); } - return $users; } @@ -83,35 +82,26 @@ public function determineStatus( int $a_usr_id, ?object $a_obj = null ): int { - global $DIC; - - $ilObjDataCache = $DIC['ilObjDataCache']; - $status = self::LP_STATUS_NOT_ATTEMPTED_NUM; - switch ($this->ilObjDataCache->lookupType($a_obj_id)) { - case 'exc': - if (ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id) || - ilExerciseMembers::_hasReturned($a_obj_id, $a_usr_id)) { - $status = self::LP_STATUS_IN_PROGRESS_NUM; - } - $ex_stat = ilExerciseMembers::_lookupStatus( - $a_obj_id, - $a_usr_id - ); - if ($ex_stat == "passed") { - $status = self::LP_STATUS_COMPLETED_NUM; - } - if ($ex_stat == "failed") { - $status = self::LP_STATUS_FAILED_NUM; - } - break; + if (strcmp($this->ilObjDataCache->lookupType($a_obj_id), 'exc') === 0) { + if (ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id) || + ilExerciseMembers::_hasReturned($a_obj_id, $a_usr_id)) { + $status = self::LP_STATUS_IN_PROGRESS_NUM; + } + $ex_stat = ilExerciseMembers::_lookupStatus( + $a_obj_id, + $a_usr_id + ); + if ($ex_stat == "passed") { + $status = self::LP_STATUS_COMPLETED_NUM; + } + if ($ex_stat == "failed") { + $status = self::LP_STATUS_FAILED_NUM; + } } return $status; } - /** - * Get members for object - */ protected static function getMembers(int $a_obj_id) { return ilExerciseMembers::_getMembers($a_obj_id); @@ -127,7 +117,7 @@ public static function _lookupCompletedForObject( if (!$a_user_ids) { $a_user_ids = self::getMembers($a_obj_id); if (!$a_user_ids) { - return array(); + return []; } } return self::_lookupStatusForObject( @@ -147,7 +137,7 @@ public static function _lookupFailedForObject( if (!$a_user_ids) { $a_user_ids = self::getMembers($a_obj_id); if (!$a_user_ids) { - return array(); + return []; } } return self::_lookupStatusForObject( @@ -167,7 +157,7 @@ public static function _lookupInProgressForObject( if (!$a_user_ids) { $a_user_ids = self::getMembers($a_obj_id); if (!$a_user_ids) { - return array(); + return []; } } return self::_lookupStatusForObject( @@ -176,4 +166,26 @@ public static function _lookupInProgressForObject( $a_user_ids ); } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_EXERCISE_RETURNED; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusIndividualAssessment.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusIndividualAssessment.php index 829643729b31..e8d34abbe6ff 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusIndividualAssessment.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusIndividualAssessment.php @@ -18,8 +18,14 @@ declare(strict_types=0); +use ILIAS\DI\Container; + class ilLPStatusIndividualAssessment extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_individual_assessment'; + protected const string LNG_TEXT_INFO = 'trac_mode_individual_assessment_info'; + protected ilLanguage $lng; + public static function _getNotAttempted(int $a_obj_id): array { return ilIndividualAssessmentLPInterface::getMembersHavingStatusIn( @@ -93,4 +99,25 @@ public function determineStatus( return self::LP_STATUS_NOT_ATTEMPTED_NUM; } } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_INDIVIDUAL_ASSESSMENT; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusLtiOutcome.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusLtiOutcome.php index 07149b60eb00..c48aaea01499 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusLtiOutcome.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusLtiOutcome.php @@ -16,26 +16,25 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\DI\Container; -/** - * Class ilLPStatusLtiOutcome - * @author Uwe Kohnle - * @author Björn Heyser - * @author Stefan Schneider - */ class ilLPStatusLtiOutcome extends ilLPStatus { - private static array $userResultCache = array(); + protected const string LNG_TEXT = 'trac_mode_lti_outcome'; + protected const string LNG_TEXT_INFO = 'trac_mode_lti_outcome_info'; + protected ilLanguage $lng; + + private static array $userResultCache = []; private function getLtiUserResult( int $objId, int $usrId ): ?ilLTIConsumerResult { if (!isset(self::$userResultCache[$objId])) { - self::$userResultCache[$objId] = array(); + self::$userResultCache[$objId] = []; } - if (!isset(self::$userResultCache[$objId][$usrId])) { $ltiUserResult = ilLTIConsumerResult::getByKeys($objId, $usrId); self::$userResultCache[$objId][$usrId] = $ltiUserResult; @@ -57,18 +56,14 @@ public function determineStatus( ?object $a_obj = null ): int { $ltiResult = $this->getLtiUserResult($a_obj_id, $a_usr_id); - if ($ltiResult instanceof ilLTIConsumerResult) { $object = $this->ensureObject($a_obj_id, $a_obj); $ltiMasteryScore = $object->getMasteryScore(); - if ($ltiResult->getResult() >= $ltiMasteryScore) { return self::LP_STATUS_COMPLETED_NUM; } - return self::LP_STATUS_IN_PROGRESS_NUM; } - return self::LP_STATUS_NOT_ATTEMPTED_NUM; } @@ -78,11 +73,30 @@ public function determinePercentage( ?object $a_obj = null ): int { $ltiResult = $this->getLtiUserResult($a_obj_id, $a_usr_id); - if ($ltiResult instanceof ilLTIConsumerResult) { return (int) $ltiResult->getResult() * 100; } - return 0; } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_LTI_OUTCOME; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusManual.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusManual.php index 937b8777f65a..8a54ac6835f7 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusManual.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusManual.php @@ -16,17 +16,30 @@ * *********************************************************************/ -declare(strict_types=0); -/** - * @author Stefan Meyer - * @ingroup ServicesTracking - */ +declare(strict_types=1); + +use ILIAS\DI\Container; +use ILIAS\Tracking\DB\Factory as TrackingDBFactory; +use ILIAS\Tracking\DB\FactoryInterface as TrackingDBFactoryInterface; + class ilLPStatusManual extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_manual'; + protected const string LNG_TEXT_INFO = 'trac_mode_manual_info'; + protected ilLanguage $lng; + + protected TrackingDBFactoryInterface $tracking_db_factory; + + public function __construct(int $a_obj_id) + { + global $DIC; + parent::__construct($a_obj_id); + $this->tracking_db_factory = new TrackingDBFactory($DIC->database()); + } + public static function _getInProgress(int $a_obj_id): array { $users = ilChangeEvent::lookupUsersInProgress($a_obj_id); - // Exclude all users with status completed. return array_diff($users, ilLPStatusWrapper::_getCompleted($a_obj_id)); } @@ -34,76 +47,56 @@ public static function _getInProgress(int $a_obj_id): array public static function _getCompleted(int $a_obj_id): array { global $DIC; - - $ilDB = $DIC['ilDB']; - - $usr_ids = array(); - - $query = "SELECT DISTINCT(usr_id) user_id FROM ut_lp_marks " . - "WHERE obj_id = " . $ilDB->quote($a_obj_id, 'integer') . " " . - "AND completed = '1' "; - - $res = $ilDB->query($query); - while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - $usr_ids[] = (int) $row->user_id; - } - return $usr_ids; + return (new TrackingDBFactory($DIC->database()))->lpMarks()->repository()->readAllEntriesOfObject($a_obj_id) + ->getSubCollectionOfElementsByCompletedStatus(true) + ->getSubCollectionOfElementsWithDistinctUsers() + ->asUserIdArray(); } - /** - * Determine status - */ public function determineStatus( int $a_obj_id, int $a_usr_id, ?object $a_obj = null ): int { - global $DIC; - - $ilObjDataCache = $DIC['ilObjDataCache']; - $ilDB = $DIC['ilDB']; - $status = self::LP_STATUS_NOT_ATTEMPTED_NUM; - switch ($this->ilObjDataCache->lookupType($a_obj_id)) { - case 'lm': - case 'copa': - case 'file': - case 'htlm': - if (ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id)) { - $status = self::LP_STATUS_IN_PROGRESS_NUM; - - // completed? - $set = $this->db->query( - $q = "SELECT usr_id FROM ut_lp_marks " . - "WHERE obj_id = " . $this->db->quote( - $a_obj_id, - 'integer' - ) . " " . - "AND usr_id = " . $this->db->quote( - $a_usr_id, - 'integer' - ) . " " . - "AND completed = '1' " - ); - if ($rec = $this->db->fetchAssoc($set)) { - $status = self::LP_STATUS_COMPLETED_NUM; - } - } - break; + if ( + in_array($this->ilObjDataCache->lookupType($a_obj_id), ['lm', 'copa', 'file', 'htlm']) && + ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id) + ) { + $lp_mark = $this->tracking_db_factory->lpMarks()->repository()->readEntryForUserOfObject( + $a_obj_id, + $a_usr_id + ); + $status = $lp_mark->isCompleted() ? self::LP_STATUS_COMPLETED_NUM : self::LP_STATUS_IN_PROGRESS_NUM; } return $status; } - /** - * Get failed users for object - * @param int $a_obj_id - * @param array|null $a_user_ids - * @return array - */ public static function _lookupFailedForObject( int $a_obj_id, ?array $a_user_ids = null ): array { - return array(); + return []; + } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_MANUAL; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusManualByTutor.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusManualByTutor.php index f33f8db3193d..db63a7c20fc5 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusManualByTutor.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusManualByTutor.php @@ -18,20 +18,28 @@ declare(strict_types=0); -/** - * @author Stefan Meyer - * @ilCtrl_Calls - * @ingroup ServicesTracking - */ +use ILIAS\DI\Container; +use ILIAS\Tracking\DB\Factory as TrackingDBFactory; +use ILIAS\Tracking\DB\FactoryInterface as TrackingDBFactoryInterface; + class ilLPStatusManualByTutor extends ilLPStatus { - /** - * get not attempted - */ - public static function _getNotAttempted(int $a_obj_id): array + protected const string LNG_TEXT = 'trac_mode_manual_by_tutor'; + protected const string LNG_TEXT_INFO = 'trac_mode_manual_by_tutor_info'; + protected ilLanguage $lng; + + protected TrackingDBFactoryInterface $tracking_db_factory; + + public function __construct(int $a_obj_id) { - $users = array(); + global $DIC; + parent::__construct($a_obj_id); + $this->tracking_db_factory = new TrackingDBFactory($DIC->database()); + } + public static function _getNotAttempted(int $a_obj_id): array + { + $users = []; $members = self::getMembers($a_obj_id); if ($members) { // diff in progress and completed (use stored result in LPStatusWrapper) @@ -44,51 +52,37 @@ public static function _getNotAttempted(int $a_obj_id): array ilLPStatusWrapper::_getCompleted($a_obj_id) ); } - return $users; } /** - * get in progress - * @access public - * @param int object id - * @return array int Array of user ids + * @return int[] int Array of user ids */ public static function _getInProgress(int $a_obj_id): array { $users = ilChangeEvent::lookupUsersInProgress($a_obj_id); - // Exclude all users with status completed. $users = array_diff( $users, ilLPStatusWrapper::_getCompleted($a_obj_id) ); - if ($users) { // Exclude all non members $users = array_intersect(self::getMembers($a_obj_id), $users); } - return $users; } + /** + * @return int[] + */ public static function _getCompleted(int $a_obj_id): array { global $DIC; - - $ilDB = $DIC['ilDB']; - - $usr_ids = array(); - - $query = "SELECT DISTINCT(usr_id) user_id FROM ut_lp_marks " . - "WHERE obj_id = " . $ilDB->quote($a_obj_id, 'integer') . " " . - "AND completed = '1' "; - - $res = $ilDB->query($query); - while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { - $usr_ids[] = (int) $row->user_id; - } - + $usr_ids = (new TrackingDBFactory($DIC->database()))->lpMarks()->repository()->readAllEntriesOfObject($a_obj_id) + ->getSubCollectionOfElementsByCompletedStatus(true) + ->getSubCollectionOfElementsWithDistinctUsers() + ->asUserIdArray(); if ($usr_ids) { // Exclude all non members $usr_ids = array_intersect(self::getMembers($a_obj_id), $usr_ids); @@ -96,43 +90,27 @@ public static function _getCompleted(int $a_obj_id): array return $usr_ids; } - /** - * Determine status - */ public function determineStatus( int $a_obj_id, int $a_usr_id, ?object $a_obj = null ): int { - global $DIC; - - $ilObjDataCache = $DIC['ilObjDataCache']; - $status = self::LP_STATUS_NOT_ATTEMPTED_NUM; - switch ($this->ilObjDataCache->lookupType($a_obj_id)) { - case "crs": - case "grp": - // completed? - $set = $this->db->query( - $q = "SELECT usr_id FROM ut_lp_marks " . - "WHERE obj_id = " . $this->db->quote( - $a_obj_id, - 'integer' - ) . " " . - "AND usr_id = " . $this->db->quote( - $a_usr_id, - 'integer' - ) . " " . - "AND completed = '1' " - ); - if ($rec = $this->db->fetchAssoc($set)) { - $status = self::LP_STATUS_COMPLETED_NUM; - } else { - if (ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id)) { - $status = self::LP_STATUS_IN_PROGRESS_NUM; - } + if (in_array($this->ilObjDataCache->lookupType($a_obj_id), ['crs', 'grp'])) { + $lp_mark = $this->tracking_db_factory->lpMarks()->repository()->readEntryForUserOfObject( + $a_obj_id, + $a_usr_id + ); + if ( + !is_null($lp_mark) && + $lp_mark->isCompleted() + ) { + $status = self::LP_STATUS_COMPLETED_NUM; + } else { + if (ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id)) { + $status = self::LP_STATUS_IN_PROGRESS_NUM; } - break; + } } return $status; } @@ -140,13 +118,10 @@ public function determineStatus( public function refreshStatus(int $a_obj_id, ?array $a_users = null): void { parent::refreshStatus($a_obj_id, $a_users); - if (ilObject::_lookupType($a_obj_id) !== 'crs') { return; } - $course_gui = new ilObjCourseGUI('', $a_obj_id, false); - $in_progress = ilLPStatusWrapper::_getInProgress($a_obj_id); $completed = ilLPStatusWrapper::_getCompleted($a_obj_id); $failed = ilLPStatusWrapper::_getFailed($a_obj_id); @@ -154,7 +129,6 @@ public function refreshStatus(int $a_obj_id, ?array $a_users = null): void $all_active_users = array_unique( array_merge($in_progress, $completed, $failed, $not_attempted) ); - foreach ($all_active_users as $usr_id) { $course_gui->updateLPFromStatus( $usr_id, @@ -163,29 +137,18 @@ public function refreshStatus(int $a_obj_id, ?array $a_users = null): void } } - /** - * Get members for object - */ protected static function getMembers(int $a_obj_id): array { global $DIC; - $ilObjDataCache = $DIC['ilObjDataCache']; - - switch ($ilObjDataCache->lookupType($a_obj_id)) { - case 'crs': - case 'grp': - return ilParticipants::getInstanceByObjId( - $a_obj_id - )->getMembers(); + if (in_array($ilObjDataCache->lookupType($a_obj_id), ['crs', 'grp'])) { + return ilParticipants::getInstanceByObjId( + $a_obj_id + )->getMembers(); } - - return array(); + return []; } - /** - * Get completed users for object - */ public static function _lookupCompletedForObject( int $a_obj_id, ?array $a_user_ids = null @@ -193,7 +156,7 @@ public static function _lookupCompletedForObject( if (!$a_user_ids) { $a_user_ids = self::getMembers($a_obj_id); if (!$a_user_ids) { - return array(); + return []; } } return self::_lookupStatusForObject( @@ -203,19 +166,13 @@ public static function _lookupCompletedForObject( ); } - /** - * Get failed users for object - */ public static function _lookupFailedForObject( int $a_obj_id, ?array $a_user_ids = null ): array { - return array(); + return []; } - /** - * Get in progress users for object - */ public static function _lookupInProgressForObject( int $a_obj_id, ?array $a_user_ids = null @@ -223,7 +180,7 @@ public static function _lookupInProgressForObject( if (!$a_user_ids) { $a_user_ids = self::getMembers($a_obj_id); if (!$a_user_ids) { - return array(); + return []; } } return self::_lookupStatusForObject( @@ -232,4 +189,25 @@ public static function _lookupInProgressForObject( $a_user_ids ); } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_MANUAL_BY_TUTOR; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusObjectives.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusObjectives.php index 4fa91a4cd198..aef432078388 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusObjectives.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusObjectives.php @@ -16,19 +16,19 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\DI\Container; -/** - * @author Stefan Meyer - * @version $Id$ - * @package ilias-tracking - */ class ilLPStatusObjectives extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_objectives'; + protected const string LNG_TEXT_INFO = 'trac_mode_objectives_info'; + protected ilLanguage $lng; + public static function _getNotAttempted(int $a_obj_id): array { - $users = array(); - + $users = []; $members = self::getMembers($a_obj_id); if ($members) { // diff in progress, completed and failed (use stored result in LPStatusWrapper) @@ -41,7 +41,7 @@ public static function _getNotAttempted(int $a_obj_id): array ilLPStatusWrapper::_getCompleted($a_obj_id) ); $users = array_diff( - (array) $members, + $members, ilLPStatusWrapper::_getFailed($a_obj_id) ); } @@ -52,16 +52,14 @@ public static function _getInProgress(int $a_obj_id): array { $objective_results = ilLPStatusWrapper::_getStatusInfo($a_obj_id); $usr_ids = (array) ($objective_results['user_status'][self::LP_STATUS_IN_PROGRESS_NUM] ?? []); - if ($usr_ids) { // Exclude all non members $usr_ids = array_intersect(self::getMembers($a_obj_id), $usr_ids); } - if ($usr_ids) { return $usr_ids; } else { - return array(); + return []; } } @@ -69,36 +67,30 @@ public static function _getCompleted(int $a_obj_id): array { $objective_results = ilLPStatusWrapper::_getStatusInfo($a_obj_id); $usr_ids = (array) ($objective_results['user_status'][self::LP_STATUS_COMPLETED_NUM] ?? []); - if ($usr_ids) { // Exclude all non members $usr_ids = array_intersect(self::getMembers($a_obj_id), $usr_ids); } - - return $usr_ids ?: array(); + return $usr_ids ?: []; } public static function _getFailed(int $a_obj_id): array { $objective_results = ilLPStatusWrapper::_getStatusInfo($a_obj_id); $usr_ids = (array) ($objective_results['user_status'][self::LP_STATUS_FAILED_NUM] ?? []); - if ($usr_ids) { // Exclude all non members $usr_ids = array_intersect(self::getMembers($a_obj_id), $usr_ids); } - return $usr_ids; } public static function _getStatusInfo(int $a_obj_id): array { global $DIC; - $ilDB = $DIC['ilDB']; - - $status_info = array(); - $status_info['user_status'] = array(); + $status_info = []; + $status_info['user_status'] = []; $status_info['objectives'] = ilCourseObjective::_getObjectiveIds( $a_obj_id, true @@ -162,35 +154,32 @@ public function determineStatus( // ilCourseObjectiveResult -> added ilLPStatusWrapper::_updateStatus() $status = self::LP_STATUS_NOT_ATTEMPTED_NUM; - switch ($this->ilObjDataCache->lookupType($a_obj_id)) { - case "crs": - if (ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id)) { - // an initial test (only) should also lead to "in progress" - $status = self::LP_STATUS_IN_PROGRESS_NUM; - - $objectives = ilCourseObjective::_getObjectiveIds( - $a_obj_id, - true - ); - if ($objectives) { - // #14051 - getSummarizedObjectiveStatusForLP() might return null - $objtv_status = ilLOUserResults::getSummarizedObjectiveStatusForLP( - $a_obj_id, - $objectives, - $a_usr_id - ); - if ($objtv_status !== null) { - $status = $objtv_status; - } - } + if ( + strcmp($this->ilObjDataCache->lookupType($a_obj_id), 'crs') === 0 && + ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id) + ) { + // an initial test (only) should also lead to "in progress" + $status = self::LP_STATUS_IN_PROGRESS_NUM; + $objectives = ilCourseObjective::_getObjectiveIds( + $a_obj_id, + true + ); + if ($objectives) { + // #14051 - getSummarizedObjectiveStatusForLP() might return null + $objtv_status = ilLOUserResults::getSummarizedObjectiveStatusForLP( + $a_obj_id, + $objectives, + $a_usr_id + ); + if ($objtv_status !== null) { + $status = $objtv_status; } - break; + } } return $status; } /** - * @param int $a_obj_id * @return int[] */ protected static function getMembers(int $a_obj_id): array @@ -209,7 +198,7 @@ public static function _lookupCompletedForObject( if (!$a_user_ids) { $a_user_ids = self::getMembers($a_obj_id); if (!$a_user_ids) { - return array(); + return []; } } return self::_lookupStatusForObject( @@ -219,19 +208,13 @@ public static function _lookupCompletedForObject( ); } - /** - * Get failed users for object - */ public static function _lookupFailedForObject( int $a_obj_id, ?array $a_user_ids = null ): array { - return array(); + return []; } - /** - * Get in progress users for object - */ public static function _lookupInProgressForObject( int $a_obj_id, ?array $a_user_ids = null @@ -239,7 +222,7 @@ public static function _lookupInProgressForObject( if (!$a_user_ids) { $a_user_ids = self::getMembers($a_obj_id); if (!$a_user_ids) { - return array(); + return []; } } return self::_lookupStatusForObject( @@ -248,4 +231,25 @@ public static function _lookupInProgressForObject( $a_user_ids ); } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_OBJECTIVES; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusPlugin.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusPlugin.php index 9dd62426b4f2..3a6b91ca1c6d 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusPlugin.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusPlugin.php @@ -16,21 +16,21 @@ * *********************************************************************/ -declare(strict_types=0); -/** - * LP handler class for plugins - * @author Jörg Lützenkirchen - * @package ServicesTracking - */ +declare(strict_types=1); + +use ILIAS\DI\Container; +use ILIAS\Tracking\DB\Factory as TrackingDBFactory; + class ilLPStatusPlugin extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_plugin'; + protected const string LNG_TEXT_INFO = ''; + protected ilLanguage $lng; + /** - * Get ilObjectPlugin for object id - * @param int $a_obj_id - * @return ilObjectPlugin|int * @todo refactor return type */ - protected static function initPluginObj(int $a_obj_id) + protected static function initPluginObj(int $a_obj_id): ilObjectPlugin|int { $olp = ilObjectLP::getInstance($a_obj_id); return $olp->getPluginInstance(); @@ -50,7 +50,7 @@ public static function _getNotAttempted(int $a_obj_id): array ); } } - return array(); + return []; } public static function _getInProgress(int $a_obj_id): array @@ -67,7 +67,7 @@ public static function _getInProgress(int $a_obj_id): array ); } } - return array(); + return []; } public static function _getCompleted(int $a_obj_id): array @@ -84,7 +84,7 @@ public static function _getCompleted(int $a_obj_id): array ); } } - return array(); + return []; } public static function _getFailed(int $a_obj_id): array @@ -101,7 +101,7 @@ public static function _getFailed(int $a_obj_id): array ); } } - return array(); + return []; } public function determineStatus( @@ -142,53 +142,22 @@ public function determinePercentage( return 0; } - /** - * Read existing LP status data - */ protected static function getLPStatusData( int $a_obj_id, int $a_status ): array { global $DIC; - - $ilDB = $DIC['ilDB']; - - $all = array(); - $set = $ilDB->query( - "SELECT usr_id" . - " FROM ut_lp_marks" . - " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer") . - " AND status = " . $ilDB->quote($a_status, "integer") - ); - while ($row = $ilDB->fetchAssoc($set)) { - $all[] = (int) $row["usr_id"]; - } - return $all; + return (new TrackingDBFactory($DIC->database()))->lpMarks()->repository()->readAllEntriesWithStatusOfObject($a_obj_id, $a_status) + ->asUserIdArray(); } - /** - * Read existing LP status data for user - */ protected static function getLPDataForUser( int $a_obj_id, int $a_user_id ): int { global $DIC; - - $ilDB = $DIC['ilDB']; - - $set = $ilDB->query( - "SELECT status" . - " FROM ut_lp_marks" . - " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer") . - " AND usr_id = " . $ilDB->quote($a_user_id, "integer") - ); - $row = $ilDB->fetchAssoc($set); - $status = $row["status"]; - if (!$status) { - $status = self::LP_STATUS_NOT_ATTEMPTED_NUM; - } - return $status; + $lp_mark = (new TrackingDBFactory($DIC->database()))->lpMarks()->repository()->readEntryForUserOfObject($a_obj_id, $a_user_id); + return is_null($lp_mark) ? self::LP_STATUS_NOT_ATTEMPTED_NUM : $lp_mark->getStatus(); } protected static function getPercentageForUser( @@ -196,16 +165,28 @@ protected static function getPercentageForUser( int $a_user_id ): int { global $DIC; + $lp_mark = (new TrackingDBFactory($DIC->database()))->lpMarks()->repository()->readEntryForUserOfObject($a_obj_id, $a_user_id); + return is_null($lp_mark) ? 0 : $lp_mark->getPercentage(); + } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_PLUGIN; + } - $ilDB = $DIC['ilDB']; + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } - $set = $ilDB->query( - "SELECT percentage" . - " FROM ut_lp_marks" . - " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer") . - " AND usr_id = " . $ilDB->quote($a_user_id, "integer") - ); - $row = $ilDB->fetchAssoc($set); - return (int) ($row["percentage"] ?? 0); + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusQuestions.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusQuestions.php index b756177b2950..7dffc523fc4a 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusQuestions.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusQuestions.php @@ -16,33 +16,29 @@ * *********************************************************************/ -declare(strict_types=0); -/** - * @author Jörg Lützenkirchen - * @version $Id: class.ilLPStatusCollectionManual.php 40252 2013-03-01 12:21:49Z jluetzen $ - * @package ilias-tracking - */ +declare(strict_types=1); + +use ILIAS\DI\Container; + class ilLPStatusQuestions extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_questions'; + protected const string LNG_TEXT_INFO = 'trac_mode_questions_info'; + protected ilLanguage $lng; + public static function _getInProgress(int $a_obj_id): array { - $users = ilChangeEvent::lookupUsersInProgress($a_obj_id); - // Exclude all users with status completed. - $users = array_diff( - $users, + return array_diff( + ilChangeEvent::lookupUsersInProgress($a_obj_id), ilLPStatusWrapper::_getCompleted($a_obj_id) ); - - return $users; } public static function _getCompleted(int $a_obj_id): array { - $usr_ids = array(); - + $usr_ids = []; $users = ilChangeEvent::lookupUsersInProgress($a_obj_id); - foreach ($users as $user_id) { // :TODO: this ought to be optimized $tracker = ilLMTracker::getInstanceByObjId($a_obj_id, $user_id); @@ -50,7 +46,6 @@ public static function _getCompleted(int $a_obj_id): array $usr_ids[] = $user_id; } } - return $usr_ids; } @@ -60,16 +55,34 @@ public function determineStatus( ?object $a_obj = null ): int { $status = self::LP_STATUS_NOT_ATTEMPTED_NUM; - if (ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id)) { $status = self::LP_STATUS_IN_PROGRESS_NUM; - $tracker = ilLMTracker::getInstanceByObjId($a_obj_id, $a_usr_id); if ($tracker->getAllQuestionsCorrect()) { $status = self::LP_STATUS_COMPLETED_NUM; } } - return $status; } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_QUESTIONS; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusSCORM.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusSCORM.php index c21b1a3df350..f013c69ef613 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusSCORM.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusSCORM.php @@ -16,18 +16,20 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\DI\Container; -/** - * @author Stefan Meyer - * @package ilias-tracking - */ class ilLPStatusSCORM extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_scorm'; + protected const string LNG_TEXT_INFO = 'trac_mode_scorm_info'; + protected ilLanguage $lng; + public static function _getInProgress(int $a_obj_id): array { $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); - $users = array(); + $users = []; foreach ($status_info['in_progress'] as $in_progress) { $users = array_merge($users, $in_progress); } @@ -36,21 +38,15 @@ public static function _getInProgress(int $a_obj_id): array $users, ilLPStatusWrapper::_getCompleted($a_obj_id) ); - $users = array_diff($users, ilLPStatusWrapper::_getFailed($a_obj_id)); - - return $users; + return array_diff($users, ilLPStatusWrapper::_getFailed($a_obj_id)); } public static function _getCompleted(int $a_obj_id): array { - global $DIC; - - $ilDB = $DIC['ilDB']; - $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); $items = $status_info['scos']; $counter = 0; - $users = array(); + $users = []; foreach ($items as $sco_id) { $tmp_users = $status_info['completed'][$sco_id]; @@ -60,19 +56,16 @@ public static function _getCompleted(int $a_obj_id): array $users = array_intersect($users, $tmp_users); } } - - $users = array_diff($users, ilLPStatusWrapper::_getFailed($a_obj_id)); - return $users; + return array_diff($users, ilLPStatusWrapper::_getFailed($a_obj_id)); } public static function _getFailed(int $a_obj_id): array { $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); - if (!count($status_info['scos'])) { - return array(); + return []; } - $users = array(); + $users = []; foreach ($status_info['scos'] as $sco_id) { $users = array_merge( $users, @@ -84,13 +77,12 @@ public static function _getFailed(int $a_obj_id): array public static function _getNotAttempted(int $a_obj_id): array { - $users = array(); - + $users = []; $members = ilObjectLP::getInstance($a_obj_id)->getMembers(); if ($members) { // diff in progress and completed (use stored result in LPStatusWrapper) $users = array_diff( - (array) $members, + $members, ilLPStatusWrapper::_getInProgress($a_obj_id) ); $users = array_diff( @@ -102,7 +94,6 @@ public static function _getNotAttempted(int $a_obj_id): array ilLPStatusWrapper::_getFailed($a_obj_id) ); } - return $users; } @@ -114,7 +105,7 @@ public static function _getStatusInfo(int $a_obj_id): array if ($collection) { $status_info['scos'] = $collection->getItems(); } else { - $status_info['scos'] = array(); + $status_info['scos'] = []; } $status_info['num_scos'] = count($status_info['scos']); @@ -180,16 +171,14 @@ public static function _getStatusInfo(int $a_obj_id): array ); break; } - - $status_info['completed'] = array(); - $status_info['failed'] = array(); - $status_info['in_progress'] = array(); + $status_info['completed'] = []; + $status_info['failed'] = []; + $status_info['in_progress'] = []; foreach ($status_info['scos'] as $sco_id) { - $status_info['completed'][$sco_id] = $info['completed'][$sco_id] ?? array(); - $status_info['failed'][$sco_id] = $info['failed'][$sco_id] ?? array(); - $status_info['in_progress'][$sco_id] = $info['in_progress'][$sco_id] ?? array(); + $status_info['completed'][$sco_id] = $info['completed'][$sco_id] ?? []; + $status_info['failed'][$sco_id] = $info['failed'][$sco_id] ?? []; + $status_info['in_progress'][$sco_id] = $info['in_progress'][$sco_id] ?? []; } - //var_dump($status_info["completed"]); return $status_info; } @@ -198,10 +187,7 @@ public function determineStatus( int $a_usr_id, ?object $a_obj = null ): int { - global $DIC; - $status = self::LP_STATUS_NOT_ATTEMPTED_NUM; - // if the user has accessed the scorm object // the status is at least "in progress" if (ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id)) { @@ -250,8 +236,6 @@ public function determineStatus( } } } - - //$ilLog->write("-".$status."-"); return $status; } @@ -338,4 +322,25 @@ public function refreshStatus(int $a_obj_id, ?array $a_users = null): void } } } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_SCORM; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusSCORMPackage.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusSCORMPackage.php index ac9a95e3dc57..5eeb1b88554a 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusSCORMPackage.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusSCORMPackage.php @@ -16,10 +16,16 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\DI\Container; class ilLPStatusSCORMPackage extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_scorm_package'; + protected const string LNG_TEXT_INFO = 'trac_mode_scorm_package_info'; + protected ilLanguage $lng; + public static function _getInProgress(int $a_obj_id): array { $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); @@ -45,32 +51,17 @@ public static function _getStatusInfo(int $a_obj_id): array { $status_info['subtype'] = "scorm2004"; $info = ilSCORM2004Tracking::_getProgressInfo($a_obj_id); - $status_info['completed'] = $info['completed']; $status_info['failed'] = $info['failed']; $status_info['in_progress'] = $info['in_progress']; - return $status_info; } - /** - * Determine status - * @param int object id - * @param int user id - * @param object object (optional depends on object type) - * @return int status - */ public function determineStatus( int $a_obj_id, int $a_usr_id, ?object $a_obj = null ): int { - global $DIC; - - $ilObjDataCache = $DIC['ilObjDataCache']; - $ilDB = $DIC['ilDB']; - $ilLog = $DIC['ilLog']; - $scorm_status = ilSCORM2004Tracking::_getProgressInfoOfUser( $a_obj_id, $a_usr_id @@ -87,31 +78,26 @@ public function determineStatus( $status = self::LP_STATUS_FAILED_NUM; break; } - return $status; } public function refreshStatus(int $a_obj_id, ?array $a_users = null): void { parent::refreshStatus($a_obj_id, $a_users); - $in_progress = ilLPStatusWrapper::_getInProgress($a_obj_id); $completed = ilLPStatusWrapper::_getCompleted($a_obj_id); $failed = ilLPStatusWrapper::_getFailed($a_obj_id); $all_active_users = array_unique( array_merge($in_progress, $completed, $failed) ); - // get all tracked users regardless of SCOs $all_tracked_users = ilSCORM2004Tracking::_getTrackedUsers($a_obj_id); - $not_attempted_users = array_diff( $all_tracked_users, $all_active_users ); unset($all_tracked_users); unset($all_active_users); - // reset all users which have no data for the current SCOs if ($not_attempted_users) { foreach ($not_attempted_users as $usr_id) { @@ -133,4 +119,25 @@ public function determinePercentage( ): int { return 0;//todo! } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_SCORM_PACKAGE; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusStudyProgramme.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusStudyProgramme.php index 158c572372d3..5546fba1786a 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusStudyProgramme.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusStudyProgramme.php @@ -18,8 +18,14 @@ declare(strict_types=1); +use ILIAS\DI\Container; + class ilLPStatusStudyProgramme extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_study_programme'; + protected const string LNG_TEXT_INFO = ''; + protected ilLanguage $lng; + protected static function getAssignments(int $obj_id, ?int $usr_id = null): array { $dic = ilStudyProgrammeDIC::dic(); @@ -84,7 +90,6 @@ protected static function getAssignmentsLPMatrix(array $assignments, int $prg_ob ilLPStatus::LP_STATUS_COMPLETED_NUM => [], ilLPStatus::LP_STATUS_FAILED_NUM => [] ]; - $user_centric = []; foreach ($assignments as $ass) { $usr_id = $ass->getUserId(); @@ -97,7 +102,6 @@ protected static function getAssignmentsLPMatrix(array $assignments, int $prg_ob $status = self::getStatusForAssignments($assignments, $prg_obj_id); $matrix[$status][] = $usr_id; } - return $matrix; } @@ -133,9 +137,30 @@ public static function _getFailed($a_obj_id): array return $matrix[ilLPStatus::LP_STATUS_FAILED_NUM]; } - public function determineStatus($a_obj_id, $a_user_id, $a_obj = null): int + public function determineStatus($a_obj_id, $a_usr_id, $a_obj = null): int { - $assignments = self::getAssignments((int) $a_obj_id, (int) $a_user_id); + $assignments = self::getAssignments((int) $a_obj_id, (int) $a_usr_id); return self::getStatusForAssignments($assignments, (int) $a_obj_id); } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_STUDY_PROGRAMME; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusSurveyFinished.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusSurveyFinished.php index 29e54d847ec0..9d62399673fd 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusSurveyFinished.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusSurveyFinished.php @@ -16,15 +16,16 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\DI\Container; -// patch-begin svy_lp -/** - * @author Jörg Lützenkirchen - * @ingroup ServicesTracking - */ class ilLPStatusSurveyFinished extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_survey_finished'; + protected const string LNG_TEXT_INFO = 'trac_mode_survey_finished_info'; + protected ilLanguage $lng; + public static function _getNotAttempted(int $a_obj_id): array { $invited = self::getInvitations($a_obj_id); @@ -32,14 +33,13 @@ public static function _getNotAttempted(int $a_obj_id): array return []; } $users = array_diff( - (array) $invited, + $invited, ilLPStatusWrapper::_getInProgress($a_obj_id) ); - $users = array_diff( + return array_diff( $users, ilLPStatusWrapper::_getCompleted($a_obj_id) ); - return $users; } public static function _getInProgress(int $a_obj_id): array @@ -62,10 +62,8 @@ public function determineStatus( return ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM; } $status = ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM; - if (ilObjSurveyAccess::_isSurveyParticipant($a_usr_id, $survey_id)) { $status = ilLPStatus::LP_STATUS_IN_PROGRESS_NUM; - if (ilObjSurveyAccess::_lookupFinished($a_obj_id, $a_usr_id)) { $status = ilLPStatus::LP_STATUS_COMPLETED_NUM; } @@ -76,7 +74,6 @@ public function determineStatus( protected static function getSurveyId(int $a_obj_id): int { global $DIC; - $ilDB = $DIC['ilDB']; $set = $ilDB->query( "SELECT survey_id FROM svy_svy" . @@ -91,21 +88,17 @@ public static function getParticipants( bool $a_only_finished = false ): array { global $DIC; - $ilDB = $DIC['ilDB']; $res = array(); $survey_id = self::getSurveyId($a_obj_id); if (!$survey_id) { return $res; } - $sql = "SELECT user_fi FROM svy_finished fin" . " WHERE fin.survey_fi = " . $ilDB->quote($survey_id, "integer"); - if ($a_only_finished) { $sql .= " AND fin.state = " . $ilDB->quote(1, "integer"); } - $set = $ilDB->query($sql); while ($row = $ilDB->fetchAssoc($set)) { $res[] = (int) $row["user_fi"]; @@ -114,13 +107,11 @@ public static function getParticipants( } /** - * @param int $a_obj_id * @return int[] */ public static function getInvitations(int $a_obj_id): array { global $DIC; - $db = $DIC->database(); $query = 'select user_id from svy_invitation si ' . 'join svy_svy ss on ss.survey_id = si.survey_id ' . @@ -132,4 +123,25 @@ public static function getInvitations(int $a_obj_id): array } return $invited; } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_SURVEY_FINISHED; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusTestFinished.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusTestFinished.php index ec10c44943e7..bffa6f34b8e0 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusTestFinished.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusTestFinished.php @@ -16,20 +16,20 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\DI\Container; -/** - * @author Stefan Meyer - * @ingroup ServicesTracking - */ class ilLPStatusTestFinished extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_test_finished'; + protected const string LNG_TEXT_INFO = 'trac_mode_test_finished_info'; + protected ilLanguage $lng; + public static function _getInProgress(int $a_obj_id): array { global $DIC; - $ilDB = $DIC['ilDB']; - $query = " SELECT active_id, user_fi, COUNT(tst_sequence.active_fi) sequences FROM tst_active @@ -40,11 +40,8 @@ public static function _getInProgress(int $a_obj_id): array GROUP BY active_id, user_fi HAVING COUNT(tst_sequence.active_fi) > {$ilDB->quote(0, "integer")} "; - $res = $ilDB->query($query); - - $user_ids = array(); - + $user_ids = []; while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { $user_ids[$row->user_fi] = (int) $row->user_fi; } @@ -54,7 +51,6 @@ public static function _getInProgress(int $a_obj_id): array public static function _getCompleted(int $a_obj_id): array { global $DIC; - $ilDB = $DIC['ilDB']; $query = " SELECT active_id, user_fi, COUNT(tst_sequence.active_fi) sequences @@ -66,11 +62,8 @@ public static function _getCompleted(int $a_obj_id): array GROUP BY active_id, user_fi HAVING COUNT(tst_sequence.active_fi) > {$ilDB->quote(0, "integer")} "; - $res = $ilDB->query($query); - - $user_ids = array(); - + $user_ids = []; while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { $user_ids[$row->user_fi] = (int) $row->user_fi; } @@ -80,9 +73,7 @@ public static function _getCompleted(int $a_obj_id): array public static function _getNotAttempted(int $a_obj_id): array { global $DIC; - $ilDB = $DIC['ilDB']; - $query = " SELECT active_id, user_fi, COUNT(tst_sequence.active_fi) sequences FROM tst_active @@ -92,32 +83,25 @@ public static function _getNotAttempted(int $a_obj_id): array GROUP BY active_id, user_fi HAVING COUNT(tst_sequence.active_fi) = {$ilDB->quote(0, "integer")} "; - $res = $ilDB->query($query); - - $user_ids = array(); - + $user_ids = []; while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { $user_ids[$row->user_fi] = (int) $row->user_fi; } - return array_values($user_ids); } public static function getParticipants($a_obj_id) { global $DIC; - $ilDB = $DIC['ilDB']; - $res = $ilDB->query( "SELECT DISTINCT user_fi FROM tst_active" . " WHERE test_fi = " . $ilDB->quote( ilObjTestAccess::_getTestIDFromObjectID($a_obj_id) ) ); - $user_ids = array(); - + $user_ids = []; while ($rec = $ilDB->fetchAssoc($res)) { $user_ids[] = (int) $rec["user_fi"]; } @@ -140,18 +124,37 @@ public function determineStatus( GROUP BY active_id, user_fi, tries " ); - $status = self::LP_STATUS_NOT_ATTEMPTED_NUM; - - if ($rec = $this->db->fetchAssoc($res)) { - if ($rec['sequences'] > 0) { - $status = self::LP_STATUS_IN_PROGRESS_NUM; - - if ($rec['tries'] > 0) { - $status = self::LP_STATUS_COMPLETED_NUM; - } + if ( + ($rec = $this->db->fetchAssoc($res)) && + $rec['sequences'] > 0 + ) { + $status = self::LP_STATUS_IN_PROGRESS_NUM; + if ($rec['tries'] > 0) { + $status = self::LP_STATUS_COMPLETED_NUM; } } return $status; } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_TEST_FINISHED; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusTestPassed.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusTestPassed.php index f8d991e89de1..b026effa0806 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusTestPassed.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusTestPassed.php @@ -16,18 +16,19 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); +use ILIAS\DI\Container; use ILIAS\Test\Results\Data\Repository; use ILIAS\Test\Participants\ParticipantRepository; use ILIAS\Test\TestDIC; -/** - * @author Stefan Meyer - * @package ilias-tracking - */ class ilLPStatusTestPassed extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_test_passed'; + protected const string LNG_TEXT_INFO = 'trac_mode_test_passed_info'; + protected ilLanguage $lng; + public static function _getInProgress(int $a_obj_id): array { $userIds = self::getUserIdsByResultArrayStatus( @@ -58,15 +59,12 @@ private static function getUserIdsByResultArrayStatus( $resultArrayStatus ) { $status_info = ilLPStatusWrapper::_getStatusInfo($objId); - - $user_ids = array(); - + $user_ids = []; foreach ($status_info['results'] as $user_data) { if (isset($user_data[$resultArrayStatus]) && $user_data[$resultArrayStatus]) { $user_ids[] = (int) $user_data['user_id']; } } - return $user_ids; } @@ -103,10 +101,8 @@ public function determineStatus( ): int { /** @var Repository $test_result_repository */ $test_result_repository = TestDIC::dic()['results.data.repository']; - $old_status = ilLPStatus::_lookupStatus($a_obj_id, $a_usr_id, false); $status = self::LP_STATUS_NOT_ATTEMPTED_NUM; - $res = $this->db->query( " SELECT tst_active.active_id, tst_active.tries, count(tst_sequence.active_fi) " . $this->db->quoteIdentifier( @@ -129,7 +125,6 @@ public function determineStatus( GROUP BY tst_active.active_id, tst_active.tries, is_last_pass " ); - if ( ($rec = $this->db->fetchAssoc($res)) && $rec['sequences'] > 0 @@ -154,13 +149,13 @@ public function determineStatus( } } } - - if ($old_status !== null - && $old_status !== self::LP_STATUS_NOT_ATTEMPTED_NUM - && $status === self::LP_STATUS_IN_PROGRESS_NUM) { + if ( + $old_status !== null && + $old_status !== self::LP_STATUS_NOT_ATTEMPTED_NUM && + $status === self::LP_STATUS_IN_PROGRESS_NUM + ) { return $old_status; } - return $status; } @@ -169,22 +164,18 @@ protected function determineStatusForScoreLastPassTests( bool $passed ): int { $status = self::LP_STATUS_IN_PROGRESS_NUM; - if ($is_finished) { $status = $this->determineLpStatus($passed); } - return $status; } protected function determineLpStatus(bool $passed): int { $status = self::LP_STATUS_FAILED_NUM; - if ($passed) { $status = self::LP_STATUS_COMPLETED_NUM; } - return $status; } @@ -207,17 +198,36 @@ public function determinePercentage( ) ); $per = 0; - if ($rec = $this->db->fetchAssoc($set)) { - if ($rec["max_points"] > 0) { - $per = (int) min( - 100, - 100 / $rec["max_points"] * $rec["reached_points"] - ); - } else { - // According to mantis #12305 - $per = 0; - } + if ( + ($rec = $this->db->fetchAssoc($set)) && + $rec["max_points"] > 0 + ) { + $per = (int) min( + 100, + 100 / $rec["max_points"] * $rec["reached_points"] + ); } - return (int) $per; + return $per; + } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_TEST_PASSED; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusTypicalLearningTime.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusTypicalLearningTime.php index cb619a6c6d7d..96f494d788b5 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusTypicalLearningTime.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusTypicalLearningTime.php @@ -16,25 +16,21 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\DI\Container; -/** - * @author Stefan Meyer - * @ingroup ServicesTracking - */ class ilLPStatusTypicalLearningTime extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_tlt'; + protected const string LNG_TEXT_INFO = 'trac_mode_tlt_info'; + protected ilLanguage $lng; + public static function _getInProgress(int $a_obj_id): array { - global $DIC; - - $ilDB = $DIC['ilDB']; - $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); $tlt = $status_info['tlt']; - $all = ilChangeEvent::_lookupReadEvents($a_obj_id); - $user_ids = []; foreach ($all as $event) { if ($event['spent_seconds'] < $tlt) { @@ -46,15 +42,10 @@ public static function _getInProgress(int $a_obj_id): array public static function _getCompleted(int $a_obj_id): array { - global $DIC; - - $ilDB = $DIC['ilDB']; - $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); $tlt = $status_info['tlt']; // TODO: move to status info $all = ilChangeEvent::_lookupReadEvents($a_obj_id); - $user_ids = []; foreach ($all as $event) { if ($event['spent_seconds'] >= $tlt) { @@ -67,10 +58,8 @@ public static function _getCompleted(int $a_obj_id): array public static function _getStatusInfo(int $a_obj_id): array { global $DIC; - /** @var ilObjectDataCache $ilObjDataCache */ $ilObjDataCache = $DIC['ilObjDataCache']; - $status_info['tlt'] = parent::_getTypicalLearningTime( $ilObjDataCache->lookupType($a_obj_id), $a_obj_id @@ -84,24 +73,20 @@ public function determineStatus( ?object $a_obj = null ): int { $status = self::LP_STATUS_NOT_ATTEMPTED_NUM; - switch ($this->ilObjDataCache->lookupType($a_obj_id)) { - case 'lm': - if (ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id)) { - $status = self::LP_STATUS_IN_PROGRESS_NUM; - - // completed? - $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); - $tlt = $status_info['tlt']; - - $re = ilChangeEvent::_lookupReadEvents( - $a_obj_id, - $a_usr_id - ); - if ($re[0]['spent_seconds'] >= $tlt) { - $status = self::LP_STATUS_COMPLETED_NUM; - } - } - break; + if ( + strcmp($this->ilObjDataCache->lookupType($a_obj_id), 'lm') === 0 && + ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id) + ) { + $status = self::LP_STATUS_IN_PROGRESS_NUM; + $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); + $tlt = $status_info['tlt']; + $re = ilChangeEvent::_lookupReadEvents( + $a_obj_id, + $a_usr_id + ); + if ($re[0]['spent_seconds'] >= $tlt) { + $status = self::LP_STATUS_COMPLETED_NUM; + } } return $status; } @@ -125,4 +110,26 @@ public function determinePercentage( } return $per; } + + public function init( + Container $DIC + ): void { + parent::init($DIC); + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_TLT; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return sprintf($this->lng->txt(self::LNG_TEXT_INFO), ilObjUserTracking::_getValidTimeSpan()); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusVisitedPages.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusVisitedPages.php index b78dd0647528..3c618397bc27 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusVisitedPages.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusVisitedPages.php @@ -16,15 +16,16 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\DI\Container; -/** - * @author Jörg Lützenkirchen - * @version $Id$ - * @ingroup ServicesTracking - */ class ilLPStatusVisitedPages extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_visited_pages'; + protected const string LNG_TEXT_INFO = 'trac_mode_visited_pages_info'; + protected ilLanguage $lng; + public static function _getInProgress(int $a_obj_id): array { $users = ilChangeEvent::lookupUsersInProgress($a_obj_id); @@ -37,17 +38,15 @@ public static function _getInProgress(int $a_obj_id): array public static function _getCompleted(int $a_obj_id): array { - $users = array(); - + $users = []; $all_page_ids = self::getLMPages($a_obj_id); foreach (self::getVisitedPages( $a_obj_id ) as $user_id => $user_page_ids) { - if (!(bool) sizeof(array_diff($all_page_ids, $user_page_ids))) { + if (!sizeof(array_diff($all_page_ids, $user_page_ids))) { $users[] = $user_id; } } - return $users; } @@ -57,18 +56,15 @@ public function determineStatus( ?object $a_obj = null ): int { $status = self::LP_STATUS_NOT_ATTEMPTED_NUM; - switch (ilObject::_lookupType($a_obj_id)) { - case 'lm': - if (ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id)) { - $status = self::LP_STATUS_IN_PROGRESS_NUM; - - if (self::hasVisitedAllPages($a_obj_id, $a_usr_id)) { - $status = self::LP_STATUS_COMPLETED_NUM; - } - } - break; + if ( + strcmp(ilObject::_lookupType($a_obj_id), 'lm') === 0 && + ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id) + ) { + $status = self::LP_STATUS_IN_PROGRESS_NUM; + if (self::hasVisitedAllPages($a_obj_id, $a_usr_id)) { + $status = self::LP_STATUS_COMPLETED_NUM; + } } - return $status; } @@ -100,11 +96,8 @@ protected static function hasVisitedAllPages( protected static function getLMPages(int $a_obj_id): array { global $DIC; - $ilDB = $DIC['ilDB']; - - $res = array(); - + $res = []; $set = $ilDB->query( "SELECT lm_data.obj_id" . " FROM lm_data" . @@ -126,33 +119,46 @@ protected static function getVisitedPages( ?int $a_user_id = null ): array { global $DIC; - $ilDB = $DIC['ilDB']; - - $res = array(); - + $res = []; $all_page_ids = self::getLMPages($a_obj_id); if (!sizeof($all_page_ids)) { return $res; } - $sql = "SELECT obj_id, usr_id" . " FROM lm_read_event" . " WHERE " . $ilDB->in("obj_id", $all_page_ids, "", "integer"); - if ($a_user_id) { $sql .= " AND usr_id = " . $ilDB->quote($a_user_id, "integer"); } - $set = $ilDB->query($sql); while ($row = $ilDB->fetchAssoc($set)) { $res[(int) $row["usr_id"]][] = (int) $row["obj_id"]; } - if ($a_user_id) { $res = $res[$a_user_id] ?? []; } - return $res; } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_VISITED_PAGES; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } } diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusVisits.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusVisits.php index c7da1d8a5cab..30c8b5c2c890 100755 --- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusVisits.php +++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusVisits.php @@ -16,23 +16,23 @@ * *********************************************************************/ -declare(strict_types=0); +declare(strict_types=1); + +use ILIAS\DI\Container; +use ILIAS\Tracking\DB\Factory as TrackingDBFactory; +use ILIAS\Tracking\DB\FactoryInterface as TrackingDBFactoryInterface; -/** - * @author Stefan Meyer - * @ingroup ServicesTracking - */ class ilLPStatusVisits extends ilLPStatus { + protected const string LNG_TEXT = 'trac_mode_visits'; + protected const string LNG_TEXT_INFO = 'trac_mode_visits_info'; + protected TrackingDBFactoryInterface $tracking_db_factory; + protected ilLanguage $lng; + public static function _getInProgress(int $a_obj_id): array { - global $DIC; - - $ilDB = $DIC['ilDB']; - $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); $required_visits = $status_info['visits']; - $all = ilChangeEvent::_lookupReadEvents($a_obj_id); $user_ids = []; foreach ($all as $event) { @@ -45,13 +45,8 @@ public static function _getInProgress(int $a_obj_id): array public static function _getCompleted(int $a_obj_id): array { - global $DIC; - - $ilDB = $DIC['ilDB']; - $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); $required_visits = $status_info['visits']; - $all = ilChangeEvent::_lookupReadEvents($a_obj_id); $user_ids = []; foreach ($all as $event) { @@ -73,30 +68,21 @@ public function determineStatus( int $a_usr_id, ?object $a_obj = null ): int { - global $DIC; - - $ilObjDataCache = $DIC['ilObjDataCache']; - $ilDB = $DIC['ilDB']; - $status = self::LP_STATUS_NOT_ATTEMPTED_NUM; - switch ($this->ilObjDataCache->lookupType($a_obj_id)) { - case 'lm': - if (ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id)) { - $status = self::LP_STATUS_IN_PROGRESS_NUM; - - // completed? - $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); - $required_visits = $status_info['visits']; - - $re = ilChangeEvent::_lookupReadEvents( - $a_obj_id, - $a_usr_id - ); - if (($re[0]['read_count'] ?? 0) >= $required_visits) { - $status = self::LP_STATUS_COMPLETED_NUM; - } - } - break; + if ( + strcmp($this->ilObjDataCache->lookupType($a_obj_id), 'lm') === 0 && + ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id) + ) { + $status = self::LP_STATUS_IN_PROGRESS_NUM; + $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id); + $required_visits = $status_info['visits']; + $re = ilChangeEvent::_lookupReadEvents( + $a_obj_id, + $a_usr_id + ); + if (($re[0]['read_count'] ?? 0) >= $required_visits) { + $status = self::LP_STATUS_COMPLETED_NUM; + } } return $status; } @@ -107,10 +93,8 @@ public function determinePercentage( ?object $a_obj = null ): int { $reqv = ilLPObjSettings::_lookupVisits($a_obj_id); - $re = ilChangeEvent::_lookupReadEvents($a_obj_id, $a_usr_id); $rc = (int) ($re[0]["read_count"] ?? 0); - if ($reqv > 0 && $rc) { $per = (int) min(100, 100 / $reqv * $rc); } else { @@ -118,4 +102,48 @@ public function determinePercentage( } return $per; } + + public function init( + Container $DIC + ): void { + $this->lng = $DIC->language(); + $this->tracking_db_factory = new TrackingDBFactory($DIC->database()); + } + + public function getCustomLPSettingsExportXML( + int $object_id + ): SimpleXMLElement { + $xml_root = new SimpleXMLElement(''); + $lp_settings = $this->tracking_db_factory->lpSettings()->repository()->readLPSettings($object_id); + $visits = is_null($lp_settings) + ? ilLPObjSettings::LP_DEFAULT_VISITS + : $lp_settings->getVisits(); + $xml_root->addAttribute('visits', (string) $visits); + return $xml_root; + } + + public function importCustomLPSettingsExportXML( + int $new_object_id, + ilImportMapping $a_mapping, + SimpleXMLElement $additional_xml_root + ): void { + $settings = $this->tracking_db_factory->lpSettings()->repository()->readLPSettings($new_object_id); + $settings = $settings->withVisits((int) $additional_xml_root->attributes()->visits); + $this->tracking_db_factory->lpSettings()->repository()->writeLPSettings($settings); + } + + public function getLPStatusId(): string + { + return (string) ilLPObjSettings::LP_MODE_VISITS; + } + + public function getLabel(): string + { + return $this->lng->txt(self::LNG_TEXT); + } + + public function getInfo(): string + { + return $this->lng->txt(self::LNG_TEXT_INFO); + } }