From a67020ec31eade26e83d5fc678771a7823a9ade8 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 28 Jun 2016 20:14:12 +0200 Subject: [PATCH] Ensures that the package Icon is displayed for installed packages. Cleans up lots of try/catch/swallows in the packaging logic, adds better xml error handling (we really need a lot more though), ensures that if any part of the package installation fails, that angular bails and doesn't keep trying to install - same logic for installing forms. --- src/Umbraco.Core/XmlHelper.cs | 84 ++++ .../dashboard/dashboard.tabs.controller.js | 38 +- .../views/install-local.controller.js | 18 +- .../src/views/packager/views/installed.html | 8 +- .../Editors/PackageInstallController.cs | 3 +- .../ContentEditing/InstalledPackageModel.cs | 3 + .../businesslogic/Packager/Installer.cs | 62 ++- .../PackageInstance/PackageInstance.cs | 27 +- .../businesslogic/Packager/data.cs | 363 +++++++++--------- 9 files changed, 342 insertions(+), 264 deletions(-) diff --git a/src/Umbraco.Core/XmlHelper.cs b/src/Umbraco.Core/XmlHelper.cs index d45f0cac3b..66dcae7358 100644 --- a/src/Umbraco.Core/XmlHelper.cs +++ b/src/Umbraco.Core/XmlHelper.cs @@ -17,6 +17,35 @@ namespace Umbraco.Core /// public class XmlHelper { + /// + /// Creates or sets an attribute on the XmlNode if an Attributes collection is available + /// + /// + /// + /// + /// + public static void SetAttribute(XmlDocument xml, XmlNode n, string name, string value) + { + if (xml == null) throw new ArgumentNullException("xml"); + if (n == null) throw new ArgumentNullException("n"); + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", "name"); + + if (n.Attributes == null) + { + return; + } + if (n.Attributes[name] == null) + { + var a = xml.CreateAttribute(name); + a.Value = value; + n.Attributes.Append(a); + } + else + { + n.Attributes[name].Value = value; + } + } + /// /// Gets a value indicating whether a specified string contains only xml whitespace characters. /// @@ -338,6 +367,9 @@ namespace Umbraco.Core /// a XmlAttribute public static XmlAttribute AddAttribute(XmlDocument xd, string name, string value) { + if (xd == null) throw new ArgumentNullException("xd"); + if (string.IsNullOrEmpty(name)) throw new ArgumentException("Value cannot be null or empty.", "name"); + var temp = xd.CreateAttribute(name); temp.Value = value; return temp; @@ -352,11 +384,37 @@ namespace Umbraco.Core /// a XmlNode public static XmlNode AddTextNode(XmlDocument xd, string name, string value) { + if (xd == null) throw new ArgumentNullException("xd"); + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", "name"); + var temp = xd.CreateNode(XmlNodeType.Element, name, ""); temp.AppendChild(xd.CreateTextNode(value)); return temp; } + /// + /// Sets or Creates a text XmlNode with the specified name and value + /// + /// The xmldocument. + /// The node to set or create the child text node on + /// The node name. + /// The node value. + /// a XmlNode + public static XmlNode SetTextNode(XmlDocument xd, XmlNode parent, string name, string value) + { + if (xd == null) throw new ArgumentNullException("xd"); + if (parent == null) throw new ArgumentNullException("parent"); + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", "name"); + + var child = parent.SelectSingleNode(name); + if (child != null) + { + child.InnerText = value; + return child; + } + return AddTextNode(xd, name, value); + } + /// /// Creates a cdata XmlNode with the specified name and value /// @@ -366,11 +424,37 @@ namespace Umbraco.Core /// A XmlNode public static XmlNode AddCDataNode(XmlDocument xd, string name, string value) { + if (xd == null) throw new ArgumentNullException("xd"); + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", "name"); + var temp = xd.CreateNode(XmlNodeType.Element, name, ""); temp.AppendChild(xd.CreateCDataSection(value)); return temp; } + /// + /// Sets or Creates a cdata XmlNode with the specified name and value + /// + /// The xmldocument. + /// The node to set or create the child text node on + /// The node name. + /// The node value. + /// a XmlNode + public static XmlNode SetCDataNode(XmlDocument xd, XmlNode parent, string name, string value) + { + if (xd == null) throw new ArgumentNullException("xd"); + if (parent == null) throw new ArgumentNullException("parent"); + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", "name"); + + var child = parent.SelectSingleNode(name); + if (child != null) + { + child.InnerXml = ""; ; + return child; + } + return AddCDataNode(xd, name, value); + } + /// /// Gets the value of a XmlNode /// diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js b/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js index 561b9dd753..42ceb86964 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js @@ -22,22 +22,26 @@ function FormsController($scope, $route, $cookieStore, packageResource) { $scope.state = "Installng package"; packageResource .fetch("CD44CF39-3D71-4C19-B6EE-948E1FAF0525") - .then(function(pack){ - $scope.state = "importing"; - return packageResource.import(pack); - }, $scope.error) - .then(function(pack){ - $scope.state = "Installing"; - return packageResource.installFiles(pack); - }, $scope.error) - .then(function(pack){ - $scope.state = "Restarting, please wait..."; - return packageResource.installData(pack); - }, $scope.error) - .then(function(pack){ - $scope.state = "All done, your browser will now refresh"; - return packageResource.cleanUp(pack); - }, $scope.error) + .then(function(pack) { + $scope.state = "importing"; + return packageResource.import(pack); + }, + $scope.error) + .then(function(pack) { + $scope.state = "Installing"; + return packageResource.installFiles(pack); + }, + $scope.error) + .then(function(pack) { + $scope.state = "Restarting, please wait..."; + return packageResource.installData(pack); + }, + $scope.error) + .then(function(pack) { + $scope.state = "All done, your browser will now refresh"; + return packageResource.cleanUp(pack); + }, + $scope.error) .then($scope.complete, $scope.error); }; @@ -50,6 +54,8 @@ function FormsController($scope, $route, $cookieStore, packageResource) { $scope.error = function(err){ $scope.state = undefined; $scope.error = err; + //This will return a rejection meaning that the promise change above will stop + return $q.reject(); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/packager/views/install-local.controller.js b/src/Umbraco.Web.UI.Client/src/views/packager/views/install-local.controller.js index c68b31038f..4d9f97718c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packager/views/install-local.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packager/views/install-local.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function PackagesInstallLocalController($scope, $route, $location, Upload, umbRequestHelper, packageResource, $cookieStore, $timeout) { + function PackagesInstallLocalController($scope, $route, $location, Upload, umbRequestHelper, packageResource, $cookieStore, $timeout, $q) { var vm = this; vm.state = "upload"; @@ -95,16 +95,11 @@ } function installPackage() { - vm.installState.status = "Installing"; + vm.installState.status = "Importing"; //TODO: If any of these fail, will they keep calling the next one? packageResource - .installFiles(vm.localPackage) - .then(function(pack) { - vm.installState.status = "Importing..."; - return packageResource.import(pack); - }, - installError) + .import(vm.localPackage) .then(function(pack) { vm.installState.status = "Installing..."; return packageResource.installFiles(pack); @@ -116,7 +111,7 @@ }, installError) .then(function(pack) { - vm.installState.status = "All done, your browser will now refresh"; + vm.installState.status = "All done, your browser will now refresh, please wait..."; return packageResource.cleanUp(pack); }, installError) @@ -135,9 +130,10 @@ }, installError); } - + function installError() { - //TODO: Need to do something about this? + //This will return a rejection meaning that the promise change above will stop + return $q.reject(); } } diff --git a/src/Umbraco.Web.UI.Client/src/views/packager/views/installed.html b/src/Umbraco.Web.UI.Client/src/views/packager/views/installed.html index 403406545c..7a445458f3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packager/views/installed.html +++ b/src/Umbraco.Web.UI.Client/src/views/packager/views/installed.html @@ -10,8 +10,8 @@
- - + +
@@ -45,8 +45,8 @@
- - + +
diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 0d814c8f7f..08fdf5303f 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -219,7 +219,8 @@ namespace Umbraco.Web.Editors Url = pack.Url, License = pack.License, LicenseUrl = pack.LicenseUrl, - Files = pack.Files + Files = pack.Files, + IconUrl = pack.IconUrl }).ToList(); } diff --git a/src/Umbraco.Web/Models/ContentEditing/InstalledPackageModel.cs b/src/Umbraco.Web/Models/ContentEditing/InstalledPackageModel.cs index 0bf6986e47..3b1bf69faf 100644 --- a/src/Umbraco.Web/Models/ContentEditing/InstalledPackageModel.cs +++ b/src/Umbraco.Web/Models/ContentEditing/InstalledPackageModel.cs @@ -29,5 +29,8 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "licenseUrl")] public string LicenseUrl { get; set; } + + [DataMember(Name = "iconUrl")] + public string IconUrl { get; set; } } } \ No newline at end of file diff --git a/src/umbraco.cms/businesslogic/Packager/Installer.cs b/src/umbraco.cms/businesslogic/Packager/Installer.cs index fc3c866327..42e76107f9 100644 --- a/src/umbraco.cms/businesslogic/Packager/Installer.cs +++ b/src/umbraco.cms/businesslogic/Packager/Installer.cs @@ -194,15 +194,8 @@ namespace umbraco.cms.businesslogic.packager // Check if the file is a valid package if (fi.Extension.ToLower() == ".umb") { - try - { - tempDir = UnPack(fi.FullName, deleteFile); - LoadConfig(tempDir); - } - catch (Exception unpackE) - { - throw new Exception("Error unpacking extension...", unpackE); - } + tempDir = UnPack(fi.FullName, deleteFile); + LoadConfig(tempDir); } else throw new Exception("Error - file isn't a package (doesn't have a .umb extension). Check if the file automatically got named '.zip' upon download."); @@ -234,6 +227,7 @@ namespace umbraco.cms.businesslogic.packager var packReadme = XmlHelper.GetNodeValue(Config.DocumentElement.SelectSingleNode("/umbPackage/info/readme")); var packLicense = XmlHelper.GetNodeValue(Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/license ")); var packUrl = XmlHelper.GetNodeValue(Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/url ")); + var iconUrl = XmlHelper.GetNodeValue(Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/iconUrl")); var enableSkins = false; var skinRepoGuid = ""; @@ -255,6 +249,7 @@ namespace umbraco.cms.businesslogic.packager insPack.Data.Readme = packReadme; insPack.Data.License = packLicense; insPack.Data.Url = packUrl; + insPack.Data.IconUrl = iconUrl; //skinning insPack.Data.EnableSkins = enableSkins; @@ -285,31 +280,22 @@ namespace umbraco.cms.businesslogic.packager foreach (XmlNode n in Config.DocumentElement.SelectNodes("//file")) { - //we enclose the whole file-moving to ensure that the entire installer doesn't crash - try - { - var destPath = GetFileName(basePath, XmlHelper.GetNodeValue(n.SelectSingleNode("orgPath"))); - var sourceFile = GetFileName(tempDir, XmlHelper.GetNodeValue(n.SelectSingleNode("guid"))); - var destFile = GetFileName(destPath, XmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); + var destPath = GetFileName(basePath, XmlHelper.GetNodeValue(n.SelectSingleNode("orgPath"))); + var sourceFile = GetFileName(tempDir, XmlHelper.GetNodeValue(n.SelectSingleNode("guid"))); + var destFile = GetFileName(destPath, XmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); - // Create the destination directory if it doesn't exist - if (Directory.Exists(destPath) == false) - Directory.CreateDirectory(destPath); - //If a file with this name exists, delete it - else if (File.Exists(destFile)) - File.Delete(destFile); + // Create the destination directory if it doesn't exist + if (Directory.Exists(destPath) == false) + Directory.CreateDirectory(destPath); + //If a file with this name exists, delete it + else if (File.Exists(destFile)) + File.Delete(destFile); - // Move the file - File.Move(sourceFile, destFile); + // Move the file + File.Move(sourceFile, destFile); - //PPH log file install - insPack.Data.Files.Add(XmlHelper.GetNodeValue(n.SelectSingleNode("orgPath")) + "/" + XmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); - - } - catch (Exception ex) - { - LogHelper.Error("Package install error", ex); - } + //PPH log file install + insPack.Data.Files.Add(XmlHelper.GetNodeValue(n.SelectSingleNode("orgPath")) + "/" + XmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); } // log that a user has install files @@ -527,7 +513,7 @@ namespace umbraco.cms.businesslogic.packager RequirementsType = reqNode != null && reqNode.Attributes != null && reqNode.Attributes["type"] != null ? Enum.Parse(reqNode.Attributes["type"].Value, true) : RequirementsType.Legacy; - var iconNode = Config.DocumentElement.SelectSingleNode("/umbPackage/info/author/iconUrl"); + var iconNode = Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/iconUrl"); if (iconNode != null) { IconUrl = iconNode.FirstChild.Value; @@ -638,17 +624,17 @@ namespace umbraco.cms.businesslogic.packager } } - try + var readmeNode = Config.DocumentElement.SelectSingleNode("/umbPackage/info/readme"); + if (readmeNode != null) { - ReadMe = XmlHelper.GetNodeValue(Config.DocumentElement.SelectSingleNode("/umbPackage/info/readme")); + ReadMe = XmlHelper.GetNodeValue(readmeNode); } - catch { } - try + var controlNode = Config.DocumentElement.SelectSingleNode("/umbPackage/control"); + if (controlNode != null) { - Control = XmlHelper.GetNodeValue(Config.DocumentElement.SelectSingleNode("/umbPackage/control")); + Control = XmlHelper.GetNodeValue(controlNode); } - catch { } } /// diff --git a/src/umbraco.cms/businesslogic/Packager/PackageInstance/PackageInstance.cs b/src/umbraco.cms/businesslogic/Packager/PackageInstance/PackageInstance.cs index 39e806133e..ca17abc440 100644 --- a/src/umbraco.cms/businesslogic/Packager/PackageInstance/PackageInstance.cs +++ b/src/umbraco.cms/businesslogic/Packager/PackageInstance/PackageInstance.cs @@ -66,20 +66,23 @@ namespace umbraco.cms.businesslogic.packager public List DataTypes { get; set; } + public string IconUrl { get; set; } + public PackageInstance() { SkinRepoGuid = Guid.Empty; - Name = ""; - Url = ""; - Folder = ""; - PackagePath = ""; - Version = ""; - Author = ""; - AuthorUrl = ""; - License = ""; - LicenseUrl = ""; - Readme = ""; - ContentNodeId = ""; + Name = string.Empty; + Url = string.Empty; + Folder = string.Empty; + PackagePath = string.Empty; + Version = string.Empty; + Author = string.Empty; + AuthorUrl = string.Empty; + License = string.Empty; + LicenseUrl = string.Empty; + Readme = string.Empty; + ContentNodeId = string.Empty; + IconUrl = string.Empty; Macros = new List(); Languages = new List(); DictionaryItems = new List(); @@ -87,7 +90,7 @@ namespace umbraco.cms.businesslogic.packager Documenttypes = new List(); Stylesheets = new List(); Files = new List(); - LoadControl = ""; + LoadControl = string.Empty; DataTypes = new List(); EnableSkins = false; ContentLoadChildNodes = false; diff --git a/src/umbraco.cms/businesslogic/Packager/data.cs b/src/umbraco.cms/businesslogic/Packager/data.cs index 2d153daaa5..e4dead2657 100644 --- a/src/umbraco.cms/businesslogic/Packager/data.cs +++ b/src/umbraco.cms/businesslogic/Packager/data.cs @@ -9,6 +9,9 @@ using Umbraco.Core.Logging; namespace umbraco.cms.businesslogic.packager { + /// + /// This is the xml data for installed packages. This is not the same xml as a pckage format! + /// public class data { private static XmlDocument _source; @@ -39,10 +42,12 @@ namespace umbraco.cms.businesslogic.packager Directory.CreateDirectory(IOHelper.MapPath(Settings.InstalledPackagesStorage)); } - StreamWriter sw = File.CreateText(dataSource); - sw.Write(umbraco.cms.businesslogic.Packager.FileResources.PackageFiles.Packages); - sw.Flush(); - sw.Close(); + using (StreamWriter sw = File.CreateText(dataSource)) + { + sw.Write(umbraco.cms.businesslogic.Packager.FileResources.PackageFiles.Packages); + sw.Flush(); + } + } if (_source == null) @@ -87,73 +92,66 @@ namespace umbraco.cms.businesslogic.packager public static PackageInstance MakeNew(string Name, string dataSource) { - PackageInstance retVal = new PackageInstance(); + Reload(dataSource); - try + int maxId = 1; + // Find max id + foreach (XmlNode n in Source.SelectNodes("packages/package")) { - Reload(dataSource); - - int _maxId = 1; - // Find max id - foreach (XmlNode n in Source.SelectNodes("packages/package")) - { - if (int.Parse(n.Attributes.GetNamedItem("id").Value) >= _maxId) - _maxId = int.Parse(n.Attributes.GetNamedItem("id").Value) + 1; - } - - XmlElement instance = Source.CreateElement("package"); - instance.Attributes.Append(xmlHelper.addAttribute(Source, "id", _maxId.ToString())); - instance.Attributes.Append(xmlHelper.addAttribute(Source, "version", "")); - instance.Attributes.Append(xmlHelper.addAttribute(Source, "url", "")); - instance.Attributes.Append(xmlHelper.addAttribute(Source, "name", Name)); - instance.Attributes.Append(xmlHelper.addAttribute(Source, "folder", System.Guid.NewGuid().ToString())); - instance.Attributes.Append(xmlHelper.addAttribute(Source, "packagepath", "")); - instance.Attributes.Append(xmlHelper.addAttribute(Source, "repositoryGuid", "")); - instance.Attributes.Append(xmlHelper.addAttribute(Source, "packageGuid", System.Guid.NewGuid().ToString())); - instance.Attributes.Append(xmlHelper.addAttribute(Source, "hasUpdate", "false")); - - instance.Attributes.Append(xmlHelper.addAttribute(Source, "enableSkins", "false")); - instance.Attributes.Append(xmlHelper.addAttribute(Source, "skinRepoGuid", "")); - - XmlElement license = Source.CreateElement("license"); - license.InnerText = "MIT License"; - license.Attributes.Append(xmlHelper.addAttribute(Source, "url", "http://opensource.org/licenses/MIT")); - instance.AppendChild(license); - - XmlElement author = Source.CreateElement("author"); - author.InnerText = ""; - author.Attributes.Append(xmlHelper.addAttribute(Source, "url", "")); - instance.AppendChild(author); - - instance.AppendChild(xmlHelper.addTextNode(Source, "readme", "")); - instance.AppendChild(xmlHelper.addTextNode(Source, "actions", "")); - - instance.AppendChild(xmlHelper.addTextNode(Source, "datatypes", "")); - - XmlElement content = Source.CreateElement("content"); - content.InnerText = ""; - content.Attributes.Append(xmlHelper.addAttribute(Source, "nodeId", "")); - content.Attributes.Append(xmlHelper.addAttribute(Source, "loadChildNodes", "false")); - instance.AppendChild(content); - - instance.AppendChild(xmlHelper.addTextNode(Source, "templates", "")); - instance.AppendChild(xmlHelper.addTextNode(Source, "stylesheets", "")); - instance.AppendChild(xmlHelper.addTextNode(Source, "documenttypes", "")); - instance.AppendChild(xmlHelper.addTextNode(Source, "macros", "")); - instance.AppendChild(xmlHelper.addTextNode(Source, "files", "")); - instance.AppendChild(xmlHelper.addTextNode(Source, "languages", "")); - instance.AppendChild(xmlHelper.addTextNode(Source, "dictionaryitems", "")); - instance.AppendChild(xmlHelper.addTextNode(Source, "loadcontrol", "")); - - Source.SelectSingleNode("packages").AppendChild(instance); - Source.Save(dataSource); - retVal = data.Package(_maxId, dataSource); - } - catch (Exception ex) - { - LogHelper.Error("An error occurred", ex); + if (int.Parse(n.Attributes.GetNamedItem("id").Value) >= maxId) + maxId = int.Parse(n.Attributes.GetNamedItem("id").Value) + 1; } + XmlElement instance = Source.CreateElement("package"); + instance.Attributes.Append(XmlHelper.AddAttribute(Source, "id", maxId.ToString())); + instance.Attributes.Append(XmlHelper.AddAttribute(Source, "version", "")); + instance.Attributes.Append(XmlHelper.AddAttribute(Source, "url", "")); + instance.Attributes.Append(XmlHelper.AddAttribute(Source, "name", Name)); + instance.Attributes.Append(XmlHelper.AddAttribute(Source, "folder", Guid.NewGuid().ToString())); + instance.Attributes.Append(XmlHelper.AddAttribute(Source, "packagepath", "")); + instance.Attributes.Append(XmlHelper.AddAttribute(Source, "repositoryGuid", "")); + instance.Attributes.Append(XmlHelper.AddAttribute(Source, "iconUrl", "")); + instance.Attributes.Append(XmlHelper.AddAttribute(Source, "packageGuid", Guid.NewGuid().ToString())); + instance.Attributes.Append(XmlHelper.AddAttribute(Source, "hasUpdate", "false")); + + instance.Attributes.Append(XmlHelper.AddAttribute(Source, "enableSkins", "false")); + instance.Attributes.Append(XmlHelper.AddAttribute(Source, "skinRepoGuid", "")); + + XmlElement license = Source.CreateElement("license"); + license.InnerText = "MIT License"; + license.Attributes.Append(XmlHelper.AddAttribute(Source, "url", "http://opensource.org/licenses/MIT")); + instance.AppendChild(license); + + XmlElement author = Source.CreateElement("author"); + author.InnerText = ""; + author.Attributes.Append(XmlHelper.AddAttribute(Source, "url", "")); + instance.AppendChild(author); + + instance.AppendChild(XmlHelper.AddTextNode(Source, "readme", "")); + instance.AppendChild(XmlHelper.AddTextNode(Source, "actions", "")); + + instance.AppendChild(XmlHelper.AddTextNode(Source, "datatypes", "")); + + XmlElement content = Source.CreateElement("content"); + content.InnerText = ""; + content.Attributes.Append(XmlHelper.AddAttribute(Source, "nodeId", "")); + content.Attributes.Append(XmlHelper.AddAttribute(Source, "loadChildNodes", "false")); + instance.AppendChild(content); + + instance.AppendChild(XmlHelper.AddTextNode(Source, "templates", "")); + instance.AppendChild(XmlHelper.AddTextNode(Source, "stylesheets", "")); + instance.AppendChild(XmlHelper.AddTextNode(Source, "documenttypes", "")); + instance.AppendChild(XmlHelper.AddTextNode(Source, "macros", "")); + instance.AppendChild(XmlHelper.AddTextNode(Source, "files", "")); + instance.AppendChild(XmlHelper.AddTextNode(Source, "languages", "")); + instance.AppendChild(XmlHelper.AddTextNode(Source, "dictionaryitems", "")); + instance.AppendChild(XmlHelper.AddTextNode(Source, "loadcontrol", "")); + + Source.SelectSingleNode("packages").AppendChild(instance); + Source.Save(dataSource); + var retVal = data.Package(maxId, dataSource); + + return retVal; } @@ -162,19 +160,11 @@ namespace umbraco.cms.businesslogic.packager } public static PackageInstance Package(string guid, string datasource) { - try - { - XmlNode node = GetFromGuid(guid, datasource, true); - if (node != null) - return ConvertXmlToPackage(node); - else - return new PackageInstance(); - } - catch (Exception ex) - { - LogHelper.Error("An error occurred", ex); - return new PackageInstance(); - } + XmlNode node = GetFromGuid(guid, datasource, true); + if (node != null) + return ConvertXmlToPackage(node); + else + return new PackageInstance(); } public static List GetAllPackages(string dataSource) { @@ -202,43 +192,45 @@ namespace umbraco.cms.businesslogic.packager PackageInstance retVal = new PackageInstance(); if (n != null) { - retVal.Id = int.Parse(safeAttribute("id",n)); - retVal.Name = safeAttribute("name",n); - retVal.Folder = safeAttribute("folder", n); - retVal.PackagePath = safeAttribute("packagepath", n); - retVal.Version = safeAttribute("version", n); - retVal.Url = safeAttribute("url", n); - retVal.RepositoryGuid = safeAttribute("repositoryGuid", n); - retVal.PackageGuid = safeAttribute("packageGuid", n); - retVal.HasUpdate = bool.Parse(safeAttribute("hasUpdate",n)); + retVal.Id = int.Parse(SafeAttribute("id",n)); + retVal.Name = SafeAttribute("name",n); + retVal.Folder = SafeAttribute("folder", n); + retVal.PackagePath = SafeAttribute("packagepath", n); + retVal.Version = SafeAttribute("version", n); + retVal.Url = SafeAttribute("url", n); + retVal.RepositoryGuid = SafeAttribute("repositoryGuid", n); + retVal.PackageGuid = SafeAttribute("packageGuid", n); + retVal.HasUpdate = bool.Parse(SafeAttribute("hasUpdate",n)); - bool _enableSkins = false; - bool.TryParse(safeAttribute("enableSkins", n), out _enableSkins); - retVal.EnableSkins = _enableSkins; + retVal.IconUrl = SafeAttribute("iconUrl", n); - retVal.SkinRepoGuid = string.IsNullOrEmpty(safeAttribute("skinRepoGuid", n)) ? Guid.Empty : new Guid(safeAttribute("skinRepoGuid", n)); + bool enableSkins = false; + bool.TryParse(SafeAttribute("enableSkins", n), out enableSkins); + retVal.EnableSkins = enableSkins; - retVal.License = safeNodeValue(n.SelectSingleNode("license")); + retVal.SkinRepoGuid = string.IsNullOrEmpty(SafeAttribute("skinRepoGuid", n)) ? Guid.Empty : new Guid(SafeAttribute("skinRepoGuid", n)); + + retVal.License = SafeNodeValue(n.SelectSingleNode("license")); retVal.LicenseUrl = n.SelectSingleNode("license").Attributes.GetNamedItem("url").Value; - retVal.Author = safeNodeValue(n.SelectSingleNode("author")); - retVal.AuthorUrl = safeAttribute("url", n.SelectSingleNode("author")); + retVal.Author = SafeNodeValue(n.SelectSingleNode("author")); + retVal.AuthorUrl = SafeAttribute("url", n.SelectSingleNode("author")); - retVal.Readme = safeNodeValue(n.SelectSingleNode("readme")); - retVal.Actions = safeNodeInnerXml(n.SelectSingleNode("actions")); + retVal.Readme = SafeNodeValue(n.SelectSingleNode("readme")); + retVal.Actions = SafeNodeInnerXml(n.SelectSingleNode("actions")); - retVal.ContentNodeId = safeAttribute("nodeId", n.SelectSingleNode("content")); - retVal.ContentLoadChildNodes = bool.Parse(safeAttribute("loadChildNodes",n.SelectSingleNode("content"))); + retVal.ContentNodeId = SafeAttribute("nodeId", n.SelectSingleNode("content")); + retVal.ContentLoadChildNodes = bool.Parse(SafeAttribute("loadChildNodes",n.SelectSingleNode("content"))); - retVal.Macros = new List(safeNodeValue(n.SelectSingleNode("macros")).Trim(',').Split(',')); - retVal.Macros = new List(safeNodeValue(n.SelectSingleNode("macros")).Trim(',').Split(',')); - retVal.Templates = new List(safeNodeValue(n.SelectSingleNode("templates")).Trim(',').Split(',')); - retVal.Stylesheets = new List(safeNodeValue(n.SelectSingleNode("stylesheets")).Trim(',').Split(',')); - retVal.Documenttypes = new List(safeNodeValue(n.SelectSingleNode("documenttypes")).Trim(',').Split(',')); - retVal.Languages = new List(safeNodeValue(n.SelectSingleNode("languages")).Trim(',').Split(',')); - retVal.DictionaryItems = new List(safeNodeValue(n.SelectSingleNode("dictionaryitems")).Trim(',').Split(',')); - retVal.DataTypes = new List(safeNodeValue(n.SelectSingleNode("datatypes")).Trim(',').Split(',')); + retVal.Macros = new List(SafeNodeValue(n.SelectSingleNode("macros")).Trim(',').Split(',')); + retVal.Macros = new List(SafeNodeValue(n.SelectSingleNode("macros")).Trim(',').Split(',')); + retVal.Templates = new List(SafeNodeValue(n.SelectSingleNode("templates")).Trim(',').Split(',')); + retVal.Stylesheets = new List(SafeNodeValue(n.SelectSingleNode("stylesheets")).Trim(',').Split(',')); + retVal.Documenttypes = new List(SafeNodeValue(n.SelectSingleNode("documenttypes")).Trim(',').Split(',')); + retVal.Languages = new List(SafeNodeValue(n.SelectSingleNode("languages")).Trim(',').Split(',')); + retVal.DictionaryItems = new List(SafeNodeValue(n.SelectSingleNode("dictionaryitems")).Trim(',').Split(',')); + retVal.DataTypes = new List(SafeNodeValue(n.SelectSingleNode("datatypes")).Trim(',').Split(',')); XmlNodeList xmlFiles = n.SelectNodes("files/file"); retVal.Files = new List(); @@ -246,7 +238,7 @@ namespace umbraco.cms.businesslogic.packager for (int i = 0; i < xmlFiles.Count; i++) retVal.Files.Add(xmlFiles[i].InnerText); - retVal.LoadControl = safeNodeValue(n.SelectSingleNode("loadcontrol")); + retVal.LoadControl = SafeNodeValue(n.SelectSingleNode("loadcontrol")); } return retVal; @@ -283,97 +275,104 @@ namespace umbraco.cms.businesslogic.packager public static void Save(PackageInstance package, string dataSource) { - try - { - Reload(dataSource); - XmlNode _xmlDef = GetFromId(package.Id, dataSource, false); - _xmlDef.Attributes.GetNamedItem("name").Value = package.Name; - _xmlDef.Attributes.GetNamedItem("version").Value = package.Version; - _xmlDef.Attributes.GetNamedItem("url").Value = package.Url; - _xmlDef.Attributes.GetNamedItem("packagepath").Value = package.PackagePath; - _xmlDef.Attributes.GetNamedItem("repositoryGuid").Value = package.RepositoryGuid; - _xmlDef.Attributes.GetNamedItem("packageGuid").Value = package.PackageGuid; + Reload(dataSource); + var xmlDef = GetFromId(package.Id, dataSource, false); + XmlHelper.SetAttribute(Source, xmlDef, "name", package.Name); + XmlHelper.SetAttribute(Source, xmlDef, "version",package.Version); + XmlHelper.SetAttribute(Source, xmlDef, "url",package.Url); + XmlHelper.SetAttribute(Source, xmlDef, "packagepath",package.PackagePath); + XmlHelper.SetAttribute(Source, xmlDef, "repositoryGuid",package.RepositoryGuid); + XmlHelper.SetAttribute(Source, xmlDef, "packageGuid",package.PackageGuid); + XmlHelper.SetAttribute(Source, xmlDef, "hasUpdate",package.HasUpdate.ToString()); + XmlHelper.SetAttribute(Source, xmlDef, "enableSkins",package.EnableSkins.ToString()); + XmlHelper.SetAttribute(Source, xmlDef, "skinRepoGuid",package.SkinRepoGuid.ToString()); + XmlHelper.SetAttribute(Source, xmlDef, "iconUrl", package.IconUrl); - _xmlDef.Attributes.GetNamedItem("hasUpdate").Value = package.HasUpdate.ToString(); - _xmlDef.Attributes.GetNamedItem("enableSkins").Value = package.EnableSkins.ToString(); - _xmlDef.Attributes.GetNamedItem("skinRepoGuid").Value = package.SkinRepoGuid.ToString(); + var licenseNode = xmlDef.SelectSingleNode("license"); + if (licenseNode == null) + { + licenseNode = Source.CreateElement("license"); + xmlDef.AppendChild(licenseNode); + } + licenseNode.InnerText = package.License; + XmlHelper.SetAttribute(Source, licenseNode, "url", package.LicenseUrl); - - - _xmlDef.SelectSingleNode("license").FirstChild.Value = package.License; - _xmlDef.SelectSingleNode("license").Attributes.GetNamedItem("url").Value = package.LicenseUrl; - - _xmlDef.SelectSingleNode("author").InnerText = package.Author; - _xmlDef.SelectSingleNode("author").Attributes.GetNamedItem("url").Value = package.AuthorUrl; - - _xmlDef.SelectSingleNode("readme").InnerXml = ""; - - if(_xmlDef.SelectSingleNode("actions") == null) - _xmlDef.AppendChild(xmlHelper.addTextNode(Source, "actions", "")); - - _xmlDef.SelectSingleNode("actions").InnerXml = package.Actions; - - _xmlDef.SelectSingleNode("content").Attributes.GetNamedItem("nodeId").Value = package.ContentNodeId.ToString(); - _xmlDef.SelectSingleNode("content").Attributes.GetNamedItem("loadChildNodes").Value = package.ContentLoadChildNodes.ToString(); - - _xmlDef.SelectSingleNode("macros").InnerText = joinList(package.Macros, ','); - _xmlDef.SelectSingleNode("templates").InnerText = joinList(package.Templates, ','); - _xmlDef.SelectSingleNode("stylesheets").InnerText = joinList(package.Stylesheets, ','); - _xmlDef.SelectSingleNode("documenttypes").InnerText = joinList(package.Documenttypes, ','); - - _xmlDef.SelectSingleNode("languages").InnerText = joinList(package.Languages, ','); - _xmlDef.SelectSingleNode("dictionaryitems").InnerText = joinList(package.DictionaryItems, ','); - _xmlDef.SelectSingleNode("datatypes").InnerText = joinList(package.DataTypes, ','); - - _xmlDef.SelectSingleNode("files").InnerXml = ""; - - foreach (string fileStr in package.Files) { - if(!string.IsNullOrEmpty(fileStr.Trim())) - _xmlDef.SelectSingleNode("files").AppendChild(xmlHelper.addTextNode(data.Source, "file", fileStr)); - } - - _xmlDef.SelectSingleNode("loadcontrol").InnerText = package.LoadControl; - - Source.Save(dataSource); - - + var authorNode = xmlDef.SelectSingleNode("author"); + if (authorNode == null) + { + authorNode = Source.CreateElement("author"); + xmlDef.AppendChild(authorNode); } - catch(Exception F) - { - LogHelper.Error("An error occurred", F); - } - - } + authorNode.InnerText = package.Author; + XmlHelper.SetAttribute(Source, authorNode, "url", package.AuthorUrl); - private static string safeAttribute(string name, XmlNode n) { + XmlHelper.SetCDataNode(Source, xmlDef, "readme", package.Readme); + XmlHelper.SetTextNode(Source, xmlDef, "actions", package.Actions); + + var contentNode = xmlDef.SelectSingleNode("content"); + if (contentNode == null) + { + contentNode = Source.CreateElement("content"); + xmlDef.AppendChild(contentNode); + } + XmlHelper.SetAttribute(Source, contentNode, "nodeId", package.ContentNodeId); + XmlHelper.SetAttribute(Source, contentNode, "loadChildNodes", package.ContentLoadChildNodes.ToString()); + + XmlHelper.SetTextNode(Source, xmlDef, "macros", JoinList(package.Macros, ',')); + XmlHelper.SetTextNode(Source, xmlDef, "templates", JoinList(package.Templates, ',')); + XmlHelper.SetTextNode(Source, xmlDef, "stylesheets", JoinList(package.Stylesheets, ',')); + XmlHelper.SetTextNode(Source, xmlDef, "documenttypes", JoinList(package.Documenttypes, ',')); + XmlHelper.SetTextNode(Source, xmlDef, "languages", JoinList(package.Languages, ',')); + XmlHelper.SetTextNode(Source, xmlDef, "dictionaryitems", JoinList(package.DictionaryItems, ',')); + XmlHelper.SetTextNode(Source, xmlDef, "datatypes", JoinList(package.DataTypes, ',')); + + var filesNode = xmlDef.SelectSingleNode("files"); + if (filesNode == null) + { + filesNode = Source.CreateElement("files"); + xmlDef.AppendChild(filesNode); + } + filesNode.InnerXml = ""; + + foreach (var fileStr in package.Files) + { + if (string.IsNullOrWhiteSpace(fileStr) == false) + filesNode.AppendChild(XmlHelper.AddTextNode(Source, "file", fileStr)); + } + + XmlHelper.SetTextNode(Source, xmlDef, "loadcontrol", package.LoadControl); + + Source.Save(dataSource); + } + + + + private static string SafeAttribute(string name, XmlNode n) + { + return n.Attributes == null || n.Attributes[name] == null ? string.Empty : n.Attributes[name].Value; + } + + private static string SafeNodeValue(XmlNode n) { try { - return n.Attributes.GetNamedItem(name).Value; + return XmlHelper.GetNodeValue(n); } catch { - return ""; + return string.Empty; } } - private static string safeNodeValue(XmlNode n) { - try { - return xmlHelper.GetNodeValue(n); - } catch { - return ""; - } - } - - private static string safeNodeInnerXml(XmlNode n) { + private static string SafeNodeInnerXml(XmlNode n) { try { return n.InnerXml; } catch { - return ""; + return string.Empty; } } - private static string joinList(List list, char seperator) { + private static string JoinList(List list, char seperator) { string retVal = ""; foreach (string str in list) { - retVal += str + seperator.ToString(); + retVal += str + seperator; } return retVal.Trim(seperator);