diff --git a/DNN Platform/Website/admin/Skins/Logo.ascx.cs b/DNN Platform/Website/admin/Skins/Logo.ascx.cs
index 59467fda11b..903019cd83a 100644
--- a/DNN Platform/Website/admin/Skins/Logo.ascx.cs
+++ b/DNN Platform/Website/admin/Skins/Logo.ascx.cs
@@ -1,37 +1,46 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information
namespace DotNetNuke.UI.Skins.Controls
{
using System;
+ using System.Linq;
using System.Web.UI.WebControls;
+ using System.Xml;
+ using System.Xml.Linq;
using DotNetNuke.Abstractions;
using DotNetNuke.Common;
using DotNetNuke.Common.Utilities;
- using DotNetNuke.Entities.Host;
using DotNetNuke.Services.Exceptions;
using DotNetNuke.Services.FileSystem;
+
using Microsoft.Extensions.DependencyInjection;
- /// -----------------------------------------------------------------------------
- ///
- ///
- ///
- /// -----------------------------------------------------------------------------
+ /// Logo Skin Object
public partial class Logo : SkinObjectBase
{
- private readonly INavigationManager _navigationManager;
+ private readonly INavigationManager navigationManager;
+ /// Initializes a new instance of the class.
public Logo()
{
- this._navigationManager = Globals.DependencyProvider.GetRequiredService();
+ this.navigationManager = Globals.DependencyProvider.GetRequiredService();
}
+ /// Gets or sets the width of the border around the image.
public string BorderWidth { get; set; }
+ /// Gets or sets the CSS class for the image.
public string CssClass { get; set; }
+ /// Gets or sets the CSS class for the hyperlink.
+ public string LinkCssClass { get; set; }
+
+ /// Gets or sets a value indicating whether to inject the SVG content inline instead of wrapping it in an img tag.
+ public bool InjectSvg { get; set; }
+
+ ///
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
@@ -47,33 +56,43 @@ protected override void OnLoad(EventArgs e)
this.imgLogo.CssClass = this.CssClass;
}
- bool logoVisible = false;
+ if (!string.IsNullOrEmpty(this.LinkCssClass))
+ {
+ this.hypLogo.CssClass = this.LinkCssClass;
+ }
+
+ this.litLogo.Visible = false;
+ this.imgLogo.Visible = false;
if (!string.IsNullOrEmpty(this.PortalSettings.LogoFile))
{
var fileInfo = this.GetLogoFileInfo();
if (fileInfo != null)
{
- string imageUrl = FileManager.Instance.GetUrl(fileInfo);
- if (!string.IsNullOrEmpty(imageUrl))
+ if (this.InjectSvg && "svg".Equals(fileInfo.Extension, StringComparison.OrdinalIgnoreCase))
+ {
+ this.litLogo.Text = this.GetSvgContent(fileInfo);
+ this.litLogo.Visible = !string.IsNullOrEmpty(this.litLogo.Text);
+ }
+
+ if (this.litLogo.Visible == false)
{
- this.imgLogo.ImageUrl = imageUrl;
- logoVisible = true;
+ string imageUrl = FileManager.Instance.GetUrl(fileInfo);
+ if (!string.IsNullOrEmpty(imageUrl))
+ {
+ this.imgLogo.ImageUrl = imageUrl;
+ this.imgLogo.Visible = true;
+ }
}
}
}
- this.imgLogo.Visible = logoVisible;
this.imgLogo.AlternateText = this.PortalSettings.PortalName;
this.hypLogo.ToolTip = this.PortalSettings.PortalName;
-
- if (!this.imgLogo.Visible)
- {
- this.hypLogo.Attributes.Add("aria-label", this.PortalSettings.PortalName);
- }
+ this.hypLogo.Attributes.Add("aria-label", this.PortalSettings.PortalName);
if (this.PortalSettings.HomeTabId != -1)
{
- this.hypLogo.NavigateUrl = this._navigationManager.NavigateURL(this.PortalSettings.HomeTabId);
+ this.hypLogo.NavigateUrl = this.navigationManager.NavigateURL(this.PortalSettings.HomeTabId);
}
else
{
@@ -100,5 +119,61 @@ private IFileInfo GetLogoFileInfoCallBack(CacheItemArgs itemArgs)
{
return FileManager.Instance.GetFile(this.PortalSettings.PortalId, this.PortalSettings.LogoFile);
}
+
+ private string GetSvgContent(IFileInfo svgFile)
+ {
+ var cacheKey = string.Format(DataCache.PortalCacheKey, this.PortalSettings.PortalId, this.PortalSettings.CultureCode) + "LogoSvg";
+ return CBO.GetCachedObject(
+ new CacheItemArgs(cacheKey, DataCache.PortalCacheTimeOut, DataCache.PortalCachePriority, svgFile),
+ (_) =>
+ {
+ try
+ {
+ XDocument svgDocument;
+ using (var fileContent = FileManager.Instance.GetFileContent(svgFile))
+ {
+ svgDocument = XDocument.Load(fileContent);
+ }
+
+ var svgXmlNode = svgDocument.Descendants()
+ .SingleOrDefault(x => x.Name.LocalName.Equals("svg", StringComparison.Ordinal));
+ if (svgXmlNode == null)
+ {
+ throw new InvalidFileContentException("The svg file has no svg node.");
+ }
+
+ if (!string.IsNullOrEmpty(this.CssClass))
+ {
+ // Append the css class.
+ var classes = svgXmlNode.Attribute("class")?.Value;
+ svgXmlNode.SetAttributeValue("class", string.IsNullOrEmpty(classes) ? this.CssClass : $"{classes} {this.CssClass}");
+ }
+
+ if (svgXmlNode.Descendants().FirstOrDefault(x => x.Name.LocalName.Equals("title", StringComparison.Ordinal)) == null)
+ {
+ // Add the title for ADA compliance.
+ var ns = svgXmlNode.GetDefaultNamespace();
+ var titleNode = new XElement(
+ ns + "title",
+ new XAttribute("id", this.litLogo.ClientID),
+ this.PortalSettings.PortalName);
+
+ svgXmlNode.AddFirst(titleNode);
+
+ // Link the title to the svg node.
+ svgXmlNode.SetAttributeValue("aria-labelledby", this.litLogo.ClientID);
+ }
+
+ // Ensure we have the image role for ADA Compliance
+ svgXmlNode.SetAttributeValue("role", "img");
+
+ return svgDocument.ToString();
+ }
+ catch (XmlException ex)
+ {
+ throw new InvalidFileContentException("Invalid SVG file: " + ex.Message);
+ }
+ });
+ }
}
}
diff --git a/DNN Platform/Website/admin/Skins/Logo.ascx.designer.cs b/DNN Platform/Website/admin/Skins/Logo.ascx.designer.cs
index 3e66ce34888..6b21e7d604b 100644
--- a/DNN Platform/Website/admin/Skins/Logo.ascx.designer.cs
+++ b/DNN Platform/Website/admin/Skins/Logo.ascx.designer.cs
@@ -1,8 +1,4 @@
-//
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-//
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
//
// This code was generated by a tool.
//
@@ -11,11 +7,13 @@
//
//------------------------------------------------------------------------------
-namespace DotNetNuke.UI.Skins.Controls {
-
-
- public partial class Logo {
-
+namespace DotNetNuke.UI.Skins.Controls
+{
+
+
+ public partial class Logo
+ {
+
///
/// hypLogo control.
///
@@ -24,7 +22,7 @@ public partial class Logo {
/// To modify move field declaration from designer file to code-behind file.
///
protected global::System.Web.UI.WebControls.HyperLink hypLogo;
-
+
///
/// imgLogo control.
///
@@ -33,5 +31,14 @@ public partial class Logo {
/// To modify move field declaration from designer file to code-behind file.
///
protected global::System.Web.UI.WebControls.Image imgLogo;
+
+ ///
+ /// litLogo control.
+ ///
+ ///
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ ///
+ protected global::System.Web.UI.WebControls.Literal litLogo;
}
}
diff --git a/DNN Platform/Website/admin/Skins/Logo.xml b/DNN Platform/Website/admin/Skins/Logo.xml
index 1d134a29973..5efd91598a1 100644
--- a/DNN Platform/Website/admin/Skins/Logo.xml
+++ b/DNN Platform/Website/admin/Skins/Logo.xml
@@ -5,4 +5,24 @@
Sets the border width of the logo image
+
+ CssClass
+ String
+ Sets a CSS class on the logo
+
+
+
+ LinkCssClass
+ String
+ Sets a CSS class on the hyperlink
+
+
+
+ InjectSvg
+ Boolean
+
+ If set to true, the control will read the contents of the Logo file, look for an svg tag, and inject it directly into the hyperlink
+
+
+
diff --git a/DNN Platform/Website/admin/Skins/logo.ascx b/DNN Platform/Website/admin/Skins/logo.ascx
index 2922fd4d030..f90ddf01c9b 100644
--- a/DNN Platform/Website/admin/Skins/logo.ascx
+++ b/DNN Platform/Website/admin/Skins/logo.ascx
@@ -1,2 +1,5 @@
-<%@ Control Language="C#" AutoEventWireup="false" Inherits="DotNetNuke.UI.Skins.Controls.Logo" ViewStateMode="Disabled" Codebehind="Logo.ascx.cs" %>
-
\ No newline at end of file
+<%@ Control Language="C#" AutoEventWireup="false" Inherits="DotNetNuke.UI.Skins.Controls.Logo" ViewStateMode="Disabled" CodeBehind="Logo.ascx.cs" %>
+
+
+
+
\ No newline at end of file