public UninstallationSummary UninstallPackage(string packageName, int userId = Constants.Security.SuperUserId) { //this is ordered by descending version var allPackageVersions = GetInstalledPackageByName(packageName)?.ToList(); if (allPackageVersions == null || allPackageVersions.Count == 0) { throw new InvalidOperationException("No installed package found by name " + packageName); } var summary = new UninstallationSummary { MetaData = allPackageVersions[0] }; var allSummaries = new List <UninstallationSummary>(); foreach (var packageVersion in allPackageVersions) { var versionUninstallSummary = _packageInstallation.UninstallPackage(packageVersion, userId); allSummaries.Add(versionUninstallSummary); //merge the summary summary.ActionErrors = summary.ActionErrors.Concat(versionUninstallSummary.ActionErrors).Distinct().ToList(); summary.Actions = summary.Actions.Concat(versionUninstallSummary.Actions).Distinct().ToList(); summary.DataTypesUninstalled = summary.DataTypesUninstalled.Concat(versionUninstallSummary.DataTypesUninstalled).Distinct().ToList(); summary.DictionaryItemsUninstalled = summary.DictionaryItemsUninstalled.Concat(versionUninstallSummary.DictionaryItemsUninstalled).Distinct().ToList(); summary.DocumentTypesUninstalled = summary.DocumentTypesUninstalled.Concat(versionUninstallSummary.DocumentTypesUninstalled).Distinct().ToList(); summary.FilesUninstalled = summary.FilesUninstalled.Concat(versionUninstallSummary.FilesUninstalled).Distinct().ToList(); summary.LanguagesUninstalled = summary.LanguagesUninstalled.Concat(versionUninstallSummary.LanguagesUninstalled).Distinct().ToList(); summary.MacrosUninstalled = summary.MacrosUninstalled.Concat(versionUninstallSummary.MacrosUninstalled).Distinct().ToList(); summary.StylesheetsUninstalled = summary.StylesheetsUninstalled.Concat(versionUninstallSummary.StylesheetsUninstalled).Distinct().ToList(); summary.TemplatesUninstalled = summary.TemplatesUninstalled.Concat(versionUninstallSummary.TemplatesUninstalled).Distinct().ToList(); SaveInstalledPackage(packageVersion); DeleteInstalledPackage(packageVersion.Id, userId); } // trigger the UninstalledPackage event UninstalledPackage.RaiseEvent(new UninstallPackageEventArgs(allSummaries, false), this); return(summary); }
/// <summary> /// SORRY :( I didn't have time to put this in a service somewhere - the old packager did this all manually too /// </summary> /// <param name="pack"></param> protected void PerformUninstall(InstalledPackage pack) { if (pack == null) { throw new ArgumentNullException("pack"); } var refreshCache = false; var removedTemplates = new List <ITemplate>(); var removedMacros = new List <IMacro>(); var removedContentTypes = new List <IContentType>(); var removedDictionaryItems = new List <IDictionaryItem>(); var removedDataTypes = new List <IDataTypeDefinition>(); var removedFiles = new List <string>(); //Uninstall templates foreach (var item in pack.Data.Templates.ToArray()) { int nId; if (int.TryParse(item, out nId) == false) { continue; } var found = Services.FileService.GetTemplate(nId); if (found != null) { removedTemplates.Add(found); ApplicationContext.Services.FileService.DeleteTemplate(found.Alias, Security.GetUserId()); } pack.Data.Templates.Remove(nId.ToString()); } //Uninstall macros foreach (var item in pack.Data.Macros.ToArray()) { int nId; if (int.TryParse(item, out nId) == false) { continue; } var macro = Services.MacroService.GetById(nId); if (macro != null) { removedMacros.Add(macro); Services.MacroService.Delete(macro); } pack.Data.Macros.Remove(nId.ToString()); } //Remove Document Types var contentTypes = new List <IContentType>(); var contentTypeService = Services.ContentTypeService; foreach (var item in pack.Data.Documenttypes.ToArray()) { int nId; if (int.TryParse(item, out nId) == false) { continue; } var contentType = contentTypeService.GetContentType(nId); if (contentType == null) { continue; } contentTypes.Add(contentType); pack.Data.Documenttypes.Remove(nId.ToString(CultureInfo.InvariantCulture)); // refresh content cache when document types are removed refreshCache = true; } //Order the DocumentTypes before removing them if (contentTypes.Any()) { //TODO: I don't think this ordering is necessary var orderedTypes = from contentType in contentTypes orderby contentType.ParentId descending, contentType.Id descending select contentType; removedContentTypes.AddRange(orderedTypes); contentTypeService.Delete(orderedTypes); } //Remove Dictionary items foreach (var item in pack.Data.DictionaryItems.ToArray()) { int nId; if (int.TryParse(item, out nId) == false) { continue; } var di = Services.LocalizationService.GetDictionaryItemById(nId); if (di != null) { removedDictionaryItems.Add(di); Services.LocalizationService.Delete(di); } pack.Data.DictionaryItems.Remove(nId.ToString()); } //Remove Data types foreach (var item in pack.Data.DataTypes.ToArray()) { int nId; if (int.TryParse(item, out nId) == false) { continue; } var dtd = Services.DataTypeService.GetDataTypeDefinitionById(nId); if (dtd != null) { removedDataTypes.Add(dtd); Services.DataTypeService.Delete(dtd); } pack.Data.DataTypes.Remove(nId.ToString()); } pack.Save(); // uninstall actions //TODO: We should probably report errors to the UI!! // This never happened before though, but we should do something now if (pack.Data.Actions.IsNullOrWhiteSpace() == false) { try { var actionsXml = new XmlDocument(); actionsXml.LoadXml("<Actions>" + pack.Data.Actions + "</Actions>"); LogHelper.Debug <PackageInstallController>("executing undo actions: {0}", () => actionsXml.OuterXml); foreach (XmlNode n in actionsXml.DocumentElement.SelectNodes("//Action")) { try { global::umbraco.cms.businesslogic.packager.PackageAction .UndoPackageAction(pack.Data.Name, n.Attributes["alias"].Value, n); } catch (Exception ex) { LogHelper.Error <PackageInstallController>("An error occurred running undo actions", ex); } } } catch (Exception ex) { LogHelper.Error <PackageInstallController>("An error occurred running undo actions", ex); } } //moved remove of files here so custom package actions can still undo //Remove files foreach (var item in pack.Data.Files.ToArray()) { removedFiles.Add(item.GetRelativePath()); //here we need to try to find the file in question as most packages does not support the tilde char var file = IOHelper.FindFile(item); if (file != null) { if (file.StartsWith("/") == false) { file = string.Format("/{0}", file); } var filePath = IOHelper.MapPath(file); if (File.Exists(filePath)) { File.Delete(filePath); } } pack.Data.Files.Remove(file); } pack.Save(); pack.Delete(Security.GetUserId()); // create a summary of what was actually removed, for PackagingService.UninstalledPackage var summary = new UninstallationSummary { MetaData = pack.GetMetaData(), TemplatesUninstalled = removedTemplates, MacrosUninstalled = removedMacros, ContentTypesUninstalled = removedContentTypes, DictionaryItemsUninstalled = removedDictionaryItems, DataTypesUninstalled = removedDataTypes, FilesUninstalled = removedFiles, PackageUninstalled = true }; // trigger the UninstalledPackage event PackagingService.OnUninstalledPackage(new UninstallPackageEventArgs <UninstallationSummary>(summary, false)); //TODO: Legacy - probably not needed if (refreshCache) { library.RefreshContent(); } TreeDefinitionCollection.Instance.ReRegisterTrees(); global::umbraco.BusinessLogic.Actions.Action.ReRegisterActionsAndHandlers(); }