Skip to content

Commit

Permalink
Merge pull request #56 from svb-wks/binaries-without-tcmuri-appended
Browse files Browse the repository at this point in the history
Implement customizable binary filenames without TCM URI
  • Loading branch information
dxasupport authored May 31, 2024
2 parents 834f2c3 + 3af79cb commit 6adae59
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 78 deletions.
42 changes: 38 additions & 4 deletions Sdl.Web.Tridion.Templates.R2/Data/DataModelBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml;
Expand All @@ -8,6 +9,7 @@
using Tridion.ContentManager;
using Tridion.ContentManager.CommunicationManagement;
using Tridion.ContentManager.ContentManagement;
using Tridion.ContentManager.Publishing.Rendering;
using Tridion.ContentManager.Templating;

namespace Sdl.Web.Tridion.Templates.R2.Data
Expand Down Expand Up @@ -359,8 +361,8 @@ protected RichTextData BuildRichTextModel(XmlElement xhtmlElement, int expandLin
xlinkElement.RemoveXlinkAttributes();
continue;
}
// Default behaviour: Hyperlink to MM Component: add the Binary and set the URL as href
string binaryUrl = Pipeline.RenderedItem.AddBinary(linkedComponent).Url;
// Default behaviour: Hyperlink to MM Component: add the Binary and set the URL as href
string binaryUrl = AddBinary(linkedComponent).Url;
xlinkElement.SetAttribute("href", binaryUrl);
xlinkElement.RemoveXlinkAttributes();
}
Expand Down Expand Up @@ -405,16 +407,48 @@ private bool ShouldBeEmbedded(Component linkedComponent)
if (Pipeline.Settings.SchemasForRichTextEmbed.Contains($"{linkedComponent.Schema.NamespaceUri}:{linkedComponent.Schema.RootElementName}"))
return true;

return false;
return false;
}
protected Binary AddBinary(Component multimediaComponent)
{
if (IsUniqueFilenameRequired(multimediaComponent))
{
return Pipeline.RenderedItem.AddBinary(multimediaComponent);
}
else
{
using (Stream stream = new MemoryStream())
{
multimediaComponent.BinaryContent.WriteToStream(stream);
return Pipeline.RenderedItem.AddBinary(stream, GetFilename(multimediaComponent), "no-tcm", multimediaComponent, multimediaComponent.BinaryContent.MultimediaType.MimeType);
}
}
}

private string GetFilename(Component component) { return component.BinaryContent.Filename; }

private bool IsUniqueFilenameRequired(Component multimediaComponent)
{
if (Pipeline.Settings.SchemasForAsIsMultimediaUrls != null)
{
Logger.Debug($"Looking for schema {multimediaComponent.Schema.Title} in set of schemas configured for as is url: {String.Join(";", Pipeline.Settings.SchemasForAsIsMultimediaUrls)}");
if (Pipeline.Settings.SchemasForAsIsMultimediaUrls.Contains(multimediaComponent.Schema.Title.ToLower()))
{
Logger.Debug($"Found!");
return false;
}
}
return true;
}

protected ContentModelData ExtractCustomMetadata(XmlElement metadata, IEnumerable<string> excludeFields)
{
if (metadata == null)
{
return null;
}

XmlElement customMetadata = (XmlElement) metadata.CloneNode(deep: true);
XmlElement customMetadata = (XmlElement)metadata.CloneNode(deep: true);
string excludeXPathPredicate = string.Join(" or ", excludeFields.Select(name => $"local-name()='{name}'"));
XmlElement[] excludeElements = customMetadata.SelectElements($"*[{excludeXPathPredicate}]").ToArray();

Expand Down
5 changes: 5 additions & 0 deletions Sdl.Web.Tridion.Templates.R2/Data/DataModelBuilderSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,10 @@ public class DataModelBuilderSettings
/// E.g: http://www.sdl.com/web/schemas/core:Article
/// </summary>
public List<string> SchemasForRichTextEmbed { get; set; }

/// <summary>
/// Gets or sets the a list of schema names used to determine if multimedia link should use the url as is from the binary filename (no tcm-id)
/// </summary>
public List<string> SchemasForAsIsMultimediaUrls { get; set; }
}
}
16 changes: 8 additions & 8 deletions Sdl.Web.Tridion.Templates.R2/Data/DefaultModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ public void BuildPageModel(ref PageModelData pageModelData, Page page)
StructureGroupId = GetDxaIdentifier(structureGroup),
SchemaId = GetDxaIdentifier(page.MetadataSchema),
Meta = null, // Default Model builder does not set PageModel.Meta; see DefaultPageMetaModelBuilder.
Title = StripSequencePrefix(page.Title, out sequencePrefix) , // See DefaultPageMetaModelBuilder
Title = StripSequencePrefix(page.Title, out sequencePrefix), // See DefaultPageMetaModelBuilder
UrlPath = GetUrlPath(page),
Regions = regionModels.Values.ToList(),
Regions = regionModels.Values.ToList(),
Metadata = pageModelMetadata,
MvcData = GetPageMvcData(pt),
HtmlClasses = GetHtmlClasses(pt),
Expand Down Expand Up @@ -197,7 +197,7 @@ private BinaryContentData BuildBinaryContentData(Component component)

return new BinaryContentData
{
Url = Pipeline.RenderedItem.AddBinary(component).Url,
Url = AddBinary(component).Url,
FileName = binaryContent.Filename,
FileSize = binaryContent.Size,
MimeType = binaryContent.MultimediaType.MimeType
Expand Down Expand Up @@ -313,7 +313,7 @@ private void AddIncludePageRegions(IDictionary<string, RegionModelData> regionMo
Page includePage;
try
{
includePage = (Page) Pipeline.Session.GetObject(includePageId);
includePage = (Page)Pipeline.Session.GetObject(includePageId);
includePage.Load(LoadFlags.None); // Force load the Page
}
catch (Exception ex)
Expand Down Expand Up @@ -370,7 +370,7 @@ private string ConvertPublishPathToWebDavUrl(string publishPath, Publication con
{
webDavUrlBuilder.Append("_System");
}
else if (i == pathSegments.Length -1)
else if (i == pathSegments.Length - 1)
{
// Last path segment (representing the Page itself)
// Convert dashes to spaces and capitalize each name segment.
Expand Down Expand Up @@ -688,8 +688,8 @@ private ComponentTemplateData GetComponentTemplateData(ComponentTemplate ct)
{
Id = GetDxaIdentifier(ct),
Namespace = GetNamespace(ct)
};
};

if (ct.Metadata == null || ct.MetadataSchema == null) return componentTemplateData;
componentTemplateData.Title = ct.Title;
componentTemplateData.RevisionDate = ct.RevisionDate;
Expand All @@ -700,7 +700,7 @@ private ComponentTemplateData GetComponentTemplateData(ComponentTemplate ct)

private FolderData GetFolderData(Component component)
{
Folder folder = (Folder) component.OrganizationalItem;
Folder folder = (Folder)component.OrganizationalItem;
return new FolderData
{
Id = folder.Id?.ItemId.ToString(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,38 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.sdl.com/web/schemas/dynamiccomponent" xmlns="http://www.sdl.com/web/schemas/dynamiccomponent" xmlns:tcmi="http://www.tridion.com/ContentManager/5.0/Instance" xmlns:xlink="http://www.w3.org/1999/xlink" elementFormDefault="qualified">
<xsd:import namespace="http://www.tridion.com/ContentManager/5.0/Instance" schemaLocation="cm_xml_inst.xsd"></xsd:import>
<xsd:annotation>
<xsd:appinfo>
<tcm:Labels xmlns:tcm="http://www.tridion.com/ContentManager/5.0">
<tcm:Label ElementName="includeComponentTemplateData" Metadata="false">Include Component Template related data</tcm:Label>
<tcm:Label ElementName="expandLinkDepth" Metadata="false">Depth to expand Component/Keyword links</tcm:Label>
<tcm:Label ElementName="modelBuilderTypeNames" Metadata="false">Type names of Model Builders to use (separated by semicolons)</tcm:Label>
<tcm:Label ElementName="schemasToEmbedInRichText" Metadata="false">List of schema identifiers (use either schema title or a namespace Uri with optional root element name (NamespaceUri:RootElementName) which will result in embedded items in Rich text fields (separated by semicolons)</tcm:Label>
</tcm:Labels>
</xsd:appinfo>
</xsd:annotation>
<xsd:element name="Parameters">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="includeComponentTemplateData" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:appinfo>
<tcm:Size xmlns:tcm="http://www.tridion.com/ContentManager/5.0">1</tcm:Size>
<tcm:listtype xmlns:tcm="http://www.tridion.com/ContentManager/5.0">select</tcm:listtype>
</xsd:appinfo>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:normalizedString">
<xsd:enumeration value="true"></xsd:enumeration>
<xsd:enumeration value="false"></xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="expandLinkDepth" minOccurs="0" maxOccurs="1" type="xsd:integer" />
<xsd:element name="modelBuilderTypeNames" minOccurs="0" maxOccurs="1" type="xsd:normalizedString" />
<xsd:element name="schemaToEmbedInRichText" minOccurs="0" maxOccurs="1" type="xsd:normalizedString" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:import namespace="http://www.tridion.com/ContentManager/5.0/Instance" schemaLocation="cm_xml_inst.xsd"></xsd:import>
<xsd:annotation>
<xsd:appinfo>
<tcm:Labels xmlns:tcm="http://www.tridion.com/ContentManager/5.0">
<tcm:Label ElementName="includeComponentTemplateData" Metadata="false">Include Component Template related data</tcm:Label>
<tcm:Label ElementName="expandLinkDepth" Metadata="false">Depth to expand Component/Keyword links</tcm:Label>
<tcm:Label ElementName="modelBuilderTypeNames" Metadata="false">Type names of Model Builders to use (separated by semicolons)</tcm:Label>
<tcm:Label ElementName="schemasToEmbedInRichText" Metadata="false">List of schema identifiers (use either schema title or a namespace Uri with optional root element name (NamespaceUri:RootElementName) which will result in embedded items in Rich text fields (separated by semicolons)</tcm:Label>
<tcm:Label ElementName="schemasForAsIsMultimediaUrls" Metadata="false">List of schema names which will result in multimedia links that should use the url as is from the binary filename without tcm-id</tcm:Label>
</tcm:Labels>
</xsd:appinfo>
</xsd:annotation>
<xsd:element name="Parameters">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="includeComponentTemplateData" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:appinfo>
<tcm:Size xmlns:tcm="http://www.tridion.com/ContentManager/5.0">1</tcm:Size>
<tcm:listtype xmlns:tcm="http://www.tridion.com/ContentManager/5.0">select</tcm:listtype>
</xsd:appinfo>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:normalizedString">
<xsd:enumeration value="true"></xsd:enumeration>
<xsd:enumeration value="false"></xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="expandLinkDepth" minOccurs="0" maxOccurs="1" type="xsd:integer" />
<xsd:element name="modelBuilderTypeNames" minOccurs="0" maxOccurs="1" type="xsd:normalizedString" />
<xsd:element name="schemaToEmbedInRichText" minOccurs="0" maxOccurs="1" type="xsd:normalizedString" />
<xsd:element name="schemasForAsIsMultimediaUrls" minOccurs="0" maxOccurs="1" type="xsd:normalizedString" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.sdl.com/web/schemas/dynamicpage" xmlns="http://www.sdl.com/web/schemas/dynamicpage" xmlns:tcmi="http://www.tridion.com/ContentManager/5.0/Instance" xmlns:xlink="http://www.w3.org/1999/xlink" elementFormDefault="qualified">
<xsd:import namespace="http://www.tridion.com/ContentManager/5.0/Instance" schemaLocation="cm_xml_inst.xsd"></xsd:import>
<xsd:annotation>
<xsd:appinfo>
<tcm:Labels xmlns:tcm="http://www.tridion.com/ContentManager/5.0">
<tcm:Label ElementName="expandLinkDepth" Metadata="false">Depth to expand Component/Keyword links</tcm:Label>
<tcm:Label ElementName="modelBuilderTypeNames" Metadata="false">Type names of Model Builders to use (separated by semicolons)</tcm:Label>
<tcm:Label ElementName="schemasToEmbedInRichText" Metadata="false">List of schema identifiers (use either schema title or a namespace Uri with optional root element name (NamespaceUri:RootElementName) which will result in embedded items in Rich text fields (separated by semicolons)</tcm:Label>
</tcm:Labels>
</xsd:appinfo>
</xsd:annotation>
<xsd:element name="Parameters">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="expandLinkDepth" minOccurs="0" maxOccurs="1" type="xsd:integer" />
<xsd:element name="modelBuilderTypeNames" minOccurs="0" maxOccurs="1" type="xsd:normalizedString" />
<xsd:element name="schemasToEmbedInRichText" minOccurs="0" maxOccurs="1" type="xsd:normalizedString" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:import namespace="http://www.tridion.com/ContentManager/5.0/Instance" schemaLocation="cm_xml_inst.xsd"></xsd:import>
<xsd:annotation>
<xsd:appinfo>
<tcm:Labels xmlns:tcm="http://www.tridion.com/ContentManager/5.0">
<tcm:Label ElementName="expandLinkDepth" Metadata="false">Depth to expand Component/Keyword links</tcm:Label>
<tcm:Label ElementName="modelBuilderTypeNames" Metadata="false">Type names of Model Builders to use (separated by semicolons)</tcm:Label>
<tcm:Label ElementName="schemasToEmbedInRichText" Metadata="false">List of schema identifiers (use either schema title or a namespace Uri with optional root element name (NamespaceUri:RootElementName) which will result in embedded items in Rich text fields (separated by semicolons)</tcm:Label>
<tcm:Label ElementName="schemasForAsIsMultimediaUrls" Metadata="false">List of schema names which will result in multimedia links that should use the url as is from the binary filename without tcm-id</tcm:Label>
</tcm:Labels>
</xsd:appinfo>
</xsd:annotation>
<xsd:element name="Parameters">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="expandLinkDepth" minOccurs="0" maxOccurs="1" type="xsd:integer" />
<xsd:element name="modelBuilderTypeNames" minOccurs="0" maxOccurs="1" type="xsd:normalizedString" />
<xsd:element name="schemasToEmbedInRichText" minOccurs="0" maxOccurs="1" type="xsd:normalizedString" />
<xsd:element name="schemasForAsIsMultimediaUrls" minOccurs="0" maxOccurs="1" type="xsd:normalizedString" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
29 changes: 21 additions & 8 deletions Sdl.Web.Tridion.Templates.R2/TemplateR2Base.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,29 @@ protected string[] GetModelBuilderTypeNames()
/// <returns>List of schema identifiers</returns>
protected List<string> GetSchemasForRichTextEmbed()
{
Logger.Info("Checking 'schemasToEmbedInRichText' template parameter for list of schema identifiers to determine what entities to embed in Rich Text fields.");
string schemasForEmbed;
List<string> schemasForEmbedList = new List<string>();
TryGetParameter("schemasToEmbedInRichText", out schemasForEmbed);
if (!string.IsNullOrEmpty(schemasForEmbed))
return GetListFromStringParameter("schemasToEmbedInRichText");
}
/// <summary>
/// Gets a list of schema identifiers to determine what binaries can be published with 'as is' Urls (without tcmUri being appended).
/// </summary>
/// <returns>List of schema identifiers</returns>

protected List<string> GetSchemasForAsIsMultimediaUrls()
{
return GetListFromStringParameter("schemasForAsIsMultimediaUrls");
}
protected List<string> GetListFromStringParameter(string parameterName)
{
Logger.Info($"Checking '{parameterName}' template parameter");
string parameterValue;
List<string> parameterList = new List<string>();
TryGetParameter(parameterName, out parameterValue);
if (!string.IsNullOrEmpty(parameterValue))
{
Logger.Info($"schemasToEmbedInRichText set to '{schemasForEmbed}'.");
schemasForEmbedList = schemasForEmbed.Split(';').Select(s => s.Trim()).ToList();
Logger.Info($"parameter value set to '{parameterValue}'.");
parameterList = parameterValue.Split(';').Select(s => s.Trim().ToLower()).ToList();
}
return schemasForEmbedList;
return parameterList;
}
}
}
7 changes: 4 additions & 3 deletions Sdl.Web.Tridion.Templates.R2/Templates/GenerateEntityModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public override void Transform(Engine engine, Package package)

int expandLinkDepth;
package.TryGetParameter("expandLinkDepth", out expandLinkDepth, Logger);

string[] modelBuilderTypeNames = GetModelBuilderTypeNames();

RenderedItem renderedItem = Engine.PublishingContext.RenderedItem;
Expand All @@ -47,14 +47,15 @@ public override void Transform(Engine engine, Package package)
{
ExpandLinkDepth = expandLinkDepth,
GenerateXpmMetadata = IsXpmEnabled || IsPreview,
SchemasForRichTextEmbed = GetSchemasForRichTextEmbed()
SchemasForRichTextEmbed = GetSchemasForRichTextEmbed(),
SchemasForAsIsMultimediaUrls = GetSchemasForAsIsMultimediaUrls()
};

DataModelBuilderPipeline modelBuilderPipeline = new DataModelBuilderPipeline(renderedItem, settings, modelBuilderTypeNames);
EntityModelData entityModel = modelBuilderPipeline.CreateEntityModel(component, ct, includeComponentTemplateData);
OutputJson = JsonSerialize(entityModel, IsPreview, DataModelBinder.SerializerSettings);

if(string.IsNullOrEmpty(OutputJson))
if (string.IsNullOrEmpty(OutputJson))
throw new DxaException("Output Json is empty!");
}
catch (Exception ex)
Expand Down
5 changes: 3 additions & 2 deletions Sdl.Web.Tridion.Templates.R2/Templates/GeneratePageModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using Tridion.ContentManager.Templating.Assembly;

namespace Sdl.Web.Tridion.Templates.R2.Templates
{
{
/// <summary>
/// Generates a DXA R2 Data Model based on the current Page
/// </summary>
Expand Down Expand Up @@ -40,7 +40,8 @@ public override void Transform(Engine engine, Package package)
ExpandLinkDepth = expandLinkDepth,
GenerateXpmMetadata = IsXpmEnabled || IsPreview,
Locale = GetLocale(),
SchemasForRichTextEmbed = GetSchemasForRichTextEmbed()
SchemasForRichTextEmbed = GetSchemasForRichTextEmbed(),
SchemasForAsIsMultimediaUrls = GetSchemasForAsIsMultimediaUrls()
};

DataModelBuilderPipeline modelBuilderPipeline = new DataModelBuilderPipeline(renderedItem, settings, modelBuilderTypeNames);
Expand Down

0 comments on commit 6adae59

Please sign in to comment.