From 4f84a7655d51e6947fc6d2ada419f7acfd3e0ac0 Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Wed, 8 May 2019 12:05:45 +0200
Subject: [PATCH] OO-4052: allow to replace video with an URL

---
 .../org/olat/modules/video/VideoManager.java  |  4 +-
 .../org/olat/modules/video/VideoMeta.java     |  2 +
 .../video/manager/VideoManagerImpl.java       | 57 +++++++++------
 .../video/ui/VideoDisplayController.java      |  3 +-
 .../video/ui/VideoResourceEditController.java | 72 ++++++++++++++++---
 .../video/ui/VideoRuntimeController.java      | 11 +++
 .../video/ui/_i18n/LocalStrings_de.properties |  1 +
 .../video/ui/_i18n/LocalStrings_en.properties |  1 +
 .../repository/handlers/VideoHandler.java     |  4 +-
 9 files changed, 120 insertions(+), 35 deletions(-)

diff --git a/src/main/java/org/olat/modules/video/VideoManager.java b/src/main/java/org/olat/modules/video/VideoManager.java
index b6cddd98240..9a76681b7b6 100644
--- a/src/main/java/org/olat/modules/video/VideoManager.java
+++ b/src/main/java/org/olat/modules/video/VideoManager.java
@@ -419,7 +419,7 @@ public interface VideoManager {
 	 * @param videoResource
 	 * @param url
 	 */
-	public RepositoryEntry updateVideoMetadata(RepositoryEntry entry, String url);
+	public RepositoryEntry updateVideoMetadata(RepositoryEntry entry, String url, VideoFormat format);
 	
 	/**
 	 * Update the duration of the video, in repository entry as expenditure of work
@@ -431,6 +431,8 @@ public interface VideoManager {
 	 */
 	public RepositoryEntry updateVideoMetadata(RepositoryEntry entry, Long durationInSeconds);
 	
+	public VideoMeta updateVideoMetadata(VideoMeta meta);
+	
 	/**
 	 * Gets the all video repo entries.
 	 *
diff --git a/src/main/java/org/olat/modules/video/VideoMeta.java b/src/main/java/org/olat/modules/video/VideoMeta.java
index 975a581fe13..7c8167b896f 100644
--- a/src/main/java/org/olat/modules/video/VideoMeta.java
+++ b/src/main/java/org/olat/modules/video/VideoMeta.java
@@ -49,6 +49,8 @@ public interface VideoMeta extends CreateInfo {
 	 */
 	public String getUrl();
 	
+	public void setUrl(String url);
+	
 	/**
 	 * @return width of transcoded video in pixel
 	 */
diff --git a/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java b/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java
index 14a1e981ba3..bf30e8cc8f7 100644
--- a/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java
+++ b/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java
@@ -717,6 +717,11 @@ public class VideoManagerImpl implements VideoManager {
 		}
 	}
 	
+	@Override
+	public VideoMeta updateVideoMetadata(VideoMeta meta) {
+		return videoMetadataDao.updateVideoMetadata(meta);
+	}
+
 	@Override
 	public void updateVideoMetadata (OLATResource videoResource,VFSLeaf uploadVideo) {	
 		VideoMeta meta = getVideoMetadata(videoResource);
@@ -755,31 +760,43 @@ public class VideoManagerImpl implements VideoManager {
 	}
 
 	@Override
-	public RepositoryEntry updateVideoMetadata(RepositoryEntry entry, String url) {
+	public RepositoryEntry updateVideoMetadata(RepositoryEntry entry, String url, VideoFormat format) {
 		OLATResource videoResource = entry.getOlatResource();
-		VFSLeaf videoFile = downloadTmpVideo(videoResource, url);
-		if(videoFile.exists() && videoFile.getSize() > 0) {
-			VideoMeta meta = videoMetadataDao.getVideoMetadata(videoResource);
-			meta.setSize(videoFile.getSize());
-
-			Size dimensions = movieService.getSize(videoFile, "mp4");
-			if(dimensions != null) {
-				meta.setWidth(dimensions.getWidth());
-				meta.setHeight(dimensions.getHeight());
+		VideoMeta meta = videoMetadataDao.getVideoMetadata(videoResource);
+		meta.setUrl(url);
+		meta.setVideoFormat(format);
+		if(format == VideoFormat.mp4 || format == VideoFormat.panopto) {
+			VFSLeaf videoFile = downloadTmpVideo(videoResource, url);
+			if(videoFile.exists() && videoFile.getSize() > 0) {
+				meta.setSize(videoFile.getSize());
+	
+				Size dimensions = movieService.getSize(videoFile, "mp4");
+				if(dimensions != null) {
+					meta.setWidth(dimensions.getWidth());
+					meta.setHeight(dimensions.getHeight());
+				}
+				
+				long duration = movieService.getDuration(videoFile, "mp4");
+				if(duration > 0) {
+					String length = Formatter.formatTimecode(duration);
+					meta.setLength(length);
+					entry = repositoryManager.setExpenditureOfWork(entry, length);
+				}
+			} else {
+				meta.setSize(0l);
+				meta.setWidth(800);
+				meta.setHeight(600);
 			}
 			
-			long duration = movieService.getDuration(videoFile, "mp4");
-			if(duration > 0) {
-				String length = Formatter.formatTimecode(duration);
-				meta.setLength(length);
-				entry = repositoryManager.setExpenditureOfWork(entry, length);
+			if(videoFile.exists()) {
+				videoFile.deleteSilently();
 			}
-			videoMetadataDao.updateVideoMetadata(meta);
-		}
-
-		if(videoFile.exists()) {
-			videoFile.deleteSilently();
+		} else {
+			meta.setSize(0l);
+			meta.setWidth(800);
+			meta.setHeight(600);
 		}
+		videoMetadataDao.updateVideoMetadata(meta);
 		return entry;
 	}
 	
diff --git a/src/main/java/org/olat/modules/video/ui/VideoDisplayController.java b/src/main/java/org/olat/modules/video/ui/VideoDisplayController.java
index dc816bff6d6..c9cbc87911e 100644
--- a/src/main/java/org/olat/modules/video/ui/VideoDisplayController.java
+++ b/src/main/java/org/olat/modules/video/ui/VideoDisplayController.java
@@ -248,7 +248,8 @@ public class VideoDisplayController extends BasicController {
 	 * @param currentTime The start time in seconds (optional)
 	 */
 	protected void reloadVideo(UserRequest ureq) {
-		if(StringHelper.containsNonWhitespace(this.videoMetadata.getUrl())) {
+		videoMetadata = videoManager.getVideoMetadata(videoEntry.getOlatResource());
+		if(StringHelper.containsNonWhitespace(videoMetadata.getUrl())) {
 			loadVideo(ureq, videoMetadata.getUrl(), videoMetadata.getVideoFormat());
 		} else {
 			//load video as VFSLeaf
diff --git a/src/main/java/org/olat/modules/video/ui/VideoResourceEditController.java b/src/main/java/org/olat/modules/video/ui/VideoResourceEditController.java
index 1087b9ec0ad..aff673765e5 100644
--- a/src/main/java/org/olat/modules/video/ui/VideoResourceEditController.java
+++ b/src/main/java/org/olat/modules/video/ui/VideoResourceEditController.java
@@ -24,18 +24,22 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.services.image.Size;
 import org.olat.core.commons.services.video.MovieService;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.FileElement;
 import org.olat.core.gui.components.form.flexible.elements.StaticTextElement;
+import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
 import org.olat.core.gui.components.form.flexible.impl.FormEvent;
 import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
 import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.util.Formatter;
+import org.olat.core.util.StringHelper;
 import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.core.util.vfs.VFSManager;
@@ -46,13 +50,15 @@ import org.olat.modules.video.VideoModule;
 import org.olat.modules.video.VideoTranscoding;
 import org.olat.modules.video.manager.VideoManagerImpl;
 import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryManager;
 import org.olat.resource.OLATResource;
 import org.springframework.beans.factory.annotation.Autowired;
 /**
  * The Class VideoResourceEditController. 
- * @autor fkiefer fabian.kiefer@frentix.com
  * this class replaces an an existing video resource with another,
  * deletes existing transcodings and recreates them considering the new resolution
+ * 
+ * @autor fkiefer fabian.kiefer@frentix.com
  */
 public class VideoResourceEditController extends FormBasicController {
 
@@ -63,33 +69,39 @@ public class VideoResourceEditController extends FormBasicController {
 	}
 	private static final String VIDEO_RESOURCE = "video.mp4";
 	
+	private VideoMeta meta;
 	private VFSContainer vfsContainer;
 	private OLATResource videoResource;
 	private RepositoryEntry entry;
 	
+	@Autowired
+	private DB dbInstance;
 	@Autowired
 	private VideoManager videoManager;
 	@Autowired
 	private VideoModule videoModule;
 	@Autowired
 	private MovieService movieService;
+	@Autowired
+	private RepositoryManager repositoryManager;
 	
+	private TextElement urlEl;
 	private StaticTextElement typeEl;
 	private FileElement uploadFileEl;
-
 	
 	public VideoResourceEditController(UserRequest ureq, WindowControl wControl, RepositoryEntry entry){
 		super(ureq, wControl);
 		this.entry = entry;
 		this.videoResource = entry.getOlatResource();
 		vfsContainer = videoManager.getMasterContainer(videoResource);
+		meta = videoManager.getVideoMetadata(videoResource);
 
 		initForm(ureq);
 	}
 	
 	@Override
 	protected void doDispose() {
-
+		//
 	}
 
 	@Override
@@ -98,23 +110,42 @@ public class VideoResourceEditController extends FormBasicController {
 		setFormDescription("video.replace.desc");
 		setFormContextHelp("ok");
 		
-		uploadFileEl = uifactory.addFileElement(getWindowControl(), "upload", "video.replace.upload", formLayout);
-		uploadFileEl.addActionListener(FormEvent.ONCHANGE);
-		uploadFileEl.limitToMimeType(videoMimeTypes, "video.mime.type.error", null);
-		
+		if(StringHelper.containsNonWhitespace(meta.getUrl())) {
+			urlEl = uifactory.addTextElement("video.config.url", 512, meta.getUrl(), formLayout);
+		} else {
+			uploadFileEl = uifactory.addFileElement(getWindowControl(), "upload", "video.replace.upload", formLayout);
+			uploadFileEl.addActionListener(FormEvent.ONCHANGE);
+			uploadFileEl.limitToMimeType(videoMimeTypes, "video.mime.type.error", null);
+		}
 		typeEl = uifactory.addStaticTextElement("video.mime.type", "video.mime.type", "", formLayout);
-		typeEl.setVisible(false);		
+		typeEl.setVisible(false);
 	
 		FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
 		formLayout.add(buttonGroupLayout);
 		uifactory.addFormSubmitButton("submit", "tab.video.exchange", buttonGroupLayout);
 
 	}
+	
+	private void doReplaceURLAndUpdateMetadata() {
+		String url = urlEl.getValue();
+		VideoFormat format = VideoFormat.valueOfUrl(url);
+		if(format == null) {
+			return;// cannot understand the URL
+		}
+		if(format == VideoFormat.panopto) {
+			url = videoManager.toPodcastVideoUrl(url);
+		}
+
+		RepositoryEntry repoEntry = repositoryManager.lookupRepositoryEntry(videoResource, true);
+		videoManager.updateVideoMetadata(repoEntry, url, format);
+		dbInstance.commit();
+		meta = videoManager.getVideoMetadata(videoResource);
+	}
 
 	private int doReplaceFileAndUpdateMetadata() {
 		VFSLeaf video = (VFSLeaf) vfsContainer.resolve(VIDEO_RESOURCE);		
 		File uploadFile = uploadFileEl.getUploadFile();
-		VideoMeta meta = videoManager.getVideoMetadata(videoResource);
+		meta = videoManager.getVideoMetadata(videoResource);
 		if (uploadFileEl.getUploadSize() > 0 && uploadFile.exists()){
 			video.delete();
 			VFSLeaf uploadVideo = vfsContainer.createChildLeaf(VIDEO_RESOURCE);
@@ -160,9 +191,29 @@ public class VideoResourceEditController extends FormBasicController {
 		}
 	}
 	
+	@Override
+	protected boolean validateFormLogic(UserRequest ureq) {
+		boolean allOk = super.validateFormLogic(ureq);
+		
+		if(urlEl != null) {
+			urlEl.clearError();
+			if(!StringHelper.containsNonWhitespace(urlEl.getValue())) {
+				urlEl.setErrorKey("form.legende.mandatory", null);
+				allOk &= false;
+			} else if(VideoFormat.valueOfUrl(urlEl.getValue()) == null) {
+				urlEl.setErrorKey("error.format.not.supported", null);
+				allOk &= false;
+			}
+		}
+
+		return allOk;
+	}
+
 	@Override
 	protected void formOK(UserRequest ureq) {
-		if (uploadFileEl.getUploadFile() != null && uploadFileEl.isUploadSuccess()) {
+		if(urlEl != null) {
+			doReplaceURLAndUpdateMetadata();
+		} else if (uploadFileEl != null && uploadFileEl.getUploadFile() != null && uploadFileEl.isUploadSuccess()) {
 			queueDeleteTranscoding();
 			int height = doReplaceFileAndUpdateMetadata();
 			queueCreateTranscoding(height);
@@ -173,5 +224,6 @@ public class VideoResourceEditController extends FormBasicController {
 			typeEl.setVisible(false);
 			showWarning("video.not.replaced");
 		}
+		fireEvent(ureq, Event.CHANGED_EVENT);
 	}
 }
diff --git a/src/main/java/org/olat/modules/video/ui/VideoRuntimeController.java b/src/main/java/org/olat/modules/video/ui/VideoRuntimeController.java
index 4d39c849d5c..3a3c2b690f2 100644
--- a/src/main/java/org/olat/modules/video/ui/VideoRuntimeController.java
+++ b/src/main/java/org/olat/modules/video/ui/VideoRuntimeController.java
@@ -29,6 +29,7 @@ import org.olat.core.gui.components.link.Link;
 import org.olat.core.gui.components.link.LinkFactory;
 import org.olat.core.gui.components.stack.PopEvent;
 import org.olat.core.gui.components.stack.RootEvent;
+import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.dtabs.Activateable2;
@@ -107,6 +108,16 @@ public class VideoRuntimeController extends RepositoryEntryRuntimeController {
 		doRefreshVideoPosterIfEntryAdmin();		
 	}
 	
+	@Override
+	protected void event(UserRequest ureq, Controller source, Event event) {
+		if(source instanceof VideoResourceEditController) {
+			if(event == Event.CHANGED_EVENT) {
+				VideoDisplayController videoDisplayCtr = (VideoDisplayController)getRuntimeController();
+				videoDisplayCtr.reloadVideo(ureq);
+			}
+		}
+	}
+	
 	private void doReplaceVideo (UserRequest ureq) {
 		VideoResourceEditController resourceCtrl = new VideoResourceEditController(ureq, getWindowControl(), repositoryEntry);
 		listenTo(resourceCtrl);
diff --git a/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_de.properties
index 2207546872a..5d6ad04c2e2 100644
--- a/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_de.properties
@@ -17,6 +17,7 @@ chapter.error.notime=Bitte geben Sie eine Zeit ein\!
 chapter.error.notitle=Bitte geben Sie einen Titel ein\!
 chapter.error.out.of.range=Ihre Zeitangabe \u00FCberschreitet die L\u00E4nge des Videos\!
 delete.transcodings=Alle Transcodings dieser Aufl\u00F6sung wurden gel\u00F6scht.
+error.format.not.supported=Format ist nicht unterst\u00FCtzt.
 error.no.duration=Dauer must gr\u00F6sser als 0 sein.
 error.percent.value=Wert muss zwischen 0 und 100 sein.
 info.transcoding=Fehlende Transcodings werden erstellt.
diff --git a/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_en.properties
index 91379b6c48c..2880ae633b0 100644
--- a/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_en.properties
@@ -17,6 +17,7 @@ chapter.error.notime=Please put a valid time\!
 chapter.error.notitle=Please set a valid Chapter Title\!
 chapter.error.out.of.range=Your Chapter Timecode exceeds the length of the Video\!
 delete.transcodings=All Transcodings of this Resolution have been deleted.
+error.format.not.supported=Format is not supported.
 error.no.duration=Duration must be greater than 0.
 error.percent.value=Value nned to be between 0 and 100
 info.transcoding=Missing Transcodings will be created.
diff --git a/src/main/java/org/olat/repository/handlers/VideoHandler.java b/src/main/java/org/olat/repository/handlers/VideoHandler.java
index 932dd4fb53f..3decc1c7eaa 100644
--- a/src/main/java/org/olat/repository/handlers/VideoHandler.java
+++ b/src/main/java/org/olat/repository/handlers/VideoHandler.java
@@ -203,9 +203,7 @@ public class VideoHandler extends FileHandler {
 		videoManager.createVideoMetadata(repoEntry, url, format);
 		dbInstance.commit();
 		
-		if(format == VideoFormat.mp4 || format == VideoFormat.panopto) {
-			repoEntry = videoManager.updateVideoMetadata(repoEntry, url);
-		}
+		repoEntry = videoManager.updateVideoMetadata(repoEntry, url, format);
 		return repoEntry;
 	}
 
-- 
GitLab