diff --git a/Brightcove.Core/Brightcove.Core.csproj b/Brightcove.Core/Brightcove.Core.csproj index 3fe9b48b..f64df6d3 100644 --- a/Brightcove.Core/Brightcove.Core.csproj +++ b/Brightcove.Core/Brightcove.Core.csproj @@ -57,6 +57,7 @@ + diff --git a/Brightcove.Core/EmbedGenerator/BrightcoveEmbedGenerator.cs b/Brightcove.Core/EmbedGenerator/BrightcoveEmbedGenerator.cs index 5c3aa91a..e032f435 100644 --- a/Brightcove.Core/EmbedGenerator/BrightcoveEmbedGenerator.cs +++ b/Brightcove.Core/EmbedGenerator/BrightcoveEmbedGenerator.cs @@ -7,7 +7,7 @@ public class BrightcoveEmbedGenerator { protected string iframeBaseUrl = "https://players.brightcove.net/{0}/{1}_default/index.html?{3}={2}"; protected string iframeTemplate = "
"; - protected string iframeResponsiveTemplate = "
"; + protected string iframeResponsiveTemplate = "

"; protected string jsTemplate = "
{6}
"; protected string jsResponsiveTemplate = "
{6}
"; @@ -91,7 +91,7 @@ protected virtual EmbedMarkup GenerateJavaScript(EmbedModel model) EmbedMarkup result = new EmbedMarkup(); string videoId = ""; string playlistId = ""; - string playlistMarkup = ""; + string innerHtml = ""; string autoplay = ""; string muted = ""; string language = ""; @@ -103,7 +103,7 @@ protected virtual EmbedMarkup GenerateJavaScript(EmbedModel model) break; case MediaType.Playlist: playlistId = model.MediaId; - playlistMarkup = "
"; + innerHtml = "
"; break; default: throw new Exception("Invalid media type for javascript embed"); @@ -126,20 +126,21 @@ protected virtual EmbedMarkup GenerateJavaScript(EmbedModel model) language = $"lang='{model.Language}'"; } + innerHtml += string.Format(jsScriptTemplate, model.AccountId, model.PlayerId); + switch (model.MediaSizing) { case MediaSizing.Responsive: string aspectRatio = ((double)model.Height / model.Width * 100.0).ToString("F2"); - result.Markup = string.Format(jsResponsiveTemplate, model.AccountId, model.PlayerId, videoId, playlistId, model.Width, aspectRatio, playlistMarkup, autoplay, muted, language); + result.Markup = string.Format(jsResponsiveTemplate, model.AccountId, model.PlayerId, videoId, playlistId, model.Width, aspectRatio, innerHtml, autoplay, muted, language); break; case MediaSizing.Fixed: - result.Markup = string.Format(jsTemplate, model.AccountId, model.PlayerId, videoId, playlistId, model.Width, model.Height, playlistMarkup, autoplay, muted, language); + result.Markup = string.Format(jsTemplate, model.AccountId, model.PlayerId, videoId, playlistId, model.Width, model.Height, innerHtml, autoplay, muted, language); break; default: throw new Exception("Invalid media sizing for javascript embed"); } - result.ScriptTag = string.Format(jsScriptTemplate, model.AccountId, model.PlayerId); result.Model = model; return result; diff --git a/Brightcove.Core/EmbedGenerator/Models/EmbedMarkup.cs b/Brightcove.Core/EmbedGenerator/Models/EmbedMarkup.cs index b3864a81..207fa50b 100644 --- a/Brightcove.Core/EmbedGenerator/Models/EmbedMarkup.cs +++ b/Brightcove.Core/EmbedGenerator/Models/EmbedMarkup.cs @@ -11,7 +11,5 @@ public class EmbedMarkup public EmbedModel Model { get; set; } = new EmbedModel(); public string Markup { get; set; } = ""; - - public string ScriptTag { get; set; } = ""; } } diff --git a/Brightcove.Core/Models/Video.cs b/Brightcove.Core/Models/Video.cs index 48c2450b..d1cad2f3 100644 --- a/Brightcove.Core/Models/Video.cs +++ b/Brightcove.Core/Models/Video.cs @@ -59,6 +59,9 @@ public class Video : Asset [JsonIgnore] public bool IngestSuccessful { get; set; } + [JsonProperty("schedule", NullValueHandling = NullValueHandling.Ignore)] + public VideoSchedule Schedule { get; set; } + public Video ShallowCopy() { return (Video)this.MemberwiseClone(); diff --git a/Brightcove.Core/Models/VideoSchedule.cs b/Brightcove.Core/Models/VideoSchedule.cs new file mode 100644 index 00000000..3f6549d0 --- /dev/null +++ b/Brightcove.Core/Models/VideoSchedule.cs @@ -0,0 +1,14 @@ +using Newtonsoft.Json; +using System; + +namespace Brightcove.Core.Models +{ + public class VideoSchedule + { + [JsonProperty("starts_at", NullValueHandling = NullValueHandling.Ignore)] + public DateTime? StartsAt { get; set; } + + [JsonProperty("ends_at", NullValueHandling = NullValueHandling.Ignore)] + public DateTime? EndsAt { get; set; } + } +} diff --git a/Brightcove.Core/Services/BrightcoveService.cs b/Brightcove.Core/Services/BrightcoveService.cs index ae40cc67..14b7f4f0 100644 --- a/Brightcove.Core/Services/BrightcoveService.cs +++ b/Brightcove.Core/Services/BrightcoveService.cs @@ -307,7 +307,9 @@ public Video UpdateVideo(Video video) newVideo.Id = null; newVideo.Images = null; - request.Content = new StringContent(JsonConvert.SerializeObject(newVideo), Encoding.UTF8, "application/json"); + string content = JsonConvert.SerializeObject(newVideo); + + request.Content = new StringContent(content, Encoding.UTF8, "application/json"); HttpResponseMessage response = SendRequest(request); diff --git a/Brightcove.DataExchangeFramework/Brightcove.DataExchangeFramework.csproj b/Brightcove.DataExchangeFramework/Brightcove.DataExchangeFramework.csproj index 28d8d7fa..ba1d3ea3 100644 --- a/Brightcove.DataExchangeFramework/Brightcove.DataExchangeFramework.csproj +++ b/Brightcove.DataExchangeFramework/Brightcove.DataExchangeFramework.csproj @@ -426,6 +426,7 @@ + @@ -465,6 +466,8 @@ + + diff --git a/Brightcove.DataExchangeFramework/Converters/ValueAccessor/DateTimePropertyValueAccessorConverter.cs b/Brightcove.DataExchangeFramework/Converters/ValueAccessor/DateTimePropertyValueAccessorConverter.cs new file mode 100644 index 00000000..6a6c26a5 --- /dev/null +++ b/Brightcove.DataExchangeFramework/Converters/ValueAccessor/DateTimePropertyValueAccessorConverter.cs @@ -0,0 +1,49 @@ +using Brightcove.DataExchangeFramework.ValueReaders; +using Brightcove.DataExchangeFramework.ValueWriters; +using Sitecore.DataExchange; +using Sitecore.DataExchange.Attributes; +using Sitecore.DataExchange.Converters.DataAccess.ValueAccessors; +using Sitecore.DataExchange.DataAccess; +using Sitecore.DataExchange.DataAccess.Readers; +using Sitecore.DataExchange.DataAccess.Writers; +using Sitecore.DataExchange.Repositories; +using Sitecore.Services.Core.Model; + +namespace Brightcove.DataExchangeFramework +{ + [SupportedIds(new string[] { "{CC5AC65C-ACAF-4D89-8811-43B2D8E8134A}" })] + public class DateTimePropertyValueAccessorConverter : ValueAccessorConverter + { + public const string FieldNamePropertyName = "PropertyName"; + + public DateTimePropertyValueAccessorConverter(IItemModelRepository repository) + : base(repository) + { + } + + protected override ConvertResult ConvertSupportedItem( + ItemModel source) + { + ConvertResult convertResult = base.ConvertSupportedItem(source); + if (!convertResult.WasConverted) + return convertResult; + string stringValue = this.GetStringValue(source, "PropertyName"); + if (string.IsNullOrWhiteSpace(stringValue)) + return this.NegativeResult(source, "The property name field must have a value specified.", "field: PropertyName"); + IValueAccessor convertedValue = convertResult.ConvertedValue; + if (convertedValue == null) + return this.NegativeResult(source, "A null value accessor was returned by the converter."); + if (convertedValue.ValueReader == null) + { + DateTimePropertyValueReader propertyValueReader = new DateTimePropertyValueReader(stringValue); + convertedValue.ValueReader = (IValueReader)propertyValueReader; + } + if (convertedValue.ValueWriter == null) + { + DateTimePropertyValueWriter propertyValueWriter = new DateTimePropertyValueWriter(stringValue); + convertedValue.ValueWriter = (IValueWriter)propertyValueWriter; + } + return this.PositiveResult(convertedValue); + } + } +} \ No newline at end of file diff --git a/Brightcove.DataExchangeFramework/ValueReaders/DateTimePropertyValueReader.cs b/Brightcove.DataExchangeFramework/ValueReaders/DateTimePropertyValueReader.cs new file mode 100644 index 00000000..6050e05f --- /dev/null +++ b/Brightcove.DataExchangeFramework/ValueReaders/DateTimePropertyValueReader.cs @@ -0,0 +1,44 @@ +using Sitecore.DataExchange.DataAccess; +using Sitecore.DataExchange.DataAccess.Readers; +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Linq; +using System.Web; + +namespace Brightcove.DataExchangeFramework.ValueReaders +{ + public class DateTimePropertyValueReader : ChainedPropertyValueReader + { + public DateTimePropertyValueReader(string propertyName) : base(propertyName) + { + } + + public override ReadResult Read(object source, DataAccessContext context) + { + if (context == null) + throw new ArgumentNullException(nameof(context)); + + var result = base.Read(source, context); + + bool wasValueRead = result.WasValueRead; + object obj = result.ReadValue; + + if(obj == null || !(obj is DateTime)) + { + obj = ""; + wasValueRead = true; + } + else + { + obj = ((DateTime)obj).ToString("yyyyMMddTHHmmss\\Z"); + } + + return new ReadResult(DateTime.UtcNow) + { + WasValueRead = wasValueRead, + ReadValue = obj + }; + } + } +} diff --git a/Brightcove.DataExchangeFramework/ValueWriters/DateTimePropertyValueWriter.cs b/Brightcove.DataExchangeFramework/ValueWriters/DateTimePropertyValueWriter.cs new file mode 100644 index 00000000..34e51f09 --- /dev/null +++ b/Brightcove.DataExchangeFramework/ValueWriters/DateTimePropertyValueWriter.cs @@ -0,0 +1,39 @@ +using Sitecore.DataExchange.DataAccess; +using System; +using System.Globalization; + +namespace Brightcove.DataExchangeFramework.ValueWriters +{ + public class DateTimePropertyValueWriter : ChainedPropertyValueWriter + { + public DateTimePropertyValueWriter(string propertyName) : base(propertyName) + { + + } + + public override bool Write(object target, object value, DataAccessContext context) + { + DateTime? returnValue = null; + + try + { + if ((value is string) && !string.IsNullOrWhiteSpace((string)value)) + { + string sourceValue = (string)value; + DateTime tmp; + + if (DateTime.TryParseExact(sourceValue, new string[2] { "yyyyMMddTHHmmss", "yyyyMMddTHHmmss\\Z" }, (IFormatProvider)CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out tmp)) + { + returnValue = tmp; + } + } + } + catch + { + returnValue = null; + } + + return base.Write(target, returnValue, context); + } + } +} \ No newline at end of file diff --git a/Brightcove.Web/EmbedGenerator/SitecoreEmbedGenerator.cs b/Brightcove.Web/EmbedGenerator/SitecoreEmbedGenerator.cs index 6f6d6ded..583d30db 100644 --- a/Brightcove.Web/EmbedGenerator/SitecoreEmbedGenerator.cs +++ b/Brightcove.Web/EmbedGenerator/SitecoreEmbedGenerator.cs @@ -13,6 +13,10 @@ public class SitecoreEmbedGenerator : BrightcoveEmbedGenerator { public SitecoreEmbedGenerator() : base() { + //1) We wrap the iframe in a paragraph tag so that the RTE handles it better + //2) We don't support using a resposive iframe in the RTE + iframeTemplate = "

"; + //1) The RTE does not like the tag and will try to incorrectly HTML encode it so we use standard