aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRon Lucke <lucke@elan-ev.de>2024-11-04 11:39:35 +0000
committerRon Lucke <lucke@elan-ev.de>2024-11-04 11:39:35 +0000
commitc7c10f40175d34d9c76fa90d328ff0cdc2c7dfd2 (patch)
treeb444b0206bd43cb87612f90f0f646eccff301348 /lib
parente8ce2c6e2bb858f9af664dbc5ac37edb958b8850 (diff)
Courseware: Rechte und Sichtbarkeit funktionieren nach unterschiedlichen Kriterien
Closes #3442 Merge request studip/studip!2635
Diffstat (limited to 'lib')
-rw-r--r--lib/classes/JsonApi/Routes/Courseware/CoursesUnitsIndex.php10
-rw-r--r--lib/classes/JsonApi/Routes/Courseware/StructuralElementsCreate.php14
-rw-r--r--lib/classes/JsonApi/Routes/Courseware/StructuralElementsReleasedIndex.php2
-rw-r--r--lib/classes/JsonApi/Routes/Courseware/StructuralElementsSharedIndex.php10
-rw-r--r--lib/classes/JsonApi/Routes/Courseware/StructuralElementsUpdate.php59
-rw-r--r--lib/classes/JsonApi/Routes/Courseware/UnitsCopy.php3
-rw-r--r--lib/classes/JsonApi/Routes/Courseware/UnitsCreate.php12
-rw-r--r--lib/classes/JsonApi/Routes/Courseware/UnitsUpdate.php95
-rw-r--r--lib/classes/JsonApi/Routes/SemestersIndex.php23
-rw-r--r--lib/classes/JsonApi/Schemas/Courseware/StructuralElement.php16
-rw-r--r--lib/classes/JsonApi/Schemas/Courseware/Unit.php23
-rw-r--r--lib/models/Courseware/StructuralElement.php329
-rw-r--r--lib/models/Courseware/Unit.php161
13 files changed, 530 insertions, 227 deletions
diff --git a/lib/classes/JsonApi/Routes/Courseware/CoursesUnitsIndex.php b/lib/classes/JsonApi/Routes/Courseware/CoursesUnitsIndex.php
index b09d0c8..9a3425f 100644
--- a/lib/classes/JsonApi/Routes/Courseware/CoursesUnitsIndex.php
+++ b/lib/classes/JsonApi/Routes/Courseware/CoursesUnitsIndex.php
@@ -39,9 +39,15 @@ class CoursesUnitsIndex extends JsonApiController
}
$resources = Unit::findCoursesUnits($course);
- $total = count($resources);
+ $readable_resources = [];
+ foreach ($resources as $resource) {
+ if ($resource->canRead($user)) {
+ $readable_resources[] = $resource;
+ }
+ }
+ $total = count($readable_resources);
[$offset, $limit] = $this->getOffsetAndLimit();
- return $this->getPaginatedContentResponse(array_slice($resources, $offset, $limit), $total);
+ return $this->getPaginatedContentResponse(array_slice($readable_resources, $offset, $limit), $total);
}
}
diff --git a/lib/classes/JsonApi/Routes/Courseware/StructuralElementsCreate.php b/lib/classes/JsonApi/Routes/Courseware/StructuralElementsCreate.php
index c038c45..99481f5 100644
--- a/lib/classes/JsonApi/Routes/Courseware/StructuralElementsCreate.php
+++ b/lib/classes/JsonApi/Routes/Courseware/StructuralElementsCreate.php
@@ -81,8 +81,18 @@ class StructuralElementsCreate extends JsonApiController
'title' => self::arrayGet($json, 'data.attributes.title', ''),
'purpose' => self::arrayGet($json, 'data.attributes.purpose', $parent->purpose),
'payload' => self::arrayGet($json, 'data.attributes.payload', ''),
- 'read_approval' => $parent->read_approval,
- 'write_approval' => $parent->write_approval,
+ 'permission_type'=> $parent->permission_type,
+ 'visible' => $parent->visible,
+ 'visible_all' => $parent->visible_all,
+ 'visible_start_date' => $parent->visible_start_date,
+ 'visible_end_date' => $parent->visible_end_date,
+ 'writable' => $parent->writable,
+ 'writable_all' => $parent->writable_all,
+ '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,
'position' => $parent->countChildren(),
'commentable' => 0
]);
diff --git a/lib/classes/JsonApi/Routes/Courseware/StructuralElementsReleasedIndex.php b/lib/classes/JsonApi/Routes/Courseware/StructuralElementsReleasedIndex.php
index b4a8e1c..699623b 100644
--- a/lib/classes/JsonApi/Routes/Courseware/StructuralElementsReleasedIndex.php
+++ b/lib/classes/JsonApi/Routes/Courseware/StructuralElementsReleasedIndex.php
@@ -49,7 +49,7 @@ class StructuralElementsReleasedIndex extends JsonApiController
);
foreach ($contents as $content) {
- if ((count($content->read_approval) && count($content->read_approval['users']) > 0) || (count($content->write_approval) && count($content->write_approval['users']) > 0)) {
+ if (count($content->content_approval) && count($content->content_approval['users']) > 0) {
$resources[] = $content;
}
}
diff --git a/lib/classes/JsonApi/Routes/Courseware/StructuralElementsSharedIndex.php b/lib/classes/JsonApi/Routes/Courseware/StructuralElementsSharedIndex.php
index 1582fbf..9ebf923 100644
--- a/lib/classes/JsonApi/Routes/Courseware/StructuralElementsSharedIndex.php
+++ b/lib/classes/JsonApi/Routes/Courseware/StructuralElementsSharedIndex.php
@@ -49,19 +49,13 @@ class StructuralElementsSharedIndex extends JsonApiController
);
foreach ($contents as $content) {
- if (!count($content->read_approval) || !count($content->write_approval)) {
+ if (count($content->content_approval) === 0) {
continue;
}
$add_content = false;
- foreach ($content->read_approval['users'] as $listedUserPerm) {
- if ($listedUserPerm['id'] == $user->id && $listedUserPerm['read']) {
- $add_content = true;
- }
- }
-
- foreach ($content->write_approval['users'] as $listedUserPerm) {
+ foreach ($content->content_approval['users'] as $listedUserPerm) {
if ($listedUserPerm['id'] == $user->id && $listedUserPerm['read']) {
$add_content = true;
}
diff --git a/lib/classes/JsonApi/Routes/Courseware/StructuralElementsUpdate.php b/lib/classes/JsonApi/Routes/Courseware/StructuralElementsUpdate.php
index 455aacc..3b3deb0 100644
--- a/lib/classes/JsonApi/Routes/Courseware/StructuralElementsUpdate.php
+++ b/lib/classes/JsonApi/Routes/Courseware/StructuralElementsUpdate.php
@@ -6,6 +6,7 @@ use Courseware\StructuralElement;
use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\Errors\RecordNotFoundException;
use JsonApi\JsonApiController;
+use JsonApi\Routes\TimestampTrait;
use JsonApi\Routes\ValidationTrait;
use JsonApi\Schemas\Courseware\StructuralElement as StructuralElementSchema;
use JsonApi\Schemas\FileRef as FileRefSchema;
@@ -19,6 +20,7 @@ use Psr\Http\Message\ServerRequestInterface as Request;
class StructuralElementsUpdate extends JsonApiController
{
use EditBlockAwareTrait;
+ use TimestampTrait;
use ValidationTrait;
/**
@@ -26,7 +28,8 @@ class StructuralElementsUpdate extends JsonApiController
*/
public function __invoke(Request $request, Response $response, $args)
{
- if (!($resource = StructuralElement::find($args['id']))) {
+ $resource = StructuralElement::find($args['id']);
+ if (!$resource) {
throw new RecordNotFoundException();
}
$json = $this->validate($request, $resource);
@@ -105,7 +108,7 @@ class StructuralElementsUpdate extends JsonApiController
}
$parentId = self::arrayGet($json, 'data.relationships.parent.data.id');
- return \Courseware\StructuralElement::find($parentId);
+ return StructuralElement::find($parentId);
}
private function updateStructuralElement(\User $user, StructuralElement $resource, array $json): StructuralElement
@@ -118,11 +121,13 @@ class StructuralElementsUpdate extends JsonApiController
'position',
'public',
'purpose',
- 'read-approval',
- 'release-date',
'title',
- 'withdraw-date',
- 'write-approval',
+ 'permission-type',
+ 'visible',
+ 'writable',
+ 'visible-approval',
+ 'writable-approval',
+ 'content-approval',
];
foreach ($attributes as $jsonKey) {
@@ -131,13 +136,43 @@ class StructuralElementsUpdate extends JsonApiController
$resource->$sormKey = $val;
}
}
-
- if (isset($json['data']['attributes']['release-date'])) {
- $resource->release_date = $json['data']['attributes']['release-date'];
+ if (self::arrayHas($json, 'data.attributes.visible-all')) {
+ $resource->visible_all = self::arrayGet($json, 'data.attributes.visible-all');
}
-
- if (isset($json['data']['attributes']['withdraw-date'])) {
- $resource->withdraw_date = $json['data']['attributes']['withdraw-date'];
+ if (self::arrayHas($json, 'data.attributes.writable-all')) {
+ $resource->writable_all = self::arrayGet($json, 'data.attributes.writable-all');
+ }
+ if (self::arrayHas($json, 'data.attributes.visible-start-date')) {
+ $visibleStartDate = self::arrayGet($json, 'data.attributes.visible-start-date');
+ if ($visibleStartDate) {
+ $visibleStartDate = self::fromISO8601($visibleStartDate);
+ $visibleStartDate = $visibleStartDate->getTimestamp();
+ }
+ $resource->visible_start_date = $visibleStartDate;
+ }
+ if (self::arrayHas($json, 'data.attributes.visible-end-date')) {
+ $visibleEndDate = self::arrayGet($json, 'data.attributes.visible-end-date');
+ if ($visibleEndDate) {
+ $visibleEndDate = self::fromISO8601($visibleEndDate);
+ $visibleEndDate = $visibleEndDate->getTimestamp();
+ }
+ $resource->visible_end_date = $visibleEndDate;
+ }
+ if (self::arrayHas($json, 'data.attributes.writable-start-date')) {
+ $writableStartDate = self::arrayGet($json, 'data.attributes.writable-start-date');
+ if ($writableStartDate) {
+ $writableStartDate = self::fromISO8601($writableStartDate);
+ $writableStartDate = $writableStartDate->getTimestamp();
+ }
+ $resource->writable_start_date = $writableStartDate;
+ }
+ if (self::arrayHas($json, 'data.attributes.writable-end-date')) {
+ $writableEndDate = self::arrayGet($json, 'data.attributes.writable-end-date');
+ if ($writableEndDate) {
+ $writableEndDate = self::fromISO8601($writableEndDate);
+ $writableEndDate = $writableEndDate->getTimestamp();
+ }
+ $resource->writable_end_date = $writableEndDate;
}
if (isset($json['data']['attributes']['commentable'])) {
diff --git a/lib/classes/JsonApi/Routes/Courseware/UnitsCopy.php b/lib/classes/JsonApi/Routes/Courseware/UnitsCopy.php
index 61ffa95..62a1d0a 100644
--- a/lib/classes/JsonApi/Routes/Courseware/UnitsCopy.php
+++ b/lib/classes/JsonApi/Routes/Courseware/UnitsCopy.php
@@ -31,6 +31,7 @@ class UnitsCopy extends NonJsonApiController
$rangeId = $data['rangeId'];
$rangeType = $data['rangeType'];
$modified = $data['modified'];
+ $duplicate = $data['duplicate'];
try {
$range = \RangeFactory::createRange($rangeType, $rangeId);
@@ -42,7 +43,7 @@ class UnitsCopy extends NonJsonApiController
throw new AuthorizationFailedException();
}
- $newUnit = $sourceUnit->copy($user, $rangeId, $rangeType, $modified);
+ $newUnit = $sourceUnit->copy($user, $rangeId, $rangeType, $modified, $duplicate);
$response = $response->withHeader('Content-Type', 'application/json');
$response->getBody()->write((string) json_encode($newUnit));
diff --git a/lib/classes/JsonApi/Routes/Courseware/UnitsCreate.php b/lib/classes/JsonApi/Routes/Courseware/UnitsCreate.php
index 9dfd2e6..8f3e217 100644
--- a/lib/classes/JsonApi/Routes/Courseware/UnitsCreate.php
+++ b/lib/classes/JsonApi/Routes/Courseware/UnitsCreate.php
@@ -97,7 +97,10 @@ class UnitsCreate extends JsonApiController
'purpose' => self::arrayGet($json, 'data.attributes.purpose', 'content'),
'payload' => self::arrayGet($json, 'data.attributes.payload', ''),
'position' => 0,
- 'commentable' => 0
+ 'commentable' => 0,
+ 'permission_type' => self::arrayGet($json, 'data.attributes.permission-type', 'all'),
+ 'visible' => self::arrayGet($json, 'data.attributes.visible', 'always'),
+ 'writable' => self::arrayGet($json, 'data.attributes.writable', 'never'),
]);
\Courseware\Container::create([
@@ -114,7 +117,7 @@ class UnitsCreate extends JsonApiController
]),
]);
- $unit = \Courseware\Unit::create([
+ $unit = Unit::create([
'range_id' => $range->getRangeId(),
'range_type' => $range->getRangeType(),
'structural_element_id' => $struct->id,
@@ -122,8 +125,9 @@ class UnitsCreate extends JsonApiController
'position' => Unit::getNewPosition($range->getRangeId()),
'creator_id' => $user->id,
'public' => self::arrayGet($json, 'data.attributes.public', '0'),
- 'release_date' => self::arrayGet($json, 'data.attributes.release-date'),
- 'withdraw_date' => self::arrayGet($json, 'data.attributes.withdraw-date'),
+ 'permission_type' => self::arrayGet($json, 'data.attributes.permission-type', 'all'),
+ 'visible' => self::arrayGet($json, 'data.attributes.visible', 'always'),
+ 'writable' => self::arrayGet($json, 'data.attributes.writable', 'never'),
]);
$instance = new \Courseware\Instance($struct);
diff --git a/lib/classes/JsonApi/Routes/Courseware/UnitsUpdate.php b/lib/classes/JsonApi/Routes/Courseware/UnitsUpdate.php
index 446d61e..4c48086 100644
--- a/lib/classes/JsonApi/Routes/Courseware/UnitsUpdate.php
+++ b/lib/classes/JsonApi/Routes/Courseware/UnitsUpdate.php
@@ -57,37 +57,92 @@ class UnitsUpdate extends JsonApiController
return 'Document must have an `id`.';
}
- if (self::arrayHas($json, 'data.attributes.release-date')) {
- $releaseDate = self::arrayGet($json, 'data.attributes.release-date');
- if (!self::isValidTimestamp($releaseDate)) {
- return '`release-date` is not an ISO 8601 timestamp.';
+ if (self::arrayHas($json, 'data.attributes.visible-start-date')) {
+ $visibleStartDate = self::arrayGet($json, 'data.attributes.visible-start-date');
+ if ($visibleStartDate && !self::isValidTimestamp($visibleStartDate)) {
+ return '`visible-start-date` is not an ISO 8601 timestamp.';
}
}
- if (self::arrayHas($json, 'data.attributes.withdraw-date')) {
- $withdrawDate = self::arrayGet($json, 'data.attributes.withdraw-date');
- if (!self::isValidTimestamp($withdrawDate)) {
- return '`withdraw-date` is not an ISO 8601 timestamp.';
+ if (self::arrayHas($json, 'data.attributes.visible-end-date')) {
+ $visibleEndDate = self::arrayGet($json, 'data.attributes.visible-end-date');
+ if ($visibleEndDate && !self::isValidTimestamp($visibleEndDate)) {
+ return '`visible-start-date` is not an ISO 8601 timestamp.';
+ }
+ }
+
+ if (self::arrayHas($json, 'data.attributes.writable-start-date')) {
+ $writableStartDate = self::arrayGet($json, 'data.attributes.writable-start-date');
+ if ($writableStartDate && !self::isValidTimestamp($writableStartDate)) {
+ return '`writable-start-date` is not an ISO 8601 timestamp.';
+ }
+ }
+
+ if (self::arrayHas($json, 'data.attributes.writable-end-date')) {
+ $writableEndDate = self::arrayGet($json, 'data.attributes.writable-end-date');
+ if ($writableEndDate && !self::isValidTimestamp($writableEndDate)) {
+ return '`writable-end-date` is not an ISO 8601 timestamp.';
}
}
}
private function updateUnit(\User $user, Unit $resource, array $json): Unit
{
- if (self::arrayHas($json, 'data.attributes.public')) {
- $resource->public = self::arrayGet($json, 'data.attributes.public');
- }
+ $attributes = [
+ 'position',
+ 'public',
+ 'permission-scope',
+ 'permission-type',
+ 'visible',
+ 'visible-approval',
+ 'writable',
+ 'writable-approval',
+ ];
- if (self::arrayHas($json, 'data.attributes.release-date')) {
- $releaseDate = self::arrayGet($json, 'data.attributes.release-date', '');
- $releaseDate = self::fromISO8601($releaseDate);
- $resource->release_date = $releaseDate->getTimestamp();
+ foreach ($attributes as $jsonKey) {
+ $sormKey = strtr($jsonKey, '-', '_');
+ $val = self::arrayGet($json, 'data.attributes.' . $jsonKey, '');
+ if ($val) {
+ $resource->$sormKey = $val;
+ }
}
-
- if (self::arrayHas($json, 'data.attributes.withdraw-date')) {
- $withdrawDate = self::arrayGet($json, 'data.attributes.withdraw-date', '');
- $withdrawDate = self::fromISO8601($withdrawDate);
- $resource->withdraw_date = $withdrawDate->getTimestamp();
+ if (self::arrayHas($json, 'data.attributes.visible-all')) {
+ $resource->visible_all = self::arrayGet($json, 'data.attributes.visible-all');
+ }
+ if (self::arrayHas($json, 'data.attributes.writable-all')) {
+ $resource->writable_all = self::arrayGet($json, 'data.attributes.writable-all');
+ }
+ if (self::arrayHas($json, 'data.attributes.visible-start-date')) {
+ $visibleStartDate = self::arrayGet($json, 'data.attributes.visible-start-date');
+ if ($visibleStartDate) {
+ $visibleStartDate = self::fromISO8601($visibleStartDate);
+ $visibleStartDate = $visibleStartDate->getTimestamp();
+ }
+ $resource->visible_start_date = $visibleStartDate;
+ }
+ if (self::arrayHas($json, 'data.attributes.visible-end-date')) {
+ $visibleEndDate = self::arrayGet($json, 'data.attributes.visible-end-date');
+ if ($visibleEndDate) {
+ $visibleEndDate = self::fromISO8601($visibleEndDate);
+ $visibleEndDate = $visibleEndDate->getTimestamp();
+ }
+ $resource->visible_end_date = $visibleEndDate;
+ }
+ if (self::arrayHas($json, 'data.attributes.writable-start-date')) {
+ $writableStartDate = self::arrayGet($json, 'data.attributes.writable-start-date');
+ if ($writableStartDate) {
+ $writableStartDate = self::fromISO8601($writableStartDate);
+ $writableStartDate = $writableStartDate->getTimestamp();
+ }
+ $resource->writable_start_date = $writableStartDate;
+ }
+ if (self::arrayHas($json, 'data.attributes.writable-end-date')) {
+ $writableEndDate = self::arrayGet($json, 'data.attributes.writable-end-date');
+ if ($writableEndDate) {
+ $writableEndDate = self::fromISO8601($writableEndDate);
+ $writableEndDate = $writableEndDate->getTimestamp();
+ }
+ $resource->writable_end_date = $writableEndDate;
}
$resource->store();
diff --git a/lib/classes/JsonApi/Routes/SemestersIndex.php b/lib/classes/JsonApi/Routes/SemestersIndex.php
index ffa1d4c..24883c1 100644
--- a/lib/classes/JsonApi/Routes/SemestersIndex.php
+++ b/lib/classes/JsonApi/Routes/SemestersIndex.php
@@ -4,6 +4,7 @@ namespace JsonApi\Routes;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
+use JsonApi\Errors\RecordNotFoundException;
use JsonApi\JsonApiController;
/**
@@ -13,10 +14,30 @@ class SemestersIndex extends JsonApiController
{
protected $allowedPagingParameters = ['offset', 'limit'];
+ protected $allowedFilteringParameters = ['current', 'timestamp'];
+
public function __invoke(Request $request, Response $response, $args)
{
list($offset, $limit) = $this->getOffsetAndLimit();
- $semesters = \Semester::getAll();
+
+ $filtering = $this->getQueryParameters()->getFilteringParameters();
+
+ if (empty($filtering)) {
+ $semesters = \Semester::getAll();
+ } else {
+ if (array_key_exists('current', $filtering)) {
+ $semester = \Semester::findCurrent();
+ }
+ if (isset($filtering['timestamp'])) {
+ $semester = \Semester::findByTimestamp($filtering['timestamp']);
+ }
+
+ if (!$semester) {
+ throw new RecordNotFoundException('Could not find semester.');
+ } else {
+ $semesters = [$semester];
+ }
+ }
return $this->getPaginatedContentResponse(
array_slice($semesters, $offset, $limit),
diff --git a/lib/classes/JsonApi/Schemas/Courseware/StructuralElement.php b/lib/classes/JsonApi/Schemas/Courseware/StructuralElement.php
index e6ccafa..f1a5841 100644
--- a/lib/classes/JsonApi/Schemas/Courseware/StructuralElement.php
+++ b/lib/classes/JsonApi/Schemas/Courseware/StructuralElement.php
@@ -47,10 +47,18 @@ class StructuralElement extends SchemaProvider
'purpose' => (string) $resource['purpose'],
'payload' => $resource['payload']->getIterator(),
'public' => (int) $resource['public'],
- 'release-date' => $resource['release_date'] ? date('Y-m-d', (int) $resource['release_date']) : null,
- 'withdraw-date' => $resource['withdraw_date'] ? date('Y-m-d', (int) $resource['withdraw_date']) : null,
- 'read-approval' => $resource['read_approval']->getIterator(),
- 'write-approval' => $resource['write_approval']->getIterator(),
+ 'permission-type' => (string) $resource['permission_type'],
+ 'visible' => (string) $resource['visible'],
+ 'visible-all' => (bool) $resource['visible_all'],
+ 'visible-start-date' => $resource['visible_start_date'] ? date('c', $resource['visible_start_date']) : null,
+ 'visible-end-date' => $resource['visible_end_date'] ? date('c', $resource['visible_end_date']) : null,
+ 'writable' => (string) $resource['writable'],
+ 'writable-all' => (bool) $resource['writable_all'],
+ 'writable-start-date' => $resource['writable_start_date'] ? date('c', $resource['writable_start_date']) : null,
+ 'writable-end-date' => $resource['writable_end_date'] ? date('c', $resource['writable_end_date']) : null,
+ 'visible-approval' => json_decode($resource['visible_approval']),
+ 'writable-approval' => json_decode($resource['writable_approval']),
+ 'content-approval' => $resource['content_approval']->getIterator(),
'copy-approval' => $resource['copy_approval']->getIterator(),
'can-edit' => $resource->canEdit($user),
'can-visit' => $resource->canVisit($user),
diff --git a/lib/classes/JsonApi/Schemas/Courseware/Unit.php b/lib/classes/JsonApi/Schemas/Courseware/Unit.php
index 6152e94..a311ac8 100644
--- a/lib/classes/JsonApi/Schemas/Courseware/Unit.php
+++ b/lib/classes/JsonApi/Schemas/Courseware/Unit.php
@@ -28,15 +28,30 @@ class Unit extends SchemaProvider
*/
public function getAttributes($resource, ContextInterface $context): iterable
{
+ $user = $this->currentUser;
+
return [
'content-type' => (string) $resource['content_type'],
'position' => (int) $resource['position'],
'public' => (int) $resource['public'],
- 'release-date' => $resource['release_date'] ? date('c', $resource['release_date']) : null,
- 'withdraw-date' => $resource['withdraw_date'] ? date('c', $resource['withdraw_date']) : null,
+ 'permission-scope' => (string) $resource['permission_scope'],
+ 'permission-type' => (string) $resource['permission_type'],
+ 'visible' => (string) $resource['visible'],
+ 'visible-all' => (bool) $resource['visible_all'],
+ 'visible-start-date' => $resource['visible_start_date'] ? date('c', $resource['visible_start_date']) : null,
+ 'visible-end-date' => $resource['visible_end_date'] ? date('c', $resource['visible_end_date']) : null,
+ 'writable' => (string) $resource['writable'],
+ 'writable-all' => (bool) $resource['writable_all'],
+ 'writable-start-date' => $resource['writable_start_date'] ? date('c', $resource['writable_start_date']) : null,
+ 'writable-end-date' => $resource['writable_end_date'] ? date('c', $resource['writable_end_date']) : null,
+ 'visible-approval' => json_decode($resource['visible_approval']),
+ 'writable-approval' => json_decode($resource['writable_approval']),
'config' => json_decode($resource['config']),
- 'mkdate' => date('c', $resource['mkdate']),
- 'chdate' => date('c', $resource['chdate']),
+ 'can-read' => $resource->canRead($user),
+ 'can-edit' => $resource->canEdit($user),
+ 'can-edit-content' => $resource->canEditContent($user),
+ 'mkdate' => date('c', $resource['mkdate']),
+ 'chdate' => date('c', $resource['chdate']),
];
}
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);
+ }
}