diff options
| author | Ron Lucke <lucke@elan-ev.de> | 2024-11-04 11:39:35 +0000 |
|---|---|---|
| committer | Ron Lucke <lucke@elan-ev.de> | 2024-11-04 11:39:35 +0000 |
| commit | c7c10f40175d34d9c76fa90d328ff0cdc2c7dfd2 (patch) | |
| tree | b444b0206bd43cb87612f90f0f646eccff301348 /lib/models/Courseware | |
| parent | e8ce2c6e2bb858f9af664dbc5ac37edb958b8850 (diff) | |
Courseware: Rechte und Sichtbarkeit funktionieren nach unterschiedlichen Kriterien
Closes #3442
Merge request studip/studip!2635
Diffstat (limited to 'lib/models/Courseware')
| -rw-r--r-- | lib/models/Courseware/StructuralElement.php | 329 | ||||
| -rw-r--r-- | lib/models/Courseware/Unit.php | 161 |
2 files changed, 322 insertions, 168 deletions
diff --git a/lib/models/Courseware/StructuralElement.php b/lib/models/Courseware/StructuralElement.php index 8e06a39..6f87e70 100644 --- a/lib/models/Courseware/StructuralElement.php +++ b/lib/models/Courseware/StructuralElement.php @@ -32,10 +32,18 @@ use User; * @property \JSONArrayObject $payload database column * @property int $public database column * @property int $commentable database column - * @property int $release_date database column - * @property int $withdraw_date database column - * @property \JSONArrayObject $read_approval database column - * @property \JSONArrayObject $write_approval database column + * @property string $permission_type database column + * @property string $visible database column + * @property bool $visible_all database column + * @property int $visible_start_date database column + * @property int $visible_end_date database column + * @property string $writable database column + * @property bool $writable_all database column + * @property int|null $writable_start_date database column + * @property int|null $writable_end_date database column + * @property \JSONArrayObject $visible_approval database column + * @property \JSONArrayObject $writable_approval database column + * @property \JSONArrayObject $content_approval database column * @property \JSONArrayObject $copy_approval database column * @property \JSONArrayObject $external_relations database column * @property int $mkdate database column @@ -60,8 +68,9 @@ class StructuralElement extends \SimpleORMap implements \PrivacyObject, \Feedbac $config['db_table'] = 'cw_structural_elements'; $config['serialized_fields']['payload'] = JSONArrayObject::class; - $config['serialized_fields']['read_approval'] = JSONArrayObject::class; - $config['serialized_fields']['write_approval'] = JSONArrayObject::class; + $config['serialized_fields']['visible_approval'] = JSONArrayObject::class; + $config['serialized_fields']['writable_approval'] = JSONArrayObject::class; + $config['serialized_fields']['content_approval'] = JSONArrayObject::class; $config['serialized_fields']['copy_approval'] = JSONArrayObject::class; $config['serialized_fields']['external_relations'] = JSONArrayObject::class; @@ -276,37 +285,42 @@ class StructuralElement extends \SimpleORMap implements \PrivacyObject, \Feedbac if ($this->range_id === $user->id) { return true; } - - return $this->hasWriteApproval($user); + + return $this->hasWriteContentApproval($user); case 'course': - $hasEditingPermission = $this->hasEditingPermission($user); - if ($this->isTask()) { - $task = $this->task; - if (!$task) { - $task = $this->findParentTask(); + $unit = $this->findUnit(); + if ($unit->permission_scope === 'unit') { + return $unit->canEditContent($user); + } else { + $hasEditingPermission = $this->hasEditingPermission($user, $unit); + if ($this->isTask()) { + $task = $this->task; if (!$task) { + $task = $this->findParentTask(); + if (!$task) { + return false; + } + } + + if ($hasEditingPermission) { return false; } - } - if ($hasEditingPermission) { - return false; - } + if ($task->isSubmitted()) { + return false; + } - if ($task->isSubmitted()) { - return false; + return $task->userIsASolver($user); } - return $task->userIsASolver($user); - } + if ($hasEditingPermission) { + return true; + } - if ($hasEditingPermission) { - return true; + return $this->hasWriteApproval($user); } - return $this->hasWriteApproval($user); - default: throw new \InvalidArgumentException('Unknown range type.'); } @@ -337,22 +351,23 @@ class StructuralElement extends \SimpleORMap implements \PrivacyObject, \Feedbac return true; } - return $this->hasReadApproval($user); + return $this->hasReadContentApproval($user); case 'course': - if (!$GLOBALS['perm']->have_studip_perm('user', $this->range_id, $user->id)) { - return false; - } + $unit = $this->findUnit(); + if ($unit->permission_scope === 'unit') { + return $unit->canRead($user); + } else { + if (!$GLOBALS['perm']->have_studip_perm('user', $this->range_id, $user->id)) { + return false; + } - if ($this->canEdit($user)) { - return true; - } + if ($this->canEdit($user)) { + return true; + } - if (!$this->releasedForReaders($this)) { - return false; + return $this->hasReadApproval($user); } - return $this->hasReadApproval($user); - default: throw new \InvalidArgumentException('Unknown range type.'); } @@ -371,7 +386,7 @@ class StructuralElement extends \SimpleORMap implements \PrivacyObject, \Feedbac return true; } - return $this->hasReadApproval($user); + return $this->hasReadContentApproval($user); case 'course': if (!$GLOBALS['perm']->have_studip_perm('user', $this->range_id, $user->id)) { @@ -411,10 +426,6 @@ class StructuralElement extends \SimpleORMap implements \PrivacyObject, \Feedbac return true; } - if (!$this->releasedForReaders($this)) { - return false; - } - return $this->hasReadApproval($user) && $this->canReadSequential($user); default: @@ -425,9 +436,11 @@ class StructuralElement extends \SimpleORMap implements \PrivacyObject, \Feedbac /** * @param \User|\Seminar_User $user */ - public function hasEditingPermission($user): bool + public function hasEditingPermission(User $user, Unit $unit = null): bool { - $unit = $this->findUnit(); + if (!isset($unit)) { + $unit = $this->findUnit(); + } return $GLOBALS['perm']->have_perm('root', $user->id) || $GLOBALS['perm']->have_studip_perm( $unit->config['editing_permission'] ?? 'tutor', @@ -438,34 +451,21 @@ class StructuralElement extends \SimpleORMap implements \PrivacyObject, \Feedbac private function hasReadApproval($user): bool { - // this property is shared between all range types. - if ($this->read_approval['all']) { - return true; - } - - // now we also check against the perms for contents. - if ($this->range_type === 'user') { - return $this->hasUserReadApproval($user); - } else { - if (!count($this->read_approval)) { + if ($this->permission_type === 'all' || $this->visible_all) { + if ($this->isVisible()) { return true; } - - // find user in users - $users = $this->read_approval['users']; - foreach ($users as $approvedUserId) { - if ($approvedUserId === $user->id) { - return true; - } - } - - // find user in groups - $groups = $this->read_approval['groups']; + return false; + } + if ($this->permission_type === 'users') { + return in_array($user->id, json_decode($this->visible_approval)) && $this->isVisible(); + } + if ($this->permission_type === 'groups') { + $groups = json_decode($this->visible_approval); foreach ($groups as $groupId) { - /** @var ?\Statusgruppen $group */ $group = \Statusgruppen::find($groupId); if ($group && $group->isMember($user->id)) { - return true; + return $this->isVisible(); } } } @@ -473,28 +473,38 @@ class StructuralElement extends \SimpleORMap implements \PrivacyObject, \Feedbac return false; } - private function hasUserReadApproval($user): bool + private function isVisible(): bool + { + if ($this->visible === 'always') { + return true; + } + if ($this->visible === 'never') { + return false; + } + + return + (empty($this->visible_start_date) || $this->visible_start_date < strtotime('today')) + && (empty($this->visible_end_date) || $this->visible_end_date >= strtotime('today')); + } + + private function hasReadContentApproval($user): bool { - if (!count($this->read_approval)) { + if (count($this->content_approval) === 0) { if ($this->isRootNode()) { return false; } - return $this->parent->hasUserReadApproval($user); + return $this->parent->hasReadContentApproval($user); } // find user in users - $users = $this->read_approval['users']; + $users = $this->content_approval['users']; foreach ($users as $listedUserPerm) { - // now for contents, there is an expiry date defined. if (!empty($listedUserPerm['expiry']) && strtotime($listedUserPerm['expiry']) < strtotime('today')) { if ($this->isRootNode()) { return false; } - return $this->parent->hasUserReadApproval($user); + return $this->parent->hasReadContentApproval($user); } - // In order to have a record of the users in the perms list of contents, - // we keep a full perm record in read_approval column, and set read property to true or false, - // this won't apply to write_approval column. if ($listedUserPerm['id'] == $user->id && $listedUserPerm['read'] == true) { return true; } @@ -505,33 +515,22 @@ class StructuralElement extends \SimpleORMap implements \PrivacyObject, \Feedbac private function hasWriteApproval($user): bool { - // this property is shared between all range types. - if ($this->write_approval['all']) { - return true; - } - - // now we also check against the perms for contents. - if ($this->range_type === 'user') { - return $this->hasUserWriteApproval($user); - } else { - if (!count($this->write_approval)) { - return false; - } - - if ($this->write_approval['all']) { - return true; - } - - // find user in users - $users = $this->write_approval['users']->getArrayCopy(); - if (in_array($user->id, $users)) { + if ($this->permission_type === 'all' || $this->writable_all) { + if ($this->isWritable()) { return true; } + return false; + } + if ($this->permission_type === 'users') { + return in_array($user->id, json_decode($this->writable_approval)) && $this->isWritable(); + } - // find user in groups - foreach (\Statusgruppen::findMany($this->write_approval['groups']->getArrayCopy()) as $group) { - if ($group->isMember($user->id)) { - return true; + if ($this->permission_type === 'groups') { + $groups = json_decode($this->writable_approval); + foreach ($groups as $groupId) { + $group = \Statusgruppen::find($groupId); + if ($group && $group->isMember($user->id)) { + return $this->isWritable(); } } } @@ -539,26 +538,39 @@ class StructuralElement extends \SimpleORMap implements \PrivacyObject, \Feedbac return false; } - private function hasUserWriteApproval($user): bool + private function isWritable(): bool { - if (!count($this->write_approval)) { + if ($this->writable === 'always') { + return true; + } + if ($this->writable === 'never') { + return false; + } + + return + (empty($this->writable_start_date) || $this->writable_start_date < strtotime('today')) + && (empty($this->writable_end_date) || $this->writable_end_date >= strtotime('today')); + } + + private function hasWriteContentApproval($user): bool + { + if (!count($this->content_approval)) { if ($this->isRootNode()) { return false; } - return $this->parent->hasUserWriteApproval($user); + return $this->parent->hasWriteContentApproval($user); } // find user in users - $users = $this->write_approval['users']; + $users = $this->content_approval['users']; foreach ($users as $listedUserPerm) { - // now for contents, there is an expiry date defined. if (!empty($listedUserPerm['expiry']) && strtotime($listedUserPerm['expiry']) < strtotime('today')) { if ($this->isRootNode()) { return false; } - return $this->parent->hasUserWriteApproval($user); + return $this->parent->hasWriteContentApproval($user); } - if ($listedUserPerm['id'] == $user->id) { + if ($listedUserPerm['id'] == $user->id && $listedUserPerm['write']) { return true; } } @@ -566,7 +578,7 @@ class StructuralElement extends \SimpleORMap implements \PrivacyObject, \Feedbac if ($this->isRootNode()) { return false; } - return $this->parent->hasUserWriteApproval($user); + return $this->parent->hasWriteContentApproval($user); } /** @@ -587,30 +599,6 @@ class StructuralElement extends \SimpleORMap implements \PrivacyObject, \Feedbac } /** - * @return bool true if the user may read this instance in time interval - * - * @SuppressWarnings(PHPMD.Superglobals) - */ - private function releasedForReaders(StructuralElement $element): bool - { - $released = false; - if (!$element->release_date || $element->release_date <= time()) { - $released = true; - } - - if ($element->withdraw_date && $element->withdraw_date <= time()) { - $released = false; - } - - $parent_released = true; - if (!$element->isRootNode()) { - $parent_released = $this->releasedForReaders($element->parent); - } - - return $released && $parent_released; - } - - /** * @param mixed $user the user to validate * * @return bool true if the user has achieved previous elements @@ -839,13 +827,18 @@ SQL; /** * Copies this instance into another course oder users contents. * - * @param User $user this user will be the owner of the copy - * @param Range $parent the target where to copy this instance + * @param User $user this user will be the owner of the copy + * @param \Range $parent the target where to copy this instance * * @return StructuralElement the copy of this instance */ - public function copyToRange(User $user, string $rangeId, string $rangeType, string $purpose = ''): StructuralElement - { + public function copyToRange( + User $user, + string $rangeId, + string $rangeType, + string $purpose = '', + bool $duplicate = false + ): StructuralElement { $element = self::build([ 'parent_id' => null, 'range_id' => $rangeId, @@ -857,7 +850,19 @@ SQL; 'purpose' => $purpose ?: $this->purpose, 'position' => 0, 'payload' => $this->payload, - 'commentable' => 0 + 'commentable' => $duplicate ? $this->commentable : 0, + 'permission_type' => $duplicate ? $this->permission_type : 'all', + 'visible' => $duplicate ? $this->visible : 'always', + 'visible_all' => $duplicate ? $this->visible_all : 0, + 'visible_start_date' => $duplicate ? $this->visible_start_date : null, + 'visible_end_date' => $duplicate ? $this->visible_end_date : null, + 'visible_approval' => $duplicate ? $this->visible_approval : '', + 'writable' => $duplicate ? $this->writable : 'never', + 'writable_all' => $duplicate ? $this->writable_all : 0, + 'writable_start_date' => $duplicate ? $this->writable_start_date : null, + 'writable_end_date' => $duplicate ? $this->writable_end_date : null, + 'writable_approval' => $duplicate ? $this->writable_approval : '', + 'content_approval' => $duplicate ? $this->content_approval : '', ]); $element->store(); @@ -869,7 +874,7 @@ SQL; $this->copyContainers($user, $element); - $this->copyChildren($user, $element, $purpose); + $this->copyChildren($user, $element, $purpose, '', $duplicate); return $element; } @@ -877,15 +882,20 @@ SQL; /** * Copies this instance as a child into another structural element. * - * @param User $user this user will be the owner of the copy + * @param User $user this user will be the owner of the copy * @param StructuralElement $parent the target where to copy this instance * @param string $purpose the purpose of copying this instance * @param string $recursiveId the optional mapping id for copying child structural elements upon recursive call to this function * * @return StructuralElement the copy of this instance */ - public function copy(User $user, StructuralElement $parent, string $purpose = '', string $recursiveId = ''): StructuralElement - { + public function copy( + User $user, + StructuralElement $parent, + string $purpose = '', + string $recursiveId = '', + bool $duplicate = false + ): StructuralElement { $ancestorIds = array_column($parent->findAncestors(), 'id'); $ancestorIds[] = $parent->id; if (in_array($this->id, $ancestorIds)) { @@ -908,9 +918,19 @@ SQL; 'payload' => $this->payload, 'image_id' => $image_id, 'image_type' => $this->image_type, - 'read_approval' => $parent->read_approval, - 'write_approval' => $parent->write_approval, - 'commentable' => 0 + 'permission_type' => $duplicate ? $this->permission_type : 'all', + 'visible' => $duplicate ? $this->visible : 'always', + 'visible_all' => $duplicate ? $this->visible_all : 0, + 'visible_start_date' => $duplicate ? $this->visible_start_date : null, + 'visible_end_date' => $duplicate ? $this->visible_end_date : null, + 'visible_approval' => $duplicate ? $this->visible_approval : '', + 'writable' => $duplicate ? $this->writable : 'never', + 'writable_all' => $duplicate ? $this->writable_all : 0, + 'writable_start_date' => $duplicate ? $this->writable_start_date : null, + 'writable_end_date' => $duplicate ? $this->writable_end_date : null, + 'writable_approval' => $duplicate ? $this->writable_approval : '', + 'content_approval' => $duplicate ? $this->content_approval : '', + 'commentable' => $duplicate ? $this->commentable : 0, ]); $element->store(); @@ -1027,10 +1047,15 @@ SQL; return [$containerMap, $blockMap]; } - private function copyChildren(User $user, StructuralElement $newElement, string $purpose = '', string $recursiveId = ''): void - { + private function copyChildren( + User $user, + StructuralElement $newElement, + string $purpose = '', + string $recursiveId = '', + bool $duplicate = false + ): void { foreach ($this->children as $child) { - $child->copy($user, $newElement, $purpose, $recursiveId); + $child->copy($user, $newElement, $purpose, $recursiveId, $duplicate); } } @@ -1049,8 +1074,16 @@ SQL; 'purpose' => $this->purpose, 'position' => $parent->countChildren(), 'payload' => $this->payload, - 'read_approval' => $parent->read_approval, - 'write_approval' => $parent->write_approval, + 'permission_type'=> $parent->permission_type, + 'visible' => $parent->visible, + 'visible_start_date' => $parent->visible_start_date, + 'visible_end_date' => $parent->visible_end_date, + 'writable' => $parent->writable, + 'writable_start_date' => $parent->writable_start_date, + 'writable_end_date' => $parent->writable_end_date, + 'visible_approval' => $parent->visible_approval, + 'writable_approval' => $parent->writable_approval, + 'content_approval' => $parent->content_approval, 'commentable' => 0 ]); diff --git a/lib/models/Courseware/Unit.php b/lib/models/Courseware/Unit.php index 2a38a29..86013e3 100644 --- a/lib/models/Courseware/Unit.php +++ b/lib/models/Courseware/Unit.php @@ -20,8 +20,18 @@ use User; * @property string $content_type database column * @property int $public database column * @property string|null $creator_id database column - * @property int|null $release_date database column - * @property int|null $withdraw_date database column + * @property string $permission_scope database column + * @property string $permission_type database column + * @property string $visible database column + * @property bool $visible_all database column + * @property int|null $visible_start_date database column + * @property int|null $visible_end_date database column + * @property string $writable database column + * @property bool $writable_all database column + * @property int|null $writable_start_date database column + * @property int|null $writable_end_date database column + * @property \JSONArrayObject $writable_approval database column + * @property \JSONArrayObject $visible_approval database column * @property \JSONArrayObject $config database column * @property int $mkdate database column * @property int $chdate database column @@ -38,6 +48,8 @@ class Unit extends \SimpleORMap implements \PrivacyObject, \FeedbackRange $config['db_table'] = 'cw_units'; $config['serialized_fields']['config'] = JSONArrayObject::class; + $config['serialized_fields']['visible_approval'] = JSONArrayObject::class; + $config['serialized_fields']['writable_approval'] = JSONArrayObject::class; $config['has_one']['structural_element'] = [ 'class_name' => StructuralElement::class, @@ -45,7 +57,7 @@ class Unit extends \SimpleORMap implements \PrivacyObject, \FeedbackRange 'on_delete' => 'delete', ]; $config['belongs_to']['course'] = [ - 'class_name' => \Course::class, + 'class_name' => \Course::class, 'foreign_key' => 'range_id', 'assoc_foreign_key' => 'seminar_id', ]; @@ -75,26 +87,116 @@ class Unit extends \SimpleORMap implements \PrivacyObject, \FeedbackRange return self::findBySQL('range_id = ? AND range_type = ?', [$course->id, 'course']); } - public static function findUsersUnits(\User $user): array + public static function findUsersUnits(User $user): array { return self::findBySQL('range_id = ? AND range_type = ?', [$user->id, 'user']); } - public function canRead(\User $user): bool + public function canRead(User $user): bool { - return $this->structural_element->canRead($user); + if ($this->canEdit($user) || $this->canEditContent($user)) { + return true; + } + if ($this->permission_scope === 'unit') { + if ($this->permission_type === 'all' || $this->visible_all) { + if ($this->isVisible()) { + return true; + } + return false; + } + if ($this->permission_type === 'users') { + return in_array($user->id, json_decode($this->visible_approval)) && $this->isVisible(); + } + if ($this->permission_type === 'groups') { + $groups = json_decode($this->visible_approval); + foreach ($groups as $groupId) { + $group = \Statusgruppen::find($groupId); + if ($group && $group->isMember($user->id)) { + return $this->isVisible(); + } + } + } + } + + return true; + } + + private function isVisible(): bool + { + if ($this->visible === 'always') { + return true; + } + if ($this->visible === 'never') { + return false; + } + + return + (empty($this->visible_start_date) || $this->visible_start_date < strtotime('today')) + && (empty($this->visible_end_date) || $this->visible_end_date >= strtotime('today')); + } + + public function canEdit(User $user): bool + { + if ($user->id === $this->range_id) { + return true; + } + + return $GLOBALS['perm']->have_perm('root', $user->id) || $GLOBALS['perm']->have_studip_perm('tutor', $this->range_id, $user->id); } - public function canEdit(\User $user): bool + public function canEditContent(User $user): bool { - return $this->structural_element->canEdit($user);; + if ($this->canEdit($user)) { + return true; + } + if ($this->permission_scope === 'unit') { + if ($this->permission_type === 'all' || $this->writable_all) { + if ($this->isWritable()) { + return true; + } + return false; + } + if ($this->permission_type === 'users') { + return in_array($user->id, json_decode($this->writable_approval)) && $this->isWritable(); + } + if ($this->permission_type === 'groups') { + $groups = json_decode($this->writable_approval); + foreach ($groups as $groupId) { + $group = \Statusgruppen::find($groupId); + if ($group && $group->isMember($user->id)) { + return $this->isWritable(); + } + } + } + } + + return false; } - public function copy(\User $user, string $rangeId, string $rangeType, array $modified = null): Unit + private function isWritable(): bool { + if ($this->writable === 'always') { + return true; + } + if ($this->writable === 'never') { + return false; + } + + return + (empty($this->writable_start_date) || $this->writable_start_date < strtotime('today')) + && (empty($this->writable_end_date) || $this->writable_end_date >= strtotime('today')); + } + + public function copy( + User $user, + string $rangeId, + string $rangeType, + array $modified = null, + bool $duplicate = false + ): Unit { $sourceUnitElement = $this->structural_element; - $newElement = $sourceUnitElement->copyToRange($user, $rangeId, $rangeType); + $newElement = $sourceUnitElement->copyToRange($user, $rangeId, $rangeType, '', $duplicate); if ($modified !== null) { $newElement->title = $modified['title'] ?? $newElement->title; @@ -108,10 +210,21 @@ class Unit extends \SimpleORMap implements \PrivacyObject, \FeedbackRange 'range_type' => $rangeType, 'structural_element_id' => $newElement->id, 'content_type' => 'courseware', + 'position' => $this->getNewPosition($rangeId), 'creator_id' => $user->id, 'public' => '', - 'release_date' => null, - 'withdraw_date' => null, + 'permission_scope' => $duplicate ? $this->permission_scope : 'unit', + 'permission_type' => $duplicate ? $this->permission_type : 'all', + 'visible' => $duplicate ? $this->visible : 'always', + 'visible_all' => $duplicate ? $this->visible_all : 0, + 'visible_start_date' => $duplicate ? $this->visible_start_date : null, + 'visible_end_date' => $duplicate ? $this->visible_end_date : null, + 'visible_approval' => $duplicate ? $this->visible_approval : '', + 'writable' => $duplicate ? $this->writable : 'never', + 'writable_all' => $duplicate ? $this->writable_all : 0, + 'writable_start_date' => $duplicate ? $this->writable_start_date : null, + 'writable_end_date' => $duplicate ? $this->writable_end_date : null, + 'writable_approval' => $duplicate ? $this->writable_approval : '', ]); $newUnit->store(); @@ -133,7 +246,7 @@ class Unit extends \SimpleORMap implements \PrivacyObject, \FeedbackRange if ($units) { $storage->addTabularData(_('Courseware Lernmaterialien'), 'cw_units', $units); } - + } public static function getNewPosition($range_id): int @@ -148,16 +261,18 @@ class Unit extends \SimpleORMap implements \PrivacyObject, \FeedbackRange } $db = \DBManager::get(); - $stmt = $db->prepare(sprintf( - 'UPDATE + $stmt = $db->prepare( + sprintf( + 'UPDATE %s SET position = position - 1 WHERE range_id = :range_id AND position > :position', - 'cw_units' - )); + 'cw_units' + ) + ); $stmt->bindValue(':range_id', $this->range_id); $stmt->bindValue(':position', $this->position); $stmt->execute(); @@ -173,7 +288,8 @@ class Unit extends \SimpleORMap implements \PrivacyObject, \FeedbackRange position = FIND_IN_SET(id, ?) - 1 WHERE range_id = ?', - 'cw_units'); + 'cw_units' + ); $args = array(join(',', $positions), $range->id); $stmt = $db->prepare($query); $stmt->execute($args); @@ -226,7 +342,7 @@ class Unit extends \SimpleORMap implements \PrivacyObject, \FeedbackRange public function getRangeUrl(): string { if ($this->structural_element->range_type === 'user') { - return 'contents/courseware/'; + return 'contents/courseware/'; } return 'course/courseware/' . '?cid=' . $this->range_id; @@ -234,7 +350,7 @@ class Unit extends \SimpleORMap implements \PrivacyObject, \FeedbackRange public function isRangeAccessible(string $user_id = null): bool { - $user = \User::find($user_id); + $user = \User::find($user_id); if ($user) { return $this->canRead($user); } @@ -249,4 +365,9 @@ class Unit extends \SimpleORMap implements \PrivacyObject, \FeedbackRange [$this->id, self::class] ); } + + public function getRange() + { + return $this->range_type::find($this->range_id); + } } |
