Skip to content

Commit

Permalink
Remove multiple videos from playlist at once, ref #970
Browse files Browse the repository at this point in the history
  • Loading branch information
Dennis Benz committed May 14, 2024
1 parent 9dd9dcd commit 3834d82
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 176 deletions.
5 changes: 2 additions & 3 deletions lib/RouteMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
59 changes: 0 additions & 59 deletions lib/Routes/Playlist/PlaylistAddVideo.php

This file was deleted.

68 changes: 68 additions & 0 deletions lib/Routes/Playlist/PlaylistAddVideos.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace Opencast\Routes\Playlist;

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Opencast\Errors\Error;
use Opencast\OpencastTrait;
use Opencast\OpencastController;
use Opencast\Models\REST\ApiPlaylistsClient;
use Opencast\Models\Playlists;
use Opencast\Models\Videos;

class PlaylistAddVideos extends OpencastController
{
use OpencastTrait;

public function __invoke(Request $request, Response $response, $args)
{
global $user, $perm;

$playlist = Playlists::findOneByToken($args['token']);

$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);

$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);
}
}
68 changes: 0 additions & 68 deletions lib/Routes/Playlist/PlaylistRemoveVideo.php

This file was deleted.

71 changes: 71 additions & 0 deletions lib/Routes/Playlist/PlaylistRemoveVideos.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

namespace Opencast\Routes\Playlist;

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Opencast\Errors\Error;
use Opencast\OpencastTrait;
use Opencast\OpencastController;
use Opencast\Models\REST\ApiPlaylistsClient;
use Opencast\Models\Playlists;
use Opencast\Models\Videos;

class PlaylistRemoveVideos extends OpencastController
{
use OpencastTrait;

public function __invoke(Request $request, Response $response, $args)
{
$playlist = Playlists::findOneByToken($args['token']);

// check what permissions the current user has on the playlist
$uperm = $playlist->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);
}
}
4 changes: 2 additions & 2 deletions vueapp/common/api.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
};

Expand Down
34 changes: 13 additions & 21 deletions vueapp/components/Videos/VideosTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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.')
});
});
},
Expand Down
31 changes: 8 additions & 23 deletions vueapp/store/playlists.module.js
Original file line number Diff line number Diff line change
Expand Up @@ -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});
});
},

/**
Expand All @@ -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) {
Expand Down

0 comments on commit 3834d82

Please sign in to comment.