private static PropertyValidationService GetPropertyValidationService()
        {
            IIOHelper                  ioHelper                  = Mock.Of <IIOHelper>();
            IDataTypeService           dataTypeService           = Mock.Of <IDataTypeService>();
            ILocalizedTextService      localizedTextService      = Mock.Of <ILocalizedTextService>();
            IEditorConfigurationParser editorConfigurationParser = Mock.Of <IEditorConfigurationParser>();

            var attribute = new DataEditorAttribute("a", "a", "a");
            IDataValueEditorFactory dataValueEditorFactory = Mock.Of <IDataValueEditorFactory>(x
                                                                                               => x.Create <TextOnlyValueEditor>(It.IsAny <DataEditorAttribute>()) == new TextOnlyValueEditor(attribute, localizedTextService, Mock.Of <IShortStringHelper>(), new JsonNetSerializer(), Mock.Of <IIOHelper>()));


            var textBoxEditor = new TextboxPropertyEditor(
                dataValueEditorFactory,
                ioHelper,
                editorConfigurationParser);

            var serializer = new ConfigurationEditorJsonSerializer();

            var mockDataTypeService = new Mock <IDataTypeService>();

            Mock.Get(dataTypeService).Setup(x => x.GetDataType(It.Is <int>(y => y == Constants.DataTypes.Textbox)))
            .Returns(new DataType(textBoxEditor, serializer));

            var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(() => new[] { textBoxEditor }));

            return(new PropertyValidationService(
                       propertyEditorCollection,
                       dataTypeService,
                       localizedTextService,
                       new ValueEditorCache()));
        }
Example #2
0
        private IPublishedContent GetContent(bool createChildren, int indexVals)
        {
            var serializer      = new ConfigurationEditorJsonSerializer();
            var dataTypeService = new TestObjects.TestDataTypeService(
                new DataType(new VoidEditor(DataValueEditorFactory), serializer)
            {
                Id = 1
            });

            var factory          = new PublishedContentTypeFactory(Mock.Of <IPublishedModelFactory>(), new PropertyValueConverterCollection(Array.Empty <IPropertyValueConverter>()), dataTypeService);
            var contentTypeAlias = createChildren ? "Parent" : "Child";
            var contentType      = new PublishedContentType(Guid.NewGuid(), 22, contentTypeAlias, PublishedItemType.Content, Enumerable.Empty <string>(), Enumerable.Empty <PublishedPropertyType>(), ContentVariation.Nothing);
            var d = new SolidPublishedContent(contentType)
            {
                CreateDate = DateTime.Now,
                CreatorId  = 1,
                Id         = 3,
                SortOrder  = 4,
                TemplateId = 5,
                UpdateDate = DateTime.Now,
                Path       = "-1,3",
                UrlSegment = "home-page",
                Name       = "Page" + Guid.NewGuid(),
                Version    = Guid.NewGuid(),
                WriterId   = 1,
                Parent     = null,
                Level      = 1,
                Children   = new List <IPublishedContent>()
            };

            d.Properties = new Collection <IPublishedProperty>(new List <IPublishedProperty>
            {
                new RawValueProperty(factory.CreatePropertyType("property1", 1), d, "value" + indexVals),
                new RawValueProperty(factory.CreatePropertyType("property2", 1), d, "value" + (indexVals + 1))
            });
            if (createChildren)
            {
                d.Children = new List <IPublishedContent>()
                {
                    GetContent(false, indexVals + 3),
                    GetContent(false, indexVals + 6),
                    GetContent(false, indexVals + 9)
                };
            }

            if (!createChildren)
            {
                //create additional columns, used to test the different columns for child nodes
                ((Collection <IPublishedProperty>)d.Properties).Add(
                    new RawValueProperty(factory.CreatePropertyType("property4", 1), d, "value" + (indexVals + 2)));
            }
            else
            {
                ((Collection <IPublishedProperty>)d.Properties).Add(
                    new RawValueProperty(factory.CreatePropertyType("property3", 1), d, "value" + (indexVals + 2)));
            }

            return(d);
        }
        public void CacheLevelTest(PropertyCacheLevel cacheLevel, int interConverts)
        {
            var converter = new CacheConverter1(cacheLevel);

            var converters = new PropertyValueConverterCollection(() => new IPropertyValueConverter[]
            {
                converter,
            });

            var configurationEditorJsonSerializer = new ConfigurationEditorJsonSerializer();
            var dataTypeServiceMock = new Mock <IDataTypeService>();
            var dataType            = new DataType(
                new VoidEditor(
                    Mock.Of <IDataValueEditorFactory>()), configurationEditorJsonSerializer)
            {
                Id = 1
            };

            dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield);

            var publishedContentTypeFactory = new PublishedContentTypeFactory(Mock.Of <IPublishedModelFactory>(), converters, dataTypeServiceMock.Object);

            IEnumerable <IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType)
            {
                yield return(publishedContentTypeFactory.CreatePropertyType(contentType, "prop1", dataType.Id));
            }

            IPublishedContentType setType1 = publishedContentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "set1", CreatePropertyTypes);

            // PublishedElementPropertyBase.GetCacheLevels:
            //
            //   if property level is > reference level, or both are None
            //     use None for property & new reference
            //   else
            //     use Content for property, & keep reference
            //
            // PublishedElement creates properties with reference being None
            // if converter specifies None, keep using None
            // anything else is not > None, use Content
            //
            // for standalone elements, it's only None or Content
            var set1 = new PublishedElement(setType1, Guid.NewGuid(), new Dictionary <string, object> {
                { "prop1", "1234" }
            }, false);

            Assert.AreEqual(1234, set1.Value(Mock.Of <IPublishedValueFallback>(), "prop1"));
            Assert.AreEqual(1, converter.SourceConverts);
            Assert.AreEqual(1, converter.InterConverts);

            // source is always converted once and cached per content
            // inter conversion depends on the specified cache level
            Assert.AreEqual(1234, set1.Value(Mock.Of <IPublishedValueFallback>(), "prop1"));
            Assert.AreEqual(1, converter.SourceConverts);
            Assert.AreEqual(interConverts, converter.InterConverts);
        }
Example #4
0
    public void SimpleConverter2Test()
    {
        var cacheMock    = new Mock <IPublishedContentCache>();
        var cacheContent = new Dictionary <int, IPublishedContent>();

        cacheMock.Setup(x => x.GetById(It.IsAny <int>()))
        .Returns <int>(id => cacheContent.TryGetValue(id, out var content) ? content : null);
        var publishedSnapshotMock = new Mock <IPublishedSnapshot>();

        publishedSnapshotMock.Setup(x => x.Content).Returns(cacheMock.Object);
        var publishedSnapshotAccessorMock = new Mock <IPublishedSnapshotAccessor>();
        var localPublishedSnapshot        = publishedSnapshotMock.Object;

        publishedSnapshotAccessorMock.Setup(x => x.TryGetPublishedSnapshot(out localPublishedSnapshot)).Returns(true);
        var publishedSnapshotAccessor = publishedSnapshotAccessorMock.Object;

        var converters = new PropertyValueConverterCollection(() => new IPropertyValueConverter[]
        {
            new SimpleConverter2(publishedSnapshotAccessor),
        });

        var serializer          = new ConfigurationEditorJsonSerializer();
        var dataTypeServiceMock = new Mock <IDataTypeService>();
        var dataType            = new DataType(
            new VoidEditor(Mock.Of <IDataValueEditorFactory>()), serializer)
        {
            Id = 1
        };

        dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield);

        var contentTypeFactory =
            new PublishedContentTypeFactory(Mock.Of <IPublishedModelFactory>(), converters, dataTypeServiceMock.Object);

        IEnumerable <IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType)
        {
            yield return(contentTypeFactory.CreatePropertyType(contentType, "prop1", 1));
        }

        var elementType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "element1", CreatePropertyTypes);

        var element1 = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary <string, object> {
            { "prop1", "1234" }
        }, false);

        var cntType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1001, "cnt1", t => Enumerable.Empty <PublishedPropertyType>());
        var cnt1     = new InternalPublishedContent(cntType1)
        {
            Id = 1234
        };

        cacheContent[cnt1.Id] = cnt1;

        Assert.AreSame(cnt1, element1.Value(Mock.Of <IPublishedValueFallback>(), "prop1"));
    }
Example #5
0
        protected override void Compose()
        {
            base.Compose();
            _publishedSnapshotAccessorMock = new Mock <IPublishedSnapshotAccessor>();
            Builder.Services.AddUnique <IPublishedSnapshotAccessor>(_publishedSnapshotAccessorMock.Object);

            Builder.Services.AddUnique <IPublishedModelFactory>(f => new PublishedModelFactory(f.GetRequiredService <TypeLoader>().GetTypes <PublishedContentModel>(), f.GetRequiredService <IPublishedValueFallback>()));
            Builder.Services.AddUnique <IPublishedContentTypeFactory, PublishedContentTypeFactory>();
            Builder.Services.AddUnique <IPublishedValueFallback, PublishedValueFallback>();

            var loggerFactory = NullLoggerFactory.Instance;
            var mediaService  = Mock.Of <IMediaService>();
            var contentTypeBaseServiceProvider = Mock.Of <IContentTypeBaseServiceProvider>();
            var umbracoContextAccessor         = Mock.Of <IUmbracoContextAccessor>();
            var backOfficeSecurityAccessor     = Mock.Of <IBackOfficeSecurityAccessor>();
            var publishedUrlProvider           = Mock.Of <IPublishedUrlProvider>();
            var imageSourceParser = new HtmlImageSourceParser(publishedUrlProvider);
            var serializer        = new ConfigurationEditorJsonSerializer();
            var mediaFileService  = new MediaFileManager(Mock.Of <IFileSystem>(), Mock.Of <IMediaPathScheme>(),
                                                         loggerFactory.CreateLogger <MediaFileManager>(), Mock.Of <IShortStringHelper>());
            var pastedImages = new RichTextEditorPastedImages(umbracoContextAccessor, loggerFactory.CreateLogger <RichTextEditorPastedImages>(), HostingEnvironment, mediaService, contentTypeBaseServiceProvider, mediaFileService, ShortStringHelper, publishedUrlProvider, serializer);
            var linkParser   = new HtmlLocalLinkParser(umbracoContextAccessor, publishedUrlProvider);

            var dataTypeService = new TestObjects.TestDataTypeService(
                new DataType(new VoidEditor(DataValueEditorFactory), serializer)
            {
                Id = 1
            },
                new DataType(new TrueFalsePropertyEditor(DataValueEditorFactory, IOHelper), serializer)
            {
                Id = 1001
            },
                new DataType(new RichTextPropertyEditor(DataValueEditorFactory, backOfficeSecurityAccessor, imageSourceParser, linkParser, pastedImages, IOHelper, Mock.Of <IImageUrlGenerator>()), serializer)
            {
                Id = 1002
            },
                new DataType(new IntegerPropertyEditor(DataValueEditorFactory), serializer)
            {
                Id = 1003
            },
                new DataType(new TextboxPropertyEditor(DataValueEditorFactory, IOHelper), serializer)
            {
                Id = 1004
            },
                new DataType(new MediaPickerPropertyEditor(DataValueEditorFactory, IOHelper), serializer)
            {
                Id = 1005
            });

            Builder.Services.AddUnique <IDataTypeService>(f => dataTypeService);
        }
        public void DropDownMultipleValueEditor_Format_Data_For_Cache()
        {
            var dataValueEditorFactoryMock = new Mock <IDataValueEditorFactory>();
            var serializer = new ConfigurationEditorJsonSerializer();
            var checkBoxListPropertyEditor = new CheckBoxListPropertyEditor(dataValueEditorFactoryMock.Object, Mock.Of <ILocalizedTextService>(), Mock.Of <IIOHelper>(), Mock.Of <IEditorConfigurationParser>());
            var dataType = new DataType(checkBoxListPropertyEditor, serializer)
            {
                Configuration = new ValueListConfiguration
                {
                    Items = new List <ValueListConfiguration.ValueListItem>
                    {
                        new ValueListConfiguration.ValueListItem {
                            Id = 4567, Value = "Value 1"
                        },
                        new ValueListConfiguration.ValueListItem {
                            Id = 1234, Value = "Value 2"
                        },
                        new ValueListConfiguration.ValueListItem {
                            Id = 8910, Value = "Value 3"
                        }
                    }
                },
                Id = 1
            };

            var dataTypeServiceMock = new Mock <IDataTypeService>();

            dataTypeServiceMock
            .Setup(x => x.GetDataType(It.IsAny <int>()))
            .Returns(dataType);

            //TODO use builders instead of this mess
            var multipleValueEditor = new MultipleValueEditor(Mock.Of <ILocalizedTextService>(), Mock.Of <IShortStringHelper>(), Mock.Of <IJsonSerializer>(), Mock.Of <IIOHelper>(), new DataEditorAttribute(Constants.PropertyEditors.Aliases.TextBox, "Test Textbox", "textbox"));

            dataValueEditorFactoryMock
            .Setup(x => x.Create <MultipleValueEditor>(It.IsAny <DataEditorAttribute>()))
            .Returns(multipleValueEditor);

            var prop = new Property(1, new PropertyType(Mock.Of <IShortStringHelper>(), dataType));

            prop.SetValue("Value 1,Value 2,Value 3");

            IDataValueEditor valueEditor = dataType.Editor.GetValueEditor();

            ((DataValueEditor)valueEditor).Configuration = dataType.Configuration;
            var result = valueEditor.ConvertDbToString(prop.PropertyType, prop.GetValue());

            Assert.AreEqual("Value 1,Value 2,Value 3", result);
        }
        static AutoPublishedContentType()
        {
            var serializer          = new ConfigurationEditorJsonSerializer();
            var dataTypeServiceMock = new Mock <IDataTypeService>();
            var dataType            = new DataType(new VoidEditor(Mock.Of <IDataValueEditorFactory>()), serializer)
            {
                Id = 666
            };

            dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield);

            var factory = new PublishedContentTypeFactory(Mock.Of <IPublishedModelFactory>(), new PropertyValueConverterCollection(Array.Empty <IPropertyValueConverter>()), dataTypeServiceMock.Object);

            Default = factory.CreatePropertyType("*", 666);
        }
        private SolidPublishedSnapshot CreatePublishedSnapshot()
        {
            var serializer      = new ConfigurationEditorJsonSerializer();
            var dataTypeService = new TestObjects.TestDataTypeService(
                new DataType(new VoidEditor(DataValueEditorFactory), serializer)
            {
                Id = 1
            });

            var factory = new PublishedContentTypeFactory(Mock.Of <IPublishedModelFactory>(), new PropertyValueConverterCollection(Array.Empty <IPropertyValueConverter>()), dataTypeService);
            var caches  = new SolidPublishedSnapshot();
            var cache   = caches.InnerContentCache;

            PopulateCache(factory, cache);
            return(caches);
        }
Example #9
0
        public override void Setup()
        {
            base.Setup();

            var dataTypes   = GetDefaultDataTypes().ToList();
            var serializer  = new ConfigurationEditorJsonSerializer();
            var rteDataType = new DataType(new VoidEditor("RTE", Mock.Of <IDataValueEditorFactory>()), serializer)
            {
                Id = 4
            };

            dataTypes.Add(rteDataType);
            _dataTypes = dataTypes.ToArray();

            _propertyDataTypes = new()
            {
Example #10
0
        public void SimpleConverter1Test()
        {
            var converters = new PropertyValueConverterCollection(() => new IPropertyValueConverter[]
            {
                new SimpleConverter1(),
            });

            var serializer          = new ConfigurationEditorJsonSerializer();
            var dataTypeServiceMock = new Mock <IDataTypeService>();
            var dataType            = new DataType(
                new VoidEditor(
                    Mock.Of <IDataValueEditorFactory>()), serializer)
            {
                Id = 1
            };

            dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield);

            var contentTypeFactory = new PublishedContentTypeFactory(Mock.Of <IPublishedModelFactory>(), converters, dataTypeServiceMock.Object);

            IEnumerable <IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType)
            {
                yield return(contentTypeFactory.CreatePropertyType(contentType, "prop1", 1));
            }

            IPublishedContentType elementType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "element1", CreatePropertyTypes);

            var element1 = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary <string, object> {
                { "prop1", "1234" }
            }, false);

            Assert.AreEqual(1234, element1.Value(Mock.Of <IPublishedValueFallback>(), "prop1"));

            // 'null' would be considered a 'missing' value by the default, magic logic
            var e = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary <string, object> {
                { "prop1", null }
            }, false);

            Assert.IsFalse(e.HasValue("prop1"));

            // '0' would not - it's a valid integer - but the converter knows better
            e = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary <string, object> {
                { "prop1", "0" }
            }, false);
            Assert.IsFalse(e.HasValue("prop1"));
        }
        protected override void Initialize()
        {
            base.Initialize();

            var converters             = Factory.GetRequiredService <PropertyValueConverterCollection>();
            var umbracoContextAccessor = Mock.Of <IUmbracoContextAccessor>();
            var publishedUrlProvider   = Mock.Of <IPublishedUrlProvider>();
            var loggerFactory          = NullLoggerFactory.Instance;
            var serializer             = new ConfigurationEditorJsonSerializer();

            var imageSourceParser = new HtmlImageSourceParser(publishedUrlProvider);
            var mediaFileManager  = new MediaFileManager(Mock.Of <IFileSystem>(), Mock.Of <IMediaPathScheme>(),
                                                         loggerFactory.CreateLogger <MediaFileManager>(), Mock.Of <IShortStringHelper>());
            var pastedImages    = new RichTextEditorPastedImages(umbracoContextAccessor, loggerFactory.CreateLogger <RichTextEditorPastedImages>(), HostingEnvironment, Mock.Of <IMediaService>(), Mock.Of <IContentTypeBaseServiceProvider>(), mediaFileManager, ShortStringHelper, publishedUrlProvider, serializer);
            var localLinkParser = new HtmlLocalLinkParser(umbracoContextAccessor, publishedUrlProvider);
            var dataTypeService = new TestObjects.TestDataTypeService(
                new DataType(new RichTextPropertyEditor(
                                 DataValueEditorFactory,
                                 Mock.Of <IBackOfficeSecurityAccessor>(),
                                 imageSourceParser,
                                 localLinkParser,
                                 pastedImages,
                                 IOHelper,
                                 Mock.Of <IImageUrlGenerator>()),
                             serializer)
            {
                Id = 1
            });


            var publishedContentTypeFactory = new PublishedContentTypeFactory(Mock.Of <IPublishedModelFactory>(), converters, dataTypeService);

            IEnumerable <IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType)
            {
                yield return(publishedContentTypeFactory.CreatePropertyType(contentType, "content", 1));
            }

            var type = new AutoPublishedContentType(Guid.NewGuid(), 0, "anything", CreatePropertyTypes);

            ContentTypesCache.GetPublishedContentTypeByAlias = alias => type;

            var umbracoContext = GetUmbracoContext("/test");

            Umbraco.Web.Composing.Current.UmbracoContextAccessor.UmbracoContext = umbracoContext;
        }
    public void GetAllReferences_All_Variants_With_IDataValueReference_Editor()
    {
        var collection = new DataValueReferenceFactoryCollection(() => Enumerable.Empty <IDataValueReferenceFactory>());

        // mediaPicker does implement IDataValueReference
        var mediaPicker = new MediaPickerPropertyEditor(
            DataValueEditorFactory,
            IOHelper,
            EditorConfigurationParser);
        var propertyEditors = new PropertyEditorCollection(new DataEditorCollection(() => mediaPicker.Yield()));
        var trackedUdi1     = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString();
        var trackedUdi2     = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString();
        var trackedUdi3     = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString();
        var trackedUdi4     = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString();
        var serializer      = new ConfigurationEditorJsonSerializer();
        var property        =
            new Property(
                new PropertyType(ShortStringHelper, new DataType(mediaPicker, serializer))
        {
            Variations = ContentVariation.CultureAndSegment,
        })
        {
            Values = new List <PropertyValue>
            {
                // Ignored (no culture)
                new() { EditedValue = trackedUdi1 },
                new() { Culture = "en-US", EditedValue = trackedUdi2 },
                new() { Culture = "en-US", Segment = "A", EditedValue = trackedUdi3 },

                // Ignored (no culture)
                new() { Segment = "A", EditedValue = trackedUdi4 },

                // Duplicate
                new() { Culture = "en-US", Segment = "B", EditedValue = trackedUdi3 },
            },
        };
        var properties = new PropertyCollection {
            property
        };
        var result = collection.GetAllReferences(properties, propertyEditors).ToArray();

        Assert.AreEqual(2, result.Count());
        Assert.AreEqual(trackedUdi2, result.ElementAt(0).Udi.ToString());
        Assert.AreEqual(trackedUdi3, result.ElementAt(1).Udi.ToString());
    }
Example #13
0
        protected override void Initialize()
        {
            base.Initialize();

            // need to specify a custom callback for unit tests
            // AutoPublishedContentTypes generates properties automatically

            var serializer      = new ConfigurationEditorJsonSerializer();
            var dataTypeService = new TestObjects.TestDataTypeService(
                new DataType(new VoidEditor(DataValueEditorFactory), serializer)
            {
                Id = 1
            });

            var factory = new PublishedContentTypeFactory(Mock.Of <IPublishedModelFactory>(), new PropertyValueConverterCollection(Array.Empty <IPropertyValueConverter>()), dataTypeService);
            var type    = new AutoPublishedContentType(Guid.NewGuid(), 0, "anything", new PublishedPropertyType[] { });

            ContentTypesCache.GetPublishedContentTypeByAlias = alias => GetPublishedContentTypeByAlias(alias) ?? type;
        }
Example #14
0
 public void DropDownMultipleValueEditor_Format_Data_For_Cache()
 {
     var dataValueEditorFactoryMock = new Mock <IDataValueEditorFactory>();
     var serializer = new ConfigurationEditorJsonSerializer();
     var checkBoxListPropertyEditor = new CheckBoxListPropertyEditor(
         dataValueEditorFactoryMock.Object,
         Mock.Of <ILocalizedTextService>(),
         Mock.Of <IIOHelper>(),
         Mock.Of <IEditorConfigurationParser>());
     var dataType = new DataType(checkBoxListPropertyEditor, serializer)
     {
         Configuration = new ValueListConfiguration
         {
             Items = new List <ValueListConfiguration.ValueListItem>
             {
                 new() { Id = 4567, Value = "Value 1" },
                 new() { Id = 1234, Value = "Value 2" },
                 new() { Id = 8910, Value = "Value 3" },
             },
         },
Example #15
0
    public override void Setup()
    {
        base.Setup();

        var dataTypes   = GetDefaultDataTypes().ToList();
        var serializer  = new ConfigurationEditorJsonSerializer();
        var rteDataType = new DataType(new VoidEditor("RTE", Mock.Of <IDataValueEditorFactory>()), serializer)
        {
            Id = 4
        };

        dataTypes.Add(rteDataType);
        _dataTypes = dataTypes.ToArray();

        _propertyDataTypes = new Dictionary <string, IDataType>
        {
            // defaults will just use the first one
            [string.Empty] = _dataTypes[0],

            // content uses the RTE
            ["content"] = _dataTypes[1],
        };
    }
Example #16
0
        public void SimpleConverter3Test()
        {
            var register = new ServiceCollection();

            var composition = new UmbracoBuilder(register, Mock.Of <IConfiguration>(), TestHelper.GetMockedTypeLoader());

            composition.WithCollectionBuilder <PropertyValueConverterCollectionBuilder>()
            .Append <SimpleConverter3A>()
            .Append <SimpleConverter3B>();

            IPublishedModelFactory factory = new PublishedModelFactory(
                new[]
            {
                typeof(PublishedSnapshotTestObjects.TestElementModel1),
                typeof(PublishedSnapshotTestObjects.TestElementModel2),
                typeof(PublishedSnapshotTestObjects.TestContentModel1),
                typeof(PublishedSnapshotTestObjects.TestContentModel2)
            }, Mock.Of <IPublishedValueFallback>());

            register.AddTransient(f => factory);

            var cacheMock    = new Mock <IPublishedContentCache>();
            var cacheContent = new Dictionary <int, IPublishedContent>();

            cacheMock.Setup(x => x.GetById(It.IsAny <int>())).Returns <int>(id =>
                                                                            cacheContent.TryGetValue(id, out IPublishedContent content) ? content : null);
            var publishedSnapshotMock = new Mock <IPublishedSnapshot>();

            publishedSnapshotMock.Setup(x => x.Content).Returns(cacheMock.Object);
            var publishedSnapshotAccessorMock = new Mock <IPublishedSnapshotAccessor>();
            var localPublishedSnapshot        = publishedSnapshotMock.Object;

            publishedSnapshotAccessorMock.Setup(x => x.TryGetPublishedSnapshot(out localPublishedSnapshot)).Returns(true);
            register.AddTransient(f => publishedSnapshotAccessorMock.Object);

            IServiceProvider registerFactory            = composition.CreateServiceProvider();
            PropertyValueConverterCollection converters =
                registerFactory.GetRequiredService <PropertyValueConverterCollection>();

            var serializer          = new ConfigurationEditorJsonSerializer();
            var dataTypeServiceMock = new Mock <IDataTypeService>();
            var dataType1           = new DataType(
                new VoidEditor(
                    Mock.Of <IDataValueEditorFactory>()),
                serializer)
            {
                Id = 1
            };
            var dataType2 = new DataType(
                new VoidEditor(
                    "2",
                    Mock.Of <IDataValueEditorFactory>()),
                serializer)
            {
                Id = 2
            };

            dataTypeServiceMock.Setup(x => x.GetAll()).Returns(new[] { dataType1, dataType2 });

            var contentTypeFactory = new PublishedContentTypeFactory(factory, converters, dataTypeServiceMock.Object);

            IEnumerable <IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType, int i)
            {
                yield return(contentTypeFactory.CreatePropertyType(contentType, "prop" + i, i));
            }

            IPublishedContentType elementType1 =
                contentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "element1", t => CreatePropertyTypes(t, 1));
            IPublishedContentType elementType2 =
                contentTypeFactory.CreateContentType(Guid.NewGuid(), 1001, "element2", t => CreatePropertyTypes(t, 2));
            IPublishedContentType contentType1 =
                contentTypeFactory.CreateContentType(Guid.NewGuid(), 1002, "content1", t => CreatePropertyTypes(t, 1));
            IPublishedContentType contentType2 =
                contentTypeFactory.CreateContentType(Guid.NewGuid(), 1003, "content2", t => CreatePropertyTypes(t, 2));

            var element1 = new PublishedElement(
                elementType1,
                Guid.NewGuid(),
                new Dictionary <string, object> {
                { "prop1", "val1" }
            },
                false);
            var element2 = new PublishedElement(
                elementType2,
                Guid.NewGuid(),
                new Dictionary <string, object> {
                { "prop2", "1003" }
            },
                false);
            var cnt1 = new InternalPublishedContent(contentType1)
            {
                Id         = 1003,
                Properties = new[]
                {
                    new InternalPublishedProperty {
                        Alias = "prop1", SolidHasValue = true, SolidValue = "val1"
                    }
                }
            };
            var cnt2 = new InternalPublishedContent(contentType1)
            {
                Id         = 1004,
                Properties = new[]
                {
                    new InternalPublishedProperty {
                        Alias = "prop2", SolidHasValue = true, SolidValue = "1003"
                    }
                }
            };

            IPublishedModelFactory publishedModelFactory = registerFactory.GetRequiredService <IPublishedModelFactory>();

            cacheContent[cnt1.Id] = cnt1.CreateModel(publishedModelFactory);
            cacheContent[cnt2.Id] = cnt2.CreateModel(publishedModelFactory);

            // can get the actual property Clr type
            // ie ModelType gets properly mapped by IPublishedContentModelFactory
            // must test ModelClrType with special equals 'cos they are not ref-equals
            Assert.IsTrue(ModelType.Equals(
                              typeof(IEnumerable <>).MakeGenericType(ModelType.For("content1")),
                              contentType2.GetPropertyType("prop2").ModelClrType));
            Assert.AreEqual(
                typeof(IEnumerable <PublishedSnapshotTestObjects.TestContentModel1>),
                contentType2.GetPropertyType("prop2").ClrType);

            // can create a model for an element
            IPublishedElement model1 = factory.CreateModel(element1);

            Assert.IsInstanceOf <PublishedSnapshotTestObjects.TestElementModel1>(model1);
            Assert.AreEqual("val1", ((PublishedSnapshotTestObjects.TestElementModel1)model1).Prop1);

            // can create a model for a published content
            IPublishedElement model2 = factory.CreateModel(element2);

            Assert.IsInstanceOf <PublishedSnapshotTestObjects.TestElementModel2>(model2);
            var mmodel2 = (PublishedSnapshotTestObjects.TestElementModel2)model2;

            // and get direct property
            Assert.IsInstanceOf <PublishedSnapshotTestObjects.TestContentModel1[]>(
                model2.Value(Mock.Of <IPublishedValueFallback>(), "prop2"));
            Assert.AreEqual(
                1,
                ((PublishedSnapshotTestObjects.TestContentModel1[])model2.Value(Mock.Of <IPublishedValueFallback>(), "prop2")).Length);

            // and get model property
            Assert.IsInstanceOf <IEnumerable <PublishedSnapshotTestObjects.TestContentModel1> >(mmodel2.Prop2);
            Assert.IsInstanceOf <PublishedSnapshotTestObjects.TestContentModel1[]>(mmodel2.Prop2);
            PublishedSnapshotTestObjects.TestContentModel1 mmodel1 = mmodel2.Prop2.First();

            // and we get what we want
            Assert.AreSame(cacheContent[mmodel1.Id], mmodel1);
        }
    private (IPublishedContentType, IPublishedContentType) CreateContentTypes()
    {
        var logger              = Mock.Of <ILogger <ProfilingLogger> >();
        var loggerFactory       = NullLoggerFactory.Instance;
        var profiler            = Mock.Of <IProfiler>();
        var proflog             = new ProfilingLogger(logger, profiler);
        var localizationService = Mock.Of <ILocalizationService>();

        PropertyEditorCollection editors = null;
        var editor = new NestedContentPropertyEditor(Mock.Of <IDataValueEditorFactory>(), Mock.Of <IIOHelper>(), Mock.Of <IEditorConfigurationParser>());

        editors = new PropertyEditorCollection(new DataEditorCollection(() => new DataEditor[] { editor }));

        var serializer = new ConfigurationEditorJsonSerializer();

        var dataType1 = new DataType(editor, serializer)
        {
            Id            = 1,
            Configuration = new NestedContentConfiguration
            {
                MinItems     = 1,
                MaxItems     = 1,
                ContentTypes = new[] { new NestedContentConfiguration.ContentType {
                                           Alias = "contentN1"
                                       } },
            },
        };

        var dataType2 = new DataType(editor, serializer)
        {
            Id            = 2,
            Configuration = new NestedContentConfiguration
            {
                MinItems     = 1,
                MaxItems     = 99,
                ContentTypes = new[] { new NestedContentConfiguration.ContentType {
                                           Alias = "contentN1"
                                       } },
            },
        };

        var dataType3 =
            new DataType(
                new TextboxPropertyEditor(Mock.Of <IDataValueEditorFactory>(), Mock.Of <IIOHelper>(), Mock.Of <IEditorConfigurationParser>()), serializer)
        {
            Id = 3
        };

        // mocked dataservice returns nested content preValues
        var dataTypeServiceMock = new Mock <IDataTypeService>();

        dataTypeServiceMock.Setup(x => x.GetAll()).Returns(new[] { dataType1, dataType2, dataType3 });

        var publishedModelFactory = new Mock <IPublishedModelFactory>();

        // mocked model factory returns model type
        var modelTypes = new Dictionary <string, Type> {
            { "contentN1", typeof(TestElementModel) }
        };

        publishedModelFactory
        .Setup(x => x.MapModelType(It.IsAny <Type>()))
        .Returns((Type type) => ModelType.Map(type, modelTypes));

        // mocked model factory creates models
        publishedModelFactory
        .Setup(x => x.CreateModel(It.IsAny <IPublishedElement>()))
        .Returns((IPublishedElement element) =>
        {
            if (element.ContentType.Alias.InvariantEquals("contentN1"))
            {
                return(new TestElementModel(element, Mock.Of <IPublishedValueFallback>()));
            }

            return(element);
        });

        // mocked model factory creates model lists
        publishedModelFactory
        .Setup(x => x.CreateModelList(It.IsAny <string>()))
        .Returns((string alias) =>
                 alias == "contentN1"
                    ? new List <TestElementModel>()
                    : new List <IPublishedElement>());

        var contentCache      = new Mock <IPublishedContentCache>();
        var publishedSnapshot = new Mock <IPublishedSnapshot>();

        // mocked published snapshot returns a content cache
        publishedSnapshot
        .Setup(x => x.Content)
        .Returns(contentCache.Object);

        var publishedSnapshotAccessor = new Mock <IPublishedSnapshotAccessor>();

        // mocked published snapshot accessor returns a facade
        var localPublishedSnapshot = publishedSnapshot.Object;

        publishedSnapshotAccessor
        .Setup(x => x.TryGetPublishedSnapshot(out localPublishedSnapshot))
        .Returns(true);

        var converters = new PropertyValueConverterCollection(() => new IPropertyValueConverter[]
        {
            new NestedContentSingleValueConverter(publishedSnapshotAccessor.Object, publishedModelFactory.Object, proflog),
            new NestedContentManyValueConverter(publishedSnapshotAccessor.Object, publishedModelFactory.Object, proflog),
        });

        var factory =
            new PublishedContentTypeFactory(publishedModelFactory.Object, converters, dataTypeServiceMock.Object);

        IEnumerable <IPublishedPropertyType> CreatePropertyTypes1(IPublishedContentType contentType)
        {
            yield return(factory.CreatePropertyType(contentType, "property1", 1));
        }

        IEnumerable <IPublishedPropertyType> CreatePropertyTypes2(IPublishedContentType contentType)
        {
            yield return(factory.CreatePropertyType(contentType, "property2", 2));
        }

        IEnumerable <IPublishedPropertyType> CreatePropertyTypesN1(IPublishedContentType contentType)
        {
            yield return(factory.CreatePropertyType(contentType, "propertyN1", 3));
        }

        var contentType1  = factory.CreateContentType(Guid.NewGuid(), 1, "content1", CreatePropertyTypes1);
        var contentType2  = factory.CreateContentType(Guid.NewGuid(), 2, "content2", CreatePropertyTypes2);
        var contentTypeN1 =
            factory.CreateContentType(Guid.NewGuid(), 2, "contentN1", CreatePropertyTypesN1, isElement: true);

        // mocked content cache returns content types
        contentCache
        .Setup(x => x.GetContentType(It.IsAny <string>()))
        .Returns((string alias) =>
        {
            if (alias.InvariantEquals("contentN1"))
            {
                return(contentTypeN1);
            }

            return(null);
        });

        return(contentType1, contentType2);
    }
        private void Init()
        {
            var factory = Mock.Of <IServiceProvider>();

            Current.Factory = factory;

            var publishedModelFactory = new NoopPublishedModelFactory();

            Mock.Get(factory).Setup(x => x.GetService(typeof(IPublishedModelFactory))).Returns(publishedModelFactory);
            Mock.Get(factory).Setup(x => x.GetService(typeof(IPublishedValueFallback))).Returns(new NoopPublishedValueFallback());

            // create a content node kit
            var kit = new ContentNodeKit
            {
                ContentTypeId = 2,
                Node          = new ContentNode(1, Guid.NewGuid(), 0, "-1,1", 0, -1, DateTime.Now, 0),
                DraftData     = new ContentData
                {
                    Name        = "It Works2!",
                    Published   = false,
                    TemplateId  = 0,
                    VersionId   = 2,
                    VersionDate = DateTime.Now,
                    WriterId    = 0,
                    Properties  = new Dictionary <string, PropertyData[]> {
                        { "prop", new[]
                          {
                              new PropertyData {
                                  Culture = "", Segment = "", Value = "val2"
                              },
                              new PropertyData {
                                  Culture = "fr-FR", Segment = "", Value = "val-fr2"
                              },
                              new PropertyData {
                                  Culture = "en-UK", Segment = "", Value = "val-uk2"
                              },
                              new PropertyData {
                                  Culture = "dk-DA", Segment = "", Value = "val-da2"
                              },
                              new PropertyData {
                                  Culture = "de-DE", Segment = "", Value = "val-de2"
                              }
                          } }
                    },
                    CultureInfos = new Dictionary <string, CultureVariation>
                    {
                        // draft data = everything, and IsDraft indicates what's edited
                        { "fr-FR", new CultureVariation {
                              Name = "name-fr2", IsDraft = true, Date = new DateTime(2018, 01, 03, 01, 00, 00)
                          } },
                        { "en-UK", new CultureVariation {
                              Name = "name-uk2", IsDraft = true, Date = new DateTime(2018, 01, 04, 01, 00, 00)
                          } },
                        { "dk-DA", new CultureVariation {
                              Name = "name-da2", IsDraft = true, Date = new DateTime(2018, 01, 05, 01, 00, 00)
                          } },
                        { "de-DE", new CultureVariation {
                              Name = "name-de1", IsDraft = false, Date = new DateTime(2018, 01, 02, 01, 00, 00)
                          } }
                    }
                },
                PublishedData = new ContentData
                {
                    Name        = "It Works1!",
                    Published   = true,
                    TemplateId  = 0,
                    VersionId   = 1,
                    VersionDate = DateTime.Now,
                    WriterId    = 0,
                    Properties  = new Dictionary <string, PropertyData[]> {
                        { "prop", new[]
                          {
                              new PropertyData {
                                  Culture = "", Segment = "", Value = "val1"
                              },
                              new PropertyData {
                                  Culture = "fr-FR", Segment = "", Value = "val-fr1"
                              },
                              new PropertyData {
                                  Culture = "en-UK", Segment = "", Value = "val-uk1"
                              }
                          } }
                    },
                    CultureInfos = new Dictionary <string, CultureVariation>
                    {
                        // published data = only what's actually published, and IsDraft has to be false
                        { "fr-FR", new CultureVariation {
                              Name = "name-fr1", IsDraft = false, Date = new DateTime(2018, 01, 01, 01, 00, 00)
                          } },
                        { "en-UK", new CultureVariation {
                              Name = "name-uk1", IsDraft = false, Date = new DateTime(2018, 01, 02, 01, 00, 00)
                          } },
                        { "de-DE", new CultureVariation {
                              Name = "name-de1", IsDraft = false, Date = new DateTime(2018, 01, 02, 01, 00, 00)
                          } }
                    }
                }
            };

            // create a data source for NuCache
            var dataSource = new TestDataSource(kit);

            _contentNestedDataSerializerFactory = new JsonContentNestedDataSerializerFactory();

            var runtime = Mock.Of <IRuntimeState>();

            Mock.Get(runtime).Setup(x => x.Level).Returns(RuntimeLevel.Run);

            var serializer = new ConfigurationEditorJsonSerializer();

            // create data types, property types and content types
            var dataType = new DataType(new VoidEditor("Editor", Mock.Of <IDataValueEditorFactory>()), serializer)
            {
                Id = 3
            };

            var dataTypes = new[]
            {
                dataType
            };

            _propertyType = new PropertyType(TestHelper.ShortStringHelper, "Umbraco.Void.Editor", ValueStorageType.Nvarchar)
            {
                Alias = "prop", DataTypeId = 3, Variations = ContentVariation.Culture
            };
            _contentType = new ContentType(TestHelper.ShortStringHelper, -1)
            {
                Id = 2, Alias = "alias-ct", Variations = ContentVariation.Culture
            };
            _contentType.AddPropertyType(_propertyType);

            var contentTypes = new[]
            {
                _contentType
            };

            var contentTypeService = new Mock <IContentTypeService>();

            contentTypeService.Setup(x => x.GetAll()).Returns(contentTypes);
            contentTypeService.Setup(x => x.GetAll(It.IsAny <int[]>())).Returns(contentTypes);

            var mediaTypeService = new Mock <IMediaTypeService>();

            mediaTypeService.Setup(x => x.GetAll()).Returns(Enumerable.Empty <IMediaType>());
            mediaTypeService.Setup(x => x.GetAll(It.IsAny <int[]>())).Returns(Enumerable.Empty <IMediaType>());

            var contentTypeServiceBaseFactory = new Mock <IContentTypeBaseServiceProvider>();

            contentTypeServiceBaseFactory.Setup(x => x.For(It.IsAny <IContentBase>())).Returns(contentTypeService.Object);

            var dataTypeService = Mock.Of <IDataTypeService>();

            Mock.Get(dataTypeService).Setup(x => x.GetAll()).Returns(dataTypes);

            // create a service context
            var serviceContext = ServiceContext.CreatePartial(
                dataTypeService: dataTypeService,
                memberTypeService: Mock.Of <IMemberTypeService>(),
                memberService: Mock.Of <IMemberService>(),
                contentTypeService: contentTypeService.Object,
                mediaTypeService: mediaTypeService.Object,
                localizationService: Mock.Of <ILocalizationService>(),
                domainService: Mock.Of <IDomainService>()
                );

            // create a scope provider
            var scopeProvider = Mock.Of <IScopeProvider>();

            Mock.Get(scopeProvider)
            .Setup(x => x.CreateScope(
                       It.IsAny <IsolationLevel>(),
                       It.IsAny <RepositoryCacheMode>(),
                       It.IsAny <IEventDispatcher>(),
                       It.IsAny <bool?>(),
                       It.IsAny <bool>(),
                       It.IsAny <bool>()))
            .Returns(Mock.Of <IScope>);

            // create a published content type factory
            var contentTypeFactory = new PublishedContentTypeFactory(
                publishedModelFactory,
                new PropertyValueConverterCollection(Array.Empty <IPropertyValueConverter>()),
                dataTypeService);

            // create a variation accessor
            _variationAccesor = new TestVariationContextAccessor();

            var typeFinder = TestHelper.GetTypeFinder();

            var globalSettings  = new GlobalSettings();
            var nuCacheSettings = new NuCacheSettings();

            // at last, create the complete NuCache snapshot service!
            var options = new PublishedSnapshotServiceOptions {
                IgnoreLocalDb = true
            };

            _snapshotService = new PublishedSnapshotService(
                options,
                null,
                serviceContext,
                contentTypeFactory,
                new TestPublishedSnapshotAccessor(),
                _variationAccesor,
                Mock.Of <IProfilingLogger>(),
                NullLoggerFactory.Instance,
                scopeProvider,
                dataSource,
                new TestDefaultCultureAccessor(),
                Microsoft.Extensions.Options.Options.Create(globalSettings),
                Mock.Of <IEntityXmlSerializer>(),
                publishedModelFactory,
                TestHelper.GetHostingEnvironment(),
                Microsoft.Extensions.Options.Options.Create(nuCacheSettings),
                _contentNestedDataSerializerFactory);

            // invariant is the current default
            _variationAccesor.VariationContext = new VariationContext();

            Mock.Get(factory).Setup(x => x.GetService(typeof(IVariationContextAccessor))).Returns(_variationAccesor);
        }
        public void GetAllReferences_All_Variants_With_IDataValueReferenceFactory()
        {
            var collection = new DataValueReferenceFactoryCollection(() => new TestDataValueReferenceFactory().Yield());

            // label does not implement IDataValueReference
            var labelEditor = new LabelPropertyEditor(
                DataValueEditorFactory,
                IOHelper);
            var propertyEditors = new PropertyEditorCollection(new DataEditorCollection(() => labelEditor.Yield()));
            var trackedUdi1     = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString();
            var trackedUdi2     = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString();
            var trackedUdi3     = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString();
            var trackedUdi4     = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString();
            var serializer      = new ConfigurationEditorJsonSerializer();
            var property        = new Property(new PropertyType(ShortStringHelper, new DataType(labelEditor, serializer))
            {
                Variations = ContentVariation.CultureAndSegment
            })
            {
                Values = new List <PropertyValue>
                {
                    // Ignored (no culture)
                    new PropertyValue
                    {
                        EditedValue = trackedUdi1
                    },
                    new PropertyValue
                    {
                        Culture     = "en-US",
                        EditedValue = trackedUdi2
                    },
                    new PropertyValue
                    {
                        Culture     = "en-US",
                        Segment     = "A",
                        EditedValue = trackedUdi3
                    },

                    // Ignored (no culture)
                    new PropertyValue
                    {
                        Segment     = "A",
                        EditedValue = trackedUdi4
                    },

                    // Duplicate
                    new PropertyValue
                    {
                        Culture     = "en-US",
                        Segment     = "B",
                        EditedValue = trackedUdi3
                    }
                }
            };
            var properties = new PropertyCollection
            {
                property
            };
            IEnumerable <UmbracoEntityReference> result = collection.GetAllReferences(properties, propertyEditors);

            Assert.AreEqual(2, result.Count());
            Assert.AreEqual(trackedUdi2, result.ElementAt(0).Udi.ToString());
            Assert.AreEqual(trackedUdi3, result.ElementAt(1).Udi.ToString());
        }
Example #20
0
        /// <summary>
        /// Generate a collection of <see cref="ContentNodeKit"/> based on legacy umbraco XML
        /// </summary>
        /// <param name="xml">The legacy umbraco XML</param>
        /// <param name="shortStringHelper"></param>
        /// <param name="contentTypes">Dynamically generates a list of <see cref="ContentType"/>s based on the XML data</param>
        /// <param name="dataTypes">Dynamically generates a list of <see cref="DataType"/> for tests</param>
        /// <returns></returns>
        public static IEnumerable <ContentNodeKit> GetContentNodeKits(
            string xml,
            IShortStringHelper shortStringHelper,
            out ContentType[] contentTypes,
            out DataType[] dataTypes)
        {
            // use the label data type for all data for these tests except in the case
            // where a property is named 'content', in which case use the RTE.
            var serializer    = new ConfigurationEditorJsonSerializer();
            var labelDataType = new DataType(new VoidEditor("Label", Mock.Of <IDataValueEditorFactory>()), serializer)
            {
                Id = 3
            };
            var rteDataType = new DataType(new VoidEditor("RTE", Mock.Of <IDataValueEditorFactory>()), serializer)
            {
                Id = 4
            };

            dataTypes = new[] { labelDataType, rteDataType };

            var kitsAndXml = new List <(ContentNodeKit kit, XElement node)>();

            var xDoc = XDocument.Parse(xml);
            IEnumerable <XElement> nodes = xDoc.XPathSelectElements("//*[@isDoc]");

            foreach (XElement node in nodes)
            {
                var  id  = node.AttributeValue <int>("id");
                Guid key = node.AttributeValue <Guid?>("key") ?? id.ToGuid();

                var propertyElements = node.Elements().Where(x => x.Attribute("id") == null);
                var properties       = new Dictionary <string, PropertyData[]>();
                foreach (XElement propertyElement in propertyElements)
                {
                    properties[propertyElement.Name.LocalName] = new[]
                    {
                        // TODO: builder?
                        new PropertyData
                        {
                            Culture = string.Empty,
                            Segment = string.Empty,
                            Value   = propertyElement.Value
                        }
                    };
                }

                var contentData = new ContentDataBuilder()
                                  .WithName(node.AttributeValue <string>("nodeName"))
                                  .WithProperties(properties)
                                  .WithPublished(true)
                                  .WithTemplateId(node.AttributeValue <int>("template"))
                                  .WithUrlSegment(node.AttributeValue <string>("urlName"))
                                  .WithVersionDate(node.AttributeValue <DateTime>("updateDate"))
                                  .WithWriterId(node.AttributeValue <int>("writerID"))
                                  .Build();

                ContentNodeKit kit = ContentNodeKitBuilder.CreateWithContent(
                    node.AttributeValue <int>("nodeType"),
                    id,
                    node.AttributeValue <string>("path"),
                    node.AttributeValue <int>("sortOrder"),
                    node.AttributeValue <int>("level"),
                    node.AttributeValue <int>("parentID"),
                    node.AttributeValue <int>("creatorID"),
                    key,
                    node.AttributeValue <DateTime>("createDate"),
                    contentData,
                    contentData);

                kitsAndXml.Add((kit, node));
            }

            // put together the unique content types
            var contentTypesIdToType = new Dictionary <int, ContentType>();

            foreach ((ContentNodeKit kit, XElement node) in kitsAndXml)
            {
                if (!contentTypesIdToType.TryGetValue(kit.ContentTypeId, out ContentType contentType))
                {
                    contentType = new ContentType(shortStringHelper, -1)
                    {
                        Id    = kit.ContentTypeId,
                        Alias = node.Name.LocalName
                    };
                    SetContentTypeProperties(shortStringHelper, labelDataType, rteDataType, kit, contentType);
                    contentTypesIdToType[kit.ContentTypeId] = contentType;
                }
                else
                {
                    // we've already created it but might need to add properties
                    SetContentTypeProperties(shortStringHelper, labelDataType, rteDataType, kit, contentType);
                }
            }

            contentTypes = contentTypesIdToType.Values.ToArray();

            return(kitsAndXml.Select(x => x.kit));
        }