diff options
| author | tgloeggl <tgloeggl@uos.de> | 2022-01-13 14:38:39 +0100 |
|---|---|---|
| committer | tgloeggl <tgloeggl@uos.de> | 2022-07-28 13:59:21 +0200 |
| commit | da3db0c846bd2c3498a487727ddb11b37324824f (patch) | |
| tree | 4b0b13adb6a1f55716372b75887e139d7f94df85 /lib | |
| parent | 7d087fcdf3218f8101e592b78f948479b3d02fe2 (diff) | |
working on creating plugin-api for im- and exportticket-334
fix bug
fix passing of custom file to block
fix custom-file creation on client side
working on crud custom file api for courseware blocks
create correct link for custom file
add read part of CRUD
add delete part of CRUD
change behaviour of add a new file, contents are passed via separate route
update custom-file content
add route to patch metadata of custom-file
changes to export for reference
fix jsonapi for custom-files
export custom-files
correctly import custom files
remove custom files from file-refs
revert changes to block
remove obsolte use statement in Block
revert changes to BlockType and Download-Block
remove obsolete implements from DownloadBlock
add doku, fix exporting of blocks without custom-files
remove debugging messages and now obsolete code
cleaning up
rework custom file check
fix error and remove call to mime-type for custom files
rename interface methods
do not assign variables in function calls
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/classes/JsonApi/RouteMap.php | 12 | ||||
| -rw-r--r-- | lib/classes/JsonApi/Routes/Courseware/CustomFilesCreate.php | 46 | ||||
| -rw-r--r-- | lib/classes/JsonApi/Routes/Courseware/CustomFilesDelete.php | 36 | ||||
| -rw-r--r-- | lib/classes/JsonApi/Routes/Courseware/CustomFilesList.php | 40 | ||||
| -rw-r--r-- | lib/classes/JsonApi/Routes/Courseware/CustomFilesShow.php | 38 | ||||
| -rw-r--r-- | lib/classes/JsonApi/Routes/Courseware/CustomFilesUpdate.php | 42 | ||||
| -rw-r--r-- | lib/classes/JsonApi/Routes/Courseware/CustomFilesUpdateAttributes.php | 47 | ||||
| -rw-r--r-- | lib/classes/JsonApi/SchemaMap.php | 1 | ||||
| -rwxr-xr-x | lib/classes/JsonApi/Schemas/Courseware/CustomFile.php | 61 | ||||
| -rw-r--r-- | lib/models/Courseware/CustomFiles.php | 69 | ||||
| -rw-r--r-- | lib/models/Courseware/Filesystem/CustomFile.php | 123 |
11 files changed, 515 insertions, 0 deletions
diff --git a/lib/classes/JsonApi/RouteMap.php b/lib/classes/JsonApi/RouteMap.php index baccc26..03dce11 100644 --- a/lib/classes/JsonApi/RouteMap.php +++ b/lib/classes/JsonApi/RouteMap.php @@ -339,6 +339,18 @@ class RouteMap // not a JSON route $group->post('/courseware-blocks/{id}/copy', Routes\Courseware\BlocksCopy::class); + // routes for custom files + + // get all referenced custom files + $group->get('/courseware-blocks/{id}/custom-files', Routes\Courseware\CustomFilesList::class); + + // CRUD routes for single custom files + $group->get('/courseware-blocks/{id}/custom-files/{file_id}', Routes\Courseware\CustomFilesShow::class); + $group->post('/courseware-blocks/{id}/custom-files', Routes\Courseware\CustomFilesCreate::class); + $group->patch('/courseware-blocks/{id}/custom-files/{file_id}', Routes\Courseware\CustomFilesUpdateAttributes::class); + $group->post('/courseware-blocks/{id}/custom-files/{file_id}', Routes\Courseware\CustomFilesUpdate::class); + $group->delete('/courseware-blocks/{id}/custom-files/{file_id}', Routes\Courseware\CustomFilesDelete::class); + $group->get('/courseware-containers/{id}', Routes\Courseware\ContainersShow::class); $group->post('/courseware-containers', Routes\Courseware\ContainersCreate::class); $group->patch('/courseware-containers/{id}', Routes\Courseware\ContainersUpdate::class); diff --git a/lib/classes/JsonApi/Routes/Courseware/CustomFilesCreate.php b/lib/classes/JsonApi/Routes/Courseware/CustomFilesCreate.php new file mode 100644 index 0000000..56615b3 --- /dev/null +++ b/lib/classes/JsonApi/Routes/Courseware/CustomFilesCreate.php @@ -0,0 +1,46 @@ +<?php + +namespace JsonApi\Routes\Courseware; + +use Courseware\Block; +use Courseware\Filesystem\CustomFile; +use JsonApi\Routes\Files\RoutesHelperTrait; +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; + +/** + * Create a block in a container. + */ +class CustomFilesCreate extends JsonApiController +{ + use RoutesHelperTrait; + + /** + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function __invoke(Request $request, Response $response, $args) + { + if (!($resource = Block::find($args['id']))) { + throw new RecordNotFoundException(); + } + + if (!Authority::canUpdateBlock($this->getUser($request), $resource)) { + throw new AuthorizationFailedException(); + } + + $body = $request->getParsedBody(); + + $custom_file = new CustomFile( + null, + $args['id'], + $body['data']['attributes'] + ); + + return $this->getContentResponse( + $resource->type->createCustomFile($custom_file) + ); + } +} diff --git a/lib/classes/JsonApi/Routes/Courseware/CustomFilesDelete.php b/lib/classes/JsonApi/Routes/Courseware/CustomFilesDelete.php new file mode 100644 index 0000000..f7e005d --- /dev/null +++ b/lib/classes/JsonApi/Routes/Courseware/CustomFilesDelete.php @@ -0,0 +1,36 @@ +<?php + +namespace JsonApi\Routes\Courseware; + +use Courseware\Block; +use JsonApi\Routes\Files\RoutesHelperTrait; +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; + +/** + * Create a block in a container. + */ +class CustomFilesDelete extends JsonApiController +{ + use RoutesHelperTrait; + + /** + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function __invoke(Request $request, Response $response, $args) + { + if (!($resource = Block::find($args['id']))) { + throw new RecordNotFoundException(); + } + + if (!Authority::canUpdateBlock($user = $this->getUser($request), $resource)) { + throw new AuthorizationFailedException(); + } + + $resource->type->deleteCustomFile($args['id']); + return $response; + } +} diff --git a/lib/classes/JsonApi/Routes/Courseware/CustomFilesList.php b/lib/classes/JsonApi/Routes/Courseware/CustomFilesList.php new file mode 100644 index 0000000..1d776c0 --- /dev/null +++ b/lib/classes/JsonApi/Routes/Courseware/CustomFilesList.php @@ -0,0 +1,40 @@ +<?php + +namespace JsonApi\Routes\Courseware; + +use Courseware\Block; +use Courseware\CustomFiles; +use JsonApi\Routes\Files\RoutesHelperTrait; +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; + +/** + * Create a block in a container. + */ +class CustomFilesList extends JsonApiController +{ + use RoutesHelperTrait; + + /** + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function __invoke(Request $request, Response $response, $args) + { + if (!($resource = Block::find($args['id']))) { + throw new RecordNotFoundException(); + } + + if (!Authority::canShowBlock($user = $this->getUser($request), $resource)) { + throw new AuthorizationFailedException(); + } + + if (!$resource->type instanceof CustomFiles) { + return $response; + } + + return $this->getContentResponse($resource->type->getCustomFiles()); + } +} diff --git a/lib/classes/JsonApi/Routes/Courseware/CustomFilesShow.php b/lib/classes/JsonApi/Routes/Courseware/CustomFilesShow.php new file mode 100644 index 0000000..0828bb7 --- /dev/null +++ b/lib/classes/JsonApi/Routes/Courseware/CustomFilesShow.php @@ -0,0 +1,38 @@ +<?php + +namespace JsonApi\Routes\Courseware; + +use Courseware\Block; +use GuzzleHttp\Psr7; +use JsonApi\Routes\Files\RoutesHelperTrait; +use JsonApi\Errors\AuthorizationFailedException; +use JsonApi\Errors\RecordNotFoundException; +use JsonApi\NonJsonApiController; +use Psr\Http\Message\ResponseInterface as Response; +use Psr\Http\Message\ServerRequestInterface as Request; + +/** + * Create a block in a container. + */ +class CustomFilesShow extends NonJsonApiController +{ + use RoutesHelperTrait; + + /** + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function __invoke(Request $request, Response $response, $args) + { + if (!($resource = Block::find($args['id']))) { + throw new RecordNotFoundException(); + } + + if (!Authority::canShowBlock($user = $this->getUser($request), $resource)) { + throw new AuthorizationFailedException(); + } + + return $response->withBody( + $stream = Psr7\stream_for($resource->type->readCustomFile($args['id'])) + ); + } +} diff --git a/lib/classes/JsonApi/Routes/Courseware/CustomFilesUpdate.php b/lib/classes/JsonApi/Routes/Courseware/CustomFilesUpdate.php new file mode 100644 index 0000000..72f3d4e --- /dev/null +++ b/lib/classes/JsonApi/Routes/Courseware/CustomFilesUpdate.php @@ -0,0 +1,42 @@ +<?php + +namespace JsonApi\Routes\Courseware; + +use Courseware\Block; +use JsonApi\Routes\Files\RoutesHelperTrait; +use JsonApi\Errors\AuthorizationFailedException; +use JsonApi\Errors\RecordNotFoundException; +use JsonApi\NonJsonApiController; +use Psr\Http\Message\ResponseInterface as Response; +use Psr\Http\Message\ServerRequestInterface as Request; + +/** + * Create a block in a container. + */ +class CustomFilesUpdate extends NonJsonApiController +{ + use RoutesHelperTrait; + + /** + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function __invoke(Request $request, Response $response, $args) + { + if (!($resource = Block::find($args['id']))) { + throw new RecordNotFoundException(); + } + + if (!Authority::canUpdateBlock($user = $this->getUser($request), $resource)) { + throw new AuthorizationFailedException(); + } + + $uploadedFile = $this->getUploadedFile($request); + + $resource->type->updateCustomFileContent( + $args['file_id'], + $content = file_get_contents($uploadedFile->getFilepath()) + ); + + return $response; + } +} diff --git a/lib/classes/JsonApi/Routes/Courseware/CustomFilesUpdateAttributes.php b/lib/classes/JsonApi/Routes/Courseware/CustomFilesUpdateAttributes.php new file mode 100644 index 0000000..cd1100b --- /dev/null +++ b/lib/classes/JsonApi/Routes/Courseware/CustomFilesUpdateAttributes.php @@ -0,0 +1,47 @@ +<?php + +namespace JsonApi\Routes\Courseware; + +use Courseware\Block; +use Courseware\Filesystem\CustomFile; +use JsonApi\Routes\Files\RoutesHelperTrait; +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; + +/** + * Create a block in a container. + */ +class CustomFilesUpdateAttributes extends JsonApiController +{ + use RoutesHelperTrait; + + /** + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function __invoke(Request $request, Response $response, $args) + { + if (!($resource = Block::find($args['id']))) { + throw new RecordNotFoundException(); + } + + if (!Authority::canUpdateBlock($user = $this->getUser($request), $resource)) { + throw new AuthorizationFailedException(); + } + + $body = $request->getParsedBody(); + + $custom_file = new CustomFile( + $body['data']['id'], + $args['id'], + $body['data']['attributes'] + ); + + return $this->getContentResponse( + $resource->type->updateCustomFileMetadata( + $args['file_id'], $custom_file) + ); + } +} diff --git a/lib/classes/JsonApi/SchemaMap.php b/lib/classes/JsonApi/SchemaMap.php index e7168cd..839962d 100644 --- a/lib/classes/JsonApi/SchemaMap.php +++ b/lib/classes/JsonApi/SchemaMap.php @@ -55,6 +55,7 @@ class SchemaMap \Courseware\BlockComment::class => Schemas\Courseware\BlockComment::class, \Courseware\BlockFeedback::class => Schemas\Courseware\BlockFeedback::class, \Courseware\Container::class => Schemas\Courseware\Container::class, + \Courseware\Filesystem\CustomFile::class => Schemas\Courseware\CustomFile::class, \Courseware\Instance::class => Schemas\Courseware\Instance::class, \Courseware\StructuralElement::class => Schemas\Courseware\StructuralElement::class, \Courseware\StructuralElementComment::class => Schemas\Courseware\StructuralElementComment::class, diff --git a/lib/classes/JsonApi/Schemas/Courseware/CustomFile.php b/lib/classes/JsonApi/Schemas/Courseware/CustomFile.php new file mode 100755 index 0000000..21105bc --- /dev/null +++ b/lib/classes/JsonApi/Schemas/Courseware/CustomFile.php @@ -0,0 +1,61 @@ +<?php + +namespace JsonApi\Schemas\Courseware; + +use JsonApi\Schemas\SchemaProvider; +use Neomerx\JsonApi\Contracts\Schema\ContextInterface; +use Neomerx\JsonApi\Schema\Link; +use Neomerx\JsonApi\Contracts\Schema\LinkInterface; + +class CustomFile extends SchemaProvider +{ + const TYPE = 'courseware-custom-file'; + //const REL_CUSTOM_FILE = 'courseware-custom-file'; + + /** + * {@inheritdoc} + */ + public function getId($resource): ?string + { + return $resource->getPayload()['id']; + } + + /** + * {@inheritdoc} + */ + public function getAttributes($resource, ContextInterface $context): iterable + { + return $resource->getPayload(); + } + + /** + * {@inheritdoc} + */ + public function getRelationships($resource, ContextInterface $context): iterable + { + + return []; + } + + public function getSelfLink($resource): LinkInterface + { + $link = new Link(true, '/courseware-blocks/' . $resource->getBlockId() + .'/custom-files', false); + return $link; + } + + /** + * @inheritdoc + */ + public function hasResourceMeta($resource): bool + { + return true; + } + + public function getResourceMeta($resource) + { + return [ + 'download-url' => $resource->getDownloadUrl() + ]; + } +} diff --git a/lib/models/Courseware/CustomFiles.php b/lib/models/Courseware/CustomFiles.php new file mode 100644 index 0000000..21a0ea6 --- /dev/null +++ b/lib/models/Courseware/CustomFiles.php @@ -0,0 +1,69 @@ +<?php + +namespace Courseware; + +use Courseware\Filesystem\CustomFile; + +/** + * This interface enables a courseware-block to have a user defined representation + * of files. This enables a block to have its own internal representation for + * arbitrary content as well allowing the import and export of said content in + * a defined and coherent way. + */ +interface CustomFiles +{ + /** + * Returns an array of CustomFile objects belongig to this block + * + * @return array<int, CustomFile> + */ + public function getCustomFiles() : array; + + /** + * create a new custom file, the contents have to be set by updateCustomFilesContent afterwards + * + * @param array $metadata any additional metadata needed, like id + * @param string $content the files contets + * + * @return CustomFile the newly created custom file + */ + public function createCustomFile(CustomFile $custom_file) : CustomFile; + + /** + * returns the contents for the custom file with the passed id + * + * @param string $id the id for the custom file + * + * @return string + */ + public function readCustomFile($id) : string; + + /** + * update the attributes of the custom file for the passed id + * + * @param string $id + * @param array $metadata + * + * @return CustomFile + */ + public function updateCustomFileMetadata($id, CustomFile $custom_file) : CustomFile; + + /** + * update the contents of the customf ile for the passed id + * + * @param string $id + * @param string $content + * + * @return CustomFile + */ + public function updateCustomFileContent($id, $content) : CustomFile; + + /** + * delete the custom file for the passed id + * + * @param string $id + * + * @return bool + */ + public function deleteCustomFile($id) : bool; +} diff --git a/lib/models/Courseware/Filesystem/CustomFile.php b/lib/models/Courseware/Filesystem/CustomFile.php new file mode 100644 index 0000000..7a6d4b8 --- /dev/null +++ b/lib/models/Courseware/Filesystem/CustomFile.php @@ -0,0 +1,123 @@ +<?php + +namespace Courseware\Filesystem; + +/** + * This class represents the metdata for a custom file in a courseware block + */ +class CustomFile +{ + /** + * The payload for this custom file, containt id, block_id and arbitrary attributes + * @var [type] + */ + protected + $payload; + + /** + * create a new custom file object, containing a self assigned id (make it unique!), + * the blocks id this custom file is referenced to and some attributes of + * your choice + * + * @param string $id an unique id for this custom file + * @param int $block_id the id of the related block + * @param array $attributes [description] + */ + public function __construct($id = null, $block_id, $attributes = []) + { + $this->payload = [ + 'id' => $id, + 'block_id' => $block_id, + 'attributes' => $attributes + ]; + } + + /** + * returns the payload: [ + * 'id' => ..., + * 'block_id' => ..., + * 'attributes' => [ ... ] + * ] + * + * @return array the payload + */ + public function getPayload() + { + return $this->payload; + } + + /** + * get id for this custom file + * + * @return string custom file id + */ + public function getId() + { + return $this->payload['id']; + } + + /** + * get id of related block + * + * @return int related block id + */ + public function getBlockId() + { + return $this->payload['block_id']; + } + + /** + * Overwrite the complete payload for this block. The payload MUST have the + * following structure: [ + * 'id' => ..., + * 'block_id' => ..., + * 'attributes' => [ ... ] + * ] + * + * @param array $payload the payload of appropriate structure + */ + public function setPayload($payload): void + { + if (!$payload['id']) { + throw new InvalidArgumentException(); + } + + if (!$payload['block_id']) { + throw new InvalidArgumentException(); + } + + $this->payload = $payload; + } + + /** + * Set the unique id for this custom file + * + * @param string $id + */ + public function setId($id): void + { + $this->payload['id'] = $id; + } + + /** + * Set the id for the related block + * + * @param int $block_id + */ + public function setBlockId($block_id): void + { + $this->payload['block_id'] = $block_id; + } + + /** + * Get the download url for this custom file + * + * @return string the download url + */ + public function getDownloadUrl() : string + { + return rtrim(\URLHelper::getUrl('jsonapi.php/v1'), '/') + . '/courseware-blocks/' . $this->payload['block_id'] + . '/custom-files/'. $this->payload['id']; + } +} |
