diff --git a/src/Umbraco.Core/Manifest/ManifestParser.cs b/src/Umbraco.Core/Manifest/ManifestParser.cs index 59753df66a..28493fe20f 100644 --- a/src/Umbraco.Core/Manifest/ManifestParser.cs +++ b/src/Umbraco.Core/Manifest/ManifestParser.cs @@ -101,6 +101,7 @@ namespace Umbraco.Core.Manifest var gridEditors = new List(); var contentApps = new List(); var dashboards = new List(); + var sections = new Dictionary(); foreach (var manifest in manifests) { @@ -111,6 +112,9 @@ namespace Umbraco.Core.Manifest if (manifest.GridEditors != null) gridEditors.AddRange(manifest.GridEditors); if (manifest.ContentApps != null) contentApps.AddRange(manifest.ContentApps); if (manifest.Dashboards != null) dashboards.AddRange(manifest.Dashboards); + if (manifest.Sections != null) + foreach (var (key, value) in manifest.Sections) + sections[key] = value; } return new PackageManifest @@ -121,7 +125,8 @@ namespace Umbraco.Core.Manifest ParameterEditors = parameterEditors.ToArray(), GridEditors = gridEditors.ToArray(), ContentApps = contentApps.ToArray(), - Dashboards = dashboards.ToArray() + Dashboards = dashboards.ToArray(), + Sections = sections }; } diff --git a/src/Umbraco.Core/Manifest/PackageManifest.cs b/src/Umbraco.Core/Manifest/PackageManifest.cs index cd806ac847..a0546f3629 100644 --- a/src/Umbraco.Core/Manifest/PackageManifest.cs +++ b/src/Umbraco.Core/Manifest/PackageManifest.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Newtonsoft.Json; using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.PropertyEditors; @@ -30,5 +31,11 @@ namespace Umbraco.Core.Manifest [JsonProperty("dashboards")] public ManifestDashboardDefinition[] Dashboards { get; set; } = Array.Empty(); + + /// + /// Declares the back office sections that this package installs + /// + [JsonProperty("sections")] + public IReadOnlyDictionary Sections { get; set; } = new Dictionary(); } } diff --git a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs index ce3d1d705c..9970d5f6b0 100644 --- a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs +++ b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs @@ -429,5 +429,23 @@ javascript: ['~/test.js',/*** some note about stuff asd09823-4**09234*/ '~/test2 Assert.AreEqual(1, db1.Sections.Length); Assert.AreEqual("forms", db1.Sections[0]); } + + [Test] + public void CanParseManifest_Sections() + { + const string json = @"{'sections': { + 'content': 'Content', + 'hello': 'World' + } +}"; + + var manifest = _parser.ParseManifest(json); + Assert.AreEqual(2, manifest.Sections.Count); + Assert.AreEqual("content", manifest.Sections.Keys.ElementAt(0)); + Assert.AreEqual("hello", manifest.Sections.Keys.ElementAt(1)); + Assert.AreEqual("Content", manifest.Sections["content"]); + Assert.AreEqual("World", manifest.Sections["hello"]); + + } } } diff --git a/src/Umbraco.Web/Services/SectionService.cs b/src/Umbraco.Web/Services/SectionService.cs index e6af27534c..b17b9f965a 100644 --- a/src/Umbraco.Web/Services/SectionService.cs +++ b/src/Umbraco.Web/Services/SectionService.cs @@ -1,22 +1,9 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Xml.Linq; -using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Events; -using Umbraco.Core.IO; -using Umbraco.Core.Models; -using Umbraco.Core.Composing; -using Umbraco.Core.Models.ContentEditing; -using Umbraco.Core.Scoping; using Umbraco.Core.Services; -using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Trees; using Umbraco.Web.Trees; -using File = System.IO.File; namespace Umbraco.Web.Services { diff --git a/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs b/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs index 54762e73d8..fdeb812363 100644 --- a/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs +++ b/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs @@ -11,5 +11,6 @@ namespace Umbraco.Web.Trees public BackOfficeSectionCollection(IEnumerable items) : base(items) { } + } } diff --git a/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs b/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs index 62d61a4090..ec5833f79c 100644 --- a/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs +++ b/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs @@ -1,10 +1,43 @@ -using Umbraco.Core.Composing; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Composing; +using Umbraco.Core.Manifest; +using Umbraco.Core.Models.ContentEditing; using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Trees { + //fixme: how can a developer re-sort the items in this collection ? public class BackOfficeSectionCollectionBuilder : OrderedCollectionBuilderBase { protected override BackOfficeSectionCollectionBuilder This => this; + + // need to inject dependencies in the collection, so override creation + public override BackOfficeSectionCollection CreateCollection(IFactory factory) + { + return new BackOfficeSectionCollection(CreateItems(factory)); + } + + protected override IEnumerable CreateItems(IFactory factory) + { + // get the manifest parser just-in-time - injecting it in the ctor would mean that + // simply getting the builder in order to configure the collection, would require + // its dependencies too, and that can create cycles or other oddities + var manifestParser = factory.GetInstance(); + + return base.CreateItems(factory).Concat(manifestParser.Manifest.Sections.Select(x => new ManifestBackOfficeSection(x.Key, x.Value))); + } + + private class ManifestBackOfficeSection : IBackOfficeSection + { + public ManifestBackOfficeSection(string @alias, string name) + { + Alias = alias; + Name = name; + } + + public string Alias { get; } + public string Name { get; } + } } }