diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index f12bf0dd63..846331a16e 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -154,6 +154,9 @@ namespace Umbraco.Core.Composing public static DataEditorCollection DataEditors => Factory.GetInstance(); + public static DataValueReferenceFactoryCollection DataValueReferenceFactories + => Factory.GetInstance(); + public static PropertyEditorCollection PropertyEditors => Factory.GetInstance(); diff --git a/src/Umbraco.Core/CompositionExtensions.cs b/src/Umbraco.Core/CompositionExtensions.cs index 5dd33c2a60..ced9a9386a 100644 --- a/src/Umbraco.Core/CompositionExtensions.cs +++ b/src/Umbraco.Core/CompositionExtensions.cs @@ -49,6 +49,13 @@ namespace Umbraco.Core public static DataEditorCollectionBuilder DataEditors(this Composition composition) => composition.WithCollectionBuilder(); + /// + /// Gets the data value reference factory collection builder. + /// + /// The composition. + public static DataValueReferenceFactoryCollectionBuilder DataValueReferenceFactories(this Composition composition) + => composition.WithCollectionBuilder(); + /// /// Gets the property value converters collection builder. /// diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs index 65f6dc0472..13b687eb4e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs @@ -36,6 +36,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement where TRepository : class, IRepository { private readonly Lazy _propertyEditors; + private readonly DataValueReferenceFactoryCollection _dataValueReferenceFactories; /// /// @@ -49,13 +50,14 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// protected ContentRepositoryBase(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, ILanguageRepository languageRepository, IRelationRepository relationRepository, IRelationTypeRepository relationTypeRepository, - Lazy propertyEditors) + Lazy propertyEditors, DataValueReferenceFactoryCollection dataValueReferenceFactories) : base(scopeAccessor, cache, logger) { LanguageRepository = languageRepository; RelationRepository = relationRepository; RelationTypeRepository = relationTypeRepository; _propertyEditors = propertyEditors; + _dataValueReferenceFactories = dataValueReferenceFactories; } protected abstract TRepository This { get; } @@ -821,21 +823,10 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected void PersistRelations(TEntity entity) { + // Get all references from our core built in DataEditors/Property Editors + // Along with seeing if deverlopers want to collect additional references from the DataValueReferenceFactories collection var trackedRelations = new List(); - - foreach (var p in entity.Properties) - { - if (!PropertyEditors.TryGet(p.PropertyType.PropertyEditorAlias, out var editor)) continue; - var valueEditor = editor.GetValueEditor(); - if (!(valueEditor is IDataValueReference reference)) continue; - - //TODO: Support variants/segments! This is not required for this initial prototype which is why there is a check here - if (!p.PropertyType.VariesByNothing()) continue; - - var val = p.GetValue(); // get the invariant value - var refs = reference.GetReferences(val); - trackedRelations.AddRange(refs); - } + trackedRelations.AddRange(_dataValueReferenceFactories.GetAllReferences(entity.Properties, PropertyEditors)); //First delete all auto-relations for this entity RelationRepository.DeleteByParent(entity.Id, Constants.Conventions.RelationTypes.AutomaticRelationTypes); diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentBlueprintRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentBlueprintRepository.cs index 60d4026ad5..e150b2e632 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentBlueprintRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentBlueprintRepository.cs @@ -20,8 +20,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { public DocumentBlueprintRepository(IScopeAccessor scopeAccessor, AppCaches appCaches, ILogger logger, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, ILanguageRepository languageRepository, IRelationRepository relationRepository, IRelationTypeRepository relationTypeRepository, - Lazy propertyEditorCollection) - : base(scopeAccessor, appCaches, logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditorCollection) + Lazy propertyEditorCollection, DataValueReferenceFactoryCollection dataValueReferenceFactories) + : base(scopeAccessor, appCaches, logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditorCollection, dataValueReferenceFactories) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs index 5e3e7f05b9..35e54a39e0 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs @@ -46,8 +46,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// public DocumentRepository(IScopeAccessor scopeAccessor, AppCaches appCaches, ILogger logger, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, ILanguageRepository languageRepository, IRelationRepository relationRepository, IRelationTypeRepository relationTypeRepository, - Lazy propertyEditors) - : base(scopeAccessor, appCaches, logger, languageRepository, relationRepository, relationTypeRepository, propertyEditors) + Lazy propertyEditors, DataValueReferenceFactoryCollection dataValueReferenceFactories) + : base(scopeAccessor, appCaches, logger, languageRepository, relationRepository, relationTypeRepository, propertyEditors, dataValueReferenceFactories) { _contentTypeRepository = contentTypeRepository ?? throw new ArgumentNullException(nameof(contentTypeRepository)); _templateRepository = templateRepository ?? throw new ArgumentNullException(nameof(templateRepository)); diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MediaRepository.cs index a3f9e45485..ad47c7af6b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MediaRepository.cs @@ -29,8 +29,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly MediaByGuidReadRepository _mediaByGuidReadRepository; public MediaRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, IMediaTypeRepository mediaTypeRepository, ITagRepository tagRepository, ILanguageRepository languageRepository, IRelationRepository relationRepository, IRelationTypeRepository relationTypeRepository, - Lazy propertyEditorCollection) - : base(scopeAccessor, cache, logger, languageRepository, relationRepository, relationTypeRepository, propertyEditorCollection) + Lazy propertyEditorCollection, DataValueReferenceFactoryCollection dataValueReferenceFactories) + : base(scopeAccessor, cache, logger, languageRepository, relationRepository, relationTypeRepository, propertyEditorCollection, dataValueReferenceFactories) { _mediaTypeRepository = mediaTypeRepository ?? throw new ArgumentNullException(nameof(mediaTypeRepository)); _tagRepository = tagRepository ?? throw new ArgumentNullException(nameof(tagRepository)); diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberRepository.cs index 2871bf1dd3..42e7d1c32f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberRepository.cs @@ -28,8 +28,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement public MemberRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, ITagRepository tagRepository, ILanguageRepository languageRepository, IRelationRepository relationRepository, IRelationTypeRepository relationTypeRepository, - Lazy propertyEditors) - : base(scopeAccessor, cache, logger, languageRepository, relationRepository, relationTypeRepository, propertyEditors) + Lazy propertyEditors, DataValueReferenceFactoryCollection dataValueReferenceFactories) + : base(scopeAccessor, cache, logger, languageRepository, relationRepository, relationTypeRepository, propertyEditors, dataValueReferenceFactories) { _memberTypeRepository = memberTypeRepository ?? throw new ArgumentNullException(nameof(memberTypeRepository)); _tagRepository = tagRepository ?? throw new ArgumentNullException(nameof(tagRepository)); diff --git a/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollection.cs b/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollection.cs new file mode 100644 index 0000000000..c1dbfbaca4 --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollection.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using Umbraco.Core.Composing; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Editors; + +namespace Umbraco.Core.PropertyEditors +{ + public class DataValueReferenceFactoryCollection : BuilderCollectionBase + { + public DataValueReferenceFactoryCollection(IEnumerable items) + : base(items) + { } + + public IEnumerable GetAllReferences(PropertyCollection properties, PropertyEditorCollection propertyEditors) + { + var trackedRelations = new List(); + + foreach (var p in properties) + { + // Injecting propertyEditorCollection is causing LightInject to throw a Recursive Dependancy error + // Hence using Current.PropertyEditors + if (!propertyEditors.TryGet(p.PropertyType.PropertyEditorAlias, out var editor)) continue; + + //TODO: Support variants/segments! This is not required for this initial prototype which is why there is a check here + if (!p.PropertyType.VariesByNothing()) continue; + var val = p.GetValue(); // get the invariant value + + var valueEditor = editor.GetValueEditor(); + if (valueEditor is IDataValueReference reference) + { + var refs = reference.GetReferences(val); + trackedRelations.AddRange(refs); + } + + // Loop over collection that may be add to existing property editors + // implementation of GetReferences in IDataValueReference. + // Allows developers to add support for references by a + // package /property editor that did not implement IDataValueReference themselves + foreach (var item in this) + { + // Check if this value reference is for this datatype/editor + // Then call it's GetReferences method - to see if the value stored + // in the dataeditor/property has referecnes to media/content items + if (item.IsForEditor(editor)) + trackedRelations.AddRange(item.GetDataValueReference().GetReferences(val)); + } + } + + return trackedRelations; + } + } +} diff --git a/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionBuilder.cs b/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionBuilder.cs new file mode 100644 index 0000000000..2cf76712c8 --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionBuilder.cs @@ -0,0 +1,9 @@ +using Umbraco.Core.Composing; + +namespace Umbraco.Core.PropertyEditors +{ + public class DataValueReferenceFactoryCollectionBuilder : OrderedCollectionBuilderBase + { + protected override DataValueReferenceFactoryCollectionBuilder This => this; + } +} diff --git a/src/Umbraco.Core/PropertyEditors/IDataValueReference.cs b/src/Umbraco.Core/PropertyEditors/IDataValueReference.cs index 8c0806a4a4..6377098bfc 100644 --- a/src/Umbraco.Core/PropertyEditors/IDataValueReference.cs +++ b/src/Umbraco.Core/PropertyEditors/IDataValueReference.cs @@ -13,6 +13,6 @@ namespace Umbraco.Core.PropertyEditors /// /// /// - IEnumerable GetReferences(object value); + IEnumerable GetReferences(object value); } } diff --git a/src/Umbraco.Core/PropertyEditors/IDataValueReferenceFactory.cs b/src/Umbraco.Core/PropertyEditors/IDataValueReferenceFactory.cs new file mode 100644 index 0000000000..6587e071bf --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/IDataValueReferenceFactory.cs @@ -0,0 +1,18 @@ +namespace Umbraco.Core.PropertyEditors +{ + public interface IDataValueReferenceFactory + { + /// + /// Gets a value indicating whether the DataValueReference lookup supports a datatype (data editor). + /// + /// The datatype. + /// A value indicating whether the converter supports a datatype. + bool IsForEditor(IDataEditor dataEditor); + + /// + /// + /// + /// + IDataValueReference GetDataValueReference(); + } +} diff --git a/src/Umbraco.Core/Runtime/CoreInitialComposer.cs b/src/Umbraco.Core/Runtime/CoreInitialComposer.cs index 1f004846d0..d95ada499b 100644 --- a/src/Umbraco.Core/Runtime/CoreInitialComposer.cs +++ b/src/Umbraco.Core/Runtime/CoreInitialComposer.cs @@ -43,7 +43,7 @@ namespace Umbraco.Core.Runtime // register persistence mappers - required by database factory so needs to be done here // means the only place the collection can be modified is in a runtime - afterwards it // has been frozen and it is too late - composition.WithCollectionBuilder().AddCoreMappers(); + composition.Mappers().AddCoreMappers(); // register the scope provider composition.RegisterUnique(); // implements both IScopeProvider and IScopeAccessor @@ -70,11 +70,15 @@ namespace Umbraco.Core.Runtime composition.ManifestFilters(); // properties and parameters derive from data editors - composition.WithCollectionBuilder() + composition.DataEditors() .Add(() => composition.TypeLoader.GetDataEditors()); composition.RegisterUnique(); composition.RegisterUnique(); + // Used to determine if a datatype/editor should be storing/tracking + // references to media item/s + composition.DataValueReferenceFactories(); + // register a server registrar, by default it's the db registrar composition.RegisterUnique(f => { @@ -101,13 +105,13 @@ namespace Umbraco.Core.Runtime factory.GetInstance(), true, new DatabaseServerMessengerOptions())); - composition.WithCollectionBuilder() + composition.CacheRefreshers() .Add(() => composition.TypeLoader.GetCacheRefreshers()); - composition.WithCollectionBuilder() + composition.PackageActions() .Add(() => composition.TypeLoader.GetPackageActions()); - composition.WithCollectionBuilder() + composition.PropertyValueConverters() .Append(composition.TypeLoader.GetTypes()); composition.RegisterUnique(); @@ -115,7 +119,7 @@ namespace Umbraco.Core.Runtime composition.RegisterUnique(factory => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetInstance()))); - composition.WithCollectionBuilder() + composition.UrlSegmentProviders() .Append(); composition.RegisterUnique(factory => new MigrationBuilder(factory)); diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 225317943b..306b764787 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -281,7 +281,10 @@ + + + diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs index 8ed935795d..f7f3adf0a0 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs @@ -40,7 +40,8 @@ namespace Umbraco.Tests.Persistence.Repositories var entityRepository = new EntityRepository(scopeAccessor); var relationRepository = new RelationRepository(scopeAccessor, Logger, relationTypeRepository, entityRepository); var propertyEditors = new Lazy(() => new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty()))); - var repository = new DocumentRepository(scopeAccessor, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors); + var dataValueReferences = new DataValueReferenceFactoryCollection(Enumerable.Empty()); + var repository = new DocumentRepository(scopeAccessor, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors, dataValueReferences); return repository; } diff --git a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs index 3a36a647f0..291525ba13 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs @@ -73,7 +73,8 @@ namespace Umbraco.Tests.Persistence.Repositories var entityRepository = new EntityRepository(scopeAccessor); var relationRepository = new RelationRepository(scopeAccessor, Logger, relationTypeRepository, entityRepository); var propertyEditors = new Lazy(() => new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty()))); - var repository = new DocumentRepository(scopeAccessor, appCaches, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors); + var dataValueReferences = new DataValueReferenceFactoryCollection(Enumerable.Empty()); + var repository = new DocumentRepository(scopeAccessor, appCaches, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors, dataValueReferences); return repository; } diff --git a/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs index ad27aed309..56138faea9 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs @@ -31,7 +31,8 @@ namespace Umbraco.Tests.Persistence.Repositories var entityRepository = new EntityRepository(accessor); var relationRepository = new RelationRepository(accessor, Logger, relationTypeRepository, entityRepository); var propertyEditors = new Lazy(() => new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty()))); - documentRepository = new DocumentRepository(accessor, Core.Cache.AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors); + var dataValueReferences = new DataValueReferenceFactoryCollection(Enumerable.Empty()); + documentRepository = new DocumentRepository(accessor, Core.Cache.AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors, dataValueReferences); var domainRepository = new DomainRepository(accessor, Core.Cache.AppCaches.Disabled, Logger); return domainRepository; } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs index ced0ee75e9..ef436a3489 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs @@ -46,7 +46,8 @@ namespace Umbraco.Tests.Persistence.Repositories var entityRepository = new EntityRepository(scopeAccessor); var relationRepository = new RelationRepository(scopeAccessor, Logger, relationTypeRepository, entityRepository); var propertyEditors = new Lazy(() => new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty()))); - var repository = new MediaRepository(scopeAccessor, appCaches, Logger, mediaTypeRepository, tagRepository, Mock.Of(), relationRepository, relationTypeRepository, propertyEditors); + var dataValueReferences = new DataValueReferenceFactoryCollection(Enumerable.Empty()); + var repository = new MediaRepository(scopeAccessor, appCaches, Logger, mediaTypeRepository, tagRepository, Mock.Of(), relationRepository, relationTypeRepository, propertyEditors, dataValueReferences); return repository; } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs index 7531d92b49..060478d64b 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs @@ -40,7 +40,8 @@ namespace Umbraco.Tests.Persistence.Repositories var entityRepository = new EntityRepository(accessor); var relationRepository = new RelationRepository(accessor, Logger, relationTypeRepository, entityRepository); var propertyEditors = new Lazy(() => new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty()))); - var repository = new MemberRepository(accessor, AppCaches.Disabled, Logger, memberTypeRepository, memberGroupRepository, tagRepo, Mock.Of(), relationRepository, relationTypeRepository, propertyEditors); + var dataValueReferences = new DataValueReferenceFactoryCollection(Enumerable.Empty()); + var repository = new MemberRepository(accessor, AppCaches.Disabled, Logger, memberTypeRepository, memberGroupRepository, tagRepo, Mock.Of(), relationRepository, relationTypeRepository, propertyEditors, dataValueReferences); return repository; } diff --git a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs index 9a65bde41f..4cf440c369 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs @@ -315,7 +315,8 @@ namespace Umbraco.Tests.Persistence.Repositories var entityRepository = new EntityRepository(accessor); var relationRepository = new RelationRepository(accessor, Logger, relationTypeRepository, entityRepository); var propertyEditors = new Lazy(() => new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty()))); - var repository = new DocumentRepository(accessor, AppCaches, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors); + var dataValueReferences = new DataValueReferenceFactoryCollection(Enumerable.Empty()); + var repository = new DocumentRepository(accessor, AppCaches, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors, dataValueReferences); return repository; } diff --git a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs index fe0db4563a..2c15e91e61 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs @@ -964,7 +964,8 @@ namespace Umbraco.Tests.Persistence.Repositories var entityRepository = new EntityRepository(accessor); var relationRepository = new RelationRepository(accessor, Logger, relationTypeRepository, entityRepository); var propertyEditors = new Lazy(() => new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty()))); - var repository = new DocumentRepository(accessor, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors); + var dataValueReferences = new DataValueReferenceFactoryCollection(Enumerable.Empty()); + var repository = new DocumentRepository(accessor, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors, dataValueReferences); return repository; } @@ -980,7 +981,8 @@ namespace Umbraco.Tests.Persistence.Repositories var entityRepository = new EntityRepository(accessor); var relationRepository = new RelationRepository(accessor, Logger, relationTypeRepository, entityRepository); var propertyEditors = new Lazy(() => new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty()))); - var repository = new MediaRepository(accessor, AppCaches.Disabled, Logger, mediaTypeRepository, tagRepository, Mock.Of(), relationRepository, relationTypeRepository, propertyEditors); + var dataValueReferences = new DataValueReferenceFactoryCollection(Enumerable.Empty()); + var repository = new MediaRepository(accessor, AppCaches.Disabled, Logger, mediaTypeRepository, tagRepository, Mock.Of(), relationRepository, relationTypeRepository, propertyEditors, dataValueReferences); return repository; } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs index 4bf50c6ffd..200447e30a 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs @@ -246,7 +246,8 @@ namespace Umbraco.Tests.Persistence.Repositories var entityRepository = new EntityRepository(ScopeProvider); var relationRepository = new RelationRepository(ScopeProvider, Logger, relationTypeRepository, entityRepository); var propertyEditors = new Lazy(() => new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty()))); - var contentRepo = new DocumentRepository(ScopeProvider, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors); + var dataValueReferences = new DataValueReferenceFactoryCollection(Enumerable.Empty()); + var contentRepo = new DocumentRepository(ScopeProvider, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors, dataValueReferences); var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage2", "Textpage"); ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate); // else, FK violation on contentType! diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs index f4ab387683..3ba00e54cf 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs @@ -35,7 +35,8 @@ namespace Umbraco.Tests.Persistence.Repositories var entityRepository = new EntityRepository(accessor); var relationRepository = new RelationRepository(accessor, Logger, relationTypeRepository, entityRepository); var propertyEditors = new Lazy(() => new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty()))); - var repository = new MediaRepository(accessor, AppCaches, Mock.Of(), mediaTypeRepository, tagRepository, Mock.Of(), relationRepository, relationTypeRepository, propertyEditors); + var dataValueReferences = new DataValueReferenceFactoryCollection(Enumerable.Empty()); + var repository = new MediaRepository(accessor, AppCaches, Mock.Of(), mediaTypeRepository, tagRepository, Mock.Of(), relationRepository, relationTypeRepository, propertyEditors, dataValueReferences); return repository; } @@ -57,7 +58,8 @@ namespace Umbraco.Tests.Persistence.Repositories var entityRepository = new EntityRepository(accessor); var relationRepository = new RelationRepository(accessor, Logger, relationTypeRepository, entityRepository); var propertyEditors = new Lazy(() => new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty()))); - var repository = new DocumentRepository(accessor, AppCaches, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors); + var dataValueReferences = new DataValueReferenceFactoryCollection(Enumerable.Empty()); + var repository = new DocumentRepository(accessor, AppCaches, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors, dataValueReferences); return repository; } diff --git a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs index 763635c393..9f4304ebee 100644 --- a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs +++ b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs @@ -52,7 +52,8 @@ namespace Umbraco.Tests.Services var entityRepository = new EntityRepository(accessor); var relationRepository = new RelationRepository(accessor, Logger, relationTypeRepository, entityRepository); var propertyEditors = new Lazy(() => new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty()))); - var repository = new DocumentRepository(accessor, AppCaches.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository, relationRepository, relationTypeRepository, propertyEditors); + var dataValueReferences = new DataValueReferenceFactoryCollection(Enumerable.Empty()); + var repository = new DocumentRepository(accessor, AppCaches.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository, relationRepository, relationTypeRepository, propertyEditors, dataValueReferences); return repository; } diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 88b5cb5c34..92d2a68472 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -3211,7 +3211,8 @@ namespace Umbraco.Tests.Services var entityRepository = new EntityRepository(accessor); var relationRepository = new RelationRepository(accessor, Logger, relationTypeRepository, entityRepository); var propertyEditors = new Lazy(() => new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty()))); - var repository = new DocumentRepository(accessor, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors); + var dataValueReferences = new DataValueReferenceFactoryCollection(Enumerable.Empty()); + var repository = new DocumentRepository(accessor, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors, dataValueReferences); return repository; } diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index ffc49b47ac..4f7de2d230 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -217,6 +217,9 @@ namespace Umbraco.Tests.Testing Composition.RegisterUnique(_ => Umbraco.Web.Composing.Current.UmbracoContextAccessor); Composition.RegisterUnique(); Composition.WithCollectionBuilder(); + + Composition.DataValueReferenceFactories(); + Composition.RegisterUnique(); Composition.RegisterUnique(); Composition.RegisterUnique(); diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 5be5e45ecd..ec65046e84 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -182,6 +182,8 @@ namespace Umbraco.Web.Composing public static DataEditorCollection DataEditors => CoreCurrent.DataEditors; + public static DataValueReferenceFactoryCollection DataValueReferenceFactories => CoreCurrent.DataValueReferenceFactories; + public static PropertyEditorCollection PropertyEditors => CoreCurrent.PropertyEditors; public static ParameterEditorCollection ParameterEditors => CoreCurrent.ParameterEditors; diff --git a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs index 228e058ee7..da4264be28 100644 --- a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs @@ -165,20 +165,15 @@ namespace Umbraco.Web.PropertyEditors public IEnumerable GetReferences(object value) { var rawJson = value == null ? string.Empty : value is string str ? str : value.ToString(); - DeserializeGridValue(rawJson, out var richTextEditorValues, out var mediaValues); foreach (var umbracoEntityReference in richTextEditorValues.SelectMany(x => _richTextPropertyValueEditor.GetReferences(x.Value))) - { yield return umbracoEntityReference; - } foreach (var umbracoEntityReference in mediaValues.SelectMany(x => _mediaPickerPropertyValueEditor.GetReferences(x.Value["udi"]))) - { yield return umbracoEntityReference; - } } } } diff --git a/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs index 1da665a622..fd7f735e68 100644 --- a/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs @@ -36,11 +36,8 @@ namespace Umbraco.Web.PropertyEditors var udiPaths = asString.Split(','); foreach (var udiPath in udiPaths) - { if (Udi.TryParse(udiPath, out var udi)) yield return new UmbracoEntityReference(udi); - } - } } } diff --git a/src/Umbraco.Web/PropertyEditors/MultiUrlPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultiUrlPickerPropertyEditor.cs index 95ac809576..8af2d98018 100644 --- a/src/Umbraco.Web/PropertyEditors/MultiUrlPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultiUrlPickerPropertyEditor.cs @@ -4,6 +4,9 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Web.PublishedCache; +using System.Collections.Generic; +using Umbraco.Core.Models.Editors; +using Newtonsoft.Json; namespace Umbraco.Web.PropertyEditors { @@ -25,7 +28,7 @@ namespace Umbraco.Web.PropertyEditors _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); _publishedSnapshotAccessor = publishedSnapshotAccessor ?? throw new ArgumentNullException(nameof(publishedSnapshotAccessor)); } - + protected override IConfigurationEditor CreateConfigurationEditor() => new MultiUrlPickerConfigurationEditor(); protected override IDataValueEditor CreateValueEditor() => new MultiUrlPickerValueEditor(_entityService, _publishedSnapshotAccessor, Logger, Attribute); diff --git a/src/Umbraco.Web/PropertyEditors/MultiUrlPickerValueEditor.cs b/src/Umbraco.Web/PropertyEditors/MultiUrlPickerValueEditor.cs index 9c42fe6cbe..853e995ed8 100644 --- a/src/Umbraco.Web/PropertyEditors/MultiUrlPickerValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultiUrlPickerValueEditor.cs @@ -190,9 +190,6 @@ namespace Umbraco.Web.PropertyEditors } } - - - } } } diff --git a/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs index 3d0605c4f9..f3e391aeab 100644 --- a/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs @@ -227,6 +227,7 @@ namespace Umbraco.Web.PropertyEditors // return json return JsonConvert.SerializeObject(deserialized); } + #endregion public IEnumerable GetReferences(object value) { @@ -252,8 +253,6 @@ namespace Umbraco.Web.PropertyEditors return result; } - - #endregion } internal class NestedContentValidator : IValueValidator diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs index 4de5e8627a..28f365fc60 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs @@ -9,9 +9,7 @@ using Umbraco.Core.Dashboards; using Umbraco.Core.Dictionary; using Umbraco.Core.Events; using Umbraco.Core.Migrations.PostMigrations; -using Umbraco.Web.Migrations.PostMigrations; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; using Umbraco.Core.Runtime; using Umbraco.Core.Services; @@ -19,7 +17,6 @@ using Umbraco.Web.Actions; using Umbraco.Web.Cache; using Umbraco.Web.Composing.CompositionExtensions; using Umbraco.Web.ContentApps; -using Umbraco.Web.Dashboards; using Umbraco.Web.Dictionary; using Umbraco.Web.Editors; using Umbraco.Web.Features; @@ -37,7 +34,6 @@ using Umbraco.Web.Security.Providers; using Umbraco.Web.Services; using Umbraco.Web.SignalR; using Umbraco.Web.Templates; -using Umbraco.Web.Tour; using Umbraco.Web.Trees; using Umbraco.Web.WebApi; using Current = Umbraco.Web.Composing.Current; @@ -150,19 +146,19 @@ namespace Umbraco.Web.Runtime .ComposeUmbracoControllers(GetType().Assembly) .SetDefaultRenderMvcController(); // default controller for template views - composition.WithCollectionBuilder() + composition.SearchableTrees() .Add(() => composition.TypeLoader.GetTypes()); composition.Register(Lifetime.Request); - composition.WithCollectionBuilder() + composition.EditorValidators() .Add(() => composition.TypeLoader.GetTypes()); - composition.WithCollectionBuilder(); + composition.TourFilters(); composition.RegisterUnique(); - composition.WithCollectionBuilder() + composition.Actions() .Add(() => composition.TypeLoader.GetTypes()); //we need to eagerly scan controller types since they will need to be routed @@ -177,26 +173,26 @@ namespace Umbraco.Web.Runtime // here because there cannot be two converters for one property editor - and we want the full // RteMacroRenderingValueConverter that converts macros, etc. So remove TinyMceValueConverter. // (the limited one, defined in Core, is there for tests) - same for others - composition.WithCollectionBuilder() + composition.PropertyValueConverters() .Remove() .Remove() .Remove(); - + // add all known factories, devs can then modify this list on application // startup either by binding to events or in their own global.asax - composition.WithCollectionBuilder() + composition.FilteredControllerFactory() .Append(); - composition.WithCollectionBuilder() + composition.UrlProviders() .Append() .Append(); - composition.WithCollectionBuilder() + composition.MediaUrlProviders() .Append(); composition.RegisterUnique(); - composition.WithCollectionBuilder() + composition.ContentFinders() // all built-in finders in the correct order, // devs can then modify this list on application startup .Append() @@ -211,7 +207,7 @@ namespace Umbraco.Web.Runtime composition.RegisterUnique(); // register *all* checks, except those marked [HideFromTypeFinder] of course - composition.WithCollectionBuilder() + composition.HealthChecks() .Add(() => composition.TypeLoader.GetTypes()); composition.WithCollectionBuilder() @@ -231,13 +227,13 @@ namespace Umbraco.Web.Runtime composition.RegisterUnique(); // register known content apps - composition.WithCollectionBuilder() + composition.ContentApps() .Append() .Append() .Append(); // register back office sections in the order we want them rendered - composition.WithCollectionBuilder() + composition.Sections() .Append() .Append() .Append() @@ -248,18 +244,18 @@ namespace Umbraco.Web.Runtime .Append(); // register core CMS dashboards and 3rd party types - will be ordered by weight attribute & merged with package.manifest dashboards - composition.WithCollectionBuilder() + composition.Dashboards() .Add(composition.TypeLoader.GetTypes()); // register back office trees // the collection builder only accepts types inheriting from TreeControllerBase // and will filter out those that are not attributed with TreeAttribute - composition.WithCollectionBuilder() + composition.Trees() .AddTreeControllers(umbracoApiControllerTypes.Where(x => typeof(TreeControllerBase).IsAssignableFrom(x))); // register OEmbed providers - no type scanning - all explicit opt-in of adding types // note: IEmbedProvider is not IDiscoverable - think about it if going for type scanning - composition.WithCollectionBuilder() + composition.OEmbedProviders() .Append() .Append() .Append() @@ -274,7 +270,7 @@ namespace Umbraco.Web.Runtime .Append() .Append() .Append(); - + // replace with web implementation composition.RegisterUnique();