Merge remote-tracking branch 'origin/netcore/netcore' into netcore/task/front-end-routing
# Conflicts: # src/Umbraco.PublishedCache.NuCache/PublishedSnapshotService.cs # src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs # src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs
This commit is contained in:
@@ -18,7 +18,7 @@ namespace Umbraco.Core
|
||||
/// <remarks>
|
||||
/// This is not the same as the Umbraco web folder which is configurable for serving front-end files.
|
||||
/// </remarks>
|
||||
public const string Umbraco = "~/Umbraco";
|
||||
public const string Umbraco = "~/umbraco";
|
||||
|
||||
/// <summary>
|
||||
/// The Umbraco data folder in the content root
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Umbraco.Core.Events;
|
||||
|
||||
@@ -26,5 +27,22 @@ namespace Umbraco.Core.DependencyInjection
|
||||
builder.Services.AddTransient(typeof(INotificationHandler<TNotification>), typeof(TNotificationHandler));
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a notification handler against the Umbraco service collection.
|
||||
/// </summary>
|
||||
/// <typeparam name="TNotification">The type of notification.</typeparam>
|
||||
/// <typeparam name="TNotificationHandler">The type of notificiation handler.</typeparam>
|
||||
/// <param name="builder">The Umbraco builder.</param>
|
||||
/// <param name="factory">Factory method</param>
|
||||
/// <returns>The <see cref="IUmbracoBuilder"/>.</returns>
|
||||
public static IUmbracoBuilder AddNotificationHandler<TNotification, TNotificationHandler>(this IUmbracoBuilder builder, Func<IServiceProvider, TNotificationHandler> factory)
|
||||
where TNotificationHandler : class, INotificationHandler<TNotification>
|
||||
where TNotification : INotification
|
||||
{
|
||||
// Register the handler as transient. This ensures that anything can be injected into it.
|
||||
builder.Services.AddTransient(typeof(INotificationHandler<TNotification>), factory);
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
16
src/Umbraco.Core/Events/UmbracoApplicationStarting.cs
Normal file
16
src/Umbraco.Core/Events/UmbracoApplicationStarting.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
public class UmbracoApplicationStarting : INotification
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoApplicationStarting"/> class.
|
||||
/// </summary>
|
||||
/// <param name="runtimeLevel">The runtime level</param>
|
||||
public UmbracoApplicationStarting(RuntimeLevel runtimeLevel) => RuntimeLevel = runtimeLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the runtime level of execution.
|
||||
/// </summary>
|
||||
public RuntimeLevel RuntimeLevel { get; }
|
||||
}
|
||||
}
|
||||
4
src/Umbraco.Core/Events/UmbracoApplicationStopping.cs
Normal file
4
src/Umbraco.Core/Events/UmbracoApplicationStopping.cs
Normal file
@@ -0,0 +1,4 @@
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
public class UmbracoApplicationStopping : INotification { }
|
||||
}
|
||||
@@ -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<XElement> Languages { get; set; } // TODO: make strongly typed
|
||||
public IEnumerable<XElement> DictionaryItems { get; set; } // TODO: make strongly typed
|
||||
public IEnumerable<XElement> DocumentTypes { get; set; } // TODO: make strongly typed
|
||||
public IEnumerable<CompiledPackageDocument> Documents { get; set; }
|
||||
public IEnumerable<XElement> MediaTypes { get; set; } // TODO: make strongly typed
|
||||
public IEnumerable<CompiledPackageContentBase> Documents { get; set; }
|
||||
public IEnumerable<CompiledPackageContentBase> Media { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models.Packaging
|
||||
{
|
||||
public class CompiledPackageDocument
|
||||
/// <summary>
|
||||
/// Compiled representation of a content base (Document or Media)
|
||||
/// </summary>
|
||||
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 <DocumentSet>", nameof(xml));
|
||||
return new CompiledPackageDocument
|
||||
public static CompiledPackageContentBase Create(XElement xml) =>
|
||||
new CompiledPackageContentBase
|
||||
{
|
||||
XmlData = xml,
|
||||
ImportMode = xml.AttributeValue<string>("importMode")
|
||||
};
|
||||
}
|
||||
|
||||
public string ImportMode { get; set; } //this is never used
|
||||
|
||||
@@ -23,4 +21,4 @@ namespace Umbraco.Core.Models.Packaging
|
||||
/// </summary>
|
||||
public XElement XmlData { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<XElement>(),
|
||||
DictionaryItems = xml.Root.Element("DictionaryItems")?.Elements("DictionaryItem") ?? Enumerable.Empty<XElement>(),
|
||||
DocumentTypes = xml.Root.Element("DocumentTypes")?.Elements("DocumentType") ?? Enumerable.Empty<XElement>(),
|
||||
Documents = xml.Root.Element("Documents")?.Elements("DocumentSet")?.Select(CompiledPackageDocument.Create) ?? Enumerable.Empty<CompiledPackageDocument>(),
|
||||
MediaTypes = xml.Root.Element("MediaTypes")?.Elements("MediaType") ?? Enumerable.Empty<XElement>(),
|
||||
Documents = xml.Root.Element("Documents")?.Elements("DocumentSet")?.Select(CompiledPackageContentBase.Create) ?? Enumerable.Empty<CompiledPackageContentBase>(),
|
||||
Media = xml.Root.Element("MediaItems")?.Elements()?.Select(CompiledPackageContentBase.Create) ?? Enumerable.Empty<CompiledPackageContentBase>(),
|
||||
};
|
||||
|
||||
def.Warnings = GetPreInstallWarnings(def, applicationRootFolder);
|
||||
|
||||
@@ -17,11 +17,13 @@ namespace Umbraco.Core.Models.Packaging
|
||||
public IEnumerable<string> FilesInstalled { get; set; } = Enumerable.Empty<string>();
|
||||
public IEnumerable<ITemplate> TemplatesInstalled { get; set; } = Enumerable.Empty<ITemplate>();
|
||||
public IEnumerable<IContentType> DocumentTypesInstalled { get; set; } = Enumerable.Empty<IContentType>();
|
||||
public IEnumerable<IMediaType> MediaTypesInstalled { get; set; } = Enumerable.Empty<IMediaType>();
|
||||
public IEnumerable<IFile> StylesheetsInstalled { get; set; } = Enumerable.Empty<IFile>();
|
||||
public IEnumerable<IContent> ContentInstalled { get; set; } = Enumerable.Empty<IContent>();
|
||||
public IEnumerable<IMedia> MediaInstalled { get; set; } = Enumerable.Empty<IMedia>();
|
||||
public IEnumerable<PackageAction> Actions { get; set; } = Enumerable.Empty<PackageAction>();
|
||||
public IEnumerable<string> ActionErrors { get; set; } = Enumerable.Empty<string>();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<string> DocumentTypes { get; set; } = new List<string>();
|
||||
|
||||
[DataMember(Name = "mediaTypes")]
|
||||
public IList<string> MediaTypes { get; set; } = new List<string>();
|
||||
|
||||
[DataMember(Name = "stylesheets")]
|
||||
public IList<string> Stylesheets { get; set; } = new List<string>();
|
||||
|
||||
@@ -133,6 +135,12 @@ namespace Umbraco.Core.Models.Packaging
|
||||
[DataMember(Name = "iconUrl")]
|
||||
public string IconUrl { get; set; } = string.Empty;
|
||||
|
||||
[DataMember(Name = "mediaUdis")]
|
||||
public IList<GuidUdi> MediaUdis { get; set; } = Array.Empty<GuidUdi>();
|
||||
|
||||
[DataMember(Name = "mediaLoadChildNodes")]
|
||||
public bool MediaLoadChildNodes { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -46,10 +46,13 @@ namespace Umbraco.Core.Packaging
|
||||
Actions = xml.Element("actions")?.ToString(SaveOptions.None) ?? "<actions></actions>", //take the entire outer xml value
|
||||
ContentNodeId = xml.Element("content")?.AttributeValue<string>("nodeId") ?? string.Empty,
|
||||
ContentLoadChildNodes = xml.Element("content")?.AttributeValue<bool>("loadChildNodes") ?? false,
|
||||
MediaUdis = xml.Element("media")?.Elements("nodeUdi").Select(x => (GuidUdi)UdiParser.Parse(x.Value)).ToList() ?? new List<GuidUdi>(),
|
||||
MediaLoadChildNodes = xml.Element("media")?.AttributeValue<bool>("loadChildNodes") ?? false,
|
||||
Macros = xml.Element("macros")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>(),
|
||||
Templates = xml.Element("templates")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>(),
|
||||
Stylesheets = xml.Element("stylesheets")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>(),
|
||||
DocumentTypes = xml.Element("documentTypes")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>(),
|
||||
MediaTypes = xml.Element("mediaTypes")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>(),
|
||||
Languages = xml.Element("languages")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>(),
|
||||
DictionaryItems = xml.Element("dictionaryitems")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>(),
|
||||
DataTypes = xml.Element("datatypes")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>(),
|
||||
@@ -103,11 +106,17 @@ namespace Umbraco.Core.Packaging
|
||||
new XElement("templates", string.Join(",", def.Templates ?? Array.Empty<string>())),
|
||||
new XElement("stylesheets", string.Join(",", def.Stylesheets ?? Array.Empty<string>())),
|
||||
new XElement("documentTypes", string.Join(",", def.DocumentTypes ?? Array.Empty<string>())),
|
||||
new XElement("mediaTypes", string.Join(",", def.MediaTypes ?? Array.Empty<string>())),
|
||||
new XElement("macros", string.Join(",", def.Macros ?? Array.Empty<string>())),
|
||||
new XElement("files", (def.Files ?? Array.Empty<string>()).Where(x => !x.IsNullOrWhiteSpace()).Select(x => new XElement("file", x))),
|
||||
new XElement("languages", string.Join(",", def.Languages ?? Array.Empty<string>())),
|
||||
new XElement("dictionaryitems", string.Join(",", def.DictionaryItems ?? Array.Empty<string>())));
|
||||
new XElement("dictionaryitems", string.Join(",", def.DictionaryItems ?? Array.Empty<string>())),
|
||||
|
||||
new XElement(
|
||||
"media",
|
||||
def.MediaUdis.Select(x=> (object)new XElement("nodeUdi", x))
|
||||
.Union(new []{new XAttribute("loadChildNodes", def.MediaLoadChildNodes) }))
|
||||
);
|
||||
return packageXml;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
@@ -65,6 +67,8 @@ namespace Umbraco.Core.Packaging
|
||||
ILoggerFactory loggerFactory,
|
||||
IUmbracoVersion umbracoVersion,
|
||||
IOptions<GlobalSettings> 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<PackageDefinitionXmlParser>(), 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<IMediaType>();
|
||||
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<IMedia> medias = _mediaService.GetByIds(definition.MediaUdis);
|
||||
|
||||
root.Add(
|
||||
new XElement(
|
||||
"MediaItems",
|
||||
medias.Select(x => new XElement("MediaSet", _serializer.Serialize(x, definition.MediaLoadChildNodes)))));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Zips the package.
|
||||
/// </summary>
|
||||
@@ -461,12 +499,12 @@ namespace Umbraco.Core.Packaging
|
||||
/// <param name="packageDirectory">The package directory.</param>
|
||||
/// <param name="filesXml">The files xml node</param>
|
||||
/// <param name="isWebFile">true if it's a web file, false if it's a content file</param>
|
||||
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<IMediaType> 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)
|
||||
{
|
||||
|
||||
|
||||
@@ -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
|
||||
/// <summary>
|
||||
/// Defines the ContentService, which is an easy access to operations involving <see cref="IContent"/>
|
||||
/// </summary>
|
||||
public interface IContentService : IContentServiceBase
|
||||
public interface IContentService : IContentServiceBase<IContent>
|
||||
{
|
||||
#region Blueprints
|
||||
|
||||
|
||||
@@ -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<TItem> : IContentServiceBase
|
||||
where TItem: class, IContentBase
|
||||
{
|
||||
TItem GetById(Guid key);
|
||||
Attempt<OperationResult> Save(IEnumerable<TItem> contents, int userId = Constants.Security.SuperUserId, bool raiseEvents = true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Placeholder for sharing logic between the content, media (and member) services
|
||||
/// TODO: Start sharing the logic!
|
||||
|
||||
@@ -58,7 +58,6 @@ namespace Umbraco.Core.Services
|
||||
|
||||
void Save(TItem item, int userId = Constants.Security.SuperUserId);
|
||||
void Save(IEnumerable<TItem> items, int userId = Constants.Security.SuperUserId);
|
||||
|
||||
void Delete(TItem item, int userId = Constants.Security.SuperUserId);
|
||||
void Delete(IEnumerable<TItem> item, int userId = Constants.Security.SuperUserId);
|
||||
|
||||
|
||||
@@ -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
|
||||
/// <summary>
|
||||
/// Defines the Media Service, which is an easy access to operations involving <see cref="IMedia"/>
|
||||
/// </summary>
|
||||
public interface IMediaService : IContentServiceBase
|
||||
public interface IMediaService : IContentServiceBase<IMedia>
|
||||
{
|
||||
int CountNotTrashed(string contentTypeAlias = null);
|
||||
int Count(string mediaTypeAlias = null);
|
||||
|
||||
@@ -1,22 +1,15 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the Umbraco runtime.
|
||||
/// </summary>
|
||||
public interface IRuntime
|
||||
public interface IRuntime : IHostedService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the runtime state.
|
||||
/// </summary>
|
||||
IRuntimeState State { get; }
|
||||
|
||||
void Start();
|
||||
|
||||
/// <summary>
|
||||
/// Terminates the runtime.
|
||||
/// </summary>
|
||||
void Terminate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="2.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="3.1.8" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Core.Manifest;
|
||||
using Umbraco.Net;
|
||||
|
||||
namespace Umbraco.Core.Compose
|
||||
{
|
||||
public sealed class ManifestWatcherComponent : IComponent
|
||||
{
|
||||
private readonly IHostingEnvironment _hosting;
|
||||
private readonly ILoggerFactory _loggerFactory;
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
|
||||
|
||||
// if configured and in debug mode, a ManifestWatcher watches App_Plugins folders for
|
||||
// package.manifest chances and restarts the application on any change
|
||||
private ManifestWatcher _mw;
|
||||
|
||||
public ManifestWatcherComponent(IHostingEnvironment hosting, ILoggerFactory loggerFactory, IHostingEnvironment hostingEnvironment, IUmbracoApplicationLifetime umbracoApplicationLifetime)
|
||||
{
|
||||
_hosting = hosting;
|
||||
_loggerFactory = loggerFactory;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_umbracoApplicationLifetime = umbracoApplicationLifetime;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
if (_hosting.IsDebugMode == false) return;
|
||||
|
||||
//if (ApplicationContext.Current.IsConfigured == false || GlobalSettings.DebugMode == false)
|
||||
// return;
|
||||
|
||||
var appPlugins = _hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.AppPlugins);
|
||||
if (Directory.Exists(appPlugins) == false) return;
|
||||
|
||||
_mw = new ManifestWatcher(_loggerFactory.CreateLogger<ManifestWatcher>(), _umbracoApplicationLifetime);
|
||||
_mw.Start(Directory.GetDirectories(appPlugins));
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
if (_mw == null) return;
|
||||
|
||||
_mw.Dispose();
|
||||
_mw = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core.Compose
|
||||
{
|
||||
public class ManifestWatcherComposer : ComponentComposer<ManifestWatcherComponent>, ICoreComposer
|
||||
{ }
|
||||
}
|
||||
@@ -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<ILoggerFactory>(),
|
||||
factory.GetRequiredService<IUmbracoVersion>(),
|
||||
factory.GetRequiredService<IOptions<GlobalSettings>>(),
|
||||
factory.GetRequiredService<IMediaService>(),
|
||||
factory.GetRequiredService<IMediaTypeService>(),
|
||||
packageRepoFileName);
|
||||
|
||||
private static LocalizedTextServiceFileSources SourcesFactory(IServiceProvider container)
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Extends the <see cref="IHostBuilder"/> to enable Umbraco to be used as the service container.
|
||||
/// </summary>
|
||||
public static class HostBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Assigns a custom service provider factory to use Umbraco's container
|
||||
/// </summary>
|
||||
/// <param name="builder"></param>
|
||||
/// <returns></returns>
|
||||
public static IHostBuilder UseUmbraco(this IHostBuilder builder)
|
||||
{
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<PackageDataInstallation> 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> globalSettings,
|
||||
ILocalizedTextService localizedTextService, IConfigurationEditorJsonSerializer serializer, IJsonSerializer jsonSerializer)
|
||||
public PackageDataInstallation(
|
||||
ILogger<PackageDataInstallation> 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> 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;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Imports and saves package xml as <see cref="IContentType"/>
|
||||
/// </summary>
|
||||
/// <param name="docTypeElements">Xml to import</param>
|
||||
/// <param name="userId">Optional id of the User performing the operation. Default is zero (admin).</param>
|
||||
/// <returns>An enumerable list of generated ContentTypes</returns>
|
||||
public IReadOnlyList<IMediaType> ImportMediaTypes(IEnumerable<XElement> docTypeElements, int userId)
|
||||
{
|
||||
return ImportDocumentTypes(docTypeElements.ToList(), true, userId, _mediaTypeService);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Content
|
||||
|
||||
|
||||
public IReadOnlyList<IContent> ImportContent(IEnumerable<CompiledPackageDocument> docs, IDictionary<string, IContentType> importedDocumentTypes, int userId)
|
||||
public IReadOnlyList<T> ImportContentBase<T, S>(
|
||||
IEnumerable<CompiledPackageContentBase> docs,
|
||||
IDictionary<string, S> importedDocumentTypes,
|
||||
int userId,
|
||||
IContentTypeBaseService<S> typeService,
|
||||
IContentServiceBase<T> service)
|
||||
where T: class, IContentBase
|
||||
where S: IContentTypeComposition
|
||||
{
|
||||
return docs.SelectMany(x => ImportContent(x, -1, importedDocumentTypes, userId)).ToList();
|
||||
return docs.SelectMany(x => ImportContentBase<T, S>(
|
||||
x.XmlData.Elements().Where(doc => (string)doc.Attribute("isDoc") == string.Empty),
|
||||
-1,
|
||||
importedDocumentTypes,
|
||||
userId,
|
||||
typeService,
|
||||
service)).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -230,17 +278,20 @@ namespace Umbraco.Core.Packaging
|
||||
/// <param name="importedDocumentTypes">A dictionary of already imported document types (basically used as a cache)</param>
|
||||
/// <param name="userId">Optional Id of the user performing the import</param>
|
||||
/// <returns>An enumerable list of generated content</returns>
|
||||
public IEnumerable<IContent> ImportContent(CompiledPackageDocument packageDocument, int parentId, IDictionary<string, IContentType> importedDocumentTypes, int userId)
|
||||
public IEnumerable<T> ImportContentBase<T, S>(
|
||||
IEnumerable<XElement> roots,
|
||||
int parentId,
|
||||
IDictionary<string, S> importedDocumentTypes,
|
||||
int userId,
|
||||
IContentTypeBaseService<S> typeService,
|
||||
IContentServiceBase<T> 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<XElement> { 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<IContent> ParseDocumentRootXml(IEnumerable<XElement> roots, int parentId, IDictionary<string, IContentType> importedContentTypes)
|
||||
private IEnumerable<T> ParseContentBaseRootXml<T, S>(
|
||||
IEnumerable<XElement> roots,
|
||||
int parentId,
|
||||
IDictionary<string, S> importedContentTypes,
|
||||
IContentTypeBaseService<S> typeService,
|
||||
IContentServiceBase<T> service)
|
||||
where T: class, IContentBase
|
||||
where S: IContentTypeComposition
|
||||
{
|
||||
var contents = new List<IContent>();
|
||||
var contents = new List<T>();
|
||||
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<T, S>(children, content, importedContentTypes, typeService, service).WhereNotNull());
|
||||
}
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
||||
private IEnumerable<IContent> CreateContentFromXml(IEnumerable<XElement> children, IContent parent, IDictionary<string, IContentType> importedContentTypes)
|
||||
private IEnumerable<T> CreateContentFromXml<T, S>(
|
||||
IEnumerable<XElement> children,
|
||||
T parent,
|
||||
IDictionary<string, S> importedContentTypes,
|
||||
IContentTypeBaseService<S> typeService,
|
||||
IContentServiceBase<T> service)
|
||||
where T: class, IContentBase
|
||||
where S: IContentTypeComposition
|
||||
{
|
||||
var list = new List<IContent>();
|
||||
var list = new List<T>();
|
||||
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<T, S>(
|
||||
XElement element,
|
||||
S contentType,
|
||||
T parent,
|
||||
int parentId,
|
||||
IContentServiceBase<T> 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<T, S>(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
|
||||
/// <returns>An enumerable list of generated ContentTypes</returns>
|
||||
public IReadOnlyList<IContentType> ImportDocumentTypes(IEnumerable<XElement> docTypeElements, int userId)
|
||||
{
|
||||
return ImportDocumentTypes(docTypeElements.ToList(), true, userId);
|
||||
return ImportDocumentTypes<IContentType>(docTypeElements.ToList(), true, userId, _contentTypeService);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -423,9 +520,10 @@ namespace Umbraco.Core.Packaging
|
||||
/// <param name="importStructure">Boolean indicating whether or not to import the </param>
|
||||
/// <param name="userId">Optional id of the User performing the operation. Default is zero (admin).</param>
|
||||
/// <returns>An enumerable list of generated ContentTypes</returns>
|
||||
public IReadOnlyList<IContentType> ImportDocumentTypes(IReadOnlyCollection<XElement> unsortedDocumentTypes, bool importStructure, int userId)
|
||||
public IReadOnlyList<T> ImportDocumentTypes<T>(IReadOnlyCollection<XElement> unsortedDocumentTypes, bool importStructure, int userId, IContentTypeBaseService<T> service)
|
||||
where T: class, IContentTypeComposition
|
||||
{
|
||||
var importedContentTypes = new Dictionary<string, IContentType>();
|
||||
var importedContentTypes = new Dictionary<string, T>();
|
||||
|
||||
//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<IContentType>();
|
||||
var updatedContentTypes = new List<T>();
|
||||
//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<string, IContentType> importedContentTypes)
|
||||
private T CreateContentTypeFromXml<T>(XElement documentType, IReadOnlyDictionary<string, T> importedContentTypes, IContentTypeBaseService<T> 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<string, IContentType> importedContentTypes)
|
||||
private T CreateContentType<T>(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<T>(XElement documentType, T contentType, IReadOnlyDictionary<string, T> importedContentTypes, IContentTypeBaseService<T> 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>(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>(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<string, IContentType> importedContentTypes)
|
||||
private T UpdateContentTypesStructure<T>(T contentType, XElement structureElement, IReadOnlyDictionary<string, T> importedContentTypes, IContentTypeBaseService<T> 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
|
||||
/// </summary>
|
||||
/// <param name="contentTypeAlias"></param>
|
||||
/// <returns></returns>
|
||||
private IContentType FindContentTypeByAlias(string contentTypeAlias)
|
||||
private S FindContentTypeByAlias<S>(string contentTypeAlias, IContentTypeBaseService<S> 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");
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System;
|
||||
using Examine;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Composing.CompositionExtensions;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.Grid;
|
||||
@@ -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;
|
||||
@@ -61,15 +62,17 @@ using Umbraco.Web.Templates;
|
||||
using Umbraco.Web.Trees;
|
||||
using TextStringValueConverter = Umbraco.Core.PropertyEditors.ValueConverters.TextStringValueConverter;
|
||||
|
||||
namespace Umbraco.Core.Runtime
|
||||
namespace Umbraco.Infrastructure.Runtime
|
||||
{
|
||||
// core's initial composer composes before all core composers
|
||||
[ComposeBefore(typeof(ICoreComposer))]
|
||||
public class CoreInitialComposer : ComponentComposer<CoreInitialComponent>
|
||||
public static class CoreInitialServices
|
||||
{
|
||||
public override void Compose(IUmbracoBuilder builder)
|
||||
public static IUmbracoBuilder AddCoreInitialServices(this IUmbracoBuilder builder)
|
||||
{
|
||||
base.Compose(builder);
|
||||
builder.AddNotificationHandler<UmbracoApplicationStarting, EssentialDirectoryCreator>();
|
||||
|
||||
builder.Services.AddSingleton<ManifestWatcher>();
|
||||
builder.AddNotificationHandler<UmbracoApplicationStarting, ManifestWatcher>(factory => factory.GetRequiredService<ManifestWatcher>());
|
||||
builder.AddNotificationHandler<UmbracoApplicationStopping, ManifestWatcher>(factory => factory.GetRequiredService<ManifestWatcher>());
|
||||
|
||||
// composers
|
||||
builder
|
||||
@@ -301,7 +304,7 @@ namespace Umbraco.Core.Runtime
|
||||
// register *all* checks, except those marked [HideFromTypeFinder] of course
|
||||
builder.Services.AddUnique<IMarkdownToHtmlConverter, MarkdownToHtmlConverter>();
|
||||
builder.HealthChecks()
|
||||
.Add(() => builder.TypeLoader.GetTypes<HealthCheck.HealthCheck>());
|
||||
.Add(() => builder.TypeLoader.GetTypes<Core.HealthCheck.HealthCheck>());
|
||||
|
||||
builder.WithCollectionBuilder<HealthCheckNotificationMethodCollectionBuilder>()
|
||||
.Add(() => builder.TypeLoader.GetTypes<IHealthCheckNotificationMethod>());
|
||||
@@ -380,6 +383,11 @@ namespace Umbraco.Core.Runtime
|
||||
|
||||
builder.Services.AddUnique<MediaPermissions>();
|
||||
builder.Services.AddUnique<IImageDimensionExtractor, ImageDimensionExtractor>();
|
||||
|
||||
|
||||
builder.Services.AddUnique<PackageDataInstallation>();
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
@@ -10,71 +13,102 @@ namespace Umbraco.Infrastructure.Runtime
|
||||
{
|
||||
public class CoreRuntime : IRuntime
|
||||
{
|
||||
public IRuntimeState State { get; }
|
||||
|
||||
private readonly ILogger<CoreRuntime> _logger;
|
||||
private readonly ILoggerFactory _loggerFactory;
|
||||
private readonly ComponentCollection _components;
|
||||
private readonly IApplicationShutdownRegistry _applicationShutdownRegistry;
|
||||
private readonly IProfilingLogger _profilingLogger;
|
||||
private readonly IMainDom _mainDom;
|
||||
private readonly IUmbracoDatabaseFactory _databaseFactory;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
|
||||
public CoreRuntime(
|
||||
ILogger<CoreRuntime> logger,
|
||||
ILoggerFactory loggerFactory,
|
||||
IRuntimeState state,
|
||||
ComponentCollection components,
|
||||
IApplicationShutdownRegistry applicationShutdownRegistry,
|
||||
IProfilingLogger profilingLogger,
|
||||
IMainDom mainDom,
|
||||
IUmbracoDatabaseFactory databaseFactory)
|
||||
IUmbracoDatabaseFactory databaseFactory,
|
||||
IEventAggregator eventAggregator,
|
||||
IHostingEnvironment hostingEnvironment)
|
||||
{
|
||||
State = state;
|
||||
_logger = logger;
|
||||
_loggerFactory = loggerFactory;
|
||||
_components = components;
|
||||
_applicationShutdownRegistry = applicationShutdownRegistry;
|
||||
_profilingLogger = profilingLogger;
|
||||
_mainDom = mainDom;
|
||||
_databaseFactory = databaseFactory;
|
||||
}
|
||||
|
||||
_eventAggregator = eventAggregator;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
|
||||
public void Start()
|
||||
|
||||
_logger = _loggerFactory.CreateLogger<CoreRuntime>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the state of the Umbraco runtime.
|
||||
/// </summary>
|
||||
public IRuntimeState State { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
StaticApplicationLogging.Initialize(_loggerFactory);
|
||||
|
||||
AppDomain.CurrentDomain.UnhandledException += (_, args) =>
|
||||
{
|
||||
var exception = (Exception)args.ExceptionObject;
|
||||
var isTerminating = args.IsTerminating; // always true?
|
||||
|
||||
var msg = "Unhandled exception in AppDomain";
|
||||
if (isTerminating) msg += " (terminating)";
|
||||
|
||||
if (isTerminating)
|
||||
{
|
||||
msg += " (terminating)";
|
||||
}
|
||||
|
||||
msg += ".";
|
||||
|
||||
_logger.LogError(exception, msg);
|
||||
};
|
||||
|
||||
AppDomain.CurrentDomain.SetData("DataDirectory", _hostingEnvironment?.MapPathContentRoot(Core.Constants.SystemDirectories.Data));
|
||||
|
||||
DetermineRuntimeLevel();
|
||||
|
||||
if (State.Level <= RuntimeLevel.BootFailed)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot start the runtime if the runtime level is less than or equal to {RuntimeLevel.BootFailed}");
|
||||
}
|
||||
|
||||
var hostingEnvironmentLifetime = _applicationShutdownRegistry;
|
||||
IApplicationShutdownRegistry hostingEnvironmentLifetime = _applicationShutdownRegistry;
|
||||
if (hostingEnvironmentLifetime == null)
|
||||
throw new InvalidOperationException($"An instance of {typeof(IApplicationShutdownRegistry)} could not be resolved from the container, ensure that one if registered in your runtime before calling {nameof(IRuntime)}.{nameof(Start)}");
|
||||
{
|
||||
throw new InvalidOperationException($"An instance of {typeof(IApplicationShutdownRegistry)} could not be resolved from the container, ensure that one if registered in your runtime before calling {nameof(IRuntime)}.{nameof(StartAsync)}");
|
||||
}
|
||||
|
||||
// acquire the main domain - if this fails then anything that should be registered with MainDom will not operate
|
||||
AcquireMainDom();
|
||||
|
||||
await _eventAggregator.PublishAsync(new UmbracoApplicationStarting(State.Level), cancellationToken);
|
||||
|
||||
// create & initialize the components
|
||||
_components.Initialize();
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_components.Terminate();
|
||||
await _eventAggregator.PublishAsync(new UmbracoApplicationStopping(), cancellationToken);
|
||||
StaticApplicationLogging.Initialize(null);
|
||||
}
|
||||
|
||||
private void AcquireMainDom()
|
||||
{
|
||||
using (var timer = _profilingLogger.DebugDuration<CoreRuntime>("Acquiring MainDom.", "Acquired."))
|
||||
using (DisposableTimer timer = _profilingLogger.DebugDuration<CoreRuntime>("Acquiring MainDom.", "Acquired."))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -90,7 +124,7 @@ namespace Umbraco.Infrastructure.Runtime
|
||||
|
||||
private void DetermineRuntimeLevel()
|
||||
{
|
||||
using var timer = _profilingLogger.DebugDuration<CoreRuntime>("Determining runtime level.", "Determined.");
|
||||
using DisposableTimer timer = _profilingLogger.DebugDuration<CoreRuntime>("Determining runtime level.", "Determined.");
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Core.Composing;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.Models;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Core.Runtime
|
||||
namespace Umbraco.Infrastructure.Runtime
|
||||
{
|
||||
public class CoreInitialComponent : IComponent
|
||||
public class EssentialDirectoryCreator : INotificationHandler<UmbracoApplicationStarting>
|
||||
{
|
||||
private readonly IIOHelper _ioHelper;
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
|
||||
public CoreInitialComponent(IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, IOptions<GlobalSettings> globalSettings)
|
||||
public EssentialDirectoryCreator(IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, IOptions<GlobalSettings> globalSettings)
|
||||
{
|
||||
_ioHelper = ioHelper;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_globalSettings = globalSettings.Value;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
public Task HandleAsync(UmbracoApplicationStarting notification, CancellationToken cancellationToken)
|
||||
{
|
||||
// ensure we have some essential directories
|
||||
// every other component can then initialize safely
|
||||
@@ -28,9 +31,8 @@ namespace Umbraco.Core.Runtime
|
||||
_ioHelper.EnsurePathExists(_hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.MvcViews));
|
||||
_ioHelper.EnsurePathExists(_hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.PartialViews));
|
||||
_ioHelper.EnsurePathExists(_hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.MacroPartials));
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{ }
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
65
src/Umbraco.Infrastructure/Runtime/ManifestWatcher.cs
Normal file
65
src/Umbraco.Infrastructure/Runtime/ManifestWatcher.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Net;
|
||||
|
||||
namespace Umbraco.Infrastructure.Runtime
|
||||
{
|
||||
public sealed class ManifestWatcher :
|
||||
INotificationHandler<UmbracoApplicationStarting>,
|
||||
INotificationHandler<UmbracoApplicationStopping>
|
||||
{
|
||||
private readonly IHostingEnvironment _hosting;
|
||||
private readonly ILoggerFactory _loggerFactory;
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
|
||||
|
||||
// if configured and in debug mode, a ManifestWatcher watches App_Plugins folders for
|
||||
// package.manifest chances and restarts the application on any change
|
||||
private Core.Manifest.ManifestWatcher _mw;
|
||||
|
||||
public ManifestWatcher(IHostingEnvironment hosting, ILoggerFactory loggerFactory, IHostingEnvironment hostingEnvironment, IUmbracoApplicationLifetime umbracoApplicationLifetime)
|
||||
{
|
||||
_hosting = hosting;
|
||||
_loggerFactory = loggerFactory;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_umbracoApplicationLifetime = umbracoApplicationLifetime;
|
||||
}
|
||||
|
||||
public Task HandleAsync(UmbracoApplicationStarting notification, CancellationToken cancellationToken)
|
||||
{
|
||||
if (_hosting.IsDebugMode == false)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
var appPlugins = _hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.AppPlugins);
|
||||
if (Directory.Exists(appPlugins) == false)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
_mw = new Core.Manifest.ManifestWatcher(_loggerFactory.CreateLogger<Core.Manifest.ManifestWatcher>(), _umbracoApplicationLifetime);
|
||||
_mw.Start(Directory.GetDirectories(appPlugins));
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task HandleAsync(UmbracoApplicationStopping notification, CancellationToken cancellationToken)
|
||||
{
|
||||
if (_mw == null)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
_mw.Dispose();
|
||||
_mw = null;
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="contents"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="raiseEvents"></param>
|
||||
/// <returns></returns>
|
||||
Attempt<OperationResult> IContentServiceBase<IContent>.Save(IEnumerable<IContent> contents, int userId,
|
||||
bool raiseEvents) => Attempt.Succeed(Save(contents, userId, raiseEvents));
|
||||
|
||||
/// <summary>
|
||||
/// Gets <see cref="IContent"/> objects by Ids
|
||||
/// </summary>
|
||||
|
||||
@@ -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()),
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets an <see cref="IMedia"/> object by Id
|
||||
/// </summary>
|
||||
@@ -643,6 +643,8 @@ namespace Umbraco.Core.Services.Implement
|
||||
|
||||
#region Save
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Saves a single <see cref="IMedia"/> object
|
||||
/// </summary>
|
||||
|
||||
@@ -33,54 +33,6 @@ namespace Umbraco.Tests.Integration
|
||||
MyComposer.Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calling AddUmbracoCore to configure the container
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task AddUmbracoCore()
|
||||
{
|
||||
var testHelper = new TestHelper();
|
||||
|
||||
var hostBuilder = new HostBuilder()
|
||||
.UseUmbraco()
|
||||
.ConfigureServices((hostContext, services) =>
|
||||
{
|
||||
var webHostEnvironment = testHelper.GetWebHostEnvironment();
|
||||
services.AddSingleton(testHelper.DbProviderFactoryCreator);
|
||||
services.AddRequiredNetCoreServices(testHelper, webHostEnvironment);
|
||||
|
||||
// Add it!
|
||||
var typeLoader = services.AddTypeLoader(
|
||||
GetType().Assembly,
|
||||
webHostEnvironment,
|
||||
testHelper.GetHostingEnvironment(),
|
||||
testHelper.ConsoleLoggerFactory,
|
||||
AppCaches.NoCache,
|
||||
hostContext.Configuration,
|
||||
testHelper.Profiler);
|
||||
|
||||
var builder = new UmbracoBuilder(services, hostContext.Configuration, typeLoader, testHelper.ConsoleLoggerFactory);
|
||||
builder.Services.AddUnique<AppCaches>(AppCaches.NoCache);
|
||||
builder.AddConfiguration();
|
||||
builder.AddUmbracoCore();
|
||||
});
|
||||
|
||||
var host = await hostBuilder.StartAsync();
|
||||
var app = new ApplicationBuilder(host.Services);
|
||||
|
||||
// assert results
|
||||
var runtimeState = app.ApplicationServices.GetRequiredService<IRuntimeState>();
|
||||
var mainDom = app.ApplicationServices.GetRequiredService<IMainDom>();
|
||||
|
||||
Assert.IsFalse(mainDom.IsMainDom); // We haven't "Started" the runtime yet
|
||||
Assert.IsNull(runtimeState.BootFailedException);
|
||||
Assert.IsFalse(MyComponent.IsInit); // We haven't "Started" the runtime yet
|
||||
|
||||
await host.StopAsync();
|
||||
|
||||
Assert.IsFalse(MyComponent.IsTerminated); // we didn't "Start" the runtime so nothing was registered for shutdown
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calling AddUmbracoCore to configure the container and UseUmbracoCore to start the runtime
|
||||
/// </summary>
|
||||
@@ -91,7 +43,6 @@ namespace Umbraco.Tests.Integration
|
||||
var testHelper = new TestHelper();
|
||||
|
||||
var hostBuilder = new HostBuilder()
|
||||
.UseUmbraco()
|
||||
.ConfigureServices((hostContext, services) =>
|
||||
{
|
||||
var webHostEnvironment = testHelper.GetWebHostEnvironment();
|
||||
@@ -109,11 +60,12 @@ namespace Umbraco.Tests.Integration
|
||||
hostContext.Configuration,
|
||||
testHelper.Profiler);
|
||||
|
||||
var builder = new UmbracoBuilder(services, hostContext.Configuration, typeLoader, testHelper.ConsoleLoggerFactory);
|
||||
var builder = new UmbracoBuilder(services, hostContext.Configuration, typeLoader,
|
||||
testHelper.ConsoleLoggerFactory);
|
||||
builder.Services.AddUnique<AppCaches>(AppCaches.NoCache);
|
||||
builder.AddConfiguration()
|
||||
.AddUmbracoCore()
|
||||
.Build();
|
||||
.AddUmbracoCore()
|
||||
.Build();
|
||||
|
||||
services.AddRouting(); // LinkGenerator
|
||||
});
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using System.Net.Http;
|
||||
@@ -36,7 +35,7 @@ namespace Umbraco.Tests.Integration.TestServerTest
|
||||
InMemoryConfiguration["Umbraco:CMS:Hosting:Debug"] = "true";
|
||||
|
||||
// create new WebApplicationFactory specifying 'this' as the IStartup instance
|
||||
var factory = new UmbracoWebApplicationFactory<UmbracoTestServerTestBase>(CreateHostBuilder);
|
||||
var factory = new UmbracoWebApplicationFactory<UmbracoTestServerTestBase>(CreateHostBuilder, BeforeHostStart);
|
||||
|
||||
// additional host configuration for web server integration tests
|
||||
Factory = factory.WithWebHostBuilder(builder =>
|
||||
@@ -72,11 +71,10 @@ namespace Umbraco.Tests.Integration.TestServerTest
|
||||
// call startup
|
||||
builder.Configure(app =>
|
||||
{
|
||||
UseTestLocalDb(app.ApplicationServices);
|
||||
Services = app.ApplicationServices;
|
||||
Configure(app);
|
||||
});
|
||||
}).UseEnvironment(Environments.Development);
|
||||
|
||||
}).UseEnvironment(Environments.Development);
|
||||
|
||||
return builder;
|
||||
}
|
||||
@@ -118,15 +116,6 @@ namespace Umbraco.Tests.Integration.TestServerTest
|
||||
|
||||
protected WebApplicationFactory<UmbracoTestServerTestBase> Factory { get; private set; }
|
||||
|
||||
[TearDown]
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
TerminateCoreRuntime();
|
||||
|
||||
Factory.Dispose();
|
||||
}
|
||||
|
||||
public override void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddTransient<TestUmbracoDatabaseFactoryProvider>();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
@@ -8,16 +8,30 @@ namespace Umbraco.Tests.Integration.TestServerTest
|
||||
public class UmbracoWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
|
||||
{
|
||||
private readonly Func<IHostBuilder> _createHostBuilder;
|
||||
private readonly Action<IHost> _beforeStart;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor to create a new WebApplicationFactory
|
||||
/// </summary>
|
||||
/// <param name="createHostBuilder">Method to create the IHostBuilder</param>
|
||||
public UmbracoWebApplicationFactory(Func<IHostBuilder> createHostBuilder)
|
||||
/// <param name="beforeStart">Method to perform an action before IHost starts</param>
|
||||
public UmbracoWebApplicationFactory(Func<IHostBuilder> createHostBuilder, Action<IHost> beforeStart = null)
|
||||
{
|
||||
_createHostBuilder = createHostBuilder;
|
||||
_beforeStart = beforeStart;
|
||||
}
|
||||
|
||||
protected override IHostBuilder CreateHostBuilder() => _createHostBuilder();
|
||||
|
||||
protected override IHost CreateHost(IHostBuilder builder)
|
||||
{
|
||||
IHost host = builder.Build();
|
||||
|
||||
_beforeStart?.Invoke(host);
|
||||
|
||||
host.Start();
|
||||
|
||||
return host;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,11 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
{
|
||||
protected ILoggerFactory _loggerFactory;
|
||||
protected IUmbracoDatabaseFactory _databaseFactory;
|
||||
protected IEnumerable<TestDbMeta> _testDatabases;
|
||||
|
||||
protected UmbracoDatabase.CommandInfo[] _cachedDatabaseInitCommands;
|
||||
protected IList<TestDbMeta> _testDatabases;
|
||||
|
||||
protected const int _threadCount = 2;
|
||||
|
||||
protected UmbracoDatabase.CommandInfo[] _cachedDatabaseInitCommands = new UmbracoDatabase.CommandInfo[0];
|
||||
|
||||
protected BlockingCollection<TestDbMeta> _prepareQueue;
|
||||
protected BlockingCollection<TestDbMeta> _readySchemaQueue;
|
||||
@@ -92,46 +94,52 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
});
|
||||
}
|
||||
|
||||
protected void RebuildSchema(IDbCommand command, TestDbMeta meta)
|
||||
private void RebuildSchema(IDbCommand command, TestDbMeta meta)
|
||||
{
|
||||
if (_cachedDatabaseInitCommands != null)
|
||||
lock (_cachedDatabaseInitCommands)
|
||||
{
|
||||
foreach (var dbCommand in _cachedDatabaseInitCommands)
|
||||
if (!_cachedDatabaseInitCommands.Any())
|
||||
{
|
||||
|
||||
if (dbCommand.Text.StartsWith("SELECT "))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
command.CommandText = dbCommand.Text;
|
||||
command.Parameters.Clear();
|
||||
|
||||
foreach (var parameterInfo in dbCommand.Parameters)
|
||||
{
|
||||
AddParameter(command, parameterInfo);
|
||||
}
|
||||
|
||||
command.ExecuteNonQuery();
|
||||
RebuildSchemaFirstTime(command, meta);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
foreach (var dbCommand in _cachedDatabaseInitCommands)
|
||||
{
|
||||
_databaseFactory.Configure(meta.ConnectionString, Core.Constants.DatabaseProviders.SqlServer);
|
||||
|
||||
using (var database = (UmbracoDatabase)_databaseFactory.CreateDatabase())
|
||||
if (dbCommand.Text.StartsWith("SELECT "))
|
||||
{
|
||||
database.LogCommands = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
using (var transaction = database.GetTransaction())
|
||||
{
|
||||
var schemaCreator = new DatabaseSchemaCreator(database, _loggerFactory.CreateLogger<DatabaseSchemaCreator>(), _loggerFactory, new UmbracoVersion());
|
||||
schemaCreator.InitializeDatabaseSchema();
|
||||
command.CommandText = dbCommand.Text;
|
||||
command.Parameters.Clear();
|
||||
|
||||
transaction.Complete();
|
||||
foreach (var parameterInfo in dbCommand.Parameters)
|
||||
{
|
||||
AddParameter(command, parameterInfo);
|
||||
}
|
||||
|
||||
_cachedDatabaseInitCommands = database.Commands.ToArray();
|
||||
}
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
private void RebuildSchemaFirstTime(IDbCommand command, TestDbMeta meta)
|
||||
{
|
||||
_databaseFactory.Configure(meta.ConnectionString, Core.Constants.DatabaseProviders.SqlServer);
|
||||
|
||||
using (var database = (UmbracoDatabase)_databaseFactory.CreateDatabase())
|
||||
{
|
||||
database.LogCommands = true;
|
||||
|
||||
using (var transaction = database.GetTransaction())
|
||||
{
|
||||
var schemaCreator = new DatabaseSchemaCreator(database, _loggerFactory.CreateLogger<DatabaseSchemaCreator>(), _loggerFactory, new UmbracoVersion());
|
||||
schemaCreator.InitializeDatabaseSchema();
|
||||
|
||||
transaction.Complete();
|
||||
|
||||
_cachedDatabaseInitCommands = database.Commands.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,6 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
private static LocalDb.Instance _localDbInstance;
|
||||
private static string _filesPath;
|
||||
|
||||
private const int _threadCount = 2;
|
||||
|
||||
public static LocalDbTestDatabase Instance { get; private set; }
|
||||
|
||||
//It's internal because `Umbraco.Core.Persistence.LocalDb` is internal
|
||||
@@ -64,13 +62,17 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
var tempName = Guid.NewGuid().ToString("N");
|
||||
_localDbInstance.CreateDatabase(tempName, _filesPath);
|
||||
_localDbInstance.DetachDatabase(tempName);
|
||||
|
||||
_prepareQueue = new BlockingCollection<TestDbMeta>();
|
||||
_readySchemaQueue = new BlockingCollection<TestDbMeta>();
|
||||
_readyEmptyQueue = new BlockingCollection<TestDbMeta>();
|
||||
|
||||
foreach (var meta in _testDatabases)
|
||||
for (var i = 0; i < _testDatabases.Count; i++)
|
||||
{
|
||||
_localDb.CopyDatabaseFiles(tempName, _filesPath, targetDatabaseName: meta.Name, overwrite: true, delete: false);
|
||||
var meta = _testDatabases[i];
|
||||
var isLast = i == _testDatabases.Count - 1;
|
||||
|
||||
_localDb.CopyDatabaseFiles(tempName, _filesPath, targetDatabaseName: meta.Name, overwrite: true, delete: isLast);
|
||||
meta.ConnectionString = _localDbInstance.GetAttachedConnectionString(meta.Name, _filesPath);
|
||||
_prepareQueue.Add(meta);
|
||||
}
|
||||
@@ -85,7 +87,9 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
public void Finish()
|
||||
{
|
||||
if (_prepareQueue == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_prepareQueue.CompleteAdding();
|
||||
while (_prepareQueue.TryTake(out _))
|
||||
@@ -100,14 +104,18 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
{ }
|
||||
|
||||
if (_filesPath == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var filename = Path.Combine(_filesPath, DatabaseName).ToUpper();
|
||||
|
||||
foreach (var database in _localDbInstance.GetDatabases())
|
||||
{
|
||||
if (database.StartsWith(filename))
|
||||
{
|
||||
_localDbInstance.DropDatabase(database);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(_filesPath))
|
||||
|
||||
@@ -17,8 +17,6 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
private readonly string _masterConnectionString;
|
||||
public const string DatabaseName = "UmbracoTests";
|
||||
|
||||
private const int _threadCount = 2;
|
||||
|
||||
public static SqlDeveloperTestDatabase Instance { get; private set; }
|
||||
|
||||
public SqlDeveloperTestDatabase(ILoggerFactory loggerFactory, IUmbracoDatabaseFactory databaseFactory, string masterConnectionString)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
|
||||
@@ -8,13 +9,20 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
{
|
||||
public static ITestDatabase Create(string filesPath, ILoggerFactory loggerFactory, TestUmbracoDatabaseFactoryProvider dbFactory)
|
||||
{
|
||||
return string.IsNullOrEmpty(Environment.GetEnvironmentVariable("UmbracoIntegrationTestConnectionString"))
|
||||
? CreateLocalDb(filesPath, loggerFactory, dbFactory.Create())
|
||||
: CreateSqlDeveloper(loggerFactory, dbFactory.Create());
|
||||
var connectionString = Environment.GetEnvironmentVariable("UmbracoIntegrationTestConnectionString");
|
||||
|
||||
return string.IsNullOrEmpty(connectionString)
|
||||
? CreateLocalDb(filesPath, loggerFactory, dbFactory)
|
||||
: CreateSqlDeveloper(loggerFactory, dbFactory, connectionString);
|
||||
}
|
||||
|
||||
private static ITestDatabase CreateLocalDb(string filesPath, ILoggerFactory loggerFactory, IUmbracoDatabaseFactory dbFactory)
|
||||
private static ITestDatabase CreateLocalDb(string filesPath, ILoggerFactory loggerFactory, TestUmbracoDatabaseFactoryProvider dbFactory)
|
||||
{
|
||||
if (!Directory.Exists(filesPath))
|
||||
{
|
||||
Directory.CreateDirectory(filesPath);
|
||||
}
|
||||
|
||||
var localDb = new LocalDb();
|
||||
|
||||
if (!localDb.IsAvailable)
|
||||
@@ -22,22 +30,21 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
throw new InvalidOperationException("LocalDB is not available.");
|
||||
}
|
||||
|
||||
return new LocalDbTestDatabase(loggerFactory, localDb, filesPath, dbFactory);
|
||||
return new LocalDbTestDatabase(loggerFactory, localDb, filesPath, dbFactory.Create());
|
||||
}
|
||||
|
||||
private static ITestDatabase CreateSqlDeveloper(ILoggerFactory loggerFactory, IUmbracoDatabaseFactory dbFactory)
|
||||
private static ITestDatabase CreateSqlDeveloper(ILoggerFactory loggerFactory, TestUmbracoDatabaseFactoryProvider dbFactory, string connectionString)
|
||||
{
|
||||
// NOTE: Example setup for Linux box.
|
||||
// $ export SA_PASSWORD=Foobar123!
|
||||
// $ export UmbracoIntegrationTestConnectionString="Server=localhost,1433;User Id=sa;Password=$SA_PASSWORD;"
|
||||
// $ docker run -e 'ACCEPT_EULA=Y' -e "SA_PASSWORD=$SA_PASSWORD" -e 'MSSQL_PID=Developer' -p 1433:1433 -d mcr.microsoft.com/mssql/server:2017-latest-ubuntu
|
||||
var connectionString = Environment.GetEnvironmentVariable("UmbracoIntegrationTestConnectionString");
|
||||
|
||||
if (string.IsNullOrEmpty(connectionString))
|
||||
{
|
||||
throw new InvalidOperationException("ENV: UmbracoIntegrationTestConnectionString is not set");
|
||||
}
|
||||
|
||||
return new SqlDeveloperTestDatabase(loggerFactory, dbFactory, connectionString);
|
||||
return new SqlDeveloperTestDatabase(loggerFactory, dbFactory.Create(), connectionString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,9 +71,14 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
foreach (var a in _testTeardown)
|
||||
a();
|
||||
}
|
||||
|
||||
_testTeardown = null;
|
||||
FirstTestInFixture = false;
|
||||
FirstTestInSession = false;
|
||||
|
||||
// Ensure CoreRuntime stopped (now it's a HostedService)
|
||||
IHost host = Services.GetRequiredService<IHost>();
|
||||
host.StopAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
@@ -94,14 +99,18 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
InMemoryConfiguration[Constants.Configuration.ConfigGlobal + ":" + nameof(GlobalSettings.InstallEmptyDatabase)] = "true";
|
||||
var hostBuilder = CreateHostBuilder();
|
||||
|
||||
var host = hostBuilder.Start();
|
||||
IHost host = hostBuilder.Build();
|
||||
BeforeHostStart(host);
|
||||
host.Start();
|
||||
|
||||
Services = host.Services;
|
||||
var app = new ApplicationBuilder(host.Services);
|
||||
|
||||
Configure(app);
|
||||
}
|
||||
|
||||
OnFixtureTearDown(() => host.Dispose());
|
||||
protected void BeforeHostStart(IHost host)
|
||||
{
|
||||
Services = host.Services;
|
||||
UseTestDatabase(Services);
|
||||
}
|
||||
|
||||
#region Generic Host Builder and Runtime
|
||||
@@ -110,13 +119,21 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
{
|
||||
try
|
||||
{
|
||||
var testOptions = TestOptionAttributeBase.GetTestOptions<UmbracoTestAttribute>();
|
||||
switch (testOptions.Logger)
|
||||
switch (TestOptions.Logger)
|
||||
{
|
||||
case UmbracoTestOptions.Logger.Mock:
|
||||
return NullLoggerFactory.Instance;
|
||||
case UmbracoTestOptions.Logger.Serilog:
|
||||
return Microsoft.Extensions.Logging.LoggerFactory.Create(builder => { builder.AddSerilog(); });
|
||||
return Microsoft.Extensions.Logging.LoggerFactory.Create(builder =>
|
||||
{
|
||||
var path = Path.Combine(TestHelper.WorkingDirectory, "logs", "umbraco_integration_tests_.txt");
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.WriteTo.File(path, rollingInterval: RollingInterval.Day)
|
||||
.CreateLogger();
|
||||
|
||||
builder.AddSerilog(Log.Logger);
|
||||
});
|
||||
case UmbracoTestOptions.Logger.Console:
|
||||
return Microsoft.Extensions.Logging.LoggerFactory.Create(builder => { builder.AddConsole(); });
|
||||
}
|
||||
@@ -141,7 +158,6 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
// create separate Host instances. So instead of UseStartup, we just call ConfigureServices/Configure ourselves,
|
||||
// and in the case of the UmbracoTestServerTestBase it will use the ConfigureWebHost to Configure the IApplicationBuilder directly.
|
||||
//.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(GetType()); })
|
||||
.UseUmbraco()
|
||||
.ConfigureAppConfiguration((context, configBuilder) =>
|
||||
{
|
||||
context.HostingEnvironment = TestHelper.GetWebHostEnvironment();
|
||||
@@ -152,8 +168,15 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
})
|
||||
.ConfigureServices((hostContext, services) =>
|
||||
{
|
||||
services.AddTransient(_ => CreateLoggerFactory());
|
||||
ConfigureServices(services);
|
||||
services.AddUnique(CreateLoggerFactory());
|
||||
|
||||
if (!TestOptions.Boot)
|
||||
{
|
||||
// If boot is false, we don't want the CoreRuntime hosted service to start
|
||||
// So we replace it with a Mock
|
||||
services.AddUnique(Mock.Of<IRuntime>());
|
||||
}
|
||||
});
|
||||
return hostBuilder;
|
||||
}
|
||||
@@ -213,29 +236,13 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
|
||||
public virtual void Configure(IApplicationBuilder app)
|
||||
{
|
||||
UseTestLocalDb(app.ApplicationServices);
|
||||
|
||||
//get the currently set options
|
||||
var testOptions = TestOptionAttributeBase.GetTestOptions<UmbracoTestAttribute>();
|
||||
if (testOptions.Boot)
|
||||
if (TestOptions.Boot)
|
||||
{
|
||||
Services.GetRequiredService<IBackOfficeSecurityFactory>().EnsureBackOfficeSecurity();
|
||||
Services.GetRequiredService<IUmbracoContextFactory>().EnsureUmbracoContext();
|
||||
app.UseUmbracoCore(); // Takes 200 ms
|
||||
|
||||
OnTestTearDown(TerminateCoreRuntime);
|
||||
}
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// Some IComponents hook onto static events (e.g. Published in ContentService)
|
||||
/// If these fire after the components host has been shutdown, errors can occur.
|
||||
/// If CoreRuntime.Start() is called We also need to de-register the events.
|
||||
/// </remarks>
|
||||
protected void TerminateCoreRuntime()
|
||||
{
|
||||
Services.GetRequiredService<IRuntime>().Terminate();
|
||||
StaticApplicationLogging.Initialize(null);
|
||||
app.UseUmbracoCore(); // This no longer starts CoreRuntime, it's very fast
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -246,25 +253,20 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
private static ITestDatabase _dbInstance;
|
||||
private static TestDbMeta _fixtureDbMeta;
|
||||
|
||||
protected void UseTestLocalDb(IServiceProvider serviceProvider)
|
||||
protected void UseTestDatabase(IServiceProvider serviceProvider)
|
||||
{
|
||||
var state = serviceProvider.GetRequiredService<IRuntimeState>();
|
||||
var testDatabaseFactoryProvider = serviceProvider.GetRequiredService<TestUmbracoDatabaseFactoryProvider>();
|
||||
var databaseFactory = serviceProvider.GetRequiredService<IUmbracoDatabaseFactory>();
|
||||
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
|
||||
|
||||
// This will create a db, install the schema and ensure the app is configured to run
|
||||
InstallTestLocalDb(testDatabaseFactoryProvider, databaseFactory, serviceProvider.GetRequiredService<ILoggerFactory>(), state, TestHelper.WorkingDirectory);
|
||||
SetupTestDatabase(testDatabaseFactoryProvider, databaseFactory, loggerFactory, state, TestHelper.WorkingDirectory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get or create an instance of <see cref="LocalDbTestDatabase"/>
|
||||
/// Get or create an instance of <see cref="ITestDatabase"/>
|
||||
/// </summary>
|
||||
/// <param name="filesPath"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="loggerFactory"></param>
|
||||
/// <param name="globalSettings"></param>
|
||||
/// <param name="dbFactory"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// There must only be ONE instance shared between all tests in a session
|
||||
/// </remarks>
|
||||
@@ -273,9 +275,12 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
lock (_dbLocker)
|
||||
{
|
||||
if (_dbInstance != null)
|
||||
{
|
||||
return _dbInstance;
|
||||
}
|
||||
|
||||
_dbInstance = TestDatabaseFactory.Create(filesPath, loggerFactory, dbFactory);
|
||||
|
||||
return _dbInstance;
|
||||
}
|
||||
}
|
||||
@@ -283,65 +288,47 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
/// <summary>
|
||||
/// Creates a LocalDb instance to use for the test
|
||||
/// </summary>
|
||||
private void InstallTestLocalDb(
|
||||
private void SetupTestDatabase(
|
||||
TestUmbracoDatabaseFactoryProvider testUmbracoDatabaseFactoryProvider,
|
||||
IUmbracoDatabaseFactory databaseFactory,
|
||||
ILoggerFactory loggerFactory,
|
||||
IRuntimeState runtimeState,
|
||||
string workingDirectory)
|
||||
{
|
||||
var dbFilePath = Path.Combine(workingDirectory, "LocalDb");
|
||||
|
||||
// get the currently set db options
|
||||
var testOptions = TestOptionAttributeBase.GetTestOptions<UmbracoTestAttribute>();
|
||||
|
||||
if (testOptions.Database == UmbracoTestOptions.Database.None)
|
||||
if (TestOptions.Database == UmbracoTestOptions.Database.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// need to manually register this factory
|
||||
DbProviderFactories.RegisterFactory(Constants.DbProviderNames.SqlServer, SqlClientFactory.Instance);
|
||||
|
||||
if (!Directory.Exists(dbFilePath))
|
||||
Directory.CreateDirectory(dbFilePath);
|
||||
var dbFilePath = Path.Combine(workingDirectory, "LocalDb");
|
||||
|
||||
var db = GetOrCreateDatabase(dbFilePath, loggerFactory, testUmbracoDatabaseFactoryProvider);
|
||||
|
||||
switch (testOptions.Database)
|
||||
switch (TestOptions.Database)
|
||||
{
|
||||
case UmbracoTestOptions.Database.NewSchemaPerTest:
|
||||
|
||||
// New DB + Schema
|
||||
var newSchemaDbMeta = db.AttachSchema();
|
||||
TestDbMeta newSchemaDbMeta = db.AttachSchema();
|
||||
|
||||
// Add teardown callback
|
||||
OnTestTearDown(() => db.Detach(newSchemaDbMeta));
|
||||
|
||||
// We must re-configure our current factory since attaching a new LocalDb from the pool changes connection strings
|
||||
if (!databaseFactory.Configured)
|
||||
{
|
||||
databaseFactory.Configure(newSchemaDbMeta.ConnectionString, Constants.DatabaseProviders.SqlServer);
|
||||
}
|
||||
|
||||
// re-run the runtime level check
|
||||
runtimeState.DetermineRuntimeLevel();
|
||||
ConfigureTestDatabaseFactory(newSchemaDbMeta, databaseFactory, runtimeState);
|
||||
|
||||
Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level);
|
||||
|
||||
break;
|
||||
case UmbracoTestOptions.Database.NewEmptyPerTest:
|
||||
var newEmptyDbMeta = db.AttachEmpty();
|
||||
TestDbMeta newEmptyDbMeta = db.AttachEmpty();
|
||||
|
||||
// Add teardown callback
|
||||
OnTestTearDown(() => db.Detach(newEmptyDbMeta));
|
||||
|
||||
// We must re-configure our current factory since attaching a new LocalDb from the pool changes connection strings
|
||||
if (!databaseFactory.Configured)
|
||||
{
|
||||
databaseFactory.Configure(newEmptyDbMeta.ConnectionString, Constants.DatabaseProviders.SqlServer);
|
||||
}
|
||||
|
||||
// re-run the runtime level check
|
||||
runtimeState.DetermineRuntimeLevel();
|
||||
ConfigureTestDatabaseFactory(newEmptyDbMeta, databaseFactory, runtimeState);
|
||||
|
||||
Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level);
|
||||
|
||||
@@ -353,21 +340,14 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
if (FirstTestInFixture)
|
||||
{
|
||||
// New DB + Schema
|
||||
var newSchemaFixtureDbMeta = db.AttachSchema();
|
||||
TestDbMeta newSchemaFixtureDbMeta = db.AttachSchema();
|
||||
_fixtureDbMeta = newSchemaFixtureDbMeta;
|
||||
|
||||
// Add teardown callback
|
||||
OnFixtureTearDown(() => db.Detach(newSchemaFixtureDbMeta));
|
||||
}
|
||||
|
||||
// We must re-configure our current factory since attaching a new LocalDb from the pool changes connection strings
|
||||
if (!databaseFactory.Configured)
|
||||
{
|
||||
databaseFactory.Configure(_fixtureDbMeta.ConnectionString, Constants.DatabaseProviders.SqlServer);
|
||||
}
|
||||
|
||||
// re-run the runtime level check
|
||||
runtimeState.DetermineRuntimeLevel();
|
||||
ConfigureTestDatabaseFactory(_fixtureDbMeta, databaseFactory, runtimeState);
|
||||
|
||||
break;
|
||||
case UmbracoTestOptions.Database.NewEmptyPerFixture:
|
||||
@@ -377,29 +357,40 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
if (FirstTestInFixture)
|
||||
{
|
||||
// New DB + Schema
|
||||
var newEmptyFixtureDbMeta = db.AttachEmpty();
|
||||
TestDbMeta newEmptyFixtureDbMeta = db.AttachEmpty();
|
||||
_fixtureDbMeta = newEmptyFixtureDbMeta;
|
||||
|
||||
// Add teardown callback
|
||||
OnFixtureTearDown(() => db.Detach(newEmptyFixtureDbMeta));
|
||||
}
|
||||
|
||||
// We must re-configure our current factory since attaching a new LocalDb from the pool changes connection strings
|
||||
if (!databaseFactory.Configured)
|
||||
{
|
||||
databaseFactory.Configure(_fixtureDbMeta.ConnectionString, Constants.DatabaseProviders.SqlServer);
|
||||
}
|
||||
ConfigureTestDatabaseFactory(_fixtureDbMeta, databaseFactory, runtimeState);
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(testOptions), testOptions, null);
|
||||
throw new ArgumentOutOfRangeException(nameof(TestOptions), TestOptions, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigureTestDatabaseFactory(TestDbMeta meta, IUmbracoDatabaseFactory factory, IRuntimeState state)
|
||||
{
|
||||
ILogger<UmbracoIntegrationTest> log = Services.GetRequiredService<ILogger<UmbracoIntegrationTest>>();
|
||||
log.LogInformation($"ConfigureTestDatabaseFactory - Using test database: [{meta.Name}] - IsEmpty: [{meta.IsEmpty}]");
|
||||
|
||||
// It's just been pulled from container and wasn't used to create test database
|
||||
Assert.IsFalse(factory.Configured);
|
||||
|
||||
factory.Configure(meta.ConnectionString, Constants.DatabaseProviders.SqlServer);
|
||||
state.DetermineRuntimeLevel();
|
||||
log.LogInformation($"ConfigureTestDatabaseFactory - Determined RuntimeLevel: [{state.Level}]");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Common services
|
||||
|
||||
protected UmbracoTestAttribute TestOptions => TestOptionAttributeBase.GetTestOptions<UmbracoTestAttribute>();
|
||||
|
||||
protected virtual T GetRequiredService<T>() => Services.GetRequiredService<T>();
|
||||
|
||||
public Dictionary<string, string> InMemoryConfiguration { get; } = new Dictionary<string, string>();
|
||||
@@ -429,7 +420,6 @@ namespace Umbraco.Tests.Integration.Testing
|
||||
/// Returns the <see cref="ILoggerFactory"/>
|
||||
/// </summary>
|
||||
protected ILoggerFactory LoggerFactory => Services.GetRequiredService<ILoggerFactory>();
|
||||
|
||||
protected AppCaches AppCaches => Services.GetRequiredService<AppCaches>();
|
||||
protected IIOHelper IOHelper => Services.GetRequiredService<IIOHelper>();
|
||||
protected IShortStringHelper ShortStringHelper => Services.GetRequiredService<IShortStringHelper>();
|
||||
|
||||
@@ -45,6 +45,8 @@ namespace Umbraco.Tests.Integration.Umbraco.Core.Packaging
|
||||
private IEntityXmlSerializer EntityXmlSerializer => GetRequiredService<IEntityXmlSerializer>();
|
||||
private IHostingEnvironment HostingEnvironment => GetRequiredService<IHostingEnvironment>();
|
||||
private IUmbracoVersion UmbracoVersion => GetRequiredService<IUmbracoVersion>();
|
||||
private IMediaService MediaService => GetRequiredService<IMediaService>();
|
||||
private IMediaTypeService MediaTypeService => GetRequiredService<IMediaTypeService>();
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -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<ILocalizationService>();
|
||||
private IMacroService MacroService => GetRequiredService<IMacroService>();
|
||||
|
||||
[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<DataEditorCollectionBuilder>()
|
||||
// .Add<Editor1>()
|
||||
// .Add<Editor2>();
|
||||
// }
|
||||
//
|
||||
// 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<PackageDataInstallation>();
|
||||
private IContentService ContentService => GetRequiredService<IContentService>();
|
||||
private IContentTypeService ContentTypeService => GetRequiredService<IContentTypeService>();
|
||||
|
||||
Builder.WithCollectionBuilder<DataEditorCollectionBuilder>()
|
||||
.Add<Editor1>()
|
||||
.Add<Editor2>();
|
||||
}
|
||||
|
||||
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<PackageDataInstallation>();
|
||||
private IMediaService MediaService => GetRequiredService<IMediaService>();
|
||||
private IMediaTypeService MediaTypeService => GetRequiredService<IMediaTypeService>();
|
||||
|
||||
[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<IEntityXmlSerializer>();
|
||||
var serializer = GetRequiredService<IEntityXmlSerializer>();
|
||||
|
||||
// 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<IDictionaryTranslation>
|
||||
@@ -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<IDictionaryTranslation>
|
||||
@@ -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<PackageDataInstallation>(), NullLoggerFactory.Instance, ServiceContext.FileService, ServiceContext.MacroService, ServiceContext.LocalizationService,
|
||||
ServiceContext.DataTypeService, ServiceContext.EntityService,
|
||||
ServiceContext.ContentTypeService, ServiceContext.ContentService,
|
||||
Factory.GetRequiredService<PropertyEditorCollection>(),
|
||||
Factory.GetRequiredService<IScopeProvider>(),
|
||||
Factory.GetRequiredService<IShortStringHelper>(),
|
||||
Microsoft.Extensions.Options.Options.Create(new GlobalSettings()),
|
||||
Factory.GetRequiredService<ILocalizedTextService>(),
|
||||
Factory.GetRequiredService<IConfigurationEditorJsonSerializer>(),
|
||||
Factory.GetRequiredService<IJsonSerializer>()
|
||||
);
|
||||
|
||||
private IPackageInstallation PackageInstallation => new PackageInstallation(
|
||||
PackageDataInstallation,
|
||||
new PackageFileInstallation(Parser, IOHelper, HostingEnvironment, ProfilingLogger),
|
||||
Parser, Mock.Of<IPackageActionRunner>(),
|
||||
//we don't want to extract package files to the real root, so extract to a test folder
|
||||
Mock.Of<IHostingEnvironment>(x => x.ApplicationPhysicalPath == _testBaseFolder.FullName));
|
||||
private IHostingEnvironment HostingEnvironment => GetRequiredService<IHostingEnvironment>();
|
||||
private IPackageInstallation PackageInstallation => GetRequiredService<IPackageInstallation>();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@@ -10,10 +10,12 @@ using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Sync;
|
||||
using Umbraco.Net;
|
||||
using Umbraco.Tests.Common.Builders;
|
||||
using Umbraco.Tests.Integration.Testing;
|
||||
using Umbraco.Tests.Testing;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Web.PublishedCache.NuCache;
|
||||
|
||||
namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services
|
||||
{
|
||||
@@ -510,7 +512,9 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services
|
||||
{
|
||||
// one simple content type, variant, with both variant and invariant properties
|
||||
// can change it to invariant and back
|
||||
GetRequiredService<IPublishedSnapshotService>(); //hack to ensure events are initialized
|
||||
|
||||
//hack to ensure events are initialized
|
||||
(GetRequiredService<IPublishedSnapshotService>() as PublishedSnapshotService)?.OnApplicationInit(null, null);
|
||||
CreateFrenchAndEnglishLangs();
|
||||
|
||||
var contentType = CreateContentType(ContentVariation.Culture);
|
||||
@@ -599,7 +603,9 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services
|
||||
// one simple content type, invariant
|
||||
// can change it to variant and back
|
||||
// can then switch one property to variant
|
||||
GetRequiredService<IPublishedSnapshotService>(); //hack to ensure events are initialized
|
||||
|
||||
//hack to ensure events are initialized
|
||||
(GetRequiredService<IPublishedSnapshotService>() as PublishedSnapshotService)?.OnApplicationInit(null, null);
|
||||
|
||||
var globalSettings = new GlobalSettings();
|
||||
|
||||
@@ -690,7 +696,9 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services
|
||||
{
|
||||
// one simple content type, variant, with both variant and invariant properties
|
||||
// can change an invariant property to variant and back
|
||||
GetRequiredService<IPublishedSnapshotService>(); //hack to ensure events are initialized
|
||||
|
||||
//hack to ensure events are initialized
|
||||
(GetRequiredService<IPublishedSnapshotService>() as PublishedSnapshotService)?.OnApplicationInit(null, null);
|
||||
CreateFrenchAndEnglishLangs();
|
||||
|
||||
var contentType = CreateContentType(ContentVariation.Culture);
|
||||
@@ -967,8 +975,8 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services
|
||||
// can change the composing content type to invariant and back
|
||||
// can change the composed content type to invariant and back
|
||||
|
||||
|
||||
GetRequiredService<IPublishedSnapshotService>(); //hack to ensure events are initialized
|
||||
//hack to ensure events are initialized
|
||||
(GetRequiredService<IPublishedSnapshotService>() as PublishedSnapshotService)?.OnApplicationInit(null, null);
|
||||
CreateFrenchAndEnglishLangs();
|
||||
|
||||
var composing = CreateContentType(ContentVariation.Culture, "composing");
|
||||
@@ -1064,7 +1072,8 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services
|
||||
// can change the composing content type to invariant and back
|
||||
// can change the variant composed content type to invariant and back
|
||||
|
||||
GetRequiredService<IPublishedSnapshotService>(); //hack to ensure events are initialized
|
||||
//hack to ensure events are initialized
|
||||
(GetRequiredService<IPublishedSnapshotService>() as PublishedSnapshotService)?.OnApplicationInit(null, null);
|
||||
CreateFrenchAndEnglishLangs();
|
||||
|
||||
var composing = CreateContentType(ContentVariation.Culture, "composing");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
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 {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string CheckboxList_Content_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("CheckboxList_Content_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string CompositionsTestPackage {
|
||||
get {
|
||||
return ResourceManager.GetString("CompositionsTestPackage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string CompositionsTestPackage_Random {
|
||||
get {
|
||||
return ResourceManager.GetString("CompositionsTestPackage_Random", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string Fanoe_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("Fanoe_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string InheritedDocTypes_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("InheritedDocTypes_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string MediaTypesAndMedia_Package_xml {
|
||||
get {
|
||||
return ResourceManager.GetString("MediaTypesAndMedia_Package.xml", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string SingleDocType {
|
||||
get {
|
||||
return ResourceManager.GetString("SingleDocType", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string StandardMvc_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("StandardMvc_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string TemplateOnly_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("TemplateOnly_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string TemplateOnly_Updated_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("TemplateOnly_Updated_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string uBlogsy_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("uBlogsy_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string XsltSearch_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("XsltSearch_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
@@ -26,36 +26,36 @@
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
@@ -118,7 +118,43 @@
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="InheritedDocTypes_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>InheritedDocTypes-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="StandardMvc_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>StandardMvc-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="uBlogsy_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>uBlogsy-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="XsltSearch_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>XsltSearch-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="SingleDocType" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>SingleDocType.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="TemplateOnly_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>TemplateOnly-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="TemplateOnly_Updated_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>TemplateOnly-Updated-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="CheckboxList_Content_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>CheckboxList-Content-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="Dictionary_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>Dictionary-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="CompositionsTestPackage" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>CompositionsTestPackage.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="CompositionsTestPackage_Random" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>CompositionsTestPackage-Random.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="Fanoe_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>Fanoe-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="MediaTypesAndMedia_Package.xml" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>MediaTypesAndMedia-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
<?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>dteam</name>
|
||||
<website>http://www.umbraco.com</website>
|
||||
</author>
|
||||
<contributors></contributors>
|
||||
<readme><![CDATA[]]></readme>
|
||||
</info>
|
||||
<DocumentTypes />
|
||||
<MediaTypes>
|
||||
<MediaType>
|
||||
<Info>
|
||||
<Name>Folder</Name>
|
||||
<Alias>Folder</Alias>
|
||||
<Icon>icon-folder</Icon>
|
||||
<Thumbnail>icon-folder</Thumbnail>
|
||||
<Description />
|
||||
<AllowAtRoot>True</AllowAtRoot>
|
||||
</Info>
|
||||
<Structure>
|
||||
<MediaType>Folder</MediaType>
|
||||
<MediaType>Image</MediaType>
|
||||
<MediaType>File</MediaType>
|
||||
</Structure>
|
||||
<GenericProperties />
|
||||
<Tabs />
|
||||
</MediaType>
|
||||
<MediaType>
|
||||
<Info>
|
||||
<Name>Image</Name>
|
||||
<Alias>Image</Alias>
|
||||
<Icon>icon-picture</Icon>
|
||||
<Thumbnail>icon-picture</Thumbnail>
|
||||
<Description />
|
||||
<AllowAtRoot>True</AllowAtRoot>
|
||||
</Info>
|
||||
<Structure />
|
||||
<GenericProperties>
|
||||
<GenericProperty>
|
||||
<Name>Upload image</Name>
|
||||
<Alias>umbracoFile</Alias>
|
||||
<Type>Umbraco.ImageCropper</Type>
|
||||
<Definition>1df9f033-e6d4-451f-b8d2-e0cbc50a836f</Definition>
|
||||
<Tab>Image</Tab>
|
||||
<Mandatory>True</Mandatory>
|
||||
<MandatoryMessage />
|
||||
<Validation />
|
||||
<ValidationRegExpMessage />
|
||||
<LabelOnTop>false</LabelOnTop>
|
||||
<Description><![CDATA[]]></Description>
|
||||
</GenericProperty>
|
||||
<GenericProperty>
|
||||
<Name>Width</Name>
|
||||
<Alias>umbracoWidth</Alias>
|
||||
<Type>Umbraco.Label</Type>
|
||||
<Definition>8e7f995c-bd81-4627-9932-c40e568ec788</Definition>
|
||||
<Tab>Image</Tab>
|
||||
<Mandatory>False</Mandatory>
|
||||
<MandatoryMessage />
|
||||
<Validation />
|
||||
<ValidationRegExpMessage />
|
||||
<LabelOnTop>false</LabelOnTop>
|
||||
<Description><![CDATA[in pixels]]></Description>
|
||||
</GenericProperty>
|
||||
<GenericProperty>
|
||||
<Name>Height</Name>
|
||||
<Alias>umbracoHeight</Alias>
|
||||
<Type>Umbraco.Label</Type>
|
||||
<Definition>8e7f995c-bd81-4627-9932-c40e568ec788</Definition>
|
||||
<Tab>Image</Tab>
|
||||
<Mandatory>False</Mandatory>
|
||||
<MandatoryMessage />
|
||||
<Validation />
|
||||
<ValidationRegExpMessage />
|
||||
<LabelOnTop>false</LabelOnTop>
|
||||
<Description><![CDATA[in pixels]]></Description>
|
||||
</GenericProperty>
|
||||
<GenericProperty>
|
||||
<Name>Size</Name>
|
||||
<Alias>umbracoBytes</Alias>
|
||||
<Type>Umbraco.Label</Type>
|
||||
<Definition>930861bf-e262-4ead-a704-f99453565708</Definition>
|
||||
<Tab>Image</Tab>
|
||||
<Mandatory>False</Mandatory>
|
||||
<MandatoryMessage />
|
||||
<Validation />
|
||||
<ValidationRegExpMessage />
|
||||
<LabelOnTop>false</LabelOnTop>
|
||||
<Description><![CDATA[in bytes]]></Description>
|
||||
</GenericProperty>
|
||||
<GenericProperty>
|
||||
<Name>Type</Name>
|
||||
<Alias>umbracoExtension</Alias>
|
||||
<Type>Umbraco.Label</Type>
|
||||
<Definition>f0bc4bfb-b499-40d6-ba86-058885a5178c</Definition>
|
||||
<Tab>Image</Tab>
|
||||
<Mandatory>False</Mandatory>
|
||||
<MandatoryMessage />
|
||||
<Validation />
|
||||
<ValidationRegExpMessage />
|
||||
<LabelOnTop>false</LabelOnTop>
|
||||
<Description><![CDATA[]]></Description>
|
||||
</GenericProperty>
|
||||
</GenericProperties>
|
||||
<Tabs>
|
||||
<Tab>
|
||||
<Id>3</Id>
|
||||
<Caption>Image</Caption>
|
||||
<SortOrder>1</SortOrder>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</MediaType>
|
||||
</MediaTypes>
|
||||
<Templates />
|
||||
<Stylesheets />
|
||||
<Macros />
|
||||
<DictionaryItems />
|
||||
<Languages />
|
||||
<DataTypes />
|
||||
<MediaItems>
|
||||
<MediaSet>
|
||||
<Image id="1145" key="cd4caf13-0705-4e31-9661-48d5a6ce2cc6" parentID="-1" level="1" creatorID="-1" sortOrder="0" createDate="2020-12-15T12:56:46" updateDate="2020-12-15T12:56:46" nodeName="Ledersidetegning Mandag 27 01 20 Rgb (1) (1)" urlName="ledersidetegning-mandag-27-01-20-rgb-1-1" path="-1,1145" isDoc="" nodeType="1032" nodeTypeAlias="Image" writerName="" writerID="0" udi="umb://media/cd4caf1307054e31966148d5a6ce2cc6">
|
||||
<umbracoFile><![CDATA[{"src":"/media/cwxfztif/ledersidetegning-mandag-27-01-20-rgb-1.jpg","crops":null}]]></umbracoFile>
|
||||
<umbracoWidth><![CDATA[940]]></umbracoWidth>
|
||||
<umbracoHeight><![CDATA[564]]></umbracoHeight>
|
||||
<umbracoBytes><![CDATA[20340]]></umbracoBytes>
|
||||
<umbracoExtension><![CDATA[jpg]]></umbracoExtension>
|
||||
</Image>
|
||||
</MediaSet>
|
||||
<MediaSet>
|
||||
<Folder id="1146" key="aef56c09-de35-4d45-b91a-93096dac5e45" parentID="-1" level="1" creatorID="-1" sortOrder="1" createDate="2020-12-15T12:57:26" updateDate="2020-12-15T12:57:26" nodeName="asd" urlName="asd" path="-1,1146" isDoc="" nodeType="1031" nodeTypeAlias="Folder" writerName="" writerID="0" udi="umb://media/aef56c09de354d45b91a93096dac5e45">
|
||||
<Image id="1147" key="4a3172d8-3c68-4c32-890f-051894e50c8e" parentID="1146" level="2" creatorID="-1" sortOrder="0" createDate="2020-12-15T12:58:00" updateDate="2020-12-15T12:58:00" nodeName="Rider" urlName="rider" path="-1,1146,1147" isDoc="" nodeType="1032" nodeTypeAlias="Image" writerName="" writerID="0" udi="umb://media/4a3172d83c684c32890f051894e50c8e">
|
||||
<umbracoFile><![CDATA[{"src":"/media/1zzdcsti/rider.png","crops":null}]]></umbracoFile>
|
||||
<umbracoWidth><![CDATA[839]]></umbracoWidth>
|
||||
<umbracoHeight><![CDATA[551]]></umbracoHeight>
|
||||
<umbracoBytes><![CDATA[37605]]></umbracoBytes>
|
||||
<umbracoExtension><![CDATA[png]]></umbracoExtension>
|
||||
</Image>
|
||||
</Folder>
|
||||
</MediaSet>
|
||||
</MediaItems>
|
||||
<Actions />
|
||||
</umbPackage>
|
||||
@@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -31,7 +32,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services
|
||||
|
||||
[TestFixture]
|
||||
[Apartment(ApartmentState.STA)]
|
||||
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)]
|
||||
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, Logger = UmbracoTestOptions.Logger.Console)]
|
||||
public class ThreadSafetyServiceTest : UmbracoIntegrationTest
|
||||
{
|
||||
private IContentService ContentService => GetRequiredService<IContentService>();
|
||||
@@ -98,13 +99,15 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services
|
||||
if (Environment.GetEnvironmentVariable("UMBRACO_TMP") != null)
|
||||
Assert.Ignore("Do not run on VSTS.");
|
||||
|
||||
var log = GetRequiredService<ILogger<ThreadSafetyServiceTest>>();
|
||||
|
||||
// the ServiceContext in that each repository in a service (i.e. ContentService) is a singleton
|
||||
var contentService = (ContentService)ContentService;
|
||||
|
||||
var threads = new List<Thread>();
|
||||
var exceptions = new List<Exception>();
|
||||
|
||||
Debug.WriteLine("Starting...");
|
||||
log.LogInformation("Starting...");
|
||||
|
||||
var done = TraceLocks();
|
||||
|
||||
@@ -114,12 +117,12 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services
|
||||
{
|
||||
try
|
||||
{
|
||||
Debug.WriteLine("[{0}] Running...", Thread.CurrentThread.ManagedThreadId);
|
||||
log.LogInformation("[{0}] Running...", Thread.CurrentThread.ManagedThreadId);
|
||||
|
||||
var name1 = "test-" + Guid.NewGuid();
|
||||
var content1 = contentService.Create(name1, -1, "umbTextpage");
|
||||
|
||||
Debug.WriteLine("[{0}] Saving content #1.", Thread.CurrentThread.ManagedThreadId);
|
||||
log.LogInformation("[{0}] Saving content #1.", Thread.CurrentThread.ManagedThreadId);
|
||||
Save(contentService, content1);
|
||||
|
||||
Thread.Sleep(100); //quick pause for maximum overlap!
|
||||
@@ -127,7 +130,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services
|
||||
var name2 = "test-" + Guid.NewGuid();
|
||||
var content2 = contentService.Create(name2, -1, "umbTextpage");
|
||||
|
||||
Debug.WriteLine("[{0}] Saving content #2.", Thread.CurrentThread.ManagedThreadId);
|
||||
log.LogInformation("[{0}] Saving content #2.", Thread.CurrentThread.ManagedThreadId);
|
||||
Save(contentService, content2);
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -139,16 +142,16 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services
|
||||
}
|
||||
|
||||
// start all threads
|
||||
Debug.WriteLine("Starting threads");
|
||||
log.LogInformation("Starting threads");
|
||||
threads.ForEach(x => x.Start());
|
||||
|
||||
// wait for all to complete
|
||||
Debug.WriteLine("Joining threads");
|
||||
log.LogInformation("Joining threads");
|
||||
threads.ForEach(x => x.Join());
|
||||
|
||||
done.Set();
|
||||
|
||||
Debug.WriteLine("Checking exceptions");
|
||||
log.LogInformation("Checking exceptions");
|
||||
if (exceptions.Count == 0)
|
||||
{
|
||||
//now look up all items, there should be 40!
|
||||
@@ -166,13 +169,16 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services
|
||||
{
|
||||
if (Environment.GetEnvironmentVariable("UMBRACO_TMP") != null)
|
||||
Assert.Ignore("Do not run on VSTS.");
|
||||
|
||||
var log = GetRequiredService<ILogger<ThreadSafetyServiceTest>>();
|
||||
|
||||
// mimick the ServiceContext in that each repository in a service (i.e. ContentService) is a singleton
|
||||
var mediaService = (MediaService)MediaService;
|
||||
|
||||
var threads = new List<Thread>();
|
||||
var exceptions = new List<Exception>();
|
||||
|
||||
Debug.WriteLine("Starting...");
|
||||
log.LogInformation("Starting...");
|
||||
|
||||
var done = TraceLocks();
|
||||
|
||||
@@ -182,18 +188,18 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services
|
||||
{
|
||||
try
|
||||
{
|
||||
Debug.WriteLine("[{0}] Running...", Thread.CurrentThread.ManagedThreadId);
|
||||
log.LogInformation("[{0}] Running...", Thread.CurrentThread.ManagedThreadId);
|
||||
|
||||
var name1 = "test-" + Guid.NewGuid();
|
||||
var media1 = mediaService.CreateMedia(name1, -1, Constants.Conventions.MediaTypes.Folder);
|
||||
Debug.WriteLine("[{0}] Saving media #1.", Thread.CurrentThread.ManagedThreadId);
|
||||
log.LogInformation("[{0}] Saving media #1.", Thread.CurrentThread.ManagedThreadId);
|
||||
Save(mediaService, media1);
|
||||
|
||||
Thread.Sleep(100); //quick pause for maximum overlap!
|
||||
|
||||
var name2 = "test-" + Guid.NewGuid();
|
||||
var media2 = mediaService.CreateMedia(name2, -1, Constants.Conventions.MediaTypes.Folder);
|
||||
Debug.WriteLine("[{0}] Saving media #2.", Thread.CurrentThread.ManagedThreadId);
|
||||
log.LogInformation("[{0}] Saving media #2.", Thread.CurrentThread.ManagedThreadId);
|
||||
Save(mediaService, media2);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -19,6 +19,16 @@
|
||||
<EmbeddedResource Remove="Views\**" />
|
||||
<None Remove="Views\**" />
|
||||
<None Remove="create_slicing_filter_condition.sh" />
|
||||
<EmbeddedResource Update="Umbraco.Infrastructure\Services\Importing\ImportResources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>ImportResources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Update="Umbraco.Infrastructure\Services\Importing\ImportResources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>ImportResources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -26,7 +36,22 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Umbraco.Infrastructure\Services\Importing\CheckboxList-Content-Package.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Umbraco.Infrastructure\Services\Importing\CompositionsTestPackage-Random.xml" />
|
||||
<Content Include="Umbraco.Infrastructure\Services\Importing\CompositionsTestPackage.xml" />
|
||||
<Content Include="Umbraco.Infrastructure\Services\Importing\Dictionary-Package.xml" />
|
||||
<Content Include="Umbraco.Infrastructure\Services\Importing\Fanoe-Package.xml" />
|
||||
<Content Include="Umbraco.Infrastructure\Services\Importing\InheritedDocTypes-Package.xml" />
|
||||
<Content Include="Umbraco.Infrastructure\Services\Importing\SingleDocType.xml" />
|
||||
<Content Include="Umbraco.Infrastructure\Services\Importing\StandardMvc-Package.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Umbraco.Infrastructure\Services\Importing\TemplateOnly-Package.xml" />
|
||||
<Content Include="Umbraco.Infrastructure\Services\Importing\TemplateOnly-Updated-Package.xml" />
|
||||
<Content Include="Umbraco.Infrastructure\Services\Importing\uBlogsy-Package.xml" />
|
||||
<Content Include="Umbraco.Infrastructure\Services\Importing\XsltSearch-Package.xml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -58,20 +83,4 @@
|
||||
<Folder Include="Umbraco\logs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Umbraco.Infrastructure\Services\Importing\ImportResources.Designer.cs">
|
||||
<DependentUpon>ImportResources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Umbraco.Infrastructure\Services\Importing\ImportResources.resx">
|
||||
<SubType>Designer</SubType>
|
||||
<LastGenOutput>ImportResources.Designer.cs</LastGenOutput>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
Binary file not shown.
@@ -1,383 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 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.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Umbraco.Tests.Services.Importing {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// 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() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string CheckboxList_Content_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("CheckboxList_Content_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string CompositionsTestPackage {
|
||||
get {
|
||||
return ResourceManager.GetString("CompositionsTestPackage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string CompositionsTestPackage_Random {
|
||||
get {
|
||||
return ResourceManager.GetString("CompositionsTestPackage_Random", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string Dictionary_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("Dictionary_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string Fanoe_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("Fanoe_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string InheritedDocTypes_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("InheritedDocTypes_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string SingleDocType {
|
||||
get {
|
||||
return ResourceManager.GetString("SingleDocType", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string StandardMvc_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("StandardMvc_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string TemplateOnly_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("TemplateOnly_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string TemplateOnly_Updated_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("TemplateOnly_Updated_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string uBlogsy_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("uBlogsy_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]";.
|
||||
/// </summary>
|
||||
internal static string XsltSearch_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("XsltSearch_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="InheritedDocTypes_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>inheriteddoctypes-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="StandardMvc_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>standardmvc-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="uBlogsy_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>ublogsy-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="XsltSearch_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>xsltsearch-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="SingleDocType" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>singledoctype.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="TemplateOnly_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>templateonly-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="TemplateOnly_Updated_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>templateonly-updated-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="CheckboxList_Content_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>checkboxlist-content-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="Dictionary_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>dictionary-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="CompositionsTestPackage" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>compositionstestpackage.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="CompositionsTestPackage_Random" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>compositionstestpackage-random.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="Fanoe_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>fanoe-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -199,7 +199,6 @@
|
||||
<Compile Include="PublishedContent\PublishedRouterTests.cs" />
|
||||
<Compile Include="PublishedContent\RootNodeTests.cs" />
|
||||
<Compile Include="Scheduling\BackgroundTaskRunnerTests.cs" />
|
||||
<Compile Include="Packaging\PackageInstallationTest.cs" />
|
||||
<Compile Include="Cache\PublishedCache\PublishedMediaCacheTests.cs" />
|
||||
<Compile Include="Models\MediaXmlTest.cs" />
|
||||
<Compile Include="Persistence\FaultHandling\ConnectionRetryTest.cs" />
|
||||
@@ -216,12 +215,6 @@
|
||||
<Compile Include="Routing\ContentFinderByAliasWithDomainsTests.cs" />
|
||||
<Compile Include="Routing\DomainsAndCulturesTests.cs" />
|
||||
<Compile Include="Routing\UrlsWithNestedDomains.cs" />
|
||||
<Compile Include="Packaging\PackageDataInstallationTests.cs" />
|
||||
<Compile Include="Services\Importing\ImportResources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>ImportResources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Web\Controllers\PluginControllerAreaTests.cs" />
|
||||
<Compile Include="TestHelpers\TestWithDatabaseBase.cs" />
|
||||
<Compile Include="Routing\ContentFinderByAliasTests.cs" />
|
||||
@@ -269,7 +262,6 @@
|
||||
<None Include="App.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="Packaging\Packages\Document_Type_Picker_1.1.umb" />
|
||||
<None Include="UmbracoExamine\TestFiles\umbraco-sort.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
@@ -309,11 +301,6 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Services\Importing\ImportResources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>ImportResources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="UmbracoExamine\TestFiles.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>TestFiles.Designer.cs</LastGenOutput>
|
||||
@@ -321,23 +308,8 @@
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Services\Importing\CheckboxList-Content-Package.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Services\Importing\CompositionsTestPackage-Random.xml" />
|
||||
<Content Include="Services\Importing\CompositionsTestPackage.xml" />
|
||||
<Content Include="Services\Importing\Dictionary-Package.xml" />
|
||||
<Content Include="Services\Importing\Fanoe-Package.xml" />
|
||||
<Content Include="UmbracoExamine\TestFiles\media.xml" />
|
||||
<Content Include="Services\Importing\InheritedDocTypes-Package.xml" />
|
||||
<Content Include="Services\Importing\SingleDocType.xml" />
|
||||
<Content Include="Services\Importing\StandardMvc-Package.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Services\Importing\TemplateOnly-Package.xml" />
|
||||
<Content Include="Services\Importing\TemplateOnly-Updated-Package.xml" />
|
||||
<Content Include="Services\Importing\uBlogsy-Package.xml" />
|
||||
<Content Include="Services\Importing\XsltSearch-Package.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
|
||||
@@ -127,20 +127,6 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
_logger = loggerFactory.CreateLogger<ContentController>();
|
||||
|
||||
_allLangs = new Lazy<IDictionary<string, ILanguage>>(() => _localizationService.GetAllLanguages().ToDictionary(x => x.IsoCode, x => x, StringComparer.InvariantCultureIgnoreCase));
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if any content types have culture variation enabled
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
// TODO: We need to move this since we are going to delete OverrideAuthorization
|
||||
[Authorize(Policy = AuthorizationPolicies.BackOfficeAccess), OverrideAuthorization]
|
||||
public bool AllowsCultureVariation()
|
||||
{
|
||||
var contentTypes = _contentTypeService.GetAll();
|
||||
return contentTypes.Any(contentType => contentType.VariesByCulture());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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<ContentTypeController> _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> globalSettings,
|
||||
PropertyEditorCollection propertyEditors,
|
||||
IScopeProvider scopeProvider,
|
||||
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
|
||||
IDataTypeService dataTypeService,
|
||||
IShortStringHelper shortStringHelper,
|
||||
IFileService fileService,
|
||||
ILogger<ContentTypeController> 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)]
|
||||
@@ -256,6 +231,19 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
});
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if any content types have culture variation enabled
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
[Authorize(Policy = AuthorizationPolicies.BackOfficeAccess)]
|
||||
public bool AllowsCultureVariation()
|
||||
{
|
||||
IEnumerable<IContentType> contentTypes = _contentTypeService.GetAll();
|
||||
return contentTypes.Any(contentType => contentType.VariesByCulture());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns where a particular composition has been used
|
||||
/// This has been wrapped in a dto instead of simple parameters to support having multiple parameters in post request body
|
||||
@@ -627,30 +615,13 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var dataInstaller = new PackageDataInstallation(
|
||||
_loggerFactory.CreateLogger<PackageDataInstallation>(),
|
||||
_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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ namespace Umbraco.Extensions
|
||||
public static IUmbracoBuilder AddBackOffice(this IUmbracoBuilder builder)
|
||||
{
|
||||
builder.Services.AddAntiforgery();
|
||||
builder.Services.AddSingleton<IFilterProvider, OverrideAuthorizationFilterProvider>();
|
||||
|
||||
builder.Services
|
||||
.AddAuthentication() // This just creates a builder, nothing more
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Filters
|
||||
{
|
||||
// TODO: This should probably be deleted, anything requiring this should move to a different controller
|
||||
public class OverrideAuthorizationAttribute : ActionFilterAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Ensures a special type of authorization filter is ignored. Defaults to <see cref="IAuthorizationFilter"/>.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of authorization filter to override. if null then <see cref="IAuthorizationFilter"/> is used.</param>
|
||||
/// <remarks>
|
||||
/// https://stackoverflow.com/questions/33558095/overrideauthorizationattribute-in-asp-net-5
|
||||
/// </remarks>
|
||||
public OverrideAuthorizationAttribute(Type filtersToOverride = null)
|
||||
{
|
||||
FiltersToOverride = filtersToOverride ?? typeof(IAuthorizationFilter);
|
||||
}
|
||||
|
||||
public Type FiltersToOverride { get;}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Filters
|
||||
{
|
||||
// TODO: This should be deleted, anything requiring this should move to a different controller
|
||||
public class OverrideAuthorizationFilterProvider : IFilterProvider, IFilterMetadata
|
||||
{
|
||||
public void OnProvidersExecuted(FilterProviderContext context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnProvidersExecuting(FilterProviderContext context)
|
||||
{
|
||||
if (context.ActionContext.ActionDescriptor.FilterDescriptors != null)
|
||||
{
|
||||
//Does the action have any UmbracoAuthorizeFilter?
|
||||
var overrideFilters = context.Results.Where(filterItem => filterItem.Filter is OverrideAuthorizationAttribute).ToArray();
|
||||
foreach (var overrideFilter in overrideFilters)
|
||||
{
|
||||
context.Results.RemoveAll(filterItem =>
|
||||
//Remove any filter for the type indicated in the UmbracoAuthorizeFilter attribute
|
||||
filterItem.Descriptor.Filter.GetType() == ((OverrideAuthorizationAttribute)overrideFilter.Filter).FiltersToOverride &&
|
||||
//Remove filters with lower scope (ie controller) than the override filter (ie action method)
|
||||
filterItem.Descriptor.Scope < overrideFilter.Descriptor.Scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//all framework providers have negative orders, so ours will come later
|
||||
public int Order => 1;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -143,11 +143,14 @@ namespace Umbraco.Core.DependencyInjection
|
||||
builder.Services.AddUnique<IUmbracoDatabase>(factory => factory.GetRequiredService<IUmbracoDatabaseFactory>().CreateDatabase());
|
||||
builder.Services.AddUnique<ISqlContext>(factory => factory.GetRequiredService<IUmbracoDatabaseFactory>().SqlContext);
|
||||
builder.Services.AddUnique<IUmbracoVersion, UmbracoVersion>();
|
||||
builder.Services.AddUnique<IRuntime, CoreRuntime>();
|
||||
builder.Services.AddUnique<IRuntimeState, RuntimeState>();
|
||||
builder.Services.AddUnique<IHostingEnvironment, AspNetCoreHostingEnvironment>();
|
||||
builder.Services.AddUnique<IMainDom, MainDom>();
|
||||
|
||||
builder.Services.AddUnique<IRuntime, CoreRuntime>();
|
||||
builder.Services.AddHostedService<IRuntime>(factory => factory.GetRequiredService<IRuntime>());
|
||||
|
||||
builder.AddCoreInitialServices();
|
||||
builder.AddComposers();
|
||||
|
||||
return builder;
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Serilog.Context;
|
||||
using SixLabors.ImageSharp.Web.DependencyInjection;
|
||||
@@ -11,7 +10,6 @@ using Smidge.Nuglify;
|
||||
using StackExchange.Profiling;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.Models;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Infrastructure.Logging.Serilog.Enrichers;
|
||||
using Umbraco.Web.Common.Middleware;
|
||||
using Umbraco.Web.Common.Plugins;
|
||||
@@ -74,10 +72,10 @@ namespace Umbraco.Extensions
|
||||
/// </summary>
|
||||
public static bool UmbracoCanBoot(this IApplicationBuilder app)
|
||||
{
|
||||
IRuntime runtime = app.ApplicationServices.GetRequiredService<IRuntime>();
|
||||
var state = app.ApplicationServices.GetRequiredService<IRuntimeState>();
|
||||
|
||||
// can't continue if boot failed
|
||||
return runtime.State.Level > RuntimeLevel.BootFailed;
|
||||
return state.Level > RuntimeLevel.BootFailed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -95,25 +93,10 @@ namespace Umbraco.Extensions
|
||||
return app;
|
||||
}
|
||||
|
||||
IHostingEnvironment hostingEnvironment = app.ApplicationServices.GetRequiredService<IHostingEnvironment>();
|
||||
AppDomain.CurrentDomain.SetData("DataDirectory", hostingEnvironment?.MapPathContentRoot(Constants.SystemDirectories.Data));
|
||||
|
||||
IRuntime runtime = app.ApplicationServices.GetRequiredService<IRuntime>();
|
||||
|
||||
// Register a listener for application shutdown in order to terminate the runtime
|
||||
IApplicationShutdownRegistry hostLifetime = app.ApplicationServices.GetRequiredService<IApplicationShutdownRegistry>();
|
||||
var runtimeShutdown = new CoreRuntimeShutdown(runtime, hostLifetime);
|
||||
hostLifetime.RegisterObject(runtimeShutdown);
|
||||
|
||||
// Register our global threadabort enricher for logging
|
||||
ThreadAbortExceptionEnricher threadAbortEnricher = app.ApplicationServices.GetRequiredService<ThreadAbortExceptionEnricher>();
|
||||
LogContext.Push(threadAbortEnricher); // NOTE: We are not in a using clause because we are not removing it, it is on the global context
|
||||
|
||||
StaticApplicationLogging.Initialize(app.ApplicationServices.GetRequiredService<ILoggerFactory>());
|
||||
|
||||
// Start the runtime!
|
||||
runtime.Start();
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
@@ -204,33 +187,6 @@ namespace Umbraco.Extensions
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures the runtime is shutdown when the application is shutting down
|
||||
/// </summary>
|
||||
private class CoreRuntimeShutdown : IRegisteredObject
|
||||
{
|
||||
public CoreRuntimeShutdown(IRuntime runtime, IApplicationShutdownRegistry hostLifetime)
|
||||
{
|
||||
_runtime = runtime;
|
||||
_hostLifetime = hostLifetime;
|
||||
}
|
||||
|
||||
private bool _completed = false;
|
||||
private readonly IRuntime _runtime;
|
||||
private readonly IApplicationShutdownRegistry _hostLifetime;
|
||||
|
||||
public void Stop(bool immediate)
|
||||
{
|
||||
if (!_completed)
|
||||
{
|
||||
_completed = true;
|
||||
_runtime.Terminate();
|
||||
_hostLifetime.UnregisterObject(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.DependencyInjection;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration.Models;
|
||||
using Umbraco.Core.Diagnostics;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Runtime;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Extensions;
|
||||
using Umbraco.Net;
|
||||
using Umbraco.Web.Common.AspNetCore;
|
||||
using Umbraco.Web.Common.Controllers;
|
||||
using Umbraco.Web.Common.Formatters;
|
||||
using Umbraco.Web.Common.Install;
|
||||
using Umbraco.Web.Common.Lifetime;
|
||||
using Umbraco.Web.Common.Macros;
|
||||
@@ -38,7 +33,6 @@ namespace Umbraco.Web.Common.Runtime
|
||||
/// Adds/replaces AspNetCore specific services
|
||||
/// </summary>
|
||||
[ComposeBefore(typeof(ICoreComposer))]
|
||||
[ComposeAfter(typeof(CoreInitialComposer))]
|
||||
public class AspNetCoreComposer : ComponentComposer<AspNetCoreComponent>, IComposer
|
||||
{
|
||||
public override void Compose(IUmbracoBuilder builder)
|
||||
|
||||
@@ -42,16 +42,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
|
||||
return {
|
||||
|
||||
allowsCultureVariation: function () {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"AllowsCultureVariation")),
|
||||
'Failed to retrieve variant content types');
|
||||
},
|
||||
|
||||
savePermissions: function (saveModel) {
|
||||
savePermissions: function (saveModel) {
|
||||
if (!saveModel) {
|
||||
throw "saveModel cannot be null";
|
||||
}
|
||||
|
||||
@@ -361,6 +361,15 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter, loca
|
||||
"HasContentNodes",
|
||||
[{ id: id }])),
|
||||
'Failed to retrieve indication for whether content type with id ' + id + ' has associated content nodes');
|
||||
},
|
||||
|
||||
allowsCultureVariation: function () {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentTypeApiBaseUrl",
|
||||
"AllowsCultureVariation")),
|
||||
'Failed to retrieve variant content types');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
* @param {navigationService} navigationService A reference to the navigationService
|
||||
*/
|
||||
function NavigationController($scope, $rootScope, $location, $log, $q, $routeParams, $timeout, $cookies, treeService, appState, navigationService, keyboardService, historyService, eventsService, angularHelper, languageResource, contentResource, editorState) {
|
||||
function NavigationController($scope, $rootScope, $location, $log, $q, $routeParams, $timeout, $cookies, treeService, appState, navigationService, keyboardService, historyService, eventsService, angularHelper, languageResource, contentTypeResource, editorState) {
|
||||
|
||||
//this is used to trigger the tree to start loading once everything is ready
|
||||
var treeInitPromise = $q.defer();
|
||||
@@ -380,7 +380,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
|
||||
*/
|
||||
function loadLanguages() {
|
||||
|
||||
return contentResource.allowsCultureVariation().then(function (b) {
|
||||
return contentTypeResource.allowsCultureVariation().then(function (b) {
|
||||
if (b === true) {
|
||||
return languageResource.getAll();
|
||||
} else {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -137,6 +137,22 @@
|
||||
|
||||
</umb-control-group>
|
||||
|
||||
|
||||
|
||||
<umb-control-group label="@general_media">
|
||||
|
||||
|
||||
|
||||
<umb-property property="vm.mediaPickerModel" ng-if="vm.loading === false">
|
||||
<umb-property-editor model="vm.mediaPickerModel" is-pre-value="true"></umb-property-editor>
|
||||
</umb-property>
|
||||
|
||||
<umb-checkbox model="vm.package.mediaLoadChildNodes"
|
||||
disabled="vm.mediaPickerModel.value.length === 0"
|
||||
text="{{vm.labels.includeAllChildNodes}}">
|
||||
</umb-checkbox>
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="@treeHeaders_documentTypes">
|
||||
<div ng-repeat="doctype in ::vm.documentTypes | orderBy:'name'">
|
||||
<umb-checkbox model="doctype.selected"
|
||||
@@ -146,11 +162,20 @@
|
||||
</div>
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="@treeHeaders_mediaTypes">
|
||||
<div ng-repeat="mediatype in ::vm.mediaTypes | orderBy:'name'">
|
||||
<umb-checkbox model="mediatype.selected"
|
||||
on-change="vm.selectMediaType(mediatype)"
|
||||
text="{{mediatype.name}}">
|
||||
</umb-checkbox>
|
||||
</div>
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="@treeHeaders_templates">
|
||||
<div ng-repeat="template in ::vm.templates | orderBy:'name'">
|
||||
<umb-checkbox model="template.selected"
|
||||
on-change="vm.selectTemplate(template)"
|
||||
text="{{template.name}}">
|
||||
text="{{template.name}}">umb-expansion-panel__content
|
||||
</umb-checkbox>
|
||||
</div>
|
||||
</umb-control-group>
|
||||
|
||||
@@ -20,7 +20,6 @@ namespace Umbraco.Web.UI.NetCore
|
||||
{
|
||||
x.ClearProviders();
|
||||
})
|
||||
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); })
|
||||
.UseUmbraco();
|
||||
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="App_Plugins" />
|
||||
<Folder Include="scripts" />
|
||||
<Folder Include="umbraco\MediaCache\2\c\6\9\3\a\6\5" />
|
||||
<Folder Include="umbraco\MediaCache\a\e\e\1\9\e\4\b" />
|
||||
|
||||
@@ -730,6 +730,7 @@
|
||||
<key alias="logout">Logout</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="mandatory">Mandatory</key>
|
||||
<key alias="media">Media</key>
|
||||
<key alias="message">Message</key>
|
||||
<key alias="move">Move</key>
|
||||
<key alias="name">Name</key>
|
||||
|
||||
@@ -1,26 +1,19 @@
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Security;
|
||||
using Microsoft.AspNet.SignalR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.DependencyInjection;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Dictionary;
|
||||
using Umbraco.Core.Templates;
|
||||
using Umbraco.Core.Runtime;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Composing.CompositionExtensions;
|
||||
using Umbraco.Web.Macros;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Web.Security;
|
||||
using Umbraco.Web.Security.Providers;
|
||||
|
||||
namespace Umbraco.Web.Runtime
|
||||
{
|
||||
// web's initial composer composes after core's, and before all core composers
|
||||
[ComposeAfter(typeof(CoreInitialComposer))]
|
||||
[ComposeBefore(typeof(ICoreComposer))]
|
||||
public sealed class WebInitialComposer : ComponentComposer<WebInitialComponent>
|
||||
{
|
||||
|
||||
@@ -141,8 +141,6 @@
|
||||
<Compile Include="Mvc\RenderMvcController.cs" />
|
||||
<Compile Include="Mvc\UmbracoViewPageOfTModel.cs" />
|
||||
<Compile Include="Security\BackOfficeSecurity.cs" />
|
||||
<Compile Include="WebApi\Filters\EnableOverrideAuthorizationAttribute.cs" />
|
||||
<Compile Include="WebApi\Filters\OverridableAuthorizationAttribute.cs" />
|
||||
<Compile Include="HttpContextAccessorExtensions.cs" />
|
||||
<Compile Include="Models\Membership\UmbracoMembershipMember.cs" />
|
||||
<Compile Include="Mvc\HttpUmbracoFormRouteStringException.cs" />
|
||||
|
||||
@@ -46,7 +46,6 @@ namespace Umbraco.Web
|
||||
|
||||
protected UmbracoApplicationBase()
|
||||
{
|
||||
|
||||
HostingSettings hostingSettings = null;
|
||||
GlobalSettings globalSettings = null;
|
||||
SecuritySettings securitySettings = null;
|
||||
@@ -60,8 +59,6 @@ namespace Umbraco.Web
|
||||
|
||||
var backOfficeInfo = new AspNetBackOfficeInfo(globalSettings, ioHelper, _loggerFactory.CreateLogger<AspNetBackOfficeInfo>(), Options.Create(webRoutingSettings));
|
||||
var profiler = GetWebProfiler(hostingEnvironment);
|
||||
StaticApplicationLogging.Initialize(_loggerFactory);
|
||||
Logger = NullLogger<UmbracoApplicationBase>.Instance;
|
||||
}
|
||||
|
||||
private IProfiler GetWebProfiler(IHostingEnvironment hostingEnvironment)
|
||||
@@ -87,7 +84,6 @@ namespace Umbraco.Web
|
||||
_loggerFactory = loggerFactory;
|
||||
|
||||
Logger = logger;
|
||||
StaticApplicationLogging.Initialize(_loggerFactory);
|
||||
}
|
||||
|
||||
protected ILogger<UmbracoApplicationBase> Logger { get; }
|
||||
@@ -189,7 +185,6 @@ namespace Umbraco.Web
|
||||
LogContext.Push(new HttpRequestIdEnricher(_factory.GetRequiredService<IRequestCache>()));
|
||||
|
||||
_runtime = _factory.GetRequiredService<IRuntime>();
|
||||
_runtime.Start();
|
||||
}
|
||||
|
||||
// called by ASP.NET (auto event wireup) once per app domain
|
||||
@@ -237,7 +232,6 @@ namespace Umbraco.Web
|
||||
{
|
||||
if (_runtime != null)
|
||||
{
|
||||
_runtime.Terminate();
|
||||
_runtime.DisposeIfDisposable();
|
||||
|
||||
_runtime = null;
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Web.WebApi.Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// This allows for Action based auth attributes to override Class based auth attributes if they are specified
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This attribute can be applied at the class level and will indicate to any class level auth attribute that inherits from OverridableAuthorizationAttribute
|
||||
/// </remarks>
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
|
||||
public sealed class EnableOverrideAuthorizationAttribute : Attribute
|
||||
{
|
||||
// TODO: we should remove this and use the System.Web.Http.OverrideAuthorizationAttribute which uses IOverrideFilter instead
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
|
||||
namespace Umbraco.Web.WebApi.Filters
|
||||
{
|
||||
// TODO: remove this since we don't need it, see notes in EnableOverrideAuthorizationAttribute
|
||||
|
||||
/// <summary>
|
||||
/// Abstract auth filter class that can be used to enable overriding class auth filters at the action level
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// To enable a class auth filter to be overridden by an action auth filter the EnableOverrideAuthorizationAttribute can be applied
|
||||
/// to the class.
|
||||
/// </remarks>
|
||||
public abstract class OverridableAuthorizationAttribute : AuthorizeAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// If the controller has an EnabledOverrideAuthorizationAttribute attribute specified and the action has any AuthorizeAttribute
|
||||
/// specified then use the action's auth attribute instead of this one
|
||||
/// </summary>
|
||||
/// <param name="actionContext">The context.</param>
|
||||
/// <exception cref="T:System.ArgumentNullException">The context parameter is null.</exception>
|
||||
public override void OnAuthorization(HttpActionContext actionContext)
|
||||
{
|
||||
if (actionContext == null) throw new ArgumentNullException("actionContext");
|
||||
|
||||
var actionAttributes = actionContext.ActionDescriptor.GetCustomAttributes<AuthorizeAttribute>();
|
||||
|
||||
//if 'this' authorize attribute exists in the current collection then continue as per normal... this is because 'this' attribute instance
|
||||
// is obviously assigned at an Action level and therefore it's already executing
|
||||
|
||||
if (actionAttributes.Any(x => Equals(x, this)))
|
||||
{
|
||||
base.OnAuthorization(actionContext);
|
||||
return;
|
||||
}
|
||||
|
||||
//if the controller is allowing authorization to be overridden at the action level and there are action level authorization attributes
|
||||
// then exit and let the action level auth attribute(s) execute.
|
||||
|
||||
if (actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<EnableOverrideAuthorizationAttribute>().Any()
|
||||
&& actionAttributes.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
base.OnAuthorization(actionContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user