Skip to content
Snippets Groups Projects
Commit 844fc84f authored by Ron Lucke's avatar Ron Lucke
Browse files

Sammelmappe für Courseware

Closes #2448 and #2675

Merge request studip/studip!1574
parent 9b9e88f7
No related branches found
No related tags found
No related merge requests found
Showing
with 743 additions and 26 deletions
...@@ -113,6 +113,7 @@ class JsupdaterController extends AuthenticatedController ...@@ -113,6 +113,7 @@ class JsupdaterController extends AuthenticatedController
{ {
$pageInfo = Request::getArray("page_info"); $pageInfo = Request::getArray("page_info");
$data = [ $data = [
'coursewareclipboard' => $this->getCoursewareClipboardUpdates($pageInfo),
'blubber' => $this->getBlubberUpdates($pageInfo), 'blubber' => $this->getBlubberUpdates($pageInfo),
'messages' => $this->getMessagesUpdates($pageInfo), 'messages' => $this->getMessagesUpdates($pageInfo),
'personalnotifications' => $this->getPersonalNotificationUpdates($pageInfo), 'personalnotifications' => $this->getPersonalNotificationUpdates($pageInfo),
...@@ -258,4 +259,9 @@ class JsupdaterController extends AuthenticatedController ...@@ -258,4 +259,9 @@ class JsupdaterController extends AuthenticatedController
return $data; return $data;
} }
private function getCoursewareClipboardUpdates($pageInfo)
{
return count(\Courseware\Clipboard::findUsersClipboards($GLOBALS["user"])) != $pageInfo['coursewareclipboard']['counter'];
}
} }
<?php
class CreateCwClipboardsTable extends Migration
{
public function description()
{
return 'create table for courseware clipboards';
}
public function up()
{
$db = DBManager::get();
$query = "CREATE TABLE IF NOT EXISTS `cw_clipboards` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`user_id` CHAR(32) COLLATE latin1_bin NOT NULL,
`name` VARCHAR(255) NOT NULL,
`description` MEDIUMTEXT NOT NULL,
`block_id` INT(11) NULL,
`container_id` INT(11) NULL,
`structural_element_id` INT(11) NULL,
`object_type` ENUM('courseware-structural-elements', 'courseware-containers', 'courseware-blocks') COLLATE latin1_bin NOT NULL,
`object_kind` VARCHAR(255) COLLATE latin1_bin NOT NULL,
`backup` MEDIUMTEXT NOT NULL,
`mkdate` INT(11) UNSIGNED NOT NULL,
`chdate` INT(11) UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
INDEX index_user_id (`user_id`)
)";
$db->exec($query);
}
public function down()
{
$db = \DBManager::get();
$db->exec('DROP TABLE IF EXISTS `cw_clipboards`');
}
}
...@@ -491,6 +491,16 @@ class RouteMap ...@@ -491,6 +491,16 @@ class RouteMap
$group->delete('/courseware-units/{id}', Routes\Courseware\UnitsDelete::class); $group->delete('/courseware-units/{id}', Routes\Courseware\UnitsDelete::class);
// not a JSON route // not a JSON route
$group->post('/courseware-units/{id}/copy', Routes\Courseware\UnitsCopy::class); $group->post('/courseware-units/{id}/copy', Routes\Courseware\UnitsCopy::class);
$group->get('/courseware-clipboards', Routes\Courseware\ClipboardsIndex::class);
$group->get('/users/{id}/courseware-clipboards', Routes\Courseware\UsersClipboardsIndex::class);
$group->delete('/users/{id}/courseware-clipboards/{type:courseware-blocks|courseware-containers}', Routes\Courseware\UsersClipboardsDelete::class);
$group->get('/courseware-clipboards/{id}', Routes\Courseware\ClipboardsShow::class);
$group->post('/courseware-clipboards', Routes\Courseware\ClipboardsCreate::class);
$group->patch('/courseware-clipboards/{id}', Routes\Courseware\ClipboardsUpdate::class);
$group->delete('/courseware-clipboards/{id}', Routes\Courseware\ClipboardsDelete::class);
$group->post('/courseware-clipboards/{id}/insert', Routes\Courseware\ClipboardsInsert::class);
} }
private function addAuthenticatedFilesRoutes(RouteCollectorProxy $group): void private function addAuthenticatedFilesRoutes(RouteCollectorProxy $group): void
......
...@@ -5,6 +5,7 @@ namespace JsonApi\Routes\Courseware; ...@@ -5,6 +5,7 @@ namespace JsonApi\Routes\Courseware;
use Courseware\Block; use Courseware\Block;
use Courseware\BlockComment; use Courseware\BlockComment;
use Courseware\BlockFeedback; use Courseware\BlockFeedback;
use Courseware\Clipboard;
use Courseware\Container; use Courseware\Container;
use Courseware\Instance; use Courseware\Instance;
use Courseware\StructuralElement; use Courseware\StructuralElement;
...@@ -512,4 +513,41 @@ class Authority ...@@ -512,4 +513,41 @@ class Authority
return $request_user->id === $user->id; return $request_user->id === $user->id;
} }
public static function canShowClipboard(User $user, Clipboard $resource): bool
{
return $resource->user_id === $user->id;
}
public static function canIndexClipboardsOfAUser(User $request_user, User $user): bool
{
return $request_user->id === $user->id;
}
public static function canIndexClipboards(User $user): bool
{
return $GLOBALS['perm']->have_perm('root', $user->id);
}
public static function canCreateClipboard(User $user): bool
{
return true;
}
public static function canUpdateClipboard(User $user, Clipboard $resource): bool
{
return $resource->user_id === $user->id;
}
public static function canDeleteClipboard(User $user, Clipboard $resource): bool
{
return self::canUpdateClipboard($user, $resource);
}
public static function canDeleteClipboardsOfAUser(User $request_user, User $user): bool
{
return self::canIndexClipboardsOfAUser($request_user, $user);
}
} }
...@@ -29,14 +29,21 @@ class BlocksCopy extends NonJsonApiController ...@@ -29,14 +29,21 @@ class BlocksCopy extends NonJsonApiController
$data = $request->getParsedBody()['data']; $data = $request->getParsedBody()['data'];
$block = \Courseware\Block::find($data['block']['id']); $block = \Courseware\Block::find($data['block']['id']);
if (!$block) {
throw new RecordNotFoundException();
}
$container = \Courseware\Container::find($data['parent_id']); $container = \Courseware\Container::find($data['parent_id']);
if (!$container) {
throw new RecordNotFoundException();
}
$sectionIndex = $data['section'];
$user = $this->getUser($request); $user = $this->getUser($request);
if (!Authority::canCreateBlocks($user, $container) || !Authority::canUpdateBlock($user, $block)) { if (!Authority::canCreateBlocks($user, $container) || !Authority::canUpdateBlock($user, $block)) {
throw new AuthorizationFailedException(); throw new AuthorizationFailedException();
} }
$new_block = $this->copyBlock($user, $block, $container); $new_block = $this->copyBlock($user, $block, $container, $sectionIndex);
$response = $response->withHeader('Content-Type', 'application/json'); $response = $response->withHeader('Content-Type', 'application/json');
$response->getBody()->write((string) json_encode($new_block)); $response->getBody()->write((string) json_encode($new_block));
...@@ -44,19 +51,8 @@ class BlocksCopy extends NonJsonApiController ...@@ -44,19 +51,8 @@ class BlocksCopy extends NonJsonApiController
return $response; return $response;
} }
private function copyBlock(\User $user, \Courseware\Block $remote_block, \Courseware\Container $container) private function copyBlock(\User $user, \Courseware\Block $remote_block, \Courseware\Container $container, $sectionIndex)
{
$block = $remote_block->copy($user, $container);
$this->updateContainer($container, $block);
return $block;
}
private function updateContainer(\Courseware\Container $container, \Courseware\Block $block)
{ {
//TODO update section block ids return $remote_block->copy($user, $container, $sectionIndex);
return true;
} }
} }
<?php
namespace JsonApi\Routes\Courseware;
use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\Errors\RecordNotFoundException;
use JsonApi\JsonApiController;
use JsonApi\Routes\ValidationTrait;
use JsonApi\Schemas\Courseware\Clipboard as ClipboardSchema;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
/**
* Create a clipboard.
*
* @author Ron Lucke <lucke@elan-ev.de>
* @license GPL2 or any later version
*
* @since Stud.IP 5.4
*/
class ClipboardsCreate extends JsonApiController
{
use ValidationTrait;
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function __invoke(Request $request, Response $response, $args)
{
$json = $this->validate($request);
$user = $this->getUser($request);
if (!Authority::canCreateClipboard($user)) {
throw new AuthorizationFailedException();
}
$object = $this->getObject($json);
if (!$object) {
throw new RecordNotFoundException();
}
$clipboard = $this->createClipboard($user, $json, $object);
return $this->getCreatedResponse($clipboard);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameters)
*/
protected function validateResourceDocument($json, $data)
{
if (!self::arrayHas($json, 'data')) {
return 'Missing `data` member at document´s top level.';
}
if (!self::arrayHas($json, 'data.attributes.name')) {
return 'Missing `name` value.';
}
if (!self::arrayHas($json, 'data.attributes.object-type')) {
return 'Missing `object-type` value.';
}
if (
!(
self::arrayHas($json, 'data.attributes.block-id')
|| self::arrayHas($json, 'data.attributes.container-id')
|| self::arrayHas($json, 'data.attributes.structural-element-id')
)
) {
return 'Missing `block-id`, `container-id` or `structural-element-id` value.';
}
if (!self::arrayHas($json, 'data.attributes.object-kind')) {
return 'Missing `object-kind` value.';
}
if (!$this->validateObjectType($json)) {
return 'Invalid `object-type` value.';
}
}
private function createClipboard(\User $user, array $json, $object)
{
$clipboard = \Courseware\Clipboard::create([
'user_id' => $user->id,
'name' => self::arrayGet($json, 'data.attributes.name'),
'block_id' => self::arrayGet($json, 'data.attributes.block-id'),
'container_id' => self::arrayGet($json, 'data.attributes.container-id'),
'structural_element_id' => self::arrayGet($json, 'data.attributes.structural-element-id'),
'object_type' => self::arrayGet($json, 'data.attributes.object-type'),
'object_kind' => self::arrayGet($json, 'data.attributes.object-kind'),
'backup' => $this->createBackup($object)
]);
return $clipboard;
}
private function createBackup($object): string
{
return $object->getClipboardBackup();
}
private function validateObjectType($json): bool
{
$type = self::arrayGet($json, 'data.attributes.object-type');
return in_array($type, ['courseware-structural-elements', 'courseware-containers', 'courseware-blocks']);
}
private function getObject($json): ?object
{
$object = null;
$type = self::arrayGet($json, 'data.attributes.object-type');
switch ($type) {
case 'courseware-structural-elements':
$object = \Courseware\StructuralElement::find(self::arrayGet($json, 'data.attributes.structural-element-id'));
break;
case 'courseware-containers':
$object = \Courseware\Container::find(self::arrayGet($json, 'data.attributes.container-id'));
break;
case 'courseware-blocks':
$object = \Courseware\Block::find(self::arrayGet($json, 'data.attributes.block-id'));
break;
}
return $object;
}
}
<?php
namespace JsonApi\Routes\Courseware;
use Courseware\Clipboard;
use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\Errors\RecordNotFoundException;
use JsonApi\JsonApiController;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
/**
* Delete one clipboard.
*
* @author Ron Lucke <lucke@elan-ev.de>
* @license GPL2 or any later version
*
* @since Stud.IP 5.4
*/
class ClipboardsDelete extends JsonApiController
{
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function __invoke(Request $request, Response $response, $args)
{
$resource = Clipboard::find($args['id']);
if (!$resource) {
throw new RecordNotFoundException();
}
$user = $this->getUser($request);
if (!Authority::canDeleteClipboard($user, $resource)) {
throw new AuthorizationFailedException();
}
$resource->delete();
return $this->getCodeResponse(204);
}
}
<?php
namespace JsonApi\Routes\Courseware;
use Courseware\Clipboard;
use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\JsonApiController;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
/**
* Displays all clipboards
*
* @author Ron Lucke <lucke@elan-ev.de>
* @license GPL2 or any later version
*
* @since Stud.IP 5.4
*/
class ClipboardsIndex extends JsonApiController
{
protected $allowedPagingParameters = ['offset', 'limit'];
protected $allowedIncludePaths = ['user'];
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function __invoke(Request $request, Response $response, $args)
{
$user = $this->getUser($request);
if (!Authority::canIndexClipboards($user)) {
throw new AuthorizationFailedException();
}
list($offset, $limit) = $this->getOffsetAndLimit();
$total = Clipboard::countBySQL('1');
$resources = Clipboard::findBySQL("1 ORDER BY mkdate LIMIT {$offset}, {$limit}");
return $this->getPaginatedContentResponse($resources, $total);
}
}
\ No newline at end of file
<?php
namespace JsonApi\Routes\Courseware;
use JsonApi\NonJsonApiController;
use Courseware\Block;
use Courseware\Clipboard;
use Courseware\Container;
use Courseware\StructuralElement;
use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\Errors\BadRequestException;
use JsonApi\Errors\RecordNotFoundException;
use JsonApi\Errors\UnprocessableEntityException;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
/**
*
*
* @author Ron Lucke <lucke@elan-ev.de>
* @license GPL2 or any later version
*
* @since Stud.IP 5.4
*/
class ClipboardsInsert extends NonJsonApiController
{
public function __invoke(Request $request, Response $response, array $args)
{
$data = $request->getParsedBody()['data'];
$clipboard = Clipboard::find($args['id']);
if (!$clipboard) {
throw new RecordNotFoundException();
}
$user = $this->getUser($request);
$backup = json_decode($clipboard->backup);
if ($clipboard->object_type === 'courseware-blocks') {
$sectionIndex = $data['section'];
$container = \Courseware\Container::find($data['parent_id']);
if (!$container) {
throw new RecordNotFoundException();
}
if (!Authority::canCreateBlocks($user, $container)) {
throw new AuthorizationFailedException();
}
$object = Block::createFromData($user, $backup, $container, $sectionIndex);
}
if ($clipboard->object_type === 'courseware-containers') {
$element = \Courseware\StructuralElement::find($data['parent_id']);
if (!$element) {
throw new RecordNotFoundException();
}
if (!Authority::canCreateContainer($user, $element)) {
throw new AuthorizationFailedException();
}
$object = Container::createFromData($user, $backup, $element);
}
$response = $response->withHeader('Content-Type', 'application/json');
$response->getBody()->write((string) json_encode($object));
return $response;
}
}
<?php
namespace JsonApi\Routes\Courseware;
use Courseware\Clipboard;
use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\Errors\RecordNotFoundException;
use JsonApi\Schemas\Courseware\Clipboard as ClipboardSchema;
use JsonApi\JsonApiController;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
/**
* Displays one clipboard.
*
* @author Ron Lucke <lucke@elan-ev.de>
* @license GPL2 or any later version
*
* @since Stud.IP 5.4
*/
class ClipboardsShow extends JsonApiController
{
protected $allowedIncludePaths = [
ClipboardSchema::REL_USER,
];
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @param array $args
* @return Response
*/
public function __invoke(Request $request, Response $response, $args)
{
/** @var ?\Courseware\Clipboard $resource */
$resource = Clipboard::find($args['id']);
if (!$resource) {
throw new RecordNotFoundException();
}
if (!Authority::canShowClipboard($this->getUser($request), $resource)) {
throw new AuthorizationFailedException();
}
return $this->getContentResponse($resource);
}
}
\ No newline at end of file
<?php
namespace JsonApi\Routes\Courseware;
use Courseware\Clipboard;
use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\Errors\RecordNotFoundException;
use JsonApi\JsonApiController;
use JsonApi\Routes\ValidationTrait;
use JsonApi\Schemas\Courseware\Unit as UnitSchema;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
/**
* Update one Clipboard.
*
* @author Ron Lucke <lucke@elan-ev.de>
* @license GPL2 or any later version
*
* @since Stud.IP 5.4
*/
class ClipboardsUpdate extends JsonApiController
{
use ValidationTrait;
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function __invoke(Request $request, Response $response, $args)
{
$resource = Clipboard::find($args['id']);
if (!$resource) {
throw new RecordNotFoundException();
}
$json = $this->validate($request, $resource);
$user = $this->getUser($request);
if (!Authority::canUpdateClipboard($user, $resource)) {
throw new AuthorizationFailedException();
}
$resource = $this->updateClipboard($user, $resource, $json);
return $this->getContentResponse($resource);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameters)
*/
protected function validateResourceDocument($json, $resource)
{
if (!self::arrayHas($json, 'data')) {
return 'Missing `data` member at document´s top level.';
}
}
private function updateClipboard(\User $user, Clipboard $resource, array $json): Clipboard
{
if (self::arrayHas($json, 'data.attributes.name')) {
$resource->name = self::arrayGet($json, 'data.attributes.name');
}
if (self::arrayHas($json, 'data.attributes.description')) {
$resource->description = self::arrayGet($json, 'data.attributes.description');
}
$resource->store();
return $resource;
}
}
...@@ -29,7 +29,13 @@ class ContainersCopy extends NonJsonApiController ...@@ -29,7 +29,13 @@ class ContainersCopy extends NonJsonApiController
$data = $request->getParsedBody()['data']; $data = $request->getParsedBody()['data'];
$container = \Courseware\Container::find($data['container']['id']); $container = \Courseware\Container::find($data['container']['id']);
if (!$container) {
throw new RecordNotFoundException();
}
$element = \Courseware\StructuralElement::find($data['parent_id']); $element = \Courseware\StructuralElement::find($data['parent_id']);
if (!$element) {
throw new RecordNotFoundException();
}
$user = $this->getUser($request); $user = $this->getUser($request);
if (!Authority::canCreateContainer($user, $element) || !Authority::canUpdateContainer($user, $container)) { if (!Authority::canCreateContainer($user, $element) || !Authority::canUpdateContainer($user, $container)) {
throw new AuthorizationFailedException(); throw new AuthorizationFailedException();
......
<?php
namespace JsonApi\Routes\Courseware;
use Courseware\Clipboard;
use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\Errors\RecordNotFoundException;
use JsonApi\JsonApiController;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
/**
* Displays all clipboards of one user.
*
* @author Ron Lucke <lucke@elan-ev.de>
* @license GPL2 or any later version
*
* @since Stud.IP 5.4
*/
class UsersClipboardsDelete extends JsonApiController
{
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function __invoke(Request $request, Response $response, $args)
{
$user = \User::find($args['id']);
if (!$user) {
throw new RecordNotFoundException();
}
$request_user = $this->getUser($request);
if (!Authority::canDeleteClipboardsOfAUser($request_user, $user)) {
throw new AuthorizationFailedException();
}
Clipboard::deleteUsersClipboards($user, $args['type']);
return $this->getCodeResponse(204);
}
}
<?php
namespace JsonApi\Routes\Courseware;
use Courseware\Clipboard;
use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\Errors\RecordNotFoundException;
use JsonApi\JsonApiController;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
/**
* Displays all clipboards of one user.
*
* @author Ron Lucke <lucke@elan-ev.de>
* @license GPL2 or any later version
*
* @since Stud.IP 5.4
*/
class UsersClipboardsIndex extends JsonApiController
{
use CoursewareInstancesHelper;
protected $allowedIncludePaths = [
'user',
];
protected $allowedPagingParameters = ['offset', 'limit'];
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function __invoke(Request $request, Response $response, $args)
{
$user = \User::find($args['id']);
if (!$user) {
throw new RecordNotFoundException();
}
$request_user = $this->getUser($request);
if (!Authority::canIndexClipboardsOfAUser($request_user, $user)) {
throw new AuthorizationFailedException();
}
$resources = Clipboard::findUsersClipboards($user);
$total = count($resources);
[$offset, $limit] = $this->getOffsetAndLimit();
return $this->getPaginatedContentResponse(array_slice($resources, $offset, $limit), $total);
}
}
...@@ -54,6 +54,7 @@ class SchemaMap ...@@ -54,6 +54,7 @@ class SchemaMap
\Courseware\Block::class => Schemas\Courseware\Block::class, \Courseware\Block::class => Schemas\Courseware\Block::class,
\Courseware\BlockComment::class => Schemas\Courseware\BlockComment::class, \Courseware\BlockComment::class => Schemas\Courseware\BlockComment::class,
\Courseware\BlockFeedback::class => Schemas\Courseware\BlockFeedback::class, \Courseware\BlockFeedback::class => Schemas\Courseware\BlockFeedback::class,
\Courseware\Clipboard::class => Schemas\Courseware\Clipboard::class,
\Courseware\Container::class => Schemas\Courseware\Container::class, \Courseware\Container::class => Schemas\Courseware\Container::class,
\Courseware\Instance::class => Schemas\Courseware\Instance::class, \Courseware\Instance::class => Schemas\Courseware\Instance::class,
\Courseware\StructuralElement::class => Schemas\Courseware\StructuralElement::class, \Courseware\StructuralElement::class => Schemas\Courseware\StructuralElement::class,
......
<?php
namespace JsonApi\Schemas\Courseware;
use JsonApi\Schemas\SchemaProvider;
use Neomerx\JsonApi\Contracts\Schema\ContextInterface;
use Neomerx\JsonApi\Schema\Link;
class Clipboard extends SchemaProvider
{
const TYPE = 'courseware-clipboards';
const REL_USER = 'user';
const REL_STRUCTURAL_ELEMENT = 'structural-element';
const REL_CONTAINER = 'container';
const REL_BLOCK = 'block';
/**
* {@inheritdoc}
*/
public function getId($resource): ?string
{
return $resource->id;
}
/**
* {@inheritdoc}
*/
public function getAttributes($resource, ContextInterface $context): iterable
{
return [
'name' => (string) $resource->name,
'description' => (string) $resource->description,
'block-id' => (int) $resource->block_id,
'container-id' => (int) $resource->container_id,
'structural-element-id' => (int) $resource->structural_element_id,
'object-type' => (string) $resource->object_type,
'object-kind' => (string) $resource->object_kind,
'backup' => $resource->backup,
'mkdate' => date('c', $resource->mkdate),
'chdate' => date('c', $resource->chdate),
];
}
/**
* {@inheritdoc}
*/
public function getRelationships($resource, ContextInterface $context): iterable
{
$relationships = [];
$relationships[self::REL_USER] = $resource->user
? [
self::RELATIONSHIP_LINKS => [
Link::RELATED => $this->createLinkToResource($resource->user),
],
self::RELATIONSHIP_DATA => $resource->user,
]
: [self::RELATIONSHIP_DATA => null];
$relationships[self::REL_BLOCK] = $resource->block
? [
self::RELATIONSHIP_LINKS => [
Link::RELATED => $this->createLinkToResource($resource->block),
],
self::RELATIONSHIP_DATA => $resource->block,
]
: [self::RELATIONSHIP_DATA => null];
$relationships[self::REL_CONTAINER] = $resource->container
? [
self::RELATIONSHIP_LINKS => [
Link::RELATED => $this->createLinkToResource($resource->container),
],
self::RELATIONSHIP_DATA => $resource->container,
]
: [self::RELATIONSHIP_DATA => null];
$relationships[self::REL_STRUCTURAL_ELEMENT] = $resource->structural_element
? [
self::RELATIONSHIP_LINKS => [
Link::RELATED => $this->createLinkToResource($resource->structural_element),
],
self::RELATIONSHIP_DATA => $resource->structural_element,
]
: [self::RELATIONSHIP_DATA => null];
return $relationships;
}
}
\ No newline at end of file
...@@ -162,6 +162,25 @@ class Block extends \SimpleORMap implements \PrivacyObject ...@@ -162,6 +162,25 @@ class Block extends \SimpleORMap implements \PrivacyObject
return $user->getFullName(); return $user->getFullName();
} }
public function getClipboardBackup(): string
{
$block = [
'type' => 'courseware-blocks',
'id' => $this->id,
'attributes' => [
'position'=> $this->position,
'block-type'=> $this->type->getType(),
'title'=> $this->type->getTitle(),
'visible'=> $this->visible,
'payload'=> $this->type->getPayload(),
'mkdate'=> $this->mkdate,
'chdate'=> $this->chdate
]
];
return json_encode($block, true);
}
/** /**
* Copies this block into another container such that the given user is the owner of the copy. * Copies this block into another container such that the given user is the owner of the copy.
* *
...@@ -170,13 +189,13 @@ class Block extends \SimpleORMap implements \PrivacyObject ...@@ -170,13 +189,13 @@ class Block extends \SimpleORMap implements \PrivacyObject
* *
* @return Block the copy of this block * @return Block the copy of this block
*/ */
public function copy(User $user, Container $container): Block public function copy(User $user, Container $container, $sectionIndex = null): Block
{ {
/** @var StructuralElement $struct */ /** @var StructuralElement $struct */
$struct = StructuralElement::find($container->structural_element_id); $struct = $container->structural_element;
$rangeId = $struct->getRangeId(); $rangeId = $struct->getRangeId();
$block = self::build([ $block = self::create([
'container_id' => $container->id, 'container_id' => $container->id,
'owner_id' => $user->id, 'owner_id' => $user->id,
'editor_id' => $user->id, 'editor_id' => $user->id,
...@@ -187,10 +206,34 @@ class Block extends \SimpleORMap implements \PrivacyObject ...@@ -187,10 +206,34 @@ class Block extends \SimpleORMap implements \PrivacyObject
'visible' => 1, 'visible' => 1,
]); ]);
//update Container payload
$container->type->addBlock($block, $sectionIndex);
$container->store();
return $block;
}
public static function createFromData(User $user, $data, Container $container, $sectionIndex = null): Block
{
$struct = $container->structural_element;
$rangeId = $struct->getRangeId();
$block = self::create([
'container_id' => $container->id,
'owner_id' => $user->id,
'editor_id' => $user->id,
'edit_blocker_id' => null,
'position' => $container->countBlocks(),
'block_type' => $data->attributes->{'block-type'},
'visible' => 1,
]);
$dataPayload = (array)$data->attributes->payload;
$block->payload = json_encode($block->type->copyPayload('', $dataPayload), true);
$block->store(); $block->store();
//update Container payload //update Container payload
$container->type->addBlock($block); $container->type->addBlock($block, $sectionIndex);
$container->store(); $container->store();
return $block; return $block;
......
...@@ -74,11 +74,13 @@ class Audio extends BlockType ...@@ -74,11 +74,13 @@ class Audio extends BlockType
} }
} }
public function copyPayload(string $rangeId = ''): array public function copyPayload(string $rangeId = '', $payload = null): array
{ {
if (!$payload) {
$payload = $this->getPayload(); $payload = $this->getPayload();
}
if ('' != $payload['file_id']) { if (!empty($payload['file_id'])) {
$payload['file_id'] = $this->copyFileById($payload['file_id'], $rangeId); $payload['file_id'] = $this->copyFileById($payload['file_id'], $rangeId);
} }
......
...@@ -75,11 +75,13 @@ class BeforeAfter extends BlockType ...@@ -75,11 +75,13 @@ class BeforeAfter extends BlockType
return $files; return $files;
} }
public function copyPayload(string $rangeId = ''): array public function copyPayload(string $rangeId = '', $payload = null): array
{ {
if (!$payload) {
$payload = $this->getPayload(); $payload = $this->getPayload();
}
if ('' != $payload['before_file_id']) { if (!empty($payload['before_file_id'])) {
$payload['before_file_id'] = $this->copyFileById($payload['before_file_id'], $rangeId); $payload['before_file_id'] = $this->copyFileById($payload['before_file_id'], $rangeId);
} }
......
...@@ -232,9 +232,9 @@ abstract class BlockType ...@@ -232,9 +232,9 @@ abstract class BlockType
} }
// TODO: (tgloeggl) DocBlock ergänzen // TODO: (tgloeggl) DocBlock ergänzen
public function copyPayload(string $rangeId = ''): array public function copyPayload(string $rangeId = '', $payload = null): array
{ {
return $this->getPayload(); return $payload ?: $this->getPayload();
} }
/** /**
...@@ -339,6 +339,10 @@ abstract class BlockType ...@@ -339,6 +339,10 @@ abstract class BlockType
return $file_map[$fileId]; return $file_map[$fileId];
} }
if ($rangeId === '') {
$rangeId = $this->block->container->structural_element->range_id;
}
$user = \User::findCurrent(); $user = \User::findCurrent();
if ($file_ref = \FileRef::find($fileId)) { if ($file_ref = \FileRef::find($fileId)) {
$copiedFile = \FileManager::copyFile( $copiedFile = \FileManager::copyFile(
...@@ -375,6 +379,10 @@ abstract class BlockType ...@@ -375,6 +379,10 @@ abstract class BlockType
return $folder_map[$folderId]; return $folder_map[$folderId];
} }
if ($rangeId === '') {
$rangeId = $this->block->container->structural_element->range_id;
}
$user = \User::findCurrent(); $user = \User::findCurrent();
$destinationFolder = $this->getDestinationFolder($user, $rangeId); $destinationFolder = $this->getDestinationFolder($user, $rangeId);
if ($sourceFolder = \Folder::find($folderId)) { if ($sourceFolder = \Folder::find($folderId)) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment