From 0151c435f162b3cdbbc2a95a16f225df619a2caa Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Wed, 16 Dec 2020 22:26:47 +0100 Subject: [PATCH] Netcore: Package support for media + media types (#9547) * Add support for media when installing a package * clean up * Fix tests * Add support for media when installing a package * clean up * Fix tests * moved tests + test data * Migrated package tests + resources * Fix issue with media picker on package page, was empty after save. * Added missing files * Fix casing issue of resources * Added test for media * Fix tests for linux * Fix test * Fix issue with move media.. * Fix issue with adding files to packages * Add MediaType permissions. * Fix test * Fix test * Retry flaky tests, and added TODOs to fix those * new attempt to fix test Co-authored-by: Mole --- .../.template.config/template.json | 2 +- .../Constants-SystemDirectories.cs | 2 +- .../Models/Packaging/CompiledPackage.cs | 5 +- ...ument.cs => CompiledPackageContentBase.cs} | 16 +- .../Packaging/CompiledPackageXmlParser.cs | 5 +- .../Packaging/InstallationSummary.cs | 4 +- .../Packaging/PackageDefinition.cs | 10 +- .../Packaging/PackageDefinitionXmlParser.cs | 11 +- .../Packaging/PackagesRepository.cs | 63 ++- src/Umbraco.Core/Services/IContentService.cs | 3 +- .../Services/IContentServiceBase.cs | 11 +- .../Services/IContentTypeServiceBase.cs | 1 - src/Umbraco.Core/Services/IMediaService.cs | 3 +- .../CompositionExtensions/Services.cs | 7 +- .../Packaging/PackageDataInstallation.cs | 296 ++++++++++---- .../Runtime/CoreInitialComposer.cs | 3 + .../Services/Implement/ContentService.cs | 11 +- .../Services/Implement/EntityXmlSerializer.cs | 8 +- .../Services/Implement/MediaService.cs | 6 +- .../Packages/Document_Type_Picker_1.1.umb | Bin .../Packages/Document_Type_Picker_1.1.zip | Bin .../TestData}/Packages/Hello_1.0.0.zip | Bin .../CreatedPackagesRepositoryTests.cs | 10 +- .../Packaging/PackageDataInstallationTests.cs | 138 ++++--- .../Packaging/PackageInstallationTest.cs | 81 +--- .../Services/EntityXmlSerializerTests.cs | 2 +- .../CheckboxList-Content-Package.xml | 0 .../CompositionsTestPackage-Random.xml | 0 .../Importing/CompositionsTestPackage.xml | 0 .../Services/Importing/Fanoe-Package.xml | 0 .../Importing/ImportResources.Designer.cs | 324 ++++++++++++++- .../Services/Importing/ImportResources.resx | 90 ++-- .../Importing/InheritedDocTypes-Package.xml | 0 .../Importing/MediaTypesAndMedia-Package.xml | 158 ++++++++ .../Services/Importing/SingleDocType.xml | 0 .../Importing/StandardMvc-Package.xml | 0 .../Importing/TemplateOnly-Package.xml | 0 .../TemplateOnly-Updated-Package.xml | 0 .../Services/Importing/XsltSearch-Package.xml | 0 .../Services/Importing/uBlogsy-Package.xml | 0 .../Umbraco.Tests.Integration.csproj | 41 +- .../SnapDictionaryTests.cs | 4 + .../LegacyXmlPublishedCache/XmlStore.cs | 5 +- .../Packages/Document_Type_Picker_1.1.umb | Bin 6147 -> 0 bytes .../Importing/ImportResources.Designer.cs | 383 ------------------ .../Services/Importing/ImportResources.resx | 157 ------- src/Umbraco.Tests/Umbraco.Tests.csproj | 28 -- .../Controllers/ContentTypeController.cs | 50 +-- .../Controllers/MediaController.cs | 2 +- .../Controllers/PackageController.cs | 4 +- .../AspNetCoreUmbracoApplicationLifetime.cs | 11 - .../src/views/packages/edit.controller.js | 99 +++-- .../src/views/packages/edit.html | 27 +- .../Umbraco.Web.UI.NetCore.csproj | 1 + .../umbraco/config/lang/en_us.xml | 1 + 55 files changed, 1130 insertions(+), 953 deletions(-) rename src/Umbraco.Core/Models/Packaging/{CompiledPackageDocument.cs => CompiledPackageContentBase.cs} (52%) rename src/Umbraco.Tests.Integration/{Umbraco.Core/Packaging => TestData}/Packages/Document_Type_Picker_1.1.umb (100%) rename src/{Umbraco.Tests/Packaging => Umbraco.Tests.Integration/TestData}/Packages/Document_Type_Picker_1.1.zip (100%) rename src/{Umbraco.Tests/Packaging => Umbraco.Tests.Integration/TestData}/Packages/Hello_1.0.0.zip (100%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration/Umbraco.Core}/Packaging/PackageDataInstallationTests.cs (87%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration/Umbraco.Core}/Packaging/PackageInstallationTest.cs (58%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration/Umbraco.Infrastructure}/Services/Importing/CheckboxList-Content-Package.xml (100%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration/Umbraco.Infrastructure}/Services/Importing/CompositionsTestPackage-Random.xml (100%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration/Umbraco.Infrastructure}/Services/Importing/CompositionsTestPackage.xml (100%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration/Umbraco.Infrastructure}/Services/Importing/Fanoe-Package.xml (100%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration/Umbraco.Infrastructure}/Services/Importing/InheritedDocTypes-Package.xml (100%) create mode 100644 src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/MediaTypesAndMedia-Package.xml rename src/{Umbraco.Tests => Umbraco.Tests.Integration/Umbraco.Infrastructure}/Services/Importing/SingleDocType.xml (100%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration/Umbraco.Infrastructure}/Services/Importing/StandardMvc-Package.xml (100%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration/Umbraco.Infrastructure}/Services/Importing/TemplateOnly-Package.xml (100%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration/Umbraco.Infrastructure}/Services/Importing/TemplateOnly-Updated-Package.xml (100%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration/Umbraco.Infrastructure}/Services/Importing/XsltSearch-Package.xml (100%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration/Umbraco.Infrastructure}/Services/Importing/uBlogsy-Package.xml (100%) delete mode 100644 src/Umbraco.Tests/Packaging/Packages/Document_Type_Picker_1.1.umb delete mode 100644 src/Umbraco.Tests/Services/Importing/ImportResources.Designer.cs delete mode 100644 src/Umbraco.Tests/Services/Importing/ImportResources.resx diff --git a/build/templates/UmbracoSolution/.template.config/template.json b/build/templates/UmbracoSolution/.template.config/template.json index 04f77a556e..26d2358639 100644 --- a/build/templates/UmbracoSolution/.template.config/template.json +++ b/build/templates/UmbracoSolution/.template.config/template.json @@ -15,7 +15,7 @@ "version": { "type": "parameter", "datatype": "string", - "defaultValue": "0.5.0-alpha003", + "defaultValue": "0.5.0-alpha*", "description": "The version of Umbraco to load using NuGet", "replaces": "UMBRACO_VERSION_FROM_TEMPLATE" }, diff --git a/src/Umbraco.Core/Constants-SystemDirectories.cs b/src/Umbraco.Core/Constants-SystemDirectories.cs index 6145f4190b..464896edd9 100644 --- a/src/Umbraco.Core/Constants-SystemDirectories.cs +++ b/src/Umbraco.Core/Constants-SystemDirectories.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core /// /// This is not the same as the Umbraco web folder which is configurable for serving front-end files. /// - public const string Umbraco = "~/Umbraco"; + public const string Umbraco = "~/umbraco"; /// /// The Umbraco data folder in the content root diff --git a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs index be514eaf44..cf48d6ac53 100644 --- a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs +++ b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Xml.Linq; namespace Umbraco.Core.Models.Packaging @@ -40,6 +39,8 @@ namespace Umbraco.Core.Models.Packaging public IEnumerable Languages { get; set; } // TODO: make strongly typed public IEnumerable DictionaryItems { get; set; } // TODO: make strongly typed public IEnumerable DocumentTypes { get; set; } // TODO: make strongly typed - public IEnumerable Documents { get; set; } + public IEnumerable MediaTypes { get; set; } // TODO: make strongly typed + public IEnumerable Documents { get; set; } + public IEnumerable Media { get; set; } } } diff --git a/src/Umbraco.Core/Models/Packaging/CompiledPackageDocument.cs b/src/Umbraco.Core/Models/Packaging/CompiledPackageContentBase.cs similarity index 52% rename from src/Umbraco.Core/Models/Packaging/CompiledPackageDocument.cs rename to src/Umbraco.Core/Models/Packaging/CompiledPackageContentBase.cs index c41966dfe1..7b668796a4 100644 --- a/src/Umbraco.Core/Models/Packaging/CompiledPackageDocument.cs +++ b/src/Umbraco.Core/Models/Packaging/CompiledPackageContentBase.cs @@ -1,20 +1,18 @@ -using System; using System.Xml.Linq; namespace Umbraco.Core.Models.Packaging { - public class CompiledPackageDocument + /// + /// Compiled representation of a content base (Document or Media) + /// + public class CompiledPackageContentBase { - public static CompiledPackageDocument Create(XElement xml) - { - if (xml.Name.LocalName != "DocumentSet") - throw new ArgumentException("The xml isn't formatted correctly, a document element is defined by ", nameof(xml)); - return new CompiledPackageDocument + public static CompiledPackageContentBase Create(XElement xml) => + new CompiledPackageContentBase { XmlData = xml, ImportMode = xml.AttributeValue("importMode") }; - } public string ImportMode { get; set; } //this is never used @@ -23,4 +21,4 @@ namespace Umbraco.Core.Models.Packaging /// public XElement XmlData { get; set; } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs index b4cd2bd03f..be3f38cb22 100644 --- a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs +++ b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs @@ -6,7 +6,6 @@ using System.Xml.Linq; using Microsoft.Extensions.Options; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.Packaging; -using File = System.IO.File; namespace Umbraco.Core.Packaging { @@ -64,7 +63,9 @@ namespace Umbraco.Core.Packaging Languages = xml.Root.Element("Languages")?.Elements("Language") ?? Enumerable.Empty(), DictionaryItems = xml.Root.Element("DictionaryItems")?.Elements("DictionaryItem") ?? Enumerable.Empty(), DocumentTypes = xml.Root.Element("DocumentTypes")?.Elements("DocumentType") ?? Enumerable.Empty(), - Documents = xml.Root.Element("Documents")?.Elements("DocumentSet")?.Select(CompiledPackageDocument.Create) ?? Enumerable.Empty(), + MediaTypes = xml.Root.Element("MediaTypes")?.Elements("MediaType") ?? Enumerable.Empty(), + Documents = xml.Root.Element("Documents")?.Elements("DocumentSet")?.Select(CompiledPackageContentBase.Create) ?? Enumerable.Empty(), + Media = xml.Root.Element("MediaItems")?.Elements()?.Select(CompiledPackageContentBase.Create) ?? Enumerable.Empty(), }; def.Warnings = GetPreInstallWarnings(def, applicationRootFolder); diff --git a/src/Umbraco.Core/Packaging/InstallationSummary.cs b/src/Umbraco.Core/Packaging/InstallationSummary.cs index 1cab17e220..abeaa82bc1 100644 --- a/src/Umbraco.Core/Packaging/InstallationSummary.cs +++ b/src/Umbraco.Core/Packaging/InstallationSummary.cs @@ -17,11 +17,13 @@ namespace Umbraco.Core.Models.Packaging public IEnumerable FilesInstalled { get; set; } = Enumerable.Empty(); public IEnumerable TemplatesInstalled { get; set; } = Enumerable.Empty(); public IEnumerable DocumentTypesInstalled { get; set; } = Enumerable.Empty(); + public IEnumerable MediaTypesInstalled { get; set; } = Enumerable.Empty(); public IEnumerable StylesheetsInstalled { get; set; } = Enumerable.Empty(); public IEnumerable ContentInstalled { get; set; } = Enumerable.Empty(); + public IEnumerable MediaInstalled { get; set; } = Enumerable.Empty(); public IEnumerable Actions { get; set; } = Enumerable.Empty(); public IEnumerable ActionErrors { get; set; } = Enumerable.Empty(); - + } } diff --git a/src/Umbraco.Core/Packaging/PackageDefinition.cs b/src/Umbraco.Core/Packaging/PackageDefinition.cs index 29a1919a2b..379b400e75 100644 --- a/src/Umbraco.Core/Packaging/PackageDefinition.cs +++ b/src/Umbraco.Core/Packaging/PackageDefinition.cs @@ -4,7 +4,6 @@ using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Runtime.Serialization; -using Umbraco.Core.Composing; namespace Umbraco.Core.Models.Packaging { @@ -114,6 +113,9 @@ namespace Umbraco.Core.Models.Packaging [DataMember(Name = "documentTypes")] public IList DocumentTypes { get; set; } = new List(); + [DataMember(Name = "mediaTypes")] + public IList MediaTypes { get; set; } = new List(); + [DataMember(Name = "stylesheets")] public IList Stylesheets { get; set; } = new List(); @@ -133,6 +135,12 @@ namespace Umbraco.Core.Models.Packaging [DataMember(Name = "iconUrl")] public string IconUrl { get; set; } = string.Empty; + [DataMember(Name = "mediaUdis")] + public IList MediaUdis { get; set; } = Array.Empty(); + + [DataMember(Name = "mediaLoadChildNodes")] + public bool MediaLoadChildNodes { get; set; } + } diff --git a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs index a9516d7e25..d194b0ea56 100644 --- a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs +++ b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs @@ -46,10 +46,13 @@ namespace Umbraco.Core.Packaging Actions = xml.Element("actions")?.ToString(SaveOptions.None) ?? "", //take the entire outer xml value ContentNodeId = xml.Element("content")?.AttributeValue("nodeId") ?? string.Empty, ContentLoadChildNodes = xml.Element("content")?.AttributeValue("loadChildNodes") ?? false, + MediaUdis = xml.Element("media")?.Elements("nodeUdi").Select(x => (GuidUdi)UdiParser.Parse(x.Value)).ToList() ?? new List(), + MediaLoadChildNodes = xml.Element("media")?.AttributeValue("loadChildNodes") ?? false, Macros = xml.Element("macros")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), Templates = xml.Element("templates")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), Stylesheets = xml.Element("stylesheets")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), DocumentTypes = xml.Element("documentTypes")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), + MediaTypes = xml.Element("mediaTypes")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), Languages = xml.Element("languages")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), DictionaryItems = xml.Element("dictionaryitems")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), DataTypes = xml.Element("datatypes")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), @@ -103,11 +106,17 @@ namespace Umbraco.Core.Packaging new XElement("templates", string.Join(",", def.Templates ?? Array.Empty())), new XElement("stylesheets", string.Join(",", def.Stylesheets ?? Array.Empty())), new XElement("documentTypes", string.Join(",", def.DocumentTypes ?? Array.Empty())), + new XElement("mediaTypes", string.Join(",", def.MediaTypes ?? Array.Empty())), new XElement("macros", string.Join(",", def.Macros ?? Array.Empty())), new XElement("files", (def.Files ?? Array.Empty()).Where(x => !x.IsNullOrWhiteSpace()).Select(x => new XElement("file", x))), new XElement("languages", string.Join(",", def.Languages ?? Array.Empty())), - new XElement("dictionaryitems", string.Join(",", def.DictionaryItems ?? Array.Empty()))); + new XElement("dictionaryitems", string.Join(",", def.DictionaryItems ?? Array.Empty())), + new XElement( + "media", + def.MediaUdis.Select(x=> (object)new XElement("nodeUdi", x)) + .Union(new []{new XAttribute("loadChildNodes", def.MediaLoadChildNodes) })) + ); return packageXml; } diff --git a/src/Umbraco.Core/Packaging/PackagesRepository.cs b/src/Umbraco.Core/Packaging/PackagesRepository.cs index 59741ab1ce..b89448d891 100644 --- a/src/Umbraco.Core/Packaging/PackagesRepository.cs +++ b/src/Umbraco.Core/Packaging/PackagesRepository.cs @@ -5,8 +5,8 @@ using System.IO; using System.IO.Compression; using System.Linq; using System.Xml.Linq; -using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; @@ -38,6 +38,8 @@ namespace Umbraco.Core.Packaging private readonly string _tempFolderPath; private readonly PackageDefinitionXmlParser _parser; private readonly IUmbracoVersion _umbracoVersion; + private readonly IMediaService _mediaService; + private readonly IMediaTypeService _mediaTypeService; /// /// Constructor @@ -65,6 +67,8 @@ namespace Umbraco.Core.Packaging ILoggerFactory loggerFactory, IUmbracoVersion umbracoVersion, IOptions globalSettings, + IMediaService mediaService, + IMediaTypeService mediaTypeService, string packageRepositoryFileName, string tempFolderPath = null, string packagesFolderPath = null, string mediaFolderPath = null) { @@ -87,6 +91,8 @@ namespace Umbraco.Core.Packaging _parser = new PackageDefinitionXmlParser(_loggerFactory.CreateLogger(), umbracoVersion); _umbracoVersion = umbracoVersion; + _mediaService = mediaService; + _mediaTypeService = mediaTypeService; } private string CreatedPackagesFile => _packagesFolderPath.EnsureEndsWith('/') + _packageRepositoryFileName; @@ -181,12 +187,15 @@ namespace Umbraco.Core.Packaging PackageDocumentsAndTags(definition, root); PackageDocumentTypes(definition, root); + PackageMediaTypes(definition, root); PackageTemplates(definition, root); PackageStylesheets(definition, root); PackageMacros(definition, root, filesXml, temporaryPath); PackageDictionaryItems(definition, root); PackageLanguages(definition, root); PackageDataTypes(definition, root); + PackageMedia(definition, root); + // TODO: This needs to be split into content vs web files, for now we are going to // assume all files are web (www) files. But this is a larger discussion/change since @@ -194,13 +203,13 @@ namespace Umbraco.Core.Packaging //Files foreach (var fileName in definition.Files) - AppendFileToPackage(fileName, temporaryPath, filesXml, true); + AppendFileToPackage(fileName, temporaryPath, filesXml); //Load view on install... if (!string.IsNullOrEmpty(definition.PackageView)) { var control = new XElement("view", definition.PackageView); - AppendFileToPackage(definition.PackageView, temporaryPath, filesXml, true); + AppendFileToPackage(definition.PackageView, temporaryPath, filesXml); root.Add(control); } @@ -310,7 +319,7 @@ namespace Umbraco.Core.Packaging macros.Add(macroXml); //if the macro has a file copy it to the xml if (!string.IsNullOrEmpty(macro.MacroSource)) - AppendFileToPackage(macro.MacroSource, temporaryPath, filesXml, false); + AppendFileToPackage(macro.MacroSource, temporaryPath, filesXml); } root.Add(macros); } @@ -358,6 +367,23 @@ namespace Umbraco.Core.Packaging root.Add(docTypesXml); } + private void PackageMediaTypes(PackageDefinition definition, XContainer root) + { + var mediaTypes = new HashSet(); + var mediaTypesXml = new XElement("MediaTypes"); + foreach (var mediaTypeId in definition.MediaTypes) + { + if (!int.TryParse(mediaTypeId, out var outInt)) continue; + var mediaType = _mediaTypeService.Get(outInt); + if (mediaType == null) continue; + AddMediaType(mediaType, mediaTypes); + } + foreach (var mediaType in mediaTypes) + mediaTypesXml.Add(_serializer.Serialize(mediaType)); + + root.Add(mediaTypesXml); + } + private void PackageDocumentsAndTags(PackageDefinition definition, XContainer root) { //Documents and tags @@ -442,6 +468,18 @@ namespace Umbraco.Core.Packaging } } + + private void PackageMedia(PackageDefinition definition, XElement root) + { + IEnumerable medias = _mediaService.GetByIds(definition.MediaUdis); + + root.Add( + new XElement( + "MediaItems", + medias.Select(x => new XElement("MediaSet", _serializer.Serialize(x, definition.MediaLoadChildNodes))))); + } + + /// /// Zips the package. /// @@ -461,12 +499,12 @@ namespace Umbraco.Core.Packaging /// The package directory. /// The files xml node /// true if it's a web file, false if it's a content file - private void AppendFileToPackage(string path, string packageDirectory, XContainer filesXml, bool isWebFile) + private void AppendFileToPackage(string path, string packageDirectory, XContainer filesXml) { if (!path.StartsWith("~/") && !path.StartsWith("/")) path = "~/" + path; - var serverPath = isWebFile ? _hostingEnvironment.MapPathWebRoot(path) : _hostingEnvironment.MapPathContentRoot(path); + var serverPath = _hostingEnvironment.MapPathContentRoot(path); if (File.Exists(serverPath)) AppendFileXml(new FileInfo(serverPath), path, packageDirectory, filesXml); @@ -562,6 +600,19 @@ namespace Umbraco.Core.Packaging dtl.Add(dt); } + private void AddMediaType(IMediaType mediaType, HashSet mediaTypes) + { + if (mediaType.ParentId > 0) + { + var parent = _mediaTypeService.Get(mediaType.ParentId); + if (parent != null) // could be a container + AddMediaType(parent, mediaTypes); + } + + if (!mediaTypes.Contains(mediaType)) + mediaTypes.Add(mediaType); + } + private static XElement GetPackageInfoXml(PackageDefinition definition, IUmbracoVersion umbracoVersion) { diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs index 25428f420b..61504b0a98 100644 --- a/src/Umbraco.Core/Services/IContentService.cs +++ b/src/Umbraco.Core/Services/IContentService.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence.Querying; @@ -10,7 +9,7 @@ namespace Umbraco.Core.Services /// /// Defines the ContentService, which is an easy access to operations involving /// - public interface IContentService : IContentServiceBase + public interface IContentService : IContentServiceBase { #region Blueprints diff --git a/src/Umbraco.Core/Services/IContentServiceBase.cs b/src/Umbraco.Core/Services/IContentServiceBase.cs index c40f49347f..ca87382494 100644 --- a/src/Umbraco.Core/Services/IContentServiceBase.cs +++ b/src/Umbraco.Core/Services/IContentServiceBase.cs @@ -1,7 +1,16 @@ -using Umbraco.Core.Models; +using System; +using System.Collections.Generic; +using Umbraco.Core.Models; namespace Umbraco.Core.Services { + public interface IContentServiceBase : IContentServiceBase + where TItem: class, IContentBase + { + TItem GetById(Guid key); + Attempt Save(IEnumerable contents, int userId = Constants.Security.SuperUserId, bool raiseEvents = true); + } + /// /// Placeholder for sharing logic between the content, media (and member) services /// TODO: Start sharing the logic! diff --git a/src/Umbraco.Core/Services/IContentTypeServiceBase.cs b/src/Umbraco.Core/Services/IContentTypeServiceBase.cs index 4c818aa87c..3c91091f8c 100644 --- a/src/Umbraco.Core/Services/IContentTypeServiceBase.cs +++ b/src/Umbraco.Core/Services/IContentTypeServiceBase.cs @@ -58,7 +58,6 @@ namespace Umbraco.Core.Services void Save(TItem item, int userId = Constants.Security.SuperUserId); void Save(IEnumerable items, int userId = Constants.Security.SuperUserId); - void Delete(TItem item, int userId = Constants.Security.SuperUserId); void Delete(IEnumerable item, int userId = Constants.Security.SuperUserId); diff --git a/src/Umbraco.Core/Services/IMediaService.cs b/src/Umbraco.Core/Services/IMediaService.cs index c1537adbc8..aa6363cc36 100644 --- a/src/Umbraco.Core/Services/IMediaService.cs +++ b/src/Umbraco.Core/Services/IMediaService.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.IO; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Querying; @@ -10,7 +9,7 @@ namespace Umbraco.Core.Services /// /// Defines the Media Service, which is an easy access to operations involving /// - public interface IMediaService : IContentServiceBase + public interface IMediaService : IContentServiceBase { int CountNotTrashed(string contentTypeAlias = null); int Count(string mediaTypeAlias = null); diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs index 696f846d13..b027a99c67 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs +++ b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs @@ -2,15 +2,14 @@ using System.IO; using System.Linq; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; -using Umbraco.Core.DependencyInjection; +using Microsoft.Extensions.Options; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Events; using Umbraco.Core.Hosting; -using Umbraco.Core.IO; using Umbraco.Core.Packaging; using Umbraco.Core.Routing; using Umbraco.Core.Services; @@ -99,6 +98,8 @@ namespace Umbraco.Core.Composing.CompositionExtensions factory.GetRequiredService(), factory.GetRequiredService(), factory.GetRequiredService>(), + factory.GetRequiredService(), + factory.GetRequiredService(), packageRepoFileName); private static LocalizedTextServiceFileSources SourcesFactory(IServiceProvider container) diff --git a/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs b/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs index 0b9572cb20..f4c3326769 100644 --- a/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs +++ b/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs @@ -34,15 +34,32 @@ namespace Umbraco.Core.Packaging private readonly GlobalSettings _globalSettings; private readonly ILocalizedTextService _localizedTextService; private readonly IConfigurationEditorJsonSerializer _serializer; + private readonly IMediaService _mediaService; + private readonly IMediaTypeService _mediaTypeService; private readonly IJsonSerializer _jsonSerializer; private readonly IEntityService _entityService; private readonly IContentTypeService _contentTypeService; private readonly IContentService _contentService; - public PackageDataInstallation(ILogger logger, ILoggerFactory loggerFactory, IFileService fileService, IMacroService macroService, ILocalizationService localizationService, - IDataTypeService dataTypeService, IEntityService entityService, IContentTypeService contentTypeService, - IContentService contentService, PropertyEditorCollection propertyEditors, IScopeProvider scopeProvider, IShortStringHelper shortStringHelper, IOptions globalSettings, - ILocalizedTextService localizedTextService, IConfigurationEditorJsonSerializer serializer, IJsonSerializer jsonSerializer) + public PackageDataInstallation( + ILogger logger, + ILoggerFactory loggerFactory, + IFileService fileService, + IMacroService macroService, + ILocalizationService localizationService, + IDataTypeService dataTypeService, + IEntityService entityService, + IContentTypeService contentTypeService, + IContentService contentService, + PropertyEditorCollection propertyEditors, + IScopeProvider scopeProvider, + IShortStringHelper shortStringHelper, + IOptions globalSettings, + ILocalizedTextService localizedTextService, + IConfigurationEditorJsonSerializer serializer, + IMediaService mediaService, + IMediaTypeService mediaTypeService, + IJsonSerializer jsonSerializer) { _logger = logger; _loggerFactory = loggerFactory; @@ -57,6 +74,8 @@ namespace Umbraco.Core.Packaging _localizedTextService = localizedTextService; _serializer = serializer; _jsonSerializer = jsonSerializer; + _mediaService = mediaService; + _mediaTypeService = mediaTypeService; _entityService = entityService; _contentTypeService = contentTypeService; _contentService = contentService; @@ -197,29 +216,58 @@ namespace Umbraco.Core.Packaging DictionaryItemsInstalled = ImportDictionaryItems(compiledPackage.DictionaryItems, userId), MacrosInstalled = ImportMacros(compiledPackage.Macros, userId), TemplatesInstalled = ImportTemplates(compiledPackage.Templates.ToList(), userId), - DocumentTypesInstalled = ImportDocumentTypes(compiledPackage.DocumentTypes, userId) + DocumentTypesInstalled = ImportDocumentTypes(compiledPackage.DocumentTypes, userId), + MediaTypesInstalled = ImportMediaTypes(compiledPackage.MediaTypes, userId), }; //we need a reference to the imported doc types to continue var importedDocTypes = installationSummary.DocumentTypesInstalled.ToDictionary(x => x.Alias, x => x); + var importedMediaTypes = installationSummary.MediaTypesInstalled.ToDictionary(x => x.Alias, x => x); installationSummary.StylesheetsInstalled = ImportStylesheets(compiledPackage.Stylesheets, userId); - installationSummary.ContentInstalled = ImportContent(compiledPackage.Documents, importedDocTypes, userId); + installationSummary.ContentInstalled = ImportContentBase(compiledPackage.Documents, importedDocTypes, userId, _contentTypeService, _contentService); + installationSummary.MediaInstalled = ImportContentBase(compiledPackage.Media, importedMediaTypes, userId, _mediaTypeService, _mediaService); scope.Complete(); return installationSummary; } } + /// + /// Imports and saves package xml as + /// + /// Xml to import + /// Optional id of the User performing the operation. Default is zero (admin). + /// An enumerable list of generated ContentTypes + public IReadOnlyList ImportMediaTypes(IEnumerable docTypeElements, int userId) + { + return ImportDocumentTypes(docTypeElements.ToList(), true, userId, _mediaTypeService); + } + + #endregion + #region Content - public IReadOnlyList ImportContent(IEnumerable docs, IDictionary importedDocumentTypes, int userId) + public IReadOnlyList ImportContentBase( + IEnumerable docs, + IDictionary importedDocumentTypes, + int userId, + IContentTypeBaseService typeService, + IContentServiceBase service) + where T: class, IContentBase + where S: IContentTypeComposition { - return docs.SelectMany(x => ImportContent(x, -1, importedDocumentTypes, userId)).ToList(); + return docs.SelectMany(x => ImportContentBase( + x.XmlData.Elements().Where(doc => (string)doc.Attribute("isDoc") == string.Empty), + -1, + importedDocumentTypes, + userId, + typeService, + service)).ToList(); } /// @@ -230,17 +278,20 @@ namespace Umbraco.Core.Packaging /// A dictionary of already imported document types (basically used as a cache) /// Optional Id of the user performing the import /// An enumerable list of generated content - public IEnumerable ImportContent(CompiledPackageDocument packageDocument, int parentId, IDictionary importedDocumentTypes, int userId) + public IEnumerable ImportContentBase( + IEnumerable roots, + int parentId, + IDictionary importedDocumentTypes, + int userId, + IContentTypeBaseService typeService, + IContentServiceBase service) + where T: class, IContentBase + where S: IContentTypeComposition { - var element = packageDocument.XmlData; - var roots = from doc in element.Elements() - where (string)doc.Attribute("isDoc") == "" - select doc; - - var contents = ParseDocumentRootXml(roots, parentId, importedDocumentTypes).ToList(); + var contents = ParseContentBaseRootXml(roots, parentId, importedDocumentTypes, typeService, service).ToList(); if (contents.Any()) - _contentService.Save(contents, userId); + service.Save(contents, userId); return contents; @@ -249,7 +300,7 @@ namespace Umbraco.Core.Packaging //{ // //This is a single doc import // var elements = new List { element }; - // var contents = ParseDocumentRootXml(elements, parentId, importedDocumentTypes).ToList(); + // var contents = ParseContentBaseRootXml(elements, parentId, importedDocumentTypes).ToList(); // if (contents.Any()) // _contentService.Save(contents, userId); @@ -261,50 +312,64 @@ namespace Umbraco.Core.Packaging // "'DocumentSet' (for structured imports) nor is the first element a Document (for single document import)."); } - private IEnumerable ParseDocumentRootXml(IEnumerable roots, int parentId, IDictionary importedContentTypes) + private IEnumerable ParseContentBaseRootXml( + IEnumerable roots, + int parentId, + IDictionary importedContentTypes, + IContentTypeBaseService typeService, + IContentServiceBase service) + where T: class, IContentBase + where S: IContentTypeComposition { - var contents = new List(); + var contents = new List(); foreach (var root in roots) { var contentTypeAlias = root.Name.LocalName; if (!importedContentTypes.ContainsKey(contentTypeAlias)) { - var contentType = FindContentTypeByAlias(contentTypeAlias); + var contentType = FindContentTypeByAlias(contentTypeAlias, typeService); importedContentTypes.Add(contentTypeAlias, contentType); } - var content = CreateContentFromXml(root, importedContentTypes[contentTypeAlias], null, parentId); + var content = CreateContentFromXml(root, importedContentTypes[contentTypeAlias], default(T), parentId, service); if (content == null) continue; contents.Add(content); - var children = (from child in root.Elements() - where (string)child.Attribute("isDoc") == "" - select child) + var children = root.Elements().Where(doc => (string)doc.Attribute("isDoc") == string.Empty) .ToList(); if (children.Count > 0) - contents.AddRange(CreateContentFromXml(children, content, importedContentTypes).WhereNotNull()); + { + contents.AddRange(CreateContentFromXml(children, content, importedContentTypes, typeService, service).WhereNotNull()); + } } return contents; } - private IEnumerable CreateContentFromXml(IEnumerable children, IContent parent, IDictionary importedContentTypes) + private IEnumerable CreateContentFromXml( + IEnumerable children, + T parent, + IDictionary importedContentTypes, + IContentTypeBaseService typeService, + IContentServiceBase service) + where T: class, IContentBase + where S: IContentTypeComposition { - var list = new List(); + var list = new List(); foreach (var child in children) { string contentTypeAlias = child.Name.LocalName; if (importedContentTypes.ContainsKey(contentTypeAlias) == false) { - var contentType = FindContentTypeByAlias(contentTypeAlias); + var contentType = FindContentTypeByAlias(contentTypeAlias, typeService); importedContentTypes.Add(contentTypeAlias, contentType); } //Create and add the child to the list - var content = CreateContentFromXml(child, importedContentTypes[contentTypeAlias], parent, default); + var content = CreateContentFromXml(child, importedContentTypes[contentTypeAlias], parent, default, service); list.Add(content); //Recursive call @@ -314,19 +379,26 @@ namespace Umbraco.Core.Packaging select grand).ToList(); if (grandChildren.Any()) - list.AddRange(CreateContentFromXml(grandChildren, content, importedContentTypes)); + list.AddRange(CreateContentFromXml(grandChildren, content,importedContentTypes, typeService, service)); } return list; } - private IContent CreateContentFromXml(XElement element, IContentType contentType, IContent parent, int parentId) + private T CreateContentFromXml( + XElement element, + S contentType, + T parent, + int parentId, + IContentServiceBase service) + where T: class, IContentBase + where S: IContentTypeComposition { var key = Guid.Empty; if (element.Attribute("key") != null && Guid.TryParse(element.Attribute("key").Value, out key)) { //if a Key is supplied, then we need to check if the content already exists and if so we ignore the installation for this item - if (_contentService.GetById(key) != null) + if (service.GetById(key) != null) return null; } @@ -346,9 +418,9 @@ namespace Umbraco.Core.Packaging var template = templateId.HasValue ? _fileService.GetTemplate(templateId.Value) : null; //now double check this is correct since its an INT it could very well be pointing to an invalid template :/ - if (template != null) + if (template != null && contentType is IContentType contentTypex) { - if (!contentType.IsAllowedTemplate(template.Alias)) + if (!contentTypex.IsAllowedTemplate(template.Alias)) { //well this is awkward, we'll set the template to null and it will be wired up to the default template // when it's persisted in the document repository @@ -356,21 +428,15 @@ namespace Umbraco.Core.Packaging } } - IContent content = parent == null - ? new Content(nodeName, parentId, contentType) - { - Level = int.Parse(level), - SortOrder = int.Parse(sortOrder), - TemplateId = template?.Id, - Key = key - } - : new Content(nodeName, parent, contentType) - { - Level = int.Parse(level), - SortOrder = int.Parse(sortOrder), - TemplateId = template?.Id, - Key = key - }; + T content = CreateContent( + nodeName, + parent, + parentId, + contentType, + key, + int.Parse(level), + int.Parse(sortOrder), + template?.Id); //Here we make sure that we take composition properties in account as well //otherwise we would skip them and end up losing content @@ -396,6 +462,37 @@ namespace Umbraco.Core.Packaging return content; } + private T CreateContent(string name, T parent, int parentId, S contentType, Guid key, int level, int sortOrder, int? templateId) + where T : class, IContentBase + where S : IContentTypeComposition + { + switch (contentType) + { + case IContentType c: + if (parent is null) + { + return new Content(name, parentId, c) { Key = key, Level = level, SortOrder = sortOrder, TemplateId = templateId, } as T; + } + else + { + return new Content(name, (IContent)parent, c) { Key = key, Level = level, SortOrder = sortOrder, TemplateId = templateId, } as T; + } + + case IMediaType m: + if (parent is null) + { + return new Umbraco.Core.Models.Media(name, parentId, m) { Key = key, Level = level, SortOrder = sortOrder, } as T; + } + else + { + return new Umbraco.Core.Models.Media(name, (IMedia)parent, m) { Key = key, Level = level, SortOrder = sortOrder, } as T; + } + + default: + throw new NotSupportedException($"Type {typeof(S)} is not supported"); + } + } + #endregion #region DocumentTypes @@ -413,7 +510,7 @@ namespace Umbraco.Core.Packaging /// An enumerable list of generated ContentTypes public IReadOnlyList ImportDocumentTypes(IEnumerable docTypeElements, int userId) { - return ImportDocumentTypes(docTypeElements.ToList(), true, userId); + return ImportDocumentTypes(docTypeElements.ToList(), true, userId, _contentTypeService); } /// @@ -423,9 +520,10 @@ namespace Umbraco.Core.Packaging /// Boolean indicating whether or not to import the /// Optional id of the User performing the operation. Default is zero (admin). /// An enumerable list of generated ContentTypes - public IReadOnlyList ImportDocumentTypes(IReadOnlyCollection unsortedDocumentTypes, bool importStructure, int userId) + public IReadOnlyList ImportDocumentTypes(IReadOnlyCollection unsortedDocumentTypes, bool importStructure, int userId, IContentTypeBaseService service) + where T: class, IContentTypeComposition { - var importedContentTypes = new Dictionary(); + var importedContentTypes = new Dictionary(); //When you are importing a single doc type we have to assume that the dependencies are already there. //Otherwise something like uSync won't work. @@ -479,10 +577,10 @@ namespace Umbraco.Core.Packaging var alias = documentType.Element("Info").Element("Alias").Value; if (importedContentTypes.ContainsKey(alias) == false) { - var contentType = _contentTypeService.Get(alias); + var contentType = service.Get(alias); importedContentTypes.Add(alias, contentType == null - ? CreateContentTypeFromXml(documentType, importedContentTypes) - : UpdateContentTypeFromXml(documentType, contentType, importedContentTypes)); + ? CreateContentTypeFromXml(documentType, importedContentTypes, service) + : UpdateContentTypeFromXml(documentType, contentType, importedContentTypes, service)); } } @@ -497,27 +595,27 @@ namespace Umbraco.Core.Packaging //Save the newly created/updated IContentType objects var list = importedContentTypes.Select(x => x.Value).ToList(); - _contentTypeService.Save(list, userId); + service.Save(list, userId); //Now we can finish the import by updating the 'structure', //which requires the doc types to be saved/available in the db if (importStructure) { - var updatedContentTypes = new List(); + var updatedContentTypes = new List(); //Update the structure here - we can't do it until all DocTypes have been created foreach (var documentType in documentTypes) { var alias = documentType.Element("Info").Element("Alias").Value; var structureElement = documentType.Element("Structure"); //Ensure that we only update ContentTypes which has actual structure-elements - if (structureElement == null || structureElement.Elements("DocumentType").Any() == false) continue; + if (structureElement == null || structureElement.Elements().Any() == false) continue; - var updated = UpdateContentTypesStructure(importedContentTypes[alias], structureElement, importedContentTypes); + var updated = UpdateContentTypesStructure(importedContentTypes[alias], structureElement, importedContentTypes, service); updatedContentTypes.Add(updated); } //Update ContentTypes with a newly added structure/list of allowed children if (updatedContentTypes.Any()) - _contentTypeService.Save(updatedContentTypes, userId); + service.Save(updatedContentTypes, userId); } return list; @@ -586,33 +684,65 @@ namespace Umbraco.Core.Packaging return _contentTypeService.GetContainer(tryCreateFolder.Result.Entity.Id); } - private IContentType CreateContentTypeFromXml(XElement documentType, IReadOnlyDictionary importedContentTypes) + private T CreateContentTypeFromXml(XElement documentType, IReadOnlyDictionary importedContentTypes, IContentTypeBaseService service) + where T : class, IContentTypeComposition { var infoElement = documentType.Element("Info"); //Name of the master corresponds to the parent var masterElement = infoElement.Element("Master"); - IContentType parent = null; + T parent = default; if (masterElement != null) { var masterAlias = masterElement.Value; parent = importedContentTypes.ContainsKey(masterAlias) ? importedContentTypes[masterAlias] - : _contentTypeService.Get(masterAlias); + : service.Get(masterAlias); } var alias = infoElement.Element("Alias").Value; - var contentType = parent == null - ? new ContentType(_shortStringHelper, -1) { Alias = alias } - : new ContentType(_shortStringHelper, parent, alias); + T contentType = CreateContentType(parent, -1, alias); if (parent != null) contentType.AddContentType(parent); - return UpdateContentTypeFromXml(documentType, contentType, importedContentTypes); + return UpdateContentTypeFromXml(documentType, contentType, importedContentTypes, service); } - private IContentType UpdateContentTypeFromXml(XElement documentType, IContentType contentType, IReadOnlyDictionary importedContentTypes) + private T CreateContentType(T parent, int parentId, string alias) + where T : class, IContentTypeComposition + { + if (typeof(T) == typeof(IContentType)) + { + if (parent is null) + { + return new ContentType(_shortStringHelper, parentId) { Alias = alias } as T; + } + else + { + return new ContentType(_shortStringHelper, (IContentType) parent, alias) as T; + } + + } + + if (typeof(T) == typeof(IMediaType)) + { + if (parent is null) + { + return new MediaType(_shortStringHelper, parentId) { Alias = alias } as T; + } + else + { + return new MediaType(_shortStringHelper, (IMediaType)parent, alias) as T; + } + + } + + throw new NotSupportedException($"Type {typeof(T)} is not supported"); + } + + private T UpdateContentTypeFromXml(XElement documentType, T contentType, IReadOnlyDictionary importedContentTypes, IContentTypeBaseService service) + where T : IContentTypeComposition { var infoElement = documentType.Element("Info"); var defaultTemplateElement = infoElement.Element("DefaultTemplate"); @@ -646,9 +776,9 @@ namespace Umbraco.Core.Packaging if (masterElement != null) { var masterAlias = masterElement.Value; - IContentType parent = importedContentTypes.ContainsKey(masterAlias) + T parent = importedContentTypes.ContainsKey(masterAlias) ? importedContentTypes[masterAlias] - : _contentTypeService.Get(masterAlias); + : service.Get(masterAlias); contentType.SetParent(parent); } @@ -665,13 +795,17 @@ namespace Umbraco.Core.Packaging var compositionAlias = composition.Value; var compositionContentType = importedContentTypes.ContainsKey(compositionAlias) ? importedContentTypes[compositionAlias] - : _contentTypeService.Get(compositionAlias); + : service.Get(compositionAlias); contentType.AddContentType(compositionContentType); } } } - UpdateContentTypesAllowedTemplates(contentType, infoElement.Element("AllowedTemplates"), defaultTemplateElement); + if (contentType is IContentType contentTypex) + { + UpdateContentTypesAllowedTemplates(contentTypex, infoElement.Element("AllowedTemplates"), defaultTemplateElement); + } + UpdateContentTypesTabs(contentType, documentType.Element("Tabs")); UpdateContentTypesProperties(contentType, documentType.Element("GenericProperties")); @@ -716,7 +850,8 @@ namespace Umbraco.Core.Packaging } } - private void UpdateContentTypesTabs(IContentType contentType, XElement tabElement) + private void UpdateContentTypesTabs(T contentType, XElement tabElement) + where T: IContentTypeComposition { if (tabElement == null) return; @@ -742,7 +877,8 @@ namespace Umbraco.Core.Packaging } } - private void UpdateContentTypesProperties(IContentType contentType, XElement genericPropertiesElement) + private void UpdateContentTypesProperties(T contentType, XElement genericPropertiesElement) + where T: IContentTypeComposition { var properties = genericPropertiesElement.Elements("GenericProperty"); foreach (var property in properties) @@ -834,15 +970,16 @@ namespace Umbraco.Core.Packaging } } - private IContentType UpdateContentTypesStructure(IContentType contentType, XElement structureElement, IReadOnlyDictionary importedContentTypes) + private T UpdateContentTypesStructure(T contentType, XElement structureElement, IReadOnlyDictionary importedContentTypes, IContentTypeBaseService service) + where T: IContentTypeComposition { var allowedChildren = contentType.AllowedContentTypes.ToList(); int sortOrder = allowedChildren.Any() ? allowedChildren.Last().SortOrder : 0; - foreach (var element in structureElement.Elements("DocumentType")) + foreach (var element in structureElement.Elements()) { var alias = element.Value; - var allowedChild = importedContentTypes.ContainsKey(alias) ? importedContentTypes[alias] : _contentTypeService.Get(alias); + var allowedChild = importedContentTypes.ContainsKey(alias) ? importedContentTypes[alias] : service.Get(alias); if (allowedChild == null) { _logger.LogWarning( @@ -866,9 +1003,10 @@ namespace Umbraco.Core.Packaging /// /// /// - private IContentType FindContentTypeByAlias(string contentTypeAlias) + private S FindContentTypeByAlias(string contentTypeAlias, IContentTypeBaseService typeService) + where S: IContentTypeComposition { - var contentType = _contentTypeService.Get(contentTypeAlias); + var contentType = typeService.Get(contentTypeAlias); if (contentType == null) throw new Exception($"ContentType matching the passed in Alias: '{contentTypeAlias}' was null"); diff --git a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs index c9a67a8543..126d235ae0 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs @@ -22,6 +22,7 @@ using Umbraco.Core.Migrations; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Migrations.PostMigrations; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Packaging; using Umbraco.Core.Persistence; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.Validators; @@ -380,6 +381,8 @@ namespace Umbraco.Core.Runtime builder.Services.AddUnique(); builder.Services.AddUnique(); + + builder.Services.AddUnique(); } } } diff --git a/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs b/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs index 120c0500e2..69dadb2b21 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.Globalization; using System.Linq; using Microsoft.Extensions.Logging; @@ -387,6 +386,16 @@ namespace Umbraco.Core.Services.Implement } } + /// + /// + /// + /// + /// + /// + /// + Attempt IContentServiceBase.Save(IEnumerable contents, int userId, + bool raiseEvents) => Attempt.Succeed(Save(contents, userId, raiseEvents)); + /// /// Gets objects by Ids /// diff --git a/src/Umbraco.Infrastructure/Services/Implement/EntityXmlSerializer.cs b/src/Umbraco.Infrastructure/Services/Implement/EntityXmlSerializer.cs index 479e5cc4d8..c33265c987 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/EntityXmlSerializer.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/EntityXmlSerializer.cs @@ -4,8 +4,6 @@ using System.Globalization; using System.Linq; using System.Net; using System.Xml.Linq; -using Newtonsoft.Json; -using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Serialization; @@ -120,6 +118,7 @@ namespace Umbraco.Core.Services.Implement //xml.Add(new XAttribute("creatorID", media.CreatorId)); xml.Add(new XAttribute("writerName", media.GetWriterProfile(_userService)?.Name ?? string.Empty)); xml.Add(new XAttribute("writerID", media.WriterId)); + xml.Add(new XAttribute("udi", media.GetUdi())); //xml.Add(new XAttribute("template", 0)); // no template for media @@ -335,6 +334,7 @@ namespace Umbraco.Core.Services.Implement return xml; } + public XElement Serialize(IMediaType mediaType) { var info = new XElement("Info", @@ -375,7 +375,7 @@ namespace Umbraco.Core.Services.Implement new XElement("Validation", propertyType.ValidationRegExp), new XElement("ValidationRegExpMessage", propertyType.ValidationRegExpMessage), new XElement("LabelOnTop", propertyType.LabelOnTop), - new XElement("Description", new XCData(propertyType.Description))); + new XElement("Description", new XCData(propertyType.Description ?? string.Empty))); genericProperties.Add(genericProperty); } @@ -498,7 +498,7 @@ namespace Umbraco.Core.Services.Implement new XElement("Alias", propertyType.Alias), new XElement("Key", propertyType.Key), new XElement("Type", propertyType.PropertyEditorAlias), - new XElement("Definition", definition.Key), + new XElement("Definition", definition.Key), new XElement("Tab", propertyGroup == null ? "" : propertyGroup.Name), new XElement("SortOrder", propertyType.SortOrder), new XElement("Mandatory", propertyType.Mandatory.ToString()), diff --git a/src/Umbraco.Infrastructure/Services/Implement/MediaService.cs b/src/Umbraco.Infrastructure/Services/Implement/MediaService.cs index 0672c3218f..5d5d4b7bd1 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/MediaService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/MediaService.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.Globalization; using System.IO; using System.Linq; @@ -8,7 +7,6 @@ using Microsoft.Extensions.Logging; using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Scoping; @@ -360,6 +358,8 @@ namespace Umbraco.Core.Services.Implement } } + + /// /// Gets an object by Id /// @@ -643,6 +643,8 @@ namespace Umbraco.Core.Services.Implement #region Save + + /// /// Saves a single object /// diff --git a/src/Umbraco.Tests.Integration/Umbraco.Core/Packaging/Packages/Document_Type_Picker_1.1.umb b/src/Umbraco.Tests.Integration/TestData/Packages/Document_Type_Picker_1.1.umb similarity index 100% rename from src/Umbraco.Tests.Integration/Umbraco.Core/Packaging/Packages/Document_Type_Picker_1.1.umb rename to src/Umbraco.Tests.Integration/TestData/Packages/Document_Type_Picker_1.1.umb diff --git a/src/Umbraco.Tests/Packaging/Packages/Document_Type_Picker_1.1.zip b/src/Umbraco.Tests.Integration/TestData/Packages/Document_Type_Picker_1.1.zip similarity index 100% rename from src/Umbraco.Tests/Packaging/Packages/Document_Type_Picker_1.1.zip rename to src/Umbraco.Tests.Integration/TestData/Packages/Document_Type_Picker_1.1.zip diff --git a/src/Umbraco.Tests/Packaging/Packages/Hello_1.0.0.zip b/src/Umbraco.Tests.Integration/TestData/Packages/Hello_1.0.0.zip similarity index 100% rename from src/Umbraco.Tests/Packaging/Packages/Hello_1.0.0.zip rename to src/Umbraco.Tests.Integration/TestData/Packages/Hello_1.0.0.zip diff --git a/src/Umbraco.Tests.Integration/Umbraco.Core/Packaging/CreatedPackagesRepositoryTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Core/Packaging/CreatedPackagesRepositoryTests.cs index 6f3702765e..e3ec2d872b 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Core/Packaging/CreatedPackagesRepositoryTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Core/Packaging/CreatedPackagesRepositoryTests.cs @@ -45,6 +45,8 @@ namespace Umbraco.Tests.Integration.Umbraco.Core.Packaging private IEntityXmlSerializer EntityXmlSerializer => GetRequiredService(); private IHostingEnvironment HostingEnvironment => GetRequiredService(); private IUmbracoVersion UmbracoVersion => GetRequiredService(); + private IMediaService MediaService => GetRequiredService(); + private IMediaTypeService MediaTypeService => GetRequiredService(); public ICreatedPackagesRepository PackageBuilder => new PackagesRepository( ContentService, ContentTypeService, DataTypeService, @@ -53,6 +55,8 @@ namespace Umbraco.Tests.Integration.Umbraco.Core.Packaging EntityXmlSerializer, LoggerFactory, UmbracoVersion, Microsoft.Extensions.Options.Options.Create(new GlobalSettings()), + MediaService, + MediaTypeService, "createdPackages.config", //temp paths tempFolderPath: "~/" + _testBaseFolder + "/temp", @@ -158,8 +162,8 @@ namespace Umbraco.Tests.Integration.Umbraco.Core.Packaging { var file1 = $"~/{_testBaseFolder}/App_Plugins/MyPlugin/package.manifest"; var file2 = $"~/{_testBaseFolder}/App_Plugins/MyPlugin/styles.css"; - var mappedFile1 = IOHelper.MapPath(file1); - var mappedFile2 = IOHelper.MapPath(file2); + var mappedFile1 = HostingEnvironment.MapPathContentRoot(file1); + var mappedFile2 = HostingEnvironment.MapPathContentRoot(file2); Directory.CreateDirectory(Path.GetDirectoryName(mappedFile1)); Directory.CreateDirectory(Path.GetDirectoryName(mappedFile2)); File.WriteAllText(mappedFile1, "hello world"); @@ -183,7 +187,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Core.Packaging def = PackageBuilder.GetById(def.Id); //re-get Assert.IsNotNull(def.PackagePath); - using (var archive = ZipFile.OpenRead(IOHelper.MapPath(zip))) + using (var archive = ZipFile.OpenRead(HostingEnvironment.MapPathWebRoot(zip))) { Assert.AreEqual(3, archive.Entries.Count); diff --git a/src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Core/Packaging/PackageDataInstallationTests.cs similarity index 87% rename from src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs rename to src/Umbraco.Tests.Integration/Umbraco.Core/Packaging/PackageDataInstallationTests.cs index 0383eb6ef8..f250a43b7f 100644 --- a/src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Core/Packaging/PackageDataInstallationTests.cs @@ -2,13 +2,11 @@ using System.Linq; using System.Threading; using System.Xml.Linq; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.CompositionExtensions; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models; using Umbraco.Core.Models.Packaging; @@ -18,7 +16,7 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; -using Umbraco.Tests.Services; +using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.Services.Importing; using Umbraco.Tests.Testing; @@ -27,9 +25,12 @@ namespace Umbraco.Tests.Packaging [TestFixture] [Category("Slow")] [Apartment(ApartmentState.STA)] - [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class PackageDataInstallationTests : TestWithSomeContentBase + [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, WithApplication = true)] + public class PackageDataInstallationTests : UmbracoIntegrationTestWithContent { + private ILocalizationService LocalizationService => GetRequiredService(); + private IMacroService MacroService => GetRequiredService(); + [HideFromTypeFinder] [DataEditor("7e062c13-7c41-4ad9-b389-41d88aeef87c", "Editor1", "editor1")] public class Editor1 : DataEditor @@ -50,31 +51,36 @@ namespace Umbraco.Tests.Packaging } } - protected override void Compose() - { - base.Compose(); + // protected override void Compose() + // { + // base.Compose(); + // + // // the packages that are used by these tests reference totally bogus property + // // editors that must exist - so they are defined here - and in order not to + // // pollute everything, they are ignored by the type finder and explicitely + // // added to the editors collection + // + // Builder.WithCollectionBuilder() + // .Add() + // .Add(); + // } + // + // protected override void ComposeApplication(bool withApplication) + // { + // base.ComposeApplication(withApplication); + // + // if (!withApplication) return; + // + // // re-register with actual media fs + // Builder.ComposeFileSystems(); + // } - // the packages that are used by these tests reference totally bogus property - // editors that must exist - so they are defined here - and in order not to - // pollute everything, they are ignored by the type finder and explicitely - // added to the editors collection + private PackageDataInstallation PackageDataInstallation => GetRequiredService(); + private IContentService ContentService => GetRequiredService(); + private IContentTypeService ContentTypeService => GetRequiredService(); - Builder.WithCollectionBuilder() - .Add() - .Add(); - } - - protected override void ComposeApplication(bool withApplication) - { - base.ComposeApplication(withApplication); - - if (!withApplication) return; - - // re-register with actual media fs - Builder.ComposeFileSystems(); - } - - private PackageDataInstallation PackageDataInstallation => Factory.GetRequiredService(); + private IMediaService MediaService => GetRequiredService(); + private IMediaTypeService MediaTypeService => GetRequiredService(); [Test] public void Can_Import_uBlogsy_ContentTypes_And_Verify_Structure() @@ -195,12 +201,12 @@ namespace Umbraco.Tests.Packaging var xml = XElement.Parse(strXml); var element = xml.Descendants("Templates").First(); - var init = ServiceContext.FileService.GetTemplates().Count(); + var init = FileService.GetTemplates().Count(); // Act var templates = PackageDataInstallation.ImportTemplates(element.Elements("Template").ToList(), 0); var numberOfTemplates = (from doc in element.Elements("Template") select doc).Count(); - var allTemplates = ServiceContext.FileService.GetTemplates(); + var allTemplates = FileService.GetTemplates(); // Assert Assert.That(templates, Is.Not.Null); @@ -322,16 +328,16 @@ namespace Umbraco.Tests.Packaging var dataTypeElement = xml.Descendants("DataTypes").First(); var docTypesElement = xml.Descendants("DocumentTypes").First(); var element = xml.Descendants("DocumentSet").First(); - var packageDocument = CompiledPackageDocument.Create(element); + var packageDocument = CompiledPackageContentBase.Create(element); // Act var dataTypeDefinitions = PackageDataInstallation.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); var contentTypes = PackageDataInstallation.ImportDocumentTypes(docTypesElement.Elements("DocumentType"), 0); var importedContentTypes = contentTypes.ToDictionary(x => x.Alias, x => x); - var contents = PackageDataInstallation.ImportContent(packageDocument, -1, importedContentTypes, 0); + var contents = PackageDataInstallation.ImportContentBase(packageDocument.Yield(), importedContentTypes, 0, ContentTypeService, ContentService); var numberOfDocs = (from doc in element.Descendants() - where (string) doc.Attribute("isDoc") == "" - select doc).Count(); + where (string) doc.Attribute("isDoc") == "" + select doc).Count(); // Assert Assert.That(contents, Is.Not.Null); @@ -341,6 +347,32 @@ namespace Umbraco.Tests.Packaging Assert.That(contents.Count(), Is.EqualTo(numberOfDocs)); } + [Test] + public void Can_Import_Media_Package_Xml() + { + // Arrange + Core.Services.Implement.MediaTypeService.ClearScopeEvents(); + string strXml = ImportResources.MediaTypesAndMedia_Package_xml; + var xml = XElement.Parse(strXml); + var mediaTypesElement = xml.Descendants("MediaTypes").First(); + var element = xml.Descendants("MediaSet").First(); + var packageMedia = CompiledPackageContentBase.Create(element); + + // Act + var mediaTypes = PackageDataInstallation.ImportMediaTypes(mediaTypesElement.Elements("MediaType"), 0); + var importedMediaTypes = mediaTypes.ToDictionary(x => x.Alias, x => x); + var medias = PackageDataInstallation.ImportContentBase(packageMedia.Yield(), importedMediaTypes, 0, MediaTypeService, MediaService); + var numberOfDocs = (from doc in element.Descendants() + where (string) doc.Attribute("isDoc") == "" + select doc).Count(); + + // Assert + Assert.That(medias, Is.Not.Null); + Assert.That(mediaTypes.Any(), Is.True); + Assert.That(medias.Any(), Is.True); + Assert.That(medias.Count(), Is.EqualTo(numberOfDocs)); + } + [Test] public void Can_Import_CheckboxList_Content_Package_Xml_With_Property_Editor_Aliases() { @@ -356,13 +388,13 @@ namespace Umbraco.Tests.Packaging var dataTypeElement = xml.Descendants("DataTypes").First(); var docTypesElement = xml.Descendants("DocumentTypes").First(); var element = xml.Descendants("DocumentSet").First(); - var packageDocument = CompiledPackageDocument.Create(element); + var packageDocument = CompiledPackageContentBase.Create(element); // Act var dataTypeDefinitions = PackageDataInstallation.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); var contentTypes = PackageDataInstallation.ImportDocumentTypes(docTypesElement.Elements("DocumentType"), 0); var importedContentTypes = contentTypes.ToDictionary(x => x.Alias, x => x); - var contents = PackageDataInstallation.ImportContent(packageDocument, -1, importedContentTypes, 0); + var contents = PackageDataInstallation.ImportContentBase(packageDocument.Yield(), importedContentTypes, 0, ContentTypeService, ContentService); var numberOfDocs = (from doc in element.Descendants() where (string)doc.Attribute("isDoc") == "" select doc).Count(); @@ -427,7 +459,7 @@ namespace Umbraco.Tests.Packaging string strXml = ImportResources.SingleDocType; var docTypeElement = XElement.Parse(strXml); - var serializer = Factory.GetRequiredService(); + var serializer = GetRequiredService(); // Act var contentTypes = PackageDataInstallation.ImportDocumentType(docTypeElement, 0); @@ -476,7 +508,7 @@ namespace Umbraco.Tests.Packaging var templateElement = newPackageXml.Descendants("Templates").First(); var templateElementUpdated = updatedPackageXml.Descendants("Templates").First(); - var fileService = ServiceContext.FileService; + var fileService = FileService; // kill default test data fileService.DeleteTemplate("Textpage"); @@ -535,11 +567,11 @@ namespace Umbraco.Tests.Packaging var dictionaryItems = PackageDataInstallation.ImportDictionaryItems(dictionaryItemsElement.Elements("DictionaryItem"), 0); // Assert - Assert.That(ServiceContext.LocalizationService.DictionaryItemExists(parentKey), "DictionaryItem parentKey does not exist"); - Assert.That(ServiceContext.LocalizationService.DictionaryItemExists(childKey), "DictionaryItem childKey does not exist"); + Assert.That(LocalizationService.DictionaryItemExists(parentKey), "DictionaryItem parentKey does not exist"); + Assert.That(LocalizationService.DictionaryItemExists(childKey), "DictionaryItem childKey does not exist"); - var parentDictionaryItem = ServiceContext.LocalizationService.GetDictionaryItemByKey(parentKey); - var childDictionaryItem = ServiceContext.LocalizationService.GetDictionaryItemByKey(childKey); + var parentDictionaryItem = LocalizationService.GetDictionaryItemByKey(parentKey); + var childDictionaryItem = LocalizationService.GetDictionaryItemByKey(childKey); Assert.That(parentDictionaryItem.ParentId, Is.Not.EqualTo(childDictionaryItem.ParentId)); Assert.That(childDictionaryItem.ParentId, Is.EqualTo(parentDictionaryItem.Key)); @@ -604,7 +636,7 @@ namespace Umbraco.Tests.Packaging // Act var languages = PackageDataInstallation.ImportLanguages(LanguageItemsElement.Elements("Language"), 0); - var allLanguages = ServiceContext.LocalizationService.GetAllLanguages(); + var allLanguages = LocalizationService.GetAllLanguages(); // Assert Assert.That(languages.Any(x => x.HasIdentity == false), Is.False); @@ -629,7 +661,7 @@ namespace Umbraco.Tests.Packaging // Assert Assert.That(macros.Any(), Is.True); - var allMacros = ServiceContext.MacroService.GetAll().ToList(); + var allMacros = MacroService.GetAll().ToList(); foreach (var macro in macros) { Assert.That(allMacros.Any(x => x.Alias == macro.Alias), Is.True); @@ -652,7 +684,7 @@ namespace Umbraco.Tests.Packaging Assert.That(macros.Any(), Is.True); Assert.That(macros.First().Properties.Values.Any(), Is.True); - var allMacros = ServiceContext.MacroService.GetAll().ToList(); + var allMacros = MacroService.GetAll().ToList(); foreach (var macro in macros) { Assert.That(allMacros.Any(x => x.Alias == macro.Alias), Is.True); @@ -718,14 +750,14 @@ namespace Umbraco.Tests.Packaging var globalSettings = new GlobalSettings(); var norwegian = new Core.Models.Language(globalSettings, "nb-NO"); var english = new Core.Models.Language(globalSettings, "en-GB"); - ServiceContext.LocalizationService.Save(norwegian, 0); - ServiceContext.LocalizationService.Save(english, 0); + LocalizationService.Save(norwegian, 0); + LocalizationService.Save(english, 0); } private void AssertDictionaryItem(string key, string expectedValue, string cultureCode) { - Assert.That(ServiceContext.LocalizationService.DictionaryItemExists(key), "DictionaryItem key does not exist"); - var dictionaryItem = ServiceContext.LocalizationService.GetDictionaryItemByKey(key); + Assert.That(LocalizationService.DictionaryItemExists(key), "DictionaryItem key does not exist"); + var dictionaryItem = LocalizationService.GetDictionaryItemByKey(key); var translation = dictionaryItem.Translations.SingleOrDefault(i => i.Language.IsoCode == cultureCode); Assert.IsNotNull(translation, "Translation to {0} was not added", cultureCode); var value = translation.Value; @@ -734,9 +766,9 @@ namespace Umbraco.Tests.Packaging private void AddExistingEnglishParentDictionaryItem(string expectedEnglishParentValue) { - var languages = ServiceContext.LocalizationService.GetAllLanguages().ToList(); + var languages = LocalizationService.GetAllLanguages().ToList(); var englishLanguage = languages.Single(l => l.IsoCode == "en-GB"); - ServiceContext.LocalizationService.Save( + LocalizationService.Save( new DictionaryItem("Parent") { Translations = new List @@ -749,10 +781,10 @@ namespace Umbraco.Tests.Packaging private void AddExistingEnglishAndNorwegianParentDictionaryItem(string expectedEnglishParentValue, string expectedNorwegianParentValue) { - var languages = ServiceContext.LocalizationService.GetAllLanguages().ToList(); + var languages = LocalizationService.GetAllLanguages().ToList(); var englishLanguage = languages.Single(l => l.IsoCode == "en-GB"); var norwegianLanguage = languages.Single(l => l.IsoCode == "nb-NO"); - ServiceContext.LocalizationService.Save( + LocalizationService.Save( new DictionaryItem("Parent") { Translations = new List diff --git a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs b/src/Umbraco.Tests.Integration/Umbraco.Core/Packaging/PackageInstallationTest.cs similarity index 58% rename from src/Umbraco.Tests/Packaging/PackageInstallationTest.cs rename to src/Umbraco.Tests.Integration/Umbraco.Core/Packaging/PackageInstallationTest.cs index 2d238c9057..93a6ef010b 100644 --- a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Core/Packaging/PackageInstallationTest.cs @@ -2,74 +2,21 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Moq; using NUnit.Framework; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.Models.Packaging; using Umbraco.Core.Packaging; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Scoping; -using Umbraco.Core.Serialization; -using Umbraco.Core.Services; -using Umbraco.Core.Strings; -using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.Testing; namespace Umbraco.Tests.Packaging { [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerFixture)] - public class PackageInstallationTest : TestWithDatabaseBase + public class PackageInstallationTest : UmbracoIntegrationTest { - private DirectoryInfo _testBaseFolder; - - public override void SetUp() - { - base.SetUp(); - var path = Path.Combine(TestHelper.WorkingDirectory, Guid.NewGuid().ToString()); - if (!Directory.Exists(path)) - Directory.CreateDirectory(path); - _testBaseFolder = new DirectoryInfo(path); - } - - public override void TearDown() - { - base.TearDown(); - - //clear out files/folders - if (_testBaseFolder.Exists) - _testBaseFolder.Delete(true); - } - - private CompiledPackageXmlParser Parser => new CompiledPackageXmlParser( - new ConflictingPackageData( - ServiceContext.MacroService, - ServiceContext.FileService), - Microsoft.Extensions.Options.Options.Create(new GlobalSettings())); - - private PackageDataInstallation PackageDataInstallation => new PackageDataInstallation( - NullLoggerFactory.Instance.CreateLogger(), NullLoggerFactory.Instance, ServiceContext.FileService, ServiceContext.MacroService, ServiceContext.LocalizationService, - ServiceContext.DataTypeService, ServiceContext.EntityService, - ServiceContext.ContentTypeService, ServiceContext.ContentService, - Factory.GetRequiredService(), - Factory.GetRequiredService(), - Factory.GetRequiredService(), - Microsoft.Extensions.Options.Options.Create(new GlobalSettings()), - Factory.GetRequiredService(), - Factory.GetRequiredService(), - Factory.GetRequiredService() - ); - - private IPackageInstallation PackageInstallation => new PackageInstallation( - PackageDataInstallation, - new PackageFileInstallation(Parser, IOHelper, HostingEnvironment, ProfilingLogger), - Parser, Mock.Of(), - //we don't want to extract package files to the real root, so extract to a test folder - Mock.Of(x => x.ApplicationPhysicalPath == _testBaseFolder.FullName)); + private IHostingEnvironment HostingEnvironment => GetRequiredService(); + private IPackageInstallation PackageInstallation => GetRequiredService(); private const string DocumentTypePickerPackage = "Document_Type_Picker_1.1.umb"; private const string HelloPackage = "Hello_1.0.0.zip"; @@ -79,7 +26,7 @@ namespace Umbraco.Tests.Packaging { var package = PackageInstallation.ReadPackage( //this is where our test zip file is - new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerPackage))); + new FileInfo(Path.Combine(HostingEnvironment.MapPathContentRoot("~/TestData/Packages"), DocumentTypePickerPackage))); Assert.IsNotNull(package); Assert.AreEqual(1, package.Files.Count); Assert.AreEqual("095e064b-ba4d-442d-9006-3050983c13d8.dll", package.Files[0].UniqueFileName); @@ -102,7 +49,7 @@ namespace Umbraco.Tests.Packaging { var package = PackageInstallation.ReadPackage( //this is where our test zip file is - new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), HelloPackage))); + new FileInfo(Path.Combine(HostingEnvironment.MapPathContentRoot("~/TestData/Packages"), HelloPackage))); Assert.IsNotNull(package); Assert.AreEqual(0, package.Files.Count); Assert.AreEqual("Hello", package.Name); @@ -128,12 +75,12 @@ namespace Umbraco.Tests.Packaging { //copy a file to the same path that the package will install so we can detect file conflicts - var filePath = Path.Combine(_testBaseFolder.FullName, "bin", "Auros.DocumentTypePicker.dll"); + var filePath = Path.Combine(HostingEnvironment.MapPathContentRoot("~/"), "bin", "Auros.DocumentTypePicker.dll"); Directory.CreateDirectory(Path.GetDirectoryName(filePath)); File.WriteAllText(filePath, "test"); //this is where our test zip file is - var packageFile = Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerPackage); + var packageFile = Path.Combine(HostingEnvironment.MapPathContentRoot("~/TestData/Packages"), DocumentTypePickerPackage); Console.WriteLine(packageFile); var package = PackageInstallation.ReadPackage(new FileInfo(packageFile)); @@ -141,7 +88,7 @@ namespace Umbraco.Tests.Packaging Assert.IsNotNull(preInstallWarnings); Assert.AreEqual(1, preInstallWarnings.FilesReplaced.Count()); - Assert.AreEqual("bin\\Auros.DocumentTypePicker.dll", preInstallWarnings.FilesReplaced.First()); + Assert.AreEqual(Path.Combine("bin", "Auros.DocumentTypePicker.dll"), preInstallWarnings.FilesReplaced.First()); // TODO: More Asserts } @@ -151,7 +98,7 @@ namespace Umbraco.Tests.Packaging { var package = PackageInstallation.ReadPackage( //this is where our test zip file is - new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerPackage))); + new FileInfo(Path.Combine(HostingEnvironment.MapPathContentRoot("~/TestData/Packages"), DocumentTypePickerPackage))); var def = PackageDefinition.FromCompiledPackage(package); def.Id = 1; @@ -161,8 +108,8 @@ namespace Umbraco.Tests.Packaging var result = PackageInstallation.InstallPackageFiles(def, package, -1).ToList(); Assert.AreEqual(1, result.Count); - Assert.AreEqual("bin\\Auros.DocumentTypePicker.dll", result[0]); - Assert.IsTrue(File.Exists(Path.Combine(_testBaseFolder.FullName, result[0]))); + Assert.AreEqual(Path.Combine("bin", "Auros.DocumentTypePicker.dll"), result[0]); + Assert.IsTrue(File.Exists(Path.Combine(HostingEnvironment.MapPathContentRoot("~/"), result[0]))); //make sure the def is updated too Assert.AreEqual(result.Count, def.Files.Count); @@ -173,7 +120,7 @@ namespace Umbraco.Tests.Packaging { var package = PackageInstallation.ReadPackage( //this is where our test zip file is - new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerPackage))); + new FileInfo(Path.Combine(HostingEnvironment.MapPathContentRoot("~/TestData/Packages"), DocumentTypePickerPackage))); var def = PackageDefinition.FromCompiledPackage(package); def.Id = 1; def.PackageId = Guid.NewGuid(); @@ -186,7 +133,5 @@ namespace Umbraco.Tests.Packaging //make sure the def is updated too Assert.AreEqual(summary.DataTypesInstalled.Count(), def.DataTypes.Count); } - - } } diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/EntityXmlSerializerTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/EntityXmlSerializerTests.cs index a0068f8c3d..8a04caeac7 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/EntityXmlSerializerTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/EntityXmlSerializerTests.cs @@ -8,7 +8,7 @@ using Umbraco.Core.Services; using Umbraco.Tests.Common.Builders; using Umbraco.Tests.Common.Builders.Extensions; using Umbraco.Tests.Integration.Testing; -using Umbraco.Tests.Integration.Umbraco.Infrastructure.Services.Importing; +using Umbraco.Tests.Services.Importing; using Umbraco.Tests.Testing; namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services diff --git a/src/Umbraco.Tests/Services/Importing/CheckboxList-Content-Package.xml b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/CheckboxList-Content-Package.xml similarity index 100% rename from src/Umbraco.Tests/Services/Importing/CheckboxList-Content-Package.xml rename to src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/CheckboxList-Content-Package.xml diff --git a/src/Umbraco.Tests/Services/Importing/CompositionsTestPackage-Random.xml b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/CompositionsTestPackage-Random.xml similarity index 100% rename from src/Umbraco.Tests/Services/Importing/CompositionsTestPackage-Random.xml rename to src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/CompositionsTestPackage-Random.xml diff --git a/src/Umbraco.Tests/Services/Importing/CompositionsTestPackage.xml b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/CompositionsTestPackage.xml similarity index 100% rename from src/Umbraco.Tests/Services/Importing/CompositionsTestPackage.xml rename to src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/CompositionsTestPackage.xml diff --git a/src/Umbraco.Tests/Services/Importing/Fanoe-Package.xml b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/Fanoe-Package.xml similarity index 100% rename from src/Umbraco.Tests/Services/Importing/Fanoe-Package.xml rename to src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/Fanoe-Package.xml diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/ImportResources.Designer.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/ImportResources.Designer.cs index 488108ebda..f7e0541d95 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/ImportResources.Designer.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/ImportResources.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services.Importing { +namespace Umbraco.Tests.Services.Importing { using System; @@ -19,7 +19,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services.Importing { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class ImportResources { @@ -61,6 +61,88 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services.Importing { } } + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> + ///<umbPackage> + /// <files /> + /// <info> + /// <package> + /// <name>CheckboxListTest</name> + /// <version>1</version> + /// <license url="http://www.opensource.org/licenses/mit-license.php">MIT license</license> + /// <url>1</url> + /// <requirements> + /// <major>3</major> + /// <minor>0</minor> + /// <patch>0</patch> + /// </requirements> + /// </package> + /// <author> + /// <name>1</name> + /// <website>1</website> + /// </author> + /// <r [rest of string was truncated]";. + /// + internal static string CheckboxList_Content_Package { + get { + return ResourceManager.GetString("CheckboxList_Content_Package", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> + ///<umbPackage> + /// <files /> + /// <info> + /// <package> + /// <name>Compositions Packaged</name> + /// <version>1.0</version> + /// <license url="http://opensource.org/licenses/MIT">MIT License</license> + /// <url>http://blog.sitereactor.dk</url> + /// <requirements> + /// <major>3</major> + /// <minor>0</minor> + /// <patch>0</patch> + /// </requirements> + /// </package> + /// <author> + /// <name>Morten Christensen</name> + /// <website>h [rest of string was truncated]";. + /// + internal static string CompositionsTestPackage { + get { + return ResourceManager.GetString("CompositionsTestPackage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> + ///<umbPackage> + /// <files /> + /// <info> + /// <package> + /// <name>Composite Test</name> + /// <version>dfsfd</version> + /// <license url="http://opensource.org/licenses/MIT">MIT License</license> + /// <url>ddsff</url> + /// <requirements> + /// <major>3</major> + /// <minor>0</minor> + /// <patch>0</patch> + /// </requirements> + /// </package> + /// <author> + /// <name>fsdfds</name> + /// <website>sfdf</website> + /// </author> + /// <rea [rest of string was truncated]";. + /// + internal static string CompositionsTestPackage_Random { + get { + return ResourceManager.GetString("CompositionsTestPackage_Random", resourceCulture); + } + } + /// /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?> ///<umbPackage> @@ -86,5 +168,243 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services.Importing { return ResourceManager.GetString("Dictionary_Package", resourceCulture); } } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> + ///<umbPackage> + /// <files> + /// <file> + /// <guid>bootstrap.min.js</guid> + /// <orgPath>/js</orgPath> + /// <orgName>bootstrap.min.js</orgName> + /// </file> + /// <file> + /// <guid>jquery.min.js</guid> + /// <orgPath>/js</orgPath> + /// <orgName>jquery.min.js</orgName> + /// </file> + /// <file> + /// <guid>top-image.jpg</guid> + /// <orgPath>/Media/1001</orgPath> + /// <orgName>top-image.jpg</orgName> + /// </file> + /// <file> + /// <guid>top-im [rest of string was truncated]";. + /// + internal static string Fanoe_Package { + get { + return ResourceManager.GetString("Fanoe_Package", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> + ///<umbPackage> + /// <files /> + /// <info> + /// <package> + /// <name>DocTypeError</name> + /// <version>1</version> + /// <license url="http://www.opensource.org/licenses/mit-license.php">Personal license</license> + /// <url>http://www.iseli-webconsulting.de</url> + /// <requirements> + /// <major>3</major> + /// <minor>0</minor> + /// <patch>0</patch> + /// </requirements> + /// </package> + /// <author> + /// <name>Iseli Webconsulting</name> [rest of string was truncated]";. + /// + internal static string InheritedDocTypes_Package { + get { + return ResourceManager.GetString("InheritedDocTypes_Package", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?> + ///<umbPackage> + /// <files /> + /// <info> + /// <package> + /// <name>Package With MediaTypes And Media + Folder</name> + /// <version>1.0.0</version> + /// <iconUrl></iconUrl> + /// <license url="http://opensource.org/licenses/MIT">MIT License</license> + /// <url>http://www.umbraco.com</url> + /// <requirements type="Strict"> + /// <major>0</major> + /// <minor>5</minor> + /// <patch>0</patch> + /// </requirements> + /// </package> + /// <author> + /// <name [rest of string was truncated]";. + /// + internal static string MediaTypesAndMedia_Package_xml { + get { + return ResourceManager.GetString("MediaTypesAndMedia_Package.xml", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?> + ///<DocumentType> + /// <Info> + /// <Name>test</Name> + /// <Alias>test</Alias> + /// <Icon>folder.gif</Icon> + /// <Thumbnail>folder.png</Thumbnail> + /// <Description> + /// </Description> + /// <AllowAtRoot>False</AllowAtRoot> + /// <AllowedTemplates> + /// <Template>test</Template> + /// </AllowedTemplates> + /// <DefaultTemplate>test</DefaultTemplate> + /// </Info> + /// <Structure> + /// <DocumentType>test</DocumentType> + /// </Structure> + /// <GenericProperties> + /// <GenericProperty> [rest of string was truncated]";. + /// + internal static string SingleDocType { + get { + return ResourceManager.GetString("SingleDocType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> + ///<umbPackage> + /// <files> + /// <file> + /// <guid>Map.cshtml</guid> + /// <orgPath>/macroScripts</orgPath> + /// <orgName>Map.cshtml</orgName> + /// </file> + /// <file> + /// <guid>AccountController.cs</guid> + /// <orgPath>/App_Code</orgPath> + /// <orgName>AccountController.cs</orgName> + /// </file> + /// <file> + /// <guid>ContactController.cs</guid> + /// <orgPath>/App_Code</orgPath> + /// <orgName>ContactController.cs</orgName> + /// </file> + /// [rest of string was truncated]";. + /// + internal static string StandardMvc_Package { + get { + return ResourceManager.GetString("StandardMvc_Package", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> + ///<umbPackage> + /// <files /> + /// <info> + /// <package> + /// <name>Template-Update</name> + /// <version>0.1</version> + /// <license url="http://www.opensource.org/licenses/mit-license.php">MIT license</license> + /// <url>https://our.umbraco.com/projects</url> + /// <requirements> + /// <major>3</major> + /// <minor>0</minor> + /// <patch>0</patch> + /// </requirements> + /// </package> + /// <author> + /// <name>Morten Christensen</name> + /// [rest of string was truncated]";. + /// + internal static string TemplateOnly_Package { + get { + return ResourceManager.GetString("TemplateOnly_Package", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> + ///<umbPackage> + /// <files /> + /// <info> + /// <package> + /// <name>Template-Update</name> + /// <version>0.1</version> + /// <license url="http://www.opensource.org/licenses/mit-license.php">MIT license</license> + /// <url>https://our.umbraco.com/projects</url> + /// <requirements> + /// <major>3</major> + /// <minor>0</minor> + /// <patch>0</patch> + /// </requirements> + /// </package> + /// <author> + /// <name>Morten Christensen</name> + /// [rest of string was truncated]";. + /// + internal static string TemplateOnly_Updated_Package { + get { + return ResourceManager.GetString("TemplateOnly_Updated_Package", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> + ///<umbPackage> + /// <files> + /// <file> + /// <guid>uBlogsy.BusinessLogic.dll</guid> + /// <orgPath>/bin</orgPath> + /// <orgName>uBlogsy.BusinessLogic.dll</orgName> + /// </file> + /// <file> + /// <guid>uBlogsy.BusinessLogic.pdb</guid> + /// <orgPath>/bin</orgPath> + /// <orgName>uBlogsy.BusinessLogic.pdb</orgName> + /// </file> + /// <file> + /// <guid>uBlogsy.Common.dll</guid> + /// <orgPath>/bin</orgPath> + /// <orgName>uBlogsy.Common.dll</orgNam [rest of string was truncated]";. + /// + internal static string uBlogsy_Package { + get { + return ResourceManager.GetString("uBlogsy_Package", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> + ///<umbPackage> + /// <files> + /// <file> + /// <guid>XSLTsearch.xslt</guid> + /// <orgPath>/xslt</orgPath> + /// <orgName>XSLTsearch.xslt</orgName> + /// </file> + /// <file> + /// <guid>XSLTsearch.cs</guid> + /// <orgPath>/App_Code</orgPath> + /// <orgName>XSLTsearch.cs</orgName> + /// </file> + /// </files> + /// <info> + /// <package> + /// <name>XSLTsearch</name> + /// <version>3.0.4</version> + /// <license url="http://www.opensource.org/licenses/mit-li [rest of string was truncated]";. + /// + internal static string XsltSearch_Package { + get { + return ResourceManager.GetString("XsltSearch_Package", resourceCulture); + } + } } } diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/ImportResources.resx b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/ImportResources.resx index fdf7880297..e8029b6520 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/ImportResources.resx +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/ImportResources.resx @@ -1,17 +1,17 @@  - @@ -118,7 +118,43 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + InheritedDocTypes-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + StandardMvc-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + uBlogsy-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + XsltSearch-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + SingleDocType.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + TemplateOnly-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + TemplateOnly-Updated-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + CheckboxList-Content-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + Dictionary-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + CompositionsTestPackage.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + CompositionsTestPackage-Random.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + Fanoe-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + MediaTypesAndMedia-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + diff --git a/src/Umbraco.Tests/Services/Importing/InheritedDocTypes-Package.xml b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/InheritedDocTypes-Package.xml similarity index 100% rename from src/Umbraco.Tests/Services/Importing/InheritedDocTypes-Package.xml rename to src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/InheritedDocTypes-Package.xml diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/MediaTypesAndMedia-Package.xml b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/MediaTypesAndMedia-Package.xml new file mode 100644 index 0000000000..e51fee48f8 --- /dev/null +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/MediaTypesAndMedia-Package.xml @@ -0,0 +1,158 @@ + + + + + + Package With MediaTypes And Media + Folder + 1.0.0 + + MIT License + http://www.umbraco.com + + 0 + 5 + 0 + + + + dteam + http://www.umbraco.com + + + + + + + + + Folder + Folder + icon-folder + icon-folder + + True + + + Folder + Image + File + + + + + + + Image + Image + icon-picture + icon-picture + + True + + + + + Upload image + umbracoFile + Umbraco.ImageCropper + 1df9f033-e6d4-451f-b8d2-e0cbc50a836f + Image + True + + + + false + + + + Width + umbracoWidth + Umbraco.Label + 8e7f995c-bd81-4627-9932-c40e568ec788 + Image + False + + + + false + + + + Height + umbracoHeight + Umbraco.Label + 8e7f995c-bd81-4627-9932-c40e568ec788 + Image + False + + + + false + + + + Size + umbracoBytes + Umbraco.Label + 930861bf-e262-4ead-a704-f99453565708 + Image + False + + + + false + + + + Type + umbracoExtension + Umbraco.Label + f0bc4bfb-b499-40d6-ba86-058885a5178c + Image + False + + + + false + + + + + + 3 + Image + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Umbraco.Tests/Services/Importing/SingleDocType.xml b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/SingleDocType.xml similarity index 100% rename from src/Umbraco.Tests/Services/Importing/SingleDocType.xml rename to src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/SingleDocType.xml diff --git a/src/Umbraco.Tests/Services/Importing/StandardMvc-Package.xml b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/StandardMvc-Package.xml similarity index 100% rename from src/Umbraco.Tests/Services/Importing/StandardMvc-Package.xml rename to src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/StandardMvc-Package.xml diff --git a/src/Umbraco.Tests/Services/Importing/TemplateOnly-Package.xml b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/TemplateOnly-Package.xml similarity index 100% rename from src/Umbraco.Tests/Services/Importing/TemplateOnly-Package.xml rename to src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/TemplateOnly-Package.xml diff --git a/src/Umbraco.Tests/Services/Importing/TemplateOnly-Updated-Package.xml b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/TemplateOnly-Updated-Package.xml similarity index 100% rename from src/Umbraco.Tests/Services/Importing/TemplateOnly-Updated-Package.xml rename to src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/TemplateOnly-Updated-Package.xml diff --git a/src/Umbraco.Tests/Services/Importing/XsltSearch-Package.xml b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/XsltSearch-Package.xml similarity index 100% rename from src/Umbraco.Tests/Services/Importing/XsltSearch-Package.xml rename to src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/XsltSearch-Package.xml diff --git a/src/Umbraco.Tests/Services/Importing/uBlogsy-Package.xml b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/uBlogsy-Package.xml similarity index 100% rename from src/Umbraco.Tests/Services/Importing/uBlogsy-Package.xml rename to src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/uBlogsy-Package.xml diff --git a/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj b/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj index b996205712..0614405e41 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj +++ b/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj @@ -19,6 +19,16 @@ + + ResXFileCodeGenerator + ImportResources.Designer.cs + Designer + + + True + True + ImportResources.resx + @@ -26,7 +36,22 @@ + + Designer + + + + + + + + Designer + + + + + @@ -58,20 +83,4 @@ - - - ImportResources.resx - True - True - - - - - - Designer - ImportResources.Designer.cs - ResXFileCodeGenerator - - - diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.PublishedCache.NuCache/SnapDictionaryTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.PublishedCache.NuCache/SnapDictionaryTests.cs index 91317848c6..05157d961a 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.PublishedCache.NuCache/SnapDictionaryTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.PublishedCache.NuCache/SnapDictionaryTests.cs @@ -92,6 +92,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Umbraco.PublishedCache Assert.AreEqual("one", s1.Get(1)); } + [Retry(5)] // TODO make this test non-flaky. [Test] public async Task CollectValues() { @@ -218,6 +219,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Umbraco.PublishedCache Assert.AreEqual(0, d.Count); } + [Retry(5)] // TODO make this test non-flaky. [Test] public async Task CollectNulls() { @@ -527,6 +529,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Umbraco.PublishedCache Assert.AreEqual(1, d.Test.GetValues(1).Length); } + [Retry(5)] // TODO make this test non-flaky. [Test] public async Task RandomTest1() { @@ -573,6 +576,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Umbraco.PublishedCache Assert.AreEqual(0, d.SnapCount); } + [Retry(5)] // TODO make this test non-flaky. [Test] public async Task RandomTest2() { diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs index 41705c7774..420ddbe952 100644 --- a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs +++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs @@ -4,11 +4,11 @@ using System.Globalization; using System.IO; using System.Linq; using System.Text; +using System.Threading.Tasks; using System.Xml; using Microsoft.Extensions.Logging; using NPoco; using Umbraco.Core; -using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Models; @@ -28,7 +28,6 @@ using Umbraco.Web.Composing; using Umbraco.Web.PublishedCache; using Umbraco.Web.Scheduling; using File = System.IO.File; -using Task = System.Threading.Tasks.Task; namespace Umbraco.Tests.LegacyXmlPublishedCache { @@ -761,7 +760,7 @@ AND (umbracoNode.id=@id)"; // The indenting resumes once the mixed content element is closed." - says MSDN // about XmlWriterSettings.Indent - // so ImportContent must also make sure of ignoring whitespaces! + // so ImportContentBase must also make sure of ignoring whitespaces! var sb = new StringBuilder(); using (var xmlWriter = XmlWriter.Create(sb, new XmlWriterSettings diff --git a/src/Umbraco.Tests/Packaging/Packages/Document_Type_Picker_1.1.umb b/src/Umbraco.Tests/Packaging/Packages/Document_Type_Picker_1.1.umb deleted file mode 100644 index 18449bd3735870c98e711525a7ea9883941e321f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6147 zcma)=RZJWVl!bAp6qn)@DHL~ich`a9GDv|U9o*dqXP~$j8>HwIcc+6CcZxg3_Ww7V z%_f^o_TGmt_vYr@m-BSARFP4L5D*YB5dOwu%SOrHjmG{vav>nF{0m`zTP^`UD|RbO zJ{xvEJ{}u(VJ6 z>RqIdc64-an*}K5AZ-UAemx4uIqk2~WIP~j*f$8$!If+UInR2e$q(g!=FuH-F4L-4 z9dYM91Y;{#CsPV><>WPb+O>B}bWg&$d6f8SWagJ$DRHjNnOwXeRSe4r{pSursKP2+ z5*!Csj==m?xdmqNt(gZb?I}|u@T-17dXyRCfw)Zm+V*Ay#4LOW7g^5bn$2t^_RxbI zb~nFqnEJIPe82VAW1vgLGN5?NciA2C@u8*RO#64`l1El`KGb^eq{hBl4d;)_RN9|h z;2vSvnrG6N7_BRX3JZ;r19(S{2)`5E;kr~#Mr_~Kl~nJtaO8z|tn0FriIPLEk-0X6 zvkrodN)M#{Ib62%^qF1q_<~==kbKIOK6YgSp`>(Lk|N2qo8u_hSPg*eGz2WtsELJg z&i!U|fb7dz**KzB*2#Yx-xvl~W{KI5olssKlTbSoK4HwQbkz%LRT0Zs&^mDvdZM^f zaJ6-Hs!Z$PJ3v>ei2UT60fWv}du)Y_hI){-2L5Ct%oxT=k6UZvoJj>&I^!)jbKH&Z zn`AY%?Dat5!Xs-{1DBUi;|eN+y0ooBU9<+W zXtE^aR5vrFAIN4;N9Ijz8F;tVH*fW17b6FKG25!*j&7OkS`7Kf{_6PgnqvHT(@?hk zLv`$3uPtrWhuOD|xBV3K-Z=x^L*J84#xI&3h8UoEF81qz>!y#mJLY5D1@>wIkH3r( zKD4hMlFtyiV)%T#VfSo7!H3Sox<$um(_bE!wiwmw%hWWmIl0OA#aZY==|=ILqn824 zdZOgHV!5W3XWn)GHS;s9Br+0=)89}`$X;b0zt|G{kaO!YVoO;^U|9U?4*?C z!%|*r>zZj^}+;2PT53CIGVe$h&mj**Cis2A- z`8%{XPB83WbizI%%r;n-d1*hl?rK}yc6^H~msEv1`WhYfE;4vHO~yK60KQbPy+H~& z`rp(kJ4~kAZ*nz~nKy2r#MMU^21S{qW`tix;>?ZXUT`dLZ6bRY-q$g#o^Br|Ldz)_ zDg*O{d2CY7!@cjB=Op+FYx~N>fq<(Ap`nroe+W26+&nUTGK}0iDtO^=(%MYj)iRO# z?oT?0ZWTHZ_P``(^9-`JtTQyLdIA#NI|)c0!3Dc?);nWKZ{Cszq-_5F9y*io>5Hs_ zAnWq_~2s-hqXHNdHM>xV6h`*qRK!=$MrB=hXz+vHdBI$$LU=ggLL z^jO=a$aVtKjpt#M5lUhlQ9Qx@QXkS}vB$}6U~xu4-=rlJC}joEaE7=&(6 z-FR1gL)Z7leecjH^`_wsAd@Ib5u$uuuP82a*C4daRl_d$88oY z?qOz0+t3y^;Qp(6uXXmoj0;jop*I%skt<_q-YP(blUACHztsDilz|0Jd@ULU$sc+RLK@h*@r?;B}v z5IR{Rml=D#;)V+nRmdHtzuv~~FmDRVv)(rn+fk1Yzhcp14yw3Di#tW^85Hq1ZQVh1EGVb^Pax`C0-tS*wo!YH)*C?b4l>Vd)h$bQvM zNSz2P#E`kRXV;MRxn)F7ARMWiXcSQ(iu@Eq6X`bGc#i~zADH>Am4e1_OzOkKBI!m< z5joA{8()ep_|OZrSOWD$LqRZUQF*|}qFR(&V0a?+IQvVvdeiP8IhwTVglv`-h2`=uZ zwI0SrzXM<)cRy#(T3;a9U#glApBlWuG3yBb(Dk~5p$5_3H;wnI@2XOw=YrfS{!*7u z!a)pbk#MBP%1@F8K3KPxe-~fzp(YrDTIB`9&np ztMlJ}{Q*|$yDUgbRY&CGkDxUh_5?3`NWEGwS7;n+Y6(spup!c*h{@AP*SUfef@0ej zlCCAABKL2mkX~}vCOp`U((16TP~2 zxKU*Dd2$2VNmPQMwt~1_3Aj|k8m7@uWe7mq1%nXTy!oGrE^CkEty^Pbnro5D>Aspl ziUt=k7gWZqNu}1Qa&_*oo?Z2$e^eRLTjSg3$omYe6;Z8!i9pU+Of8oM{Iqvl_}wkRr_ix0&v0i6~@8!2pJC z0?yO1Lt}PzprseZS^620EvXAmX#;6|$gCV5aw66pHHh;7pohN53HJUgym11h0jGT- znJ#Tb$S;1B9Xh0Q7{kcJ_icsw*?<*Go{dAqDRdLD{m}#B1gZm$H28~O^a20@7UFd; z^36^G%h6?Y1+qrj_`+%8r5B+Oov?kBJsBZ})OR8HZny>6jN6V{zL7h7RpcaO z5gO`zz>0is7z+KjO(6iDFK#}CfU5I7l!)6=*Ub>G`aIq+tQvmPydGtaCD@oHL7j90pUrRf%j^&T{Jpd~)}G*FsWLG6xG|$2-QLDh zs_|#`jtveNrTh3?w*S(#Uy?=#qbF-XKV_X`86NIM@j3^XQuIuxS==-_^47lWv$vJq zAS-P47_7Qm>CT+iJm*k8G{$l8J-3y)##sctTD3kLG_*=!qr&g1_QQB(#59Eb%crLV zyB0Zy2en_nt@k~(T!~f6Jdu38;wfg|vSD{Jz{iU_vPH+URQobavCM`S`ojBP9;v#WL= z>Z>yLbwtLvJL$L%%hHAtZ)_WxxdjDH?IaWh#|7-DgT4f|^*0Mk?5N0h@9(^Ql#GIQ zIPZo_?1=li8lhhfl>D5VUi_o>5u6|BkcdlML!dv$Kug0CZ>N#VXU~Vj14NKiemoKL z8^EUPT9E^p7+)OUXJn4d@ETz@+s$N&yHVJsIlvm?kZ-d?&o2WH?C?`O%u(#MA9=o$ zFRG_EyMLUP8e&~#83rVlo?X{NHswSt)xi)PQDuT0WK_FkPNI*INOd%XY!yZvU(ZCP zliy@uGXh7|XauM@$j8aYgvj>o&U@JHj=HIZDP;bHTs~l z#J%r#h;A3H8V{i4hs=?{$rrsAJ!&sZf`nK1fw!_E1@2Ahg8SUhmgqI(azDLQ4M@iN zC^^OE24Bns*a5 zYX13M#}>VKWJ{)NbfNLRWwol7POHxS-zz(`+@#DH?~BEaN{`5>vKM7uzs4yEHtZ6? z%b<$VnhJ`OpC?)Tqq&=9t&ST?%NVFxmMrV7#gut+RWr>z947bo(U#Wsuepn;P z2CFR7mLNf@aY{4MQuz%Ey_;>92&Gazd0)1pkuV>KwP$FYH0)fzzAyzRb18KS!#fP| zDm)@sn%t?!zS76PA{H;7zsbm`LvQ< zujr5-h3qLt)ms{ZJ(|eq>yHUna6T$~q`<+!`i{I(0_}hdrjfw{)sLA>FU8Y#MTJzp z*e50C?c_m#FH~OBZ=h(72(>P=r?NoiPd(G^7sqAn!C@OdA#19pGdl0kztLc)mT@T{ z7Be~GoNdd0Ql|LXVMXGm$s{cIE-K^)y>^vSo|GH9rXpxxY-9~l>K#GNBhG=cQF4E7 zPQ)#W|4u#$G>eS?!x}d`c5DPSs!rJR`EPK;qm=L;;3B%{6}`SczsYyVAJc^r&E~K3qG|;RjqSU&+G3p*#4?VcqDZL6ezyGN!?Y&PAwMCGXttI%{xhL8yTaq?Eq< z!Dq0=I+ttmY;wh-`*-ieub$qXlxxTIW~q$@is3z}pp}|?M^7ZTK{O0Ozv+k!XItJ+ ztD2PAu@d&U|2j?_Wf89v($Jg`iub|tXMYh$t*YDIY6l0NCw1QrW4HSAJsemBZ5|$j zc=CN$8#*Yuse0CY|4tT1nYIGD4da+(W(J81-!t|qml8NsXvJnZY`DH*u52LwX6eOO zS=lmpgRjK@9j`nq4@p?zC}%LCs(}HYF7g11dgq<8GP&Ae+?Lx6RC8wWoWnR|#or^n z#*ni+O-L?dB$%ySp}o{={FHmXPRfKTAdMzNu`Kd!M#z({447Y!hR=?#UPT;3TsRPy zp4Ci{VaAufHd_@(ddu4eCH3r1WMq6r})JmSFPFdJrM`@a{?6axWC`G}A^DqGoIlg>9x%ssmFHAc zA;yh4FL&ObY{WN%1-N@ZkQEL$$G;3WwzQ5C?2izkG6-CG9J)TO|IP@-u!NrV(IF!O z^B$y&*w-qd>0l#76lq7<_+~i>wK9}j-kQ0>a__4_Y*flT4t|0TMxo|Gdl@&YMrW|_ zyf>Rk#+sy%!PnQtW14igo!1F%z6^)&_4m-!DYYxrb*s~~n$M{#zt~jJ>Kv8V(9+i4 z*g{(07N zU#$Pmp^gUD6>_j~06U-(Tzh@KF1lDf`}$<|G`?Nw)~I&+x44+O+%wT@SuA!g(T~rN zmHKA#w_@Giy|&*|g5qw%ZWaBZm22Khof#gU!Ab#UAiM>3)4w63*ZCrZ{O}|}InXr) zDEm-=^Z;@c|HA%q!+sU`IP!MD@9;zfov$>&X%zS7{fYQ{R}k>5k%iHQbAPk6 zv>`9*-r5WeOnzihj!z!MY(Xwx=F_No(zlR6)h*&N*Y?j*K;h+iW6?!6m(t{sdS4>4 zTY#&rxiRB(jqCp|IZW2TpJOt1#LY=mIgpIsnu_FWt6e;Mw;{xXkgAk8nI`qZsD(Bv zyvkm`XZB0;m2<6&qi_R=jZU%pn;+RV=FBo@`K9B9KhnO?%gL_4Nh)<;z>P1{#oja~ zP5Tq~;tO(M&{(VFdC$4z)(}~%)j} zHaDuLH34?Tfy}eJl|Mlb3)|1$JHVBocd@TYa85+6|IRZ*9m?fCGU0)xkq{6-Cf*ZaN#F@~PP8t@EI#8X^FN|lf;z-*2tigPkH zbrg##Zrs60*X2O={)MXU%7Jr7nG#W4#aq<9*%R6EOj#p%)rC#(AeEk5y&=)qjcZUYRKJY3dvzFX0C%hZGvfmP~T#f zQE#0|`ZS;WNqe8?#T>YB${6@t4y*v{!=MN#$xTUjBy>z@K=aez!CKP*$1RsptqQGc zk|dGUV%496zS~E$+R}9%)*?sIBLm?z(d9%m`4Vn|Q4@2fa3w3t2p9ictT=2AdNUk? zLMN+KIpxkKthpLGVjEiap8)2v_dljd3GU)?Wp^bc@nX?%6L_7;3XYi#EDg^QzNTP` zBCVgG%9kK`2UACUoY-(lhqhT1bsm4*L4MLduukZszN-JxqW4DwVYV}pKLAJ%KHlO7 zpyewOysjBD1=o3I%T2PT-pko?rE%RcxC@rsV8_gkw$Oz4V4M&15?no@=0_tjhZ+fC z8$IL`v60`W-u5o)k=v(nZlh|cA|eqX{NLI6KX&^c_5V%M|5cUzFV+9;;P?NfNc#_` z|9SmC{EUV0?-Bt45rGV0H$DE%j^h-f<+aM~_CI_MRr*hAsiLC&dxP{(H~m8q(toG_ E0K6^9ApigX diff --git a/src/Umbraco.Tests/Services/Importing/ImportResources.Designer.cs b/src/Umbraco.Tests/Services/Importing/ImportResources.Designer.cs deleted file mode 100644 index c0f070d1e9..0000000000 --- a/src/Umbraco.Tests/Services/Importing/ImportResources.Designer.cs +++ /dev/null @@ -1,383 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Umbraco.Tests.Services.Importing { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class ImportResources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal ImportResources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Umbraco.Tests.Services.Importing.ImportResources", typeof(ImportResources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> - ///<umbPackage> - /// <files /> - /// <info> - /// <package> - /// <name>CheckboxListTest</name> - /// <version>1</version> - /// <license url="http://www.opensource.org/licenses/mit-license.php">MIT license</license> - /// <url>1</url> - /// <requirements> - /// <major>3</major> - /// <minor>0</minor> - /// <patch>0</patch> - /// </requirements> - /// </package> - /// <author> - /// <name>1</name> - /// <website>1</website> - /// </author> - /// <r [rest of string was truncated]";. - /// - internal static string CheckboxList_Content_Package { - get { - return ResourceManager.GetString("CheckboxList_Content_Package", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> - ///<umbPackage> - /// <files /> - /// <info> - /// <package> - /// <name>Compositions Packaged</name> - /// <version>1.0</version> - /// <license url="http://opensource.org/licenses/MIT">MIT License</license> - /// <url>http://blog.sitereactor.dk</url> - /// <requirements> - /// <major>3</major> - /// <minor>0</minor> - /// <patch>0</patch> - /// </requirements> - /// </package> - /// <author> - /// <name>Morten Christensen</name> - /// <website>h [rest of string was truncated]";. - /// - internal static string CompositionsTestPackage { - get { - return ResourceManager.GetString("CompositionsTestPackage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> - ///<umbPackage> - /// <files /> - /// <info> - /// <package> - /// <name>Composite Test</name> - /// <version>dfsfd</version> - /// <license url="http://opensource.org/licenses/MIT">MIT License</license> - /// <url>ddsff</url> - /// <requirements> - /// <major>3</major> - /// <minor>0</minor> - /// <patch>0</patch> - /// </requirements> - /// </package> - /// <author> - /// <name>fsdfds</name> - /// <website>sfdf</website> - /// </author> - /// <rea [rest of string was truncated]";. - /// - internal static string CompositionsTestPackage_Random { - get { - return ResourceManager.GetString("CompositionsTestPackage_Random", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?> - ///<umbPackage> - /// <files /> - /// <info> - /// <package> - /// <name>Dictionary-Package</name> - /// <version>1.0</version> - /// <license url="http://www.opensource.org/licenses/mit-license.php">MIT license</license> - /// <url>http://not.available</url> - /// <requirements> - /// <major>3</major> - /// <minor>0</minor> - /// <patch>0</patch> - /// </requirements> - /// </package> - /// <author> - /// <name>Test</name> - /// <website>http://not.available</w [rest of string was truncated]";. - /// - internal static string Dictionary_Package { - get { - return ResourceManager.GetString("Dictionary_Package", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> - ///<umbPackage> - /// <files> - /// <file> - /// <guid>bootstrap.min.js</guid> - /// <orgPath>/js</orgPath> - /// <orgName>bootstrap.min.js</orgName> - /// </file> - /// <file> - /// <guid>jquery.min.js</guid> - /// <orgPath>/js</orgPath> - /// <orgName>jquery.min.js</orgName> - /// </file> - /// <file> - /// <guid>top-image.jpg</guid> - /// <orgPath>/Media/1001</orgPath> - /// <orgName>top-image.jpg</orgName> - /// </file> - /// <file> - /// <guid>top-im [rest of string was truncated]";. - /// - internal static string Fanoe_Package { - get { - return ResourceManager.GetString("Fanoe_Package", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> - ///<umbPackage> - /// <files /> - /// <info> - /// <package> - /// <name>DocTypeError</name> - /// <version>1</version> - /// <license url="http://www.opensource.org/licenses/mit-license.php">Personal license</license> - /// <url>http://www.iseli-webconsulting.de</url> - /// <requirements> - /// <major>3</major> - /// <minor>0</minor> - /// <patch>0</patch> - /// </requirements> - /// </package> - /// <author> - /// <name>Iseli Webconsulting</name> [rest of string was truncated]";. - /// - internal static string InheritedDocTypes_Package { - get { - return ResourceManager.GetString("InheritedDocTypes_Package", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?> - ///<DocumentType> - /// <Info> - /// <Name>test</Name> - /// <Alias>test</Alias> - /// <Icon>folder.gif</Icon> - /// <Thumbnail>folder.png</Thumbnail> - /// <Description> - /// </Description> - /// <AllowAtRoot>False</AllowAtRoot> - /// <AllowedTemplates> - /// <Template>test</Template> - /// </AllowedTemplates> - /// <DefaultTemplate>test</DefaultTemplate> - /// </Info> - /// <Structure> - /// <DocumentType>test</DocumentType> - /// </Structure> - /// <GenericProperties> - /// <GenericProperty> [rest of string was truncated]";. - /// - internal static string SingleDocType { - get { - return ResourceManager.GetString("SingleDocType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> - ///<umbPackage> - /// <files> - /// <file> - /// <guid>Map.cshtml</guid> - /// <orgPath>/macroScripts</orgPath> - /// <orgName>Map.cshtml</orgName> - /// </file> - /// <file> - /// <guid>AccountController.cs</guid> - /// <orgPath>/App_Code</orgPath> - /// <orgName>AccountController.cs</orgName> - /// </file> - /// <file> - /// <guid>ContactController.cs</guid> - /// <orgPath>/App_Code</orgPath> - /// <orgName>ContactController.cs</orgName> - /// </file> - /// [rest of string was truncated]";. - /// - internal static string StandardMvc_Package { - get { - return ResourceManager.GetString("StandardMvc_Package", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> - ///<umbPackage> - /// <files /> - /// <info> - /// <package> - /// <name>Template-Update</name> - /// <version>0.1</version> - /// <license url="http://www.opensource.org/licenses/mit-license.php">MIT license</license> - /// <url>https://our.umbraco.com/projects</url> - /// <requirements> - /// <major>3</major> - /// <minor>0</minor> - /// <patch>0</patch> - /// </requirements> - /// </package> - /// <author> - /// <name>Morten Christensen</name> - /// [rest of string was truncated]";. - /// - internal static string TemplateOnly_Package { - get { - return ResourceManager.GetString("TemplateOnly_Package", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> - ///<umbPackage> - /// <files /> - /// <info> - /// <package> - /// <name>Template-Update</name> - /// <version>0.1</version> - /// <license url="http://www.opensource.org/licenses/mit-license.php">MIT license</license> - /// <url>https://our.umbraco.com/projects</url> - /// <requirements> - /// <major>3</major> - /// <minor>0</minor> - /// <patch>0</patch> - /// </requirements> - /// </package> - /// <author> - /// <name>Morten Christensen</name> - /// [rest of string was truncated]";. - /// - internal static string TemplateOnly_Updated_Package { - get { - return ResourceManager.GetString("TemplateOnly_Updated_Package", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> - ///<umbPackage> - /// <files> - /// <file> - /// <guid>uBlogsy.BusinessLogic.dll</guid> - /// <orgPath>/bin</orgPath> - /// <orgName>uBlogsy.BusinessLogic.dll</orgName> - /// </file> - /// <file> - /// <guid>uBlogsy.BusinessLogic.pdb</guid> - /// <orgPath>/bin</orgPath> - /// <orgName>uBlogsy.BusinessLogic.pdb</orgName> - /// </file> - /// <file> - /// <guid>uBlogsy.Common.dll</guid> - /// <orgPath>/bin</orgPath> - /// <orgName>uBlogsy.Common.dll</orgNam [rest of string was truncated]";. - /// - internal static string uBlogsy_Package { - get { - return ResourceManager.GetString("uBlogsy_Package", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?> - ///<umbPackage> - /// <files> - /// <file> - /// <guid>XSLTsearch.xslt</guid> - /// <orgPath>/xslt</orgPath> - /// <orgName>XSLTsearch.xslt</orgName> - /// </file> - /// <file> - /// <guid>XSLTsearch.cs</guid> - /// <orgPath>/App_Code</orgPath> - /// <orgName>XSLTsearch.cs</orgName> - /// </file> - /// </files> - /// <info> - /// <package> - /// <name>XSLTsearch</name> - /// <version>3.0.4</version> - /// <license url="http://www.opensource.org/licenses/mit-li [rest of string was truncated]";. - /// - internal static string XsltSearch_Package { - get { - return ResourceManager.GetString("XsltSearch_Package", resourceCulture); - } - } - } -} diff --git a/src/Umbraco.Tests/Services/Importing/ImportResources.resx b/src/Umbraco.Tests/Services/Importing/ImportResources.resx deleted file mode 100644 index 97fb2469be..0000000000 --- a/src/Umbraco.Tests/Services/Importing/ImportResources.resx +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - inheriteddoctypes-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - - standardmvc-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - - ublogsy-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - - xsltsearch-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - - singledoctype.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - - templateonly-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - - templateonly-updated-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - - checkboxlist-content-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - - dictionary-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - - compositionstestpackage.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - - compositionstestpackage-random.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - - fanoe-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - \ No newline at end of file diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 807c64f315..861a16a2f3 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -200,7 +200,6 @@ - @@ -217,12 +216,6 @@ - - - True - True - ImportResources.resx - @@ -271,7 +264,6 @@ Designer - Designer @@ -311,11 +303,6 @@ - - ResXFileCodeGenerator - ImportResources.Designer.cs - Designer - ResXFileCodeGenerator TestFiles.Designer.cs @@ -323,23 +310,8 @@ - - Designer - - - - - - - - Designer - - - - - diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs index cc87797b85..05e4db5daa 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs @@ -11,18 +11,14 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using Umbraco.Core; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Dictionary; using Umbraco.Core.Hosting; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Packaging; using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Scoping; using Umbraco.Core.Security; -using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Web.Common.Attributes; @@ -45,9 +41,7 @@ namespace Umbraco.Web.BackOffice.Controllers // It would be possible to have something like a ContentTypeInfoController for the GetAllPropertyTypeAliases/GetCount/GetAllowedChildren/etc... actions private readonly IEntityXmlSerializer _serializer; - private readonly GlobalSettings _globalSettings; private readonly PropertyEditorCollection _propertyEditors; - private readonly IScopeProvider _scopeProvider; private readonly IContentTypeService _contentTypeService; private readonly UmbracoMapper _umbracoMapper; private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor; @@ -56,15 +50,10 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly ILocalizedTextService _localizedTextService; private readonly IFileService _fileService; private readonly ILogger _logger; - private readonly ILoggerFactory _loggerFactory; private readonly IContentService _contentService; private readonly IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider; - private readonly ILocalizationService _LocalizationService; - private readonly IMacroService _macroService; - private readonly IEntityService _entityService; private readonly IHostingEnvironment _hostingEnvironment; - private readonly IConfigurationEditorJsonSerializer _configurationEditorJsonSerializer; - private readonly IJsonSerializer _jsonSerializer; + private readonly PackageDataInstallation _packageDataInstallation; public ContentTypeController( ICultureDictionary cultureDictionary, @@ -74,24 +63,17 @@ namespace Umbraco.Web.BackOffice.Controllers UmbracoMapper umbracoMapper, ILocalizedTextService localizedTextService, IEntityXmlSerializer serializer, - IOptions globalSettings, PropertyEditorCollection propertyEditors, - IScopeProvider scopeProvider, IBackOfficeSecurityAccessor backofficeSecurityAccessor, IDataTypeService dataTypeService, IShortStringHelper shortStringHelper, IFileService fileService, ILogger logger, - ILoggerFactory loggerFactory, IContentService contentService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, - ILocalizationService localizationService, - IMacroService macroService, - IEntityService entityService, IHostingEnvironment hostingEnvironment, EditorValidatorCollection editorValidatorCollection, - IConfigurationEditorJsonSerializer configurationEditorJsonSerializer, - IJsonSerializer jsonSerializer) + PackageDataInstallation packageDataInstallation) : base(cultureDictionary, editorValidatorCollection, contentTypeService, @@ -101,9 +83,7 @@ namespace Umbraco.Web.BackOffice.Controllers localizedTextService) { _serializer = serializer; - _globalSettings = globalSettings.Value; _propertyEditors = propertyEditors; - _scopeProvider = scopeProvider; _contentTypeService = contentTypeService; _umbracoMapper = umbracoMapper; _backofficeSecurityAccessor = backofficeSecurityAccessor; @@ -112,15 +92,10 @@ namespace Umbraco.Web.BackOffice.Controllers _localizedTextService = localizedTextService; _fileService = fileService; _logger = logger; - _loggerFactory = loggerFactory; _contentService = contentService; _contentTypeBaseServiceProvider = contentTypeBaseServiceProvider; - _LocalizationService = localizationService; - _macroService = macroService; - _entityService = entityService; _hostingEnvironment = hostingEnvironment; - _configurationEditorJsonSerializer = configurationEditorJsonSerializer; - _jsonSerializer = jsonSerializer; + _packageDataInstallation = packageDataInstallation; } [Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)] @@ -640,30 +615,13 @@ namespace Umbraco.Web.BackOffice.Controllers return NotFound(); } - var dataInstaller = new PackageDataInstallation( - _loggerFactory.CreateLogger(), - _loggerFactory, - _fileService, - _macroService, - _LocalizationService, - _dataTypeService, - _entityService, - _contentTypeService, - _contentService, - _propertyEditors, - _scopeProvider, - _shortStringHelper, - Options.Create(_globalSettings), - _localizedTextService, - _configurationEditorJsonSerializer, - _jsonSerializer); var xd = new XmlDocument {XmlResolver = null}; xd.Load(filePath); var userId = _backofficeSecurityAccessor.BackOfficeSecurity.GetUserId().ResultOr(0); var element = XElement.Parse(xd.InnerXml); - dataInstaller.ImportDocumentType(element, userId); + _packageDataInstallation.ImportDocumentType(element, userId); // Try to clean up the temporary file. try diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs index f03130b537..67cd41ff29 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs @@ -479,7 +479,7 @@ namespace Umbraco.Web.BackOffice.Controllers { // Authorize... var requirement = new MediaPermissionsResourceRequirement(); - var authorizationResult = await _authorizationService.AuthorizeAsync(User, _mediaService.GetById(move.Id), requirement); + var authorizationResult = await _authorizationService.AuthorizeAsync(User, new MediaPermissionsResource(_mediaService.GetById(move.Id)), requirement); if (!authorizationResult.Succeeded) { return Forbid(); diff --git a/src/Umbraco.Web.BackOffice/Controllers/PackageController.cs b/src/Umbraco.Web.BackOffice/Controllers/PackageController.cs index 36bf4d2fca..7f6bfe781f 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/PackageController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/PackageController.cs @@ -13,11 +13,9 @@ using Umbraco.Core.Hosting; using Umbraco.Core.Models.Packaging; using Umbraco.Core.Security; using Umbraco.Core.Services; -using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.Common.Attributes; using Umbraco.Web.Common.Authorization; using Umbraco.Web.Common.Exceptions; -using Umbraco.Web.Security; namespace Umbraco.Web.BackOffice.Controllers { @@ -105,7 +103,7 @@ namespace Umbraco.Web.BackOffice.Controllers if (package == null) return NotFound(); - var fullPath = _hostingEnvironment.MapPathContentRoot(package.PackagePath); + var fullPath = _hostingEnvironment.MapPathWebRoot(package.PackagePath); if (!System.IO.File.Exists(fullPath)) throw HttpResponseException.CreateNotificationValidationErrorResponse("No file found for path " + package.PackagePath); diff --git a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs index 38d78860b0..f34197d23e 100644 --- a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs @@ -1,5 +1,4 @@ using System; -using System.Threading; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; using Umbraco.Net; @@ -21,16 +20,6 @@ namespace Umbraco.Web.Common.AspNetCore public void Restart() { IsRestarting = true; - - var httpContext = _httpContextAccessor.HttpContext; - if (httpContext != null) - { - // unload app domain - we must null out all identities otherwise we get serialization errors - // http://www.zpqrtbnk.net/posts/custom-iidentity-serialization-issue - httpContext.User = null; - } - - Thread.CurrentPrincipal = null; _hostApplicationLifetime.StopApplication(); } diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index de8ad6d1c4..cb9c42e44d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -16,6 +16,7 @@ vm.filesOpen = true; vm.actionsOpen = true; vm.loading = true; + vm.mediaNodeDisplayModels = []; vm.back = back; vm.createOrUpdatePackage = createOrUpdatePackage; vm.removeContentItem = removeContentItem; @@ -28,6 +29,7 @@ vm.contributorsEditor = null; vm.selectDocumentType = selectDocumentType; + vm.selectMediaType = selectMediaType; vm.selectTemplate = selectTemplate; vm.selectStyleSheet = selectStyleSheet; vm.selectMacro = selectMacro; @@ -35,6 +37,15 @@ vm.selectDictionaryItem = selectDictionaryItem; vm.selectDataType = selectDataType; + vm.mediaPickerModel = { + hideLabel: true, + view: "mediapicker", + value: "", + config: { + multiPicker: true, + allowEdit:false + } + } vm.labels = {}; vm.versionRegex = /^(\d+\.)(\d+\.)(\*|\d+)$/; @@ -76,6 +87,7 @@ }); } + vm.mediaPickerModel.value = vm.package.mediaUdis.join(','); }); @@ -88,20 +100,31 @@ function loadResources() { - // Get all document types - entityResource.getAll("DocumentType").then(documentTypes => { - // a package stores the id as a string so we - // need to convert all ids to string for comparison - documentTypes.forEach(documentType => { - documentType.id = documentType.id.toString(); - documentType.selected = vm.package.documentTypes.indexOf(documentType.id) !== -1; - }); - vm.documentTypes = documentTypes; + // Get all document types + entityResource.getAll("DocumentType").then(documentTypes => { + // a package stores the id as a string so we + // need to convert all ids to string for comparison + documentTypes.forEach(documentType => { + documentType.id = documentType.id.toString(); + documentType.selected = vm.package.documentTypes.indexOf(documentType.id) !== -1; }); + vm.documentTypes = documentTypes; + }); + + // Get all media types + entityResource.getAll("MediaType").then(mediaTypes => { + // a package stores the id as a string so we + // need to convert all ids to string for comparison + mediaTypes.forEach(mediaType => { + mediaType.id = mediaType.id.toString(); + mediaType.selected = vm.package.mediaTypes.indexOf(mediaType.id) !== -1; + }); + vm.mediaTypes = mediaTypes; + }); // Get all templates entityResource.getAll("Template").then(templates => { - // a package stores the id as a string so we + // a package stores the id as a string so we // need to convert all ids to string for comparison templates.forEach(template => { template.id = template.id.toString(); @@ -120,7 +143,7 @@ // Get all macros entityResource.getAll("Macro").then(macros => { - // a package stores the id as a string so we + // a package stores the id as a string so we // need to convert all ids to string for comparison macros.forEach(macro => { macro.id = macro.id.toString(); @@ -131,7 +154,7 @@ // Get all languages entityResource.getAll("Language").then(languages => { - // a package stores the id as a string so we + // a package stores the id as a string so we // need to convert all ids to string for comparison languages.forEach(language => { language.id = language.id.toString(); @@ -142,7 +165,7 @@ // Get all dictionary items entityResource.getAll("DictionaryItem").then(dictionaryItems => { - // a package stores the id as a string so we + // a package stores the id as a string so we // need to convert all ids to string for comparison dictionaryItems.forEach(dictionaryItem => { dictionaryItem.id = dictionaryItem.id.toString(); @@ -153,7 +176,7 @@ // Get all data types entityResource.getAll("DataType").then(dataTypes => { - // a package stores the id as a string so we + // a package stores the id as a string so we // need to convert all ids to string for comparison dataTypes.forEach(dataType => { dataType.id = dataType.id.toString(); @@ -181,10 +204,12 @@ function createOrUpdatePackage(editPackageForm) { - let contributors = vm.contributorsEditor.value.map(o => o.value); + let contributors = vm.contributorsEditor.value.map(o => o.value) vm.package.contributors = contributors; + // Split by comma and remove empty entries + vm.package.mediaUdis = vm.mediaPickerModel.value.split(",").filter(i => i); if (formHelper.submitForm({ formCtrl: editPackageForm, scope: $scope })) { vm.buttonState = "busy"; @@ -215,23 +240,23 @@ vm.package.contentNodeId = null; } - function openContentPicker() { - const contentPicker = { - submit: function (model) { - if (model.selection && model.selection.length > 0) { - vm.package.contentNodeId = model.selection[0].id.toString(); - vm.contentNodeDisplayModel = model.selection[0]; - } - editorService.close(); - }, - close: function () { - editorService.close(); - } - }; - editorService.contentPicker(contentPicker); - } + function openContentPicker() { + const contentPicker = { + submit: function (model) { + if (model.selection && model.selection.length > 0) { + vm.package.contentNodeId = model.selection[0].id.toString(); + vm.contentNodeDisplayModel = model.selection[0]; + } + editorService.close(); + }, + close: function () { + editorService.close(); + } + }; + editorService.contentPicker(contentPicker); + } - function openFilePicker() { + function openFilePicker() { let selection = Utilities.copy(vm.package.files); @@ -313,6 +338,18 @@ } } + function selectMediaType(mediatype) { + + // Check if the document type is already selected. + var index = vm.package.mediaTypes.indexOf(mediatype.id); + + if (index === -1) { + vm.package.mediaTypes.push(mediatype.id); + } else { + vm.package.mediaTypes.splice(index, 1); + } + } + function selectTemplate(template) { // Check if the template is already selected. diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index ce65d1cff6..f4011a9d78 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -137,6 +137,22 @@ + + + + + + + + + + + + + +
+ +
+ + +
+
+
+ text="{{template.name}}">umb-expansion-panel__content
diff --git a/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj b/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj index 211238d951..8d9ca58ea9 100644 --- a/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj +++ b/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj @@ -22,6 +22,7 @@ + diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml index 0bbba93c89..b48fad5edd 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml @@ -730,6 +730,7 @@ Logout Macro Mandatory + Media Message Move Name