diff --git a/app/Umbraco/Archetype.Courier/Archetype.Courier.csproj b/app/Umbraco/Archetype.Courier/Archetype.Courier.csproj new file mode 100644 index 0000000..f7f437d --- /dev/null +++ b/app/Umbraco/Archetype.Courier/Archetype.Courier.csproj @@ -0,0 +1,116 @@ + + + + + Debug + AnyCPU + {FE8BE437-8B11-4E49-9B02-F45994E6D723} + Library + Properties + Archetype.Courier + Archetype.Courier + v4.5 + 512 + ..\ + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\UmbracoCms.Core.7.1.2\lib\businesslogic.dll + False + + + ..\packages\UmbracoCms.Core.7.1.2\lib\cms.dll + False + + + ..\packages\UmbracoCms.Core.7.1.2\lib\interfaces.dll + False + + + ..\packages\UmbracoCms.Core.7.1.2\lib\log4net.dll + False + + + ..\packages\Newtonsoft.Json.6.0.2\lib\net45\Newtonsoft.Json.dll + False + + + + + + + ..\packages\UmbracoCms.Core.7.1.2\lib\umbraco.dll + False + + + ..\packages\UmbracoCms.Core.7.1.2\lib\Umbraco.Core.dll + False + + + lib\Umbraco.Courier.Core.dll + False + + + lib\Umbraco.Courier.DataResolvers.dll + False + + + lib\Umbraco.Courier.Providers.dll + False + + + ..\packages\UmbracoCms.Core.7.1.2\lib\umbraco.providers.dll + False + + + + + Properties\VersionInfo.cs + + + + + + + + + + {7d185d41-4228-4978-acb8-83f9a48ad94f} + Archetype.Umbraco + True + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/app/Umbraco/Archetype.Courier/DataResolvers/ArchetypeDataResolver.cs b/app/Umbraco/Archetype.Courier/DataResolvers/ArchetypeDataResolver.cs new file mode 100644 index 0000000..9040479 --- /dev/null +++ b/app/Umbraco/Archetype.Courier/DataResolvers/ArchetypeDataResolver.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Archetype.Models; +using Archetype.PropertyConverters; +using Newtonsoft.Json; +using Umbraco.Core; +using Umbraco.Core.Logging; +using Umbraco.Core.Models; +using Umbraco.Core.Models.PublishedContent; +using Umbraco.Courier.Core; +using Umbraco.Courier.DataResolvers; +using Umbraco.Courier.ItemProviders; + +namespace Archetype.Courier.DataResolvers +{ + public class ArchetypeDataResolver : PropertyDataResolverProvider + { + private enum Direction + { + Extracting, + Packaging + } + + public override string EditorAlias + { + get + { + return Archetype.Constants.PropertyEditorAlias; + } + } + + public override void ExtractingDataType(DataType item) + { + // No longer need to extract the DataType (int) Ids as they now reference the Guid [LK] + } + + public override void ExtractingProperty(Item item, ContentProperty propertyData) + { + ReplacePropertyDataIds(item, propertyData, Direction.Extracting); + } + + public override void PackagingDataType(DataType item) + { + AddDataTypeDependencies(item); + } + + public override void PackagingProperty(Item item, ContentProperty propertyData) + { + ReplacePropertyDataIds(item, propertyData, Direction.Packaging); + } + + private void AddDataTypeDependencies(DataType item) + { + if (item.Prevalues != null && item.Prevalues.Count > 0) + { + var prevalue = item.Prevalues[0]; + if (prevalue.Alias.InvariantEquals(Archetype.Constants.PreValueAlias) && !string.IsNullOrWhiteSpace(prevalue.Value)) + { + var config = JsonConvert.DeserializeObject(prevalue.Value); + + if (config != null && config.Fieldsets != null) + { + foreach (var property in config.Fieldsets.SelectMany(x => x.Properties)) + { + item.Dependencies.Add(property.DataTypeGuid.ToString(), ProviderIDCollection.dataTypeItemProviderGuid); + } + + item.Prevalues[0].Value = JsonConvert.SerializeObject(config, Formatting.None); + } + } + } + } + + private void ReplacePropertyDataIds(Item item, ContentProperty propertyData, Direction direction) + { + if (propertyData != null && propertyData.Value != null) + { + // just look at the amount of dancing around we have to do in order to fake a `PublishedPropertyType`?! + var dataTypeId = PersistenceManager.Default.GetNodeId(propertyData.DataType, NodeObjectTypes.DataType); + var fakePropertyType = this.CreateDummyPropertyType(dataTypeId, this.EditorAlias); + + var converter = new ArchetypeValueConverter(); + var archetype = (ArchetypeModel)converter.ConvertDataToSource(fakePropertyType, propertyData.Value, false); + + if (archetype != null) + { + // create a 'fake' provider, as ultimately only the 'Packaging' enum will be referenced. + var fakeItemProvider = new PropertyItemProvider(); + + foreach (var property in archetype.Fieldsets.SelectMany(x => x.Properties)) + { + if (property == null || string.IsNullOrWhiteSpace(property.PropertyEditorAlias)) + continue; + + // create a 'fake' item for Courier to process + var fakeItem = new ContentPropertyData() + { + ItemId = item.ItemId, + Name = string.Format("{0} [{1}: Nested {2} ({3})]", new[] { item.Name, this.EditorAlias, property.PropertyEditorAlias, property.Alias }), + Data = new List + { + new ContentProperty + { + Alias = property.Alias, + DataType = PersistenceManager.Default.GetUniqueId(property.DataTypeId, NodeObjectTypes.DataType), + PropertyEditorAlias = property.PropertyEditorAlias, + Value = property.Value + } + } + }; + + if (direction == Direction.Packaging) + { + try + { + // run the 'fake' item through Courier's data resolvers + ResolutionManager.Instance.PackagingItem(fakeItem, fakeItemProvider); + } + catch (Exception ex) + { + LogHelper.Error(string.Concat("Error packaging data value: ", fakeItem.Name), ex); + } + + // pass up the dependencies and resources + item.Dependencies.AddRange(fakeItem.Dependencies); + item.Resources.AddRange(fakeItem.Resources); + } + else if (direction == Direction.Extracting) + { + try + { + // run the 'fake' item through Courier's data resolvers + ResolutionManager.Instance.ExtractingItem(fakeItem, fakeItemProvider); + } + catch (Exception ex) + { + LogHelper.Error(string.Concat("Error extracting data value: ", fakeItem.Name), ex); + } + } + + if (fakeItem.Data != null && fakeItem.Data.Any()) + { + var firstDataType = fakeItem.Data.FirstOrDefault(); + if (firstDataType != null) + { + // set the resolved property data value + property.Value = firstDataType.Value; + + // (if packaging) add a dependency for the property's data-type + if (direction == Direction.Packaging) + item.Dependencies.Add(firstDataType.DataType.ToString(), ProviderIDCollection.dataTypeItemProviderGuid); + } + } + } + + if (item.Name.Contains(string.Concat(this.EditorAlias, ": Nested"))) + { + // if the Archetype is nested, then we only want to return the object itself - not a serialized string + propertyData.Value = archetype; + } + else + { + // if the Archetype is the root/container, then we can serialize it to a string + propertyData.Value = archetype.SerializeForPersistence(); + } + } + } + } + + private PublishedPropertyType CreateDummyPropertyType(int dataTypeId, string propertyEditorAlias) + { + return new PublishedPropertyType(null, new PropertyType(new DataTypeDefinition(-1, propertyEditorAlias) { Id = dataTypeId })); + } + } +} \ No newline at end of file diff --git a/app/Umbraco/Archetype.Courier/Properties/AssemblyInfo.cs b/app/Umbraco/Archetype.Courier/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..00fbf9d --- /dev/null +++ b/app/Umbraco/Archetype.Courier/Properties/AssemblyInfo.cs @@ -0,0 +1,14 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Archetype.Courier")] +[assembly: AssemblyDescription("A set of tools to support Archetype with Umbraco Courier")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Umbrella Inc Ltd")] +[assembly: AssemblyProduct("Archetype.Courier")] +[assembly: AssemblyCopyright("Copyright \xa9 Lee Kelleher, Umbrella Inc Ltd 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("6F05C431-ABBF-4D77-9D3D-5AF6C8E318AF")] diff --git a/app/Umbraco/Archetype.Courier/lib/Umbraco.Courier.Core.dll b/app/Umbraco/Archetype.Courier/lib/Umbraco.Courier.Core.dll new file mode 100644 index 0000000..b690a35 Binary files /dev/null and b/app/Umbraco/Archetype.Courier/lib/Umbraco.Courier.Core.dll differ diff --git a/app/Umbraco/Archetype.Courier/lib/Umbraco.Courier.DataResolvers.dll b/app/Umbraco/Archetype.Courier/lib/Umbraco.Courier.DataResolvers.dll new file mode 100644 index 0000000..88534f5 Binary files /dev/null and b/app/Umbraco/Archetype.Courier/lib/Umbraco.Courier.DataResolvers.dll differ diff --git a/app/Umbraco/Archetype.Courier/lib/Umbraco.Courier.Providers.dll b/app/Umbraco/Archetype.Courier/lib/Umbraco.Courier.Providers.dll new file mode 100644 index 0000000..07910fc Binary files /dev/null and b/app/Umbraco/Archetype.Courier/lib/Umbraco.Courier.Providers.dll differ diff --git a/app/Umbraco/Archetype.Courier/packages.config b/app/Umbraco/Archetype.Courier/packages.config new file mode 100644 index 0000000..ee6c9d2 --- /dev/null +++ b/app/Umbraco/Archetype.Courier/packages.config @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/Umbraco/Umbraco.Archetype.sln b/app/Umbraco/Umbraco.Archetype.sln index bb5fa55..342d893 100644 --- a/app/Umbraco/Umbraco.Archetype.sln +++ b/app/Umbraco/Umbraco.Archetype.sln @@ -14,6 +14,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Archetype.Tests", "Archetyp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DatabaseSizer", "DatabaseSizer\DatabaseSizer.csproj", "{0114C963-C514-49C1-B7AB-DCB1825F498C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Archetype.Courier", "Archetype.Courier\Archetype.Courier.csproj", "{FE8BE437-8B11-4E49-9B02-F45994E6D723}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -32,6 +34,10 @@ Global {0114C963-C514-49C1-B7AB-DCB1825F498C}.Debug|Any CPU.Build.0 = Debug|Any CPU {0114C963-C514-49C1-B7AB-DCB1825F498C}.Release|Any CPU.ActiveCfg = Release|Any CPU {0114C963-C514-49C1-B7AB-DCB1825F498C}.Release|Any CPU.Build.0 = Release|Any CPU + {FE8BE437-8B11-4E49-9B02-F45994E6D723}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FE8BE437-8B11-4E49-9B02-F45994E6D723}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FE8BE437-8B11-4E49-9B02-F45994E6D723}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FE8BE437-8B11-4E49-9B02-F45994E6D723}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj b/app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj index 5ad60a2..3a97867 100644 --- a/app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj +++ b/app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj @@ -232,7 +232,9 @@ - + + + diff --git a/app/Umbraco/Umbraco.Archetype/Extensions/ArchetypeHelper.cs b/app/Umbraco/Umbraco.Archetype/Extensions/ArchetypeHelper.cs index a4cbcc8..edd02e0 100644 --- a/app/Umbraco/Umbraco.Archetype/Extensions/ArchetypeHelper.cs +++ b/app/Umbraco/Umbraco.Archetype/Extensions/ArchetypeHelper.cs @@ -26,11 +26,11 @@ namespace Archetype.Extensions _app = ApplicationContext.Current; } - internal Models.ArchetypeModel DeserializeJsonToArchetype(string sourceJson, PreValueCollection dataTypePreValues) + internal ArchetypeModel DeserializeJsonToArchetype(string sourceJson, PreValueCollection dataTypePreValues) { try { - var archetype = JsonConvert.DeserializeObject(sourceJson, _jsonSettings); + var archetype = JsonConvert.DeserializeObject(sourceJson, _jsonSettings); try { @@ -46,15 +46,15 @@ namespace Archetype.Extensions } catch { - return new Models.ArchetypeModel(); + return new ArchetypeModel(); } } - internal Models.ArchetypeModel DeserializeJsonToArchetype(string sourceJson, int dataTypeId, PublishedContentType hostContentType = null) + internal ArchetypeModel DeserializeJsonToArchetype(string sourceJson, int dataTypeId, PublishedContentType hostContentType = null) { try { - var archetype = JsonConvert.DeserializeObject(sourceJson, _jsonSettings); + var archetype = JsonConvert.DeserializeObject(sourceJson, _jsonSettings); try { @@ -70,7 +70,7 @@ namespace Archetype.Extensions } catch { - return new Models.ArchetypeModel(); + return new ArchetypeModel(); } } @@ -113,7 +113,7 @@ namespace Archetype.Extensions /// /// The Archetype to add the additional metadata to /// The configuration of the Archetype - private void RetrieveAdditionalProperties(ref Models.ArchetypeModel archetype, ArchetypePreValue preValue, PublishedContentType hostContentType = null) + private void RetrieveAdditionalProperties(ref ArchetypeModel archetype, ArchetypePreValue preValue, PublishedContentType hostContentType = null) { foreach (var fieldset in preValue.Fieldsets) { @@ -140,7 +140,7 @@ namespace Archetype.Extensions /// /// The Archetype to add the additional metadata to /// The configuration of the Archetype - private void RetrieveAdditionalProperties(ref Models.ArchetypePreValue preValue) + private void RetrieveAdditionalProperties(ref ArchetypePreValue preValue) { foreach (var fieldset in preValue.Fieldsets) { diff --git a/app/Umbraco/Umbraco.Archetype/Extensions/ArchetypePropertyModelExtensions.cs b/app/Umbraco/Umbraco.Archetype/Extensions/ArchetypePropertyModelExtensions.cs new file mode 100644 index 0000000..c14ee73 --- /dev/null +++ b/app/Umbraco/Umbraco.Archetype/Extensions/ArchetypePropertyModelExtensions.cs @@ -0,0 +1,20 @@ +using Archetype.Models; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Core.Models.PublishedContent; + +namespace Archetype.Extensions +{ + public static class ArchetypePropertyModelExtensions + { + public static bool IsArchetype(this ArchetypePropertyModel prop) + { + return prop.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditorAlias); + } + + internal static PublishedPropertyType CreateDummyPropertyType(this ArchetypePropertyModel prop) + { + return new PublishedPropertyType(prop.HostContentType, new PropertyType(new DataTypeDefinition(-1, prop.PropertyEditorAlias) { Id = prop.DataTypeId })); + } + } +} \ No newline at end of file diff --git a/app/Umbraco/Umbraco.Archetype/Extensions/Extensions.cs b/app/Umbraco/Umbraco.Archetype/Extensions/HtmlHelperExtensions.cs similarity index 70% rename from app/Umbraco/Umbraco.Archetype/Extensions/Extensions.cs rename to app/Umbraco/Umbraco.Archetype/Extensions/HtmlHelperExtensions.cs index 7206088..5144b02 100644 --- a/app/Umbraco/Umbraco.Archetype/Extensions/Extensions.cs +++ b/app/Umbraco/Umbraco.Archetype/Extensions/HtmlHelperExtensions.cs @@ -1,32 +1,14 @@ -using System; +using System.Text; using System.Web; using System.Web.Mvc; using System.Web.Mvc.Html; -using System.Text; -using System.Text.RegularExpressions; -using System.Collections.Generic; -using Umbraco.Core; -using Umbraco.Core.Logging; -using Umbraco.Web; using Archetype.Models; +using Umbraco.Core.Logging; namespace Archetype.Extensions { - public static class Extensions + public static class HtmlHelperExtensions { - //lifted from the core as it is marked 'internal' - public static bool DetectIsJson(this string input) - { - input = input.Trim(); - return input.StartsWith("{") && input.EndsWith("}") - || input.StartsWith("[") && input.EndsWith("]"); - } - - public static bool IsArchetype(this ArchetypePropertyModel prop) - { - return prop.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditorAlias); - } - public static IHtmlString RenderArchetypePartials(this HtmlHelper htmlHelper, ArchetypeModel archetypeModel) { return RenderPartials(htmlHelper, archetypeModel, null, null); @@ -44,10 +26,10 @@ namespace Archetype.Extensions public static IHtmlString RenderArchetypePartials(this HtmlHelper htmlHelper, ArchetypeModel archetypeModel, string partialPath, ViewDataDictionary viewDataDictionary) { - return RenderPartials(htmlHelper, archetypeModel, partialPath, viewDataDictionary); + return htmlHelper.RenderPartials(archetypeModel, partialPath, viewDataDictionary); } - private static IHtmlString RenderPartials(HtmlHelper htmlHelper, ArchetypeModel archetypeModel, string partialPath, ViewDataDictionary viewDataDictionary) + private static IHtmlString RenderPartials(this HtmlHelper htmlHelper, ArchetypeModel archetypeModel, string partialPath, ViewDataDictionary viewDataDictionary) { var context = HttpContext.Current; @@ -57,7 +39,7 @@ namespace Archetype.Extensions } var sb = new StringBuilder(); - + var pathToPartials = "~/Views/Partials/Archetype/"; if (!string.IsNullOrEmpty(partialPath)) { @@ -81,4 +63,4 @@ namespace Archetype.Extensions return new HtmlString(sb.ToString()); } } -} +} \ No newline at end of file diff --git a/app/Umbraco/Umbraco.Archetype/Extensions/StringExtensions.cs b/app/Umbraco/Umbraco.Archetype/Extensions/StringExtensions.cs new file mode 100644 index 0000000..47636cb --- /dev/null +++ b/app/Umbraco/Umbraco.Archetype/Extensions/StringExtensions.cs @@ -0,0 +1,13 @@ +namespace Archetype.Extensions +{ + public static class StringExtensions + { + //lifted from the core as it is marked 'internal' + public static bool DetectIsJson(this string input) + { + input = input.Trim(); + return input.StartsWith("{") && input.EndsWith("}") + || input.StartsWith("[") && input.EndsWith("]"); + } + } +} \ No newline at end of file diff --git a/app/Umbraco/Umbraco.Archetype/Models/ArchetypePropertyModel.cs b/app/Umbraco/Umbraco.Archetype/Models/ArchetypePropertyModel.cs index 66773df..4d9abb4 100644 --- a/app/Umbraco/Umbraco.Archetype/Models/ArchetypePropertyModel.cs +++ b/app/Umbraco/Umbraco.Archetype/Models/ArchetypePropertyModel.cs @@ -1,15 +1,16 @@ using System.Collections.Generic; using System.Linq; +using Archetype.Extensions; using Newtonsoft.Json; using Umbraco.Core; -using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; using Umbraco.Web; namespace Archetype.Models { - public class ArchetypePropertyModel { + public class ArchetypePropertyModel + { [JsonProperty("alias")] public string Alias { get; internal set; } @@ -54,7 +55,7 @@ namespace Archetype.Models private Attempt TryConvertWithPropertyValueConverters(object value, IEnumerable converters) { - var properyType = CreateDummyPropertyType(DataTypeId, PropertyEditorAlias); + var properyType = this.CreateDummyPropertyType(); // In umbraco, there are default value converters that try to convert the // value if all else fails. The problem is, they are also in the list of @@ -80,14 +81,5 @@ namespace Archetype.Models return Attempt.Fail(); } - - private PublishedPropertyType CreateDummyPropertyType(int dataTypeId, string propertyEditorAlias) - { - return new PublishedPropertyType(this.HostContentType, - new PropertyType(new DataTypeDefinition(-1, propertyEditorAlias) - { - Id = dataTypeId - })); - } } -} +} \ No newline at end of file