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/Unit.php | |
| parent | e8ce2c6e2bb858f9af664dbc5ac37edb958b8850 (diff) | |
Courseware: Rechte und Sichtbarkeit funktionieren nach unterschiedlichen Kriterien
Closes #3442
Merge request studip/studip!2635
Diffstat (limited to 'lib/models/Courseware/Unit.php')
| -rw-r--r-- | lib/models/Courseware/Unit.php | 161 |
1 files changed, 141 insertions, 20 deletions
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); + } } |
