diff --git a/src/Umbraco.Core/Services/IIconService.cs b/src/Umbraco.Core/Services/IIconService.cs index 963edb22a5..72174a0504 100644 --- a/src/Umbraco.Core/Services/IIconService.cs +++ b/src/Umbraco.Core/Services/IIconService.cs @@ -9,13 +9,13 @@ namespace Umbraco.Core.Services /// Gets an IconModel containing the icon name and SvgString according to an icon name found at the global icons path /// /// - /// + /// IconModel GetIcon(string iconName); /// /// Gets a list of all svg icons found at at the global icons path. /// - /// + /// A list of IList GetAllIcons(); } } diff --git a/src/Umbraco.Web/Services/IconService.cs b/src/Umbraco.Web/Services/IconService.cs index 206af296f9..ba6692c7b9 100644 --- a/src/Umbraco.Web/Services/IconService.cs +++ b/src/Umbraco.Web/Services/IconService.cs @@ -19,13 +19,11 @@ namespace Umbraco.Web.Services _globalSettings = globalSettings; } - /// public IList GetAllIcons() { var icons = new List(); - var directory = new DirectoryInfo(IOHelper.MapPath($"{_globalSettings.IconsPath}/")); - var iconNames = directory.GetFiles("*.svg"); + var iconNames = GetAllIconNames(); iconNames.OrderBy(f => f.Name).ToList().ForEach(iconInfo => { @@ -45,15 +43,15 @@ namespace Umbraco.Web.Services { return string.IsNullOrWhiteSpace(iconName) ? null - : CreateIconModel(iconName.StripFileExtension(), IOHelper.MapPath($"{_globalSettings.IconsPath}/{iconName}.svg")); + : CreateIconModel(iconName.StripFileExtension()); } /// /// Gets an IconModel using values from a FileInfo model /// /// - /// - private IconModel GetIcon(FileInfo fileInfo) + /// + private IconModel GetIcon(FileSystemInfo fileInfo) { return fileInfo == null || string.IsNullOrWhiteSpace(fileInfo.Name) ? null @@ -64,17 +62,37 @@ namespace Umbraco.Web.Services /// Gets an IconModel containing the icon name and SvgString /// /// - /// - /// - private IconModel CreateIconModel(string iconName, string iconPath) + /// + private IconModel CreateIconModel(string iconName) { - var sanitizer = new HtmlSanitizer(); - sanitizer.AllowedAttributes.UnionWith(Constants.SvgSanitizer.Attributes); - sanitizer.AllowedCssProperties.UnionWith(Constants.SvgSanitizer.Attributes); - sanitizer.AllowedTags.UnionWith(Constants.SvgSanitizer.Tags); + if (string.IsNullOrWhiteSpace(iconName)) + return null; + + var iconNames = GetAllIconNames(); + var iconPath = iconNames.FirstOrDefault(x => x.Name.InvariantEquals($"{iconName}.svg"))?.FullName; + return iconPath == null + ? null + : CreateIconModel(iconName, iconPath); + } + + /// + /// Gets an IconModel containing the icon name and SvgString + /// + /// + /// + /// + private static IconModel CreateIconModel(string iconName, string iconPath) + { + if (string.IsNullOrWhiteSpace(iconPath)) + return null; try { + var sanitizer = new HtmlSanitizer(); + sanitizer.AllowedAttributes.UnionWith(Constants.SvgSanitizer.Attributes); + sanitizer.AllowedCssProperties.UnionWith(Constants.SvgSanitizer.Attributes); + sanitizer.AllowedTags.UnionWith(Constants.SvgSanitizer.Tags); + var svgContent = System.IO.File.ReadAllText(iconPath); var sanitizedString = sanitizer.Sanitize(svgContent); @@ -91,5 +109,26 @@ namespace Umbraco.Web.Services return null; } } + + private IEnumerable GetAllIconNames() + { + // add icons from plugins + var appPlugins = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)); + var pluginIcons = appPlugins.Exists == false + ? new List() + : appPlugins.GetDirectories() + // Find all directories in App_Plugins that are named "Icons" and get a list of SVGs from them + .SelectMany(x => x.GetDirectories("Icons", SearchOption.AllDirectories)) + .SelectMany(x => x.GetFiles("*.svg", SearchOption.TopDirectoryOnly)); + + // add icons from IconsPath if not already added from plugins + var directory = new DirectoryInfo(IOHelper.MapPath($"{_globalSettings.IconsPath}/")); + var iconNames = directory.GetFiles("*.svg") + .Where(x => pluginIcons.Any(i => i.Name == x.Name) == false); + + iconNames = iconNames.Concat(pluginIcons).ToList(); + + return iconNames; + } } }