diff --git a/lib/RouteMap.php b/lib/RouteMap.php index 04d7361f..a873d2f3 100644 --- a/lib/RouteMap.php +++ b/lib/RouteMap.php @@ -74,9 +74,8 @@ public function authenticatedRoutes(RouteCollectorProxy $group) $group->post("/playlists/{token}/copy", Routes\Playlist\PlaylistCopy::class); $group->get("/playlists/{token}/videos", Routes\Playlist\PlaylistVideoList::class); - - $group->put("/playlists/{token}/video/{vid_token}", Routes\Playlist\PlaylistAddVideo::class); - $group->delete("/playlists/{token}/video/{vid_token}", Routes\Playlist\PlaylistRemoveVideo::class); + $group->put("/playlists/{token}/videos", Routes\Playlist\PlaylistAddVideos::class); + $group->delete("/playlists/{token}/videos", Routes\Playlist\PlaylistRemoveVideos::class); $group->put("/playlists/{token}/user", Routes\Playlist\PlaylistAddUser::class); $group->delete("/playlists/{token}/user/{username}", Routes\Playlist\PlaylistRemoveUser::class); diff --git a/lib/Routes/Playlist/PlaylistAddVideo.php b/lib/Routes/Playlist/PlaylistAddVideo.php deleted file mode 100644 index 614b7f6f..00000000 --- a/lib/Routes/Playlist/PlaylistAddVideo.php +++ /dev/null @@ -1,59 +0,0 @@ -config_id); - $oc_playlist = $playlist_client->getPlaylist($playlist->service_playlist_id); - - $entries = $oc_playlist->entries; - - // Only add video if not contained in entries - $entry_exists = current(array_filter($entries, function($e) use ($video) { - return $e->contentId === $video->episode; - })); - - if (!$entry_exists) { - $entries[] = [ - 'contentId' => $video->episode, - 'type' => 'EVENT' - ]; - - $oc_playlist = $playlist_client->updateEntries($oc_playlist->id, $entries); - if (!$oc_playlist) { - throw new Error(_('Das Video konnte nicht hinzugefügt werden.'), 500); - } - } - - // Update playlist videos in DB - $playlist->setEntries($oc_playlist->entries); - - return $response->withStatus(204); - } -} \ No newline at end of file diff --git a/lib/Routes/Playlist/PlaylistAddVideos.php b/lib/Routes/Playlist/PlaylistAddVideos.php new file mode 100644 index 00000000..3abe9caf --- /dev/null +++ b/lib/Routes/Playlist/PlaylistAddVideos.php @@ -0,0 +1,68 @@ +getRequestData($request); + $videos = array_map(function ($token) { return Videos::findOneByToken($token); }, $video_tokens); + + // Get playlist entries from Opencast + $playlist_client = ApiPlaylistsClient::getInstance($playlist->config_id); + $oc_playlist = $playlist_client->getPlaylist($playlist->service_playlist_id); + + $entries = $oc_playlist->entries; + + foreach ($videos as $video) { + // check what permissions the current user has on the playlist and video + if (!Authority::canAddVideoToPlaylist($user, $playlist, $video)) { + throw new \AccessDeniedException(); + } + + $entries[] = [ + 'contentId' => $video->episode, + 'type' => 'EVENT' + ]; + + // Only add video if not contained in entries + $entry_exists = current(array_filter($entries, function($e) use ($video) { + return $e->contentId === $video->episode; + })); + + if (!$entry_exists) { + $entries[] = [ + 'contentId' => $video->episode, + 'type' => 'EVENT' + ]; + } + } + + // Update videos in playlist of Opencast + $oc_playlist = $playlist_client->updateEntries($oc_playlist->id, $entries); + if (!$oc_playlist) { + throw new Error(_('Die Videos konnten nicht hinzugefügt werden.'), 500); + } + + // Update playlist videos in DB + $playlist->setEntries($oc_playlist->entries); + + return $response->withStatus(204); + } +} \ No newline at end of file diff --git a/lib/Routes/Playlist/PlaylistRemoveVideo.php b/lib/Routes/Playlist/PlaylistRemoveVideo.php deleted file mode 100644 index de8992ac..00000000 --- a/lib/Routes/Playlist/PlaylistRemoveVideo.php +++ /dev/null @@ -1,68 +0,0 @@ -getUserPerm(); - - if ((empty($uperm) || - $uperm != 'owner' && $uperm != 'write')) - { - throw new \AccessDeniedException(); - } - - // Prevent removing video from playlist when it is livestream. - if ((bool) $video->is_livestream) { - return $this->createResponse([ - 'message' => [ - 'type' => 'error', - 'text' => _('Entfernung des Livestream-Videos aus der Wiedergabeliste ist nicht erlaubt.') - ], - ], $response->withStatus(403)); - } - - // Add video in playlist of Opencast - $playlist_client = ApiPlaylistsClient::getInstance($playlist->config_id); - $oc_playlist = $playlist_client->getPlaylist($playlist->service_playlist_id); - - $existing_entries = $oc_playlist->entries; - - // Remove all occurrences of video from entries - $entries = array_values(array_filter($existing_entries, function ($entry) use ($video) { - return $entry->contentId !== $video->episode; - })); - - if (count($entries) < count($existing_entries)) { - $oc_playlist = $playlist_client->updateEntries($oc_playlist->id, $entries); - if (!$oc_playlist) { - throw new Error(_('Das Video konnte nicht entfernt werden.'), 500); - } - } - - // Update playlist videos in DB - $playlist->setEntries($oc_playlist->entries); - - return $response->withStatus(204); - } -} diff --git a/lib/Routes/Playlist/PlaylistRemoveVideos.php b/lib/Routes/Playlist/PlaylistRemoveVideos.php new file mode 100644 index 00000000..1e3381e5 --- /dev/null +++ b/lib/Routes/Playlist/PlaylistRemoveVideos.php @@ -0,0 +1,71 @@ +getUserPerm(); + + if ((empty($uperm) || + $uperm != 'owner' && $uperm != 'write')) + { + throw new \AccessDeniedException(); + } + + $video_tokens = $this->getRequestData($request); + $videos = array_map(function ($token) { return Videos::findOneByToken($token); }, $video_tokens); + + // Get playlist entries from Opencast + $playlist_client = ApiPlaylistsClient::getInstance($playlist->config_id); + $oc_playlist = $playlist_client->getPlaylist($playlist->service_playlist_id); + + $old_entries = $oc_playlist->entries; + $entries = $oc_playlist->entries; + + foreach ($videos as $video) { + // Prevent removing video from playlist when it is livestream. + if ((bool) $video->is_livestream) { + return $this->createResponse([ + 'message' => [ + 'type' => 'error', + 'text' => _('Entfernung eines Livestream-Videos aus der Wiedergabeliste ist nicht erlaubt.') + ], + ], $response->withStatus(403)); + } + + // Remove all occurrences of video from entries + $entries = array_values(array_filter($entries, function ($entry) use ($video) { + return $entry->contentId !== $video->episode; + })); + } + + if (count($entries) < count($old_entries)) { + // Remove videos in playlist of Opencast + $oc_playlist = $playlist_client->updateEntries($oc_playlist->id, $entries); + if (!$oc_playlist) { + throw new Error(_('Die Videos konnten nicht entfernt werden.'), 500); + } + } + + // Update playlist videos in DB + $playlist->setEntries($oc_playlist->entries); + + return $response->withStatus(204); + } +} diff --git a/vueapp/common/api.service.js b/vueapp/common/api.service.js index 7990d3ef..942b304b 100644 --- a/vueapp/common/api.service.js +++ b/vueapp/common/api.service.js @@ -22,8 +22,8 @@ const ApiService = { return axios.put(`${resource}`, params); }, - delete(resource) { - return axios.delete(resource); + delete(resource, params) { + return axios.delete(resource, params); } }; diff --git a/vueapp/components/Videos/VideosTable.vue b/vueapp/components/Videos/VideosTable.vue index 790a86b1..b198fd02 100644 --- a/vueapp/components/Videos/VideosTable.vue +++ b/vueapp/components/Videos/VideosTable.vue @@ -512,38 +512,30 @@ export default { removeVideosFromPlaylist() { let view = this; + if (this.selectedVideos.find(video => video?.livestream)) { + view.$store.dispatch('addMessage', { + type: 'error', + text: view.$gettext('Livestream-Videos können nicht entfernt werden.') + }); + return; + } + this.$store.dispatch('removeVideosFromPlaylist', { playlist: this.playlist.token, videos: this.selectedVideos - }).then(({removedCount, forbiddenCount}) => { - let type = 'success'; - let text = view.$gettext('Die Videos wurden von der Wiedergabeliste entfernt.') - if (forbiddenCount > 0) { - type = 'warning'; - text = view.$gettext('%{removed_count} Video(s) wurde(n) von der Wiedergabeliste entfernt. %{forbbiden_count} Video(s) konnte(n) nicht.', { - removed_count: removedCount, - forbbiden_count: forbiddenCount - }); - } + }).then(() => { this.updateSelectedVideos([]); view.$store.dispatch('addMessage', { - type: type, - text: text + type: 'success', + text: view.$gettext('Die Videos wurden von der Wiedergabeliste entfernt.') }); this.loadVideos(); - }).catch(({forbiddenCount}) => { - let text = view.$gettext('Die Videos konnten von der Wiedergabeliste nicht entfernt werden.'); - if (forbiddenCount > 0) { - text += ' ' + view.$gettext('%{forbbiden_count} davon war(en) nicht erlaubt.',{ - forbbiden_count: forbiddenCount - }); - } - + }).catch(() => { view.$store.dispatch('addMessage', { type: 'error', - text: text + text: view.$gettext('Die Videos konnten von der Wiedergabeliste nicht entfernt werden.') }); }); }, diff --git a/vueapp/store/playlists.module.js b/vueapp/store/playlists.module.js index 6e13fcca..d83f5997 100644 --- a/vueapp/store/playlists.module.js +++ b/vueapp/store/playlists.module.js @@ -236,10 +236,10 @@ const actions = { * @param data.videos list of video tokens to add */ async addVideosToPlaylist(context, data) { - for (let i = 0; i < data.videos.length; i++) { - await ApiService.put('/playlists/' + data.playlist + '/video/' + data.videos[i]); - } - context.commit('addToVideosCount', {'token': data.playlist, 'addToCount': data.videos.length}); + return ApiService.put('/playlists/' + data.playlist + '/videos', data.videos) + .then(() => { + context.commit('addToVideosCount', {'token': data.playlist, 'addToCount': data.videos.length}); + }); }, /** @@ -251,25 +251,10 @@ const actions = { * @param data.videos list of video tokens to remove */ async removeVideosFromPlaylist(context, data) { - let removedCount = 0; - let forbiddenCount = 0; - for (let i = 0; i < data.videos.length; i++) { - try { - await ApiService.delete('/playlists/' + data.playlist + '/video/' + data.videos[i]); - removedCount++; - } catch (err) { - // We send back 403 for those livestream video, when removing from playlist. - if (err?.response?.status == 403) { - forbiddenCount++; - } - } - } - context.commit('addToVideosCount', {'token': data.playlist, 'addToCount': -removedCount}); - - if (removedCount > 0) { - return Promise.resolve({removedCount, forbiddenCount}); - } - return Promise.reject({removedCount, forbiddenCount}); + return ApiService.delete('/playlists/' + data.playlist + '/videos', {data: data.videos}) + .then(() => { + context.commit('addToVideosCount', {'token': data.playlist, 'addToCount': -data.videos.removedCount}); + }); }, addPlaylistUI({ commit }, show) {