Skip to content

Commit

Permalink
Preserve more of the original Logo logic
Browse files Browse the repository at this point in the history
  • Loading branch information
bdukes committed Jul 10, 2020
1 parent dd33b94 commit 8428629
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 143 deletions.
259 changes: 117 additions & 142 deletions DNN Platform/Website/admin/Skins/Logo.ascx.cs
Original file line number Diff line number Diff line change
@@ -1,184 +1,103 @@
// 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.Collections.Generic;
using System.Linq;
using System.Web.UI.WebControls;
using System.Xml;
using System.Xml.Linq;
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.Services.Cache;
using DotNetNuke.Services.Exceptions;
using DotNetNuke.Services.FileSystem;
using Microsoft.Extensions.DependencyInjection;
using DotNetNuke.Services.FileSystem;

/// <summary>
/// Logo SkinObject.
/// </summary>
using Microsoft.Extensions.DependencyInjection;

/// <summary>Logo Skin Object</summary>
public partial class Logo : SkinObjectBase
{
private readonly INavigationManager navigationManager;
private readonly string svgCacheKey;

/// <summary>
/// Initializes a new instance of the <see cref="Logo"/> class.
/// </summary>

/// <summary>Initializes a new instance of the <see cref="Logo"/> class.</summary>
public Logo()
{
this.navigationManager = Globals.DependencyProvider.GetRequiredService<INavigationManager>();
this.svgCacheKey = string.Format(DataCache.PortalCacheKey, this.PortalSettings.PortalId, this.PortalSettings.CultureCode) + "LogoSvg";
}

/// <summary>
/// Gets or sets the width of the border around the image.
/// </summary>
/// <summary>Gets or sets the width of the border around the image.</summary>
public string BorderWidth { get; set; }

/// <summary>
/// Gets or sets the css class for the image.
/// </summary>
public string CssClass { get; set; }

/// <summary>
/// Gets or sets the css class for the hyperlink.
/// </summary>
/// <summary>Gets or sets the CSS class for the image.</summary>
public string CssClass { get; set; }

/// <summary>Gets or sets the CSS class for the hyperlink.</summary>
public string LinkCssClass { get; set; }

/// <summary>
/// Gets or sets a value indicating wether to inject the svg content inline instead or wrapping it in an img tag.
/// </summary>
public bool? InjectSVG { get; set; }

/// <inheritdoc/>
/// <summary>Gets or sets a value indicating whether to inject the SVG content inline instead of wrapping it in an img tag.</summary>
public bool InjectSvg { get; set; }

/// <inheritdoc/>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
try
{
this.imgLogo.Visible = false;

if (!string.IsNullOrEmpty(this.PortalSettings.LogoFile))
{
if (!string.IsNullOrEmpty(this.BorderWidth))
{
// default value in case we can't load an image or svg
this.litLogo.Text = this.PortalSettings.PortalName;
this.imgLogo.BorderWidth = Unit.Parse(this.BorderWidth);
}

if (!string.IsNullOrEmpty(this.CssClass))
{
this.imgLogo.CssClass = this.CssClass;
}

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)
{
if (this.InjectSVG.GetValueOrDefault() && fileInfo.Extension.Equals("svg", StringComparison.OrdinalIgnoreCase))
{
// svg injection was requested and we have an svg file.
this.imgLogo.Visible = false;
string svg = DataCache.GetCache<string>(this.svgCacheKey);
if (string.IsNullOrEmpty(svg))
{
try
{
var svgXmlDoc = new XDocument();
using (var fileContent = FileManager.Instance.GetFileContent(fileInfo))
{
svgXmlDoc = XDocument.Load(fileContent);
}

var svgXmlNode = svgXmlDoc.Descendants().Where(x => x.Name.LocalName == "svg").SingleOrDefault();

if (svgXmlNode == null)
{
throw new InvalidFileContentException("The svg file has no svg node.");
}

var ns = svgXmlNode.GetDefaultNamespace();

if (!string.IsNullOrEmpty(this.CssClass))
{
// Append the css class.
List<string> classList = new List<string>();
classList.Add(this.CssClass);

if (svgXmlNode.Attribute("class") != null)
{
classList.AddRange(svgXmlNode.Attribute("class").Value.Split(' '));
}

svgXmlNode.SetAttributeValue("class", string.Join(" ", classList.ToArray()));
}

if (svgXmlNode.Descendants().FirstOrDefault(x => x.Name.LocalName == "title") == null)
{
// Add the title for ADA compliance.
var titleNode = new XElement(
ns + "title",
new XAttribute("id", this.litLogo.UniqueID),
this.PortalSettings.PortalName);

svgXmlNode.AddFirst(new XElement(titleNode));

// Link the title to the svg node.
svgXmlNode.SetAttributeValue("aria-labelledby", this.litLogo.UniqueID);
}

// Ensure we have the image role for ADA Compliance
svgXmlNode.SetAttributeValue("role", "img");

svg = svgXmlNode.ToString();
DataCache.SetCache(this.svgCacheKey, svg);
}
catch (XmlException ex)
{
throw new InvalidFileContentException("Invalid svg file: " + ex.Message);
}
}

this.litLogo.Text = svg;
{
if (this.InjectSvg && "svg".Equals(fileInfo.Extension, StringComparison.OrdinalIgnoreCase))
{
this.litLogo.Text = this.GetSvgContent(fileInfo);
this.litLogo.Visible = !string.IsNullOrEmpty(this.litLogo.Text);
}
else
{
// display the raster image
this.imgLogo.Visible = true;

string imageUrl = FileManager.Instance.GetUrl(fileInfo);
if (!string.IsNullOrEmpty(imageUrl))
{
this.litLogo.Visible = false;
this.imgLogo.ImageUrl = imageUrl;
}

if (!string.IsNullOrEmpty(this.BorderWidth))
{
this.imgLogo.BorderWidth = Unit.Parse(this.BorderWidth);
}

if (!string.IsNullOrEmpty(this.CssClass))
{
this.imgLogo.CssClass = this.CssClass;
if (this.litLogo.Visible == false)
{
string imageUrl = FileManager.Instance.GetUrl(fileInfo);
if (!string.IsNullOrEmpty(imageUrl))
{
this.imgLogo.ImageUrl = imageUrl;
this.imgLogo.Visible = true;
}

this.imgLogo.AlternateText = this.PortalSettings.PortalName;
}
}
}
}

if (!string.IsNullOrEmpty(this.LinkCssClass))
{
this.hypLogo.CssClass = this.LinkCssClass;
}

this.hypLogo.ToolTip = this.PortalSettings.PortalName;
this.hypLogo.Attributes.Add("aria-label", this.PortalSettings.PortalName);
}

this.imgLogo.AlternateText = this.PortalSettings.PortalName;
this.hypLogo.ToolTip = 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);
}
else
{
this.hypLogo.NavigateUrl = Globals.AddHTTP(this.PortalSettings.PortalAlias.HTTPAlias);
}
}
}
catch (Exception exc)
{
Expand All @@ -200,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<string>(
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 ?? string.Empty;
svgXmlNode.SetAttributeValue("class", $"{classes} {this.CssClass}");

This comment has been minimized.

Copy link
@valadas

valadas Jul 11, 2020

Contributor

This would do class=" myClass" (spaced before the class, if the original svg had no classnames but we give the skinobject a CssClass... If the reason for this change was for the performance of List, this will only run once after each clear cache, so i prefer the previous way. If we keep this way, then can we put that in a variable maybe and then do a .TrimStart or some such.

}
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);
}
});
}
}
}
2 changes: 1 addition & 1 deletion DNN Platform/Website/admin/Skins/Logo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<Value></Value>
</Setting>
<Setting>
<Name>InjectSVG</Name>
<Name>InjectSvg</Name>
<Type>Boolean</Type>
<Help>
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
Expand Down

0 comments on commit 8428629

Please sign in to comment.